Skip to content

Commit

Permalink
observeAuthMode: read from default config instead of hardcoding
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Hunt <[email protected]>
  • Loading branch information
haircommander committed Dec 5, 2024
1 parent 1061920 commit 07665c1
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 38 deletions.
35 changes: 35 additions & 0 deletions bindata/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package bindata

import (
"bytes"
"encoding/json"
"fmt"
"path/filepath"

kyaml "k8s.io/apimachinery/pkg/util/yaml"
)

func UnstructuredDefaultConfig() (map[string]any, error) {
asset := filepath.Join("assets", "config", "defaultconfig.yaml")
raw, err := Asset(asset)
if err != nil {
return nil, fmt.Errorf("failed to get default config asset asset=%s - %s", asset, err)
}

rawJSON, err := kyaml.ToJSON(raw)
if err != nil {
return nil, fmt.Errorf("failed to convert asset yaml to JSON asset=%s - %s", asset, err)
}

return ConvertToUnstructured(rawJSON)
}

func ConvertToUnstructured(raw []byte) (map[string]interface{}, error) {
decoder := json.NewDecoder(bytes.NewBuffer(raw))
u := map[string]interface{}{}
if err := decoder.Decode(&u); err != nil {
return nil, err
}

return u, nil
}
30 changes: 3 additions & 27 deletions pkg/cmd/render/render.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package render

import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
Expand Down Expand Up @@ -32,7 +31,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
kyaml "k8s.io/apimachinery/pkg/util/yaml"
auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
"k8s.io/klog/v2"
)
Expand Down Expand Up @@ -324,22 +322,10 @@ func (r *renderOpts) Run() error {
}

func bootstrapDefaultConfig(featureGates featuregates.FeatureGate) ([]byte, error) {
asset := filepath.Join("assets", "config", "defaultconfig.yaml")
raw, err := bindata.Asset(asset)
defaultConfig, err := bindata.UnstructuredDefaultConfig()
if err != nil {
return nil, fmt.Errorf("failed to get default config asset asset=%s - %s", asset, err)
return nil, fmt.Errorf("failed to get unstructured default config: %v", err)
}

rawJSON, err := kyaml.ToJSON(raw)
if err != nil {
return nil, fmt.Errorf("failed to convert asset yaml to JSON asset=%s - %s", asset, err)
}

defaultConfig, err := convertToUnstructured(rawJSON)
if err != nil {
return nil, fmt.Errorf("failed to decode default config into unstructured - %s", err)
}

policy, err := libgoaudit.GetAuditPolicy(configv1.Audit{Profile: configv1.DefaultAuditProfileType})
if err != nil {
return nil, fmt.Errorf("failed to retreive default audit policy: %v", err)
Expand All @@ -359,7 +345,7 @@ func bootstrapDefaultConfig(featureGates featuregates.FeatureGate) ([]byte, erro
}

if featureGates.Enabled(features.FeatureGateMinimumKubeletVersion) {
if err := node.SetAPIServerArgumentsToEnforceMinimumKubeletVersion(defaultConfig, true); err != nil {
if err := node.SetAPIServerArgumentsToEnforceMinimumKubeletVersion(node.AuthModesFromUnstructured(defaultConfig), defaultConfig, true); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -408,16 +394,6 @@ func addAuditPolicyToConfig(config map[string]interface{}, policy *auditv1.Polic
return nil
}

func convertToUnstructured(raw []byte) (map[string]interface{}, error) {
decoder := json.NewDecoder(bytes.NewBuffer(raw))
u := map[string]interface{}{}
if err := decoder.Decode(&u); err != nil {
return nil, err
}

return u, nil
}

func mustReadTemplateFile(fname string) genericrenderoptions.Template {
bs, err := ioutil.ReadFile(fname)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
configv1 "github.com/openshift/api/config/v1"
"github.com/openshift/api/features"
kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
"github.com/openshift/cluster-kube-apiserver-operator/bindata"
libgoaudit "github.com/openshift/library-go/pkg/operator/apiserver/audit"
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
genericrenderoptions "github.com/openshift/library-go/pkg/operator/render/options"
Expand Down Expand Up @@ -700,7 +701,7 @@ func TestGetDefaultConfigWithAuditPolicy(t *testing.T) {
require.NoError(t, err)
rawPolicyJSON, err := kyaml.ToJSON(defaultPolicy)
require.NoError(t, err)
policyExpected, err := convertToUnstructured(rawPolicyJSON)
policyExpected, err := bindata.ConvertToUnstructured(rawPolicyJSON)
require.NoError(t, err)

isEqual := equality.Semantic.DeepEqual(policyExpected, auditConfigPolicyGot)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

configv1 "github.com/openshift/api/config/v1"
"github.com/openshift/api/features"
"github.com/openshift/cluster-kube-apiserver-operator/bindata"
"github.com/openshift/library-go/pkg/operator/configobserver"
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
"github.com/openshift/library-go/pkg/operator/events"
Expand All @@ -19,9 +20,6 @@ var (
authModeFlag = "authorization-mode"
apiServerArgs = "apiServerArguments"
authModePath = []string{apiServerArgs, authModeFlag}
// The default value for apiServerArguments.authorization-mode.
// Should be synced with bindata/assets/config/defaultconfig.yaml
DefaultAuthorizationModes = []string{"Scope", "SystemMasters", "RBAC", "Node"}
)

type minimumKubeletVersionObserver struct {
Expand Down Expand Up @@ -85,14 +83,30 @@ func (o *minimumKubeletVersionObserver) ObserveMinimumKubeletVersion(genericList

type authorizationModeObserver struct {
featureGateAccessor featuregates.FeatureGateAccess
authModes []string
}

func NewAuthorizationModeObserver(featureGateAccessor featuregates.FeatureGateAccess) configobserver.ObserveConfigFunc {
defaultConfig, err := bindata.UnstructuredDefaultConfig()
if err != nil {
// programming error, the built-in configuration should always be valid
panic(err)
}

return (&authorizationModeObserver{
featureGateAccessor: featureGateAccessor,
authModes: AuthModesFromUnstructured(defaultConfig),
}).ObserveAuthorizationMode
}

func AuthModesFromUnstructured(config map[string]any) []string {
authModes, found, err := unstructured.NestedStringSlice(config, authModePath...)
if !found || err != nil {
return []string{}
}
return authModes
}

// ObserveAuthorizationMode watches the featuregate configuration and generates the apiServerArguments.authorization-mode
// It currently hardcodes the default set and adds MinimumKubeletVersion if the feature is set to on.
func (o *authorizationModeObserver) ObserveAuthorizationMode(genericListers configobserver.Listers, _ events.Recorder, existingConfig map[string]interface{}) (ret map[string]interface{}, errs []error) {
Expand All @@ -111,7 +125,7 @@ func (o *authorizationModeObserver) ObserveAuthorizationMode(genericListers conf
ret = configobserver.Pruned(ret, authModePath)
}()

if err := SetAPIServerArgumentsToEnforceMinimumKubeletVersion(ret, featureGates.Enabled(features.FeatureGateMinimumKubeletVersion)); err != nil {
if err := SetAPIServerArgumentsToEnforceMinimumKubeletVersion(o.authModes, ret, featureGates.Enabled(features.FeatureGateMinimumKubeletVersion)); err != nil {
return existingConfig, append(errs, err)
}
return ret, nil
Expand All @@ -120,13 +134,14 @@ func (o *authorizationModeObserver) ObserveAuthorizationMode(genericListers conf
// SetAPIServerArgumentsToEnforceMinimumKubeletVersion modifies the passed in config
// to add the "authorization-mode": "MinimumKubeletVersion" if the feature is on. If it's off, it
// removes it instead.
func SetAPIServerArgumentsToEnforceMinimumKubeletVersion(newConfig map[string]interface{}, on bool) error {
defaultSet := DefaultAuthorizationModes
// This function assumes MinimumKubeletVersion auth mode isn't present by default,
// and should likely be removed when it is.
func SetAPIServerArgumentsToEnforceMinimumKubeletVersion(defaultAuthModes []string, newConfig map[string]interface{}, on bool) error {
if on {
defaultSet = append(defaultSet, ModeMinimumKubeletVersion)
defaultAuthModes = append(defaultAuthModes, ModeMinimumKubeletVersion)
}
sort.Sort(sort.StringSlice(defaultSet))
sort.Sort(sort.StringSlice(defaultAuthModes))

unstructured.RemoveNestedField(newConfig, authModePath...)
return unstructured.SetNestedStringSlice(newConfig, defaultSet, authModePath...)
return unstructured.SetNestedStringSlice(newConfig, defaultAuthModes, authModePath...)
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func TestObserveKubeletMinimumVersion(t *testing.T) {

func TestSetAPIServerArgumentsToEnforceMinimumKubeletVersion(t *testing.T) {
for _, on := range []bool{false, true} {
defaultSet := []string{"Node", "RBAC", "Scope", "SystemMasters"}
expectedSet := []any{"Node", "RBAC", "Scope", "SystemMasters"}
if on {
expectedSet = append([]any{ModeMinimumKubeletVersion}, expectedSet...)
Expand Down Expand Up @@ -164,7 +165,7 @@ func TestSetAPIServerArgumentsToEnforceMinimumKubeletVersion(t *testing.T) {
name += "off"
}
t.Run(name, func(t *testing.T) {
if err := SetAPIServerArgumentsToEnforceMinimumKubeletVersion(tc.existingConfig, on); err != nil {
if err := SetAPIServerArgumentsToEnforceMinimumKubeletVersion(defaultSet, tc.existingConfig, on); err != nil {
t.Fatal(err)
}

Expand Down

0 comments on commit 07665c1

Please sign in to comment.