Skip to content

Commit

Permalink
[CSPM] k8sconfig: better handling of CLI/Kubelet config precedence (#…
Browse files Browse the repository at this point in the history
…21196)

This commit introduces the proper logic to handle the precedence of
the configuration parameters for Kubelet between CLI args and Kubelet
configuration file.

Kubelet can be configured both using CLI arguments and a configuration file.
CLI arguments take precedence over Kubelet configuration parameters. With this
change, CLI args default values are properly hidden if an associated value was
setup as part of the configuration file. The rules associated can more easily
make the proper decision.
  • Loading branch information
jinroh authored Dec 20, 2023
1 parent 3966088 commit 3584679
Show file tree
Hide file tree
Showing 4 changed files with 452 additions and 206 deletions.
63 changes: 54 additions & 9 deletions pkg/compliance/k8sconfig/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,38 @@ func (l *loader) loadConfigFileMeta(name string) *K8sConfigFileMeta {
}
}

func (l *loader) getConfigFromPath(meta *K8sConfigFileMeta, path string) (map[string]interface{}, string, bool) {
if meta == nil || meta.Content == nil {
return nil, "", false
}
content, ok := meta.Content.(map[string]interface{})
if !ok {
return nil, "", false
}
fields := strings.Split(path, ".")
if len(fields) == 0 {
return nil, "", false
}
if len(fields) > 1 {
for _, field := range fields[:len(fields)-1] {
content, ok = content[field].(map[string]interface{})
if !ok {
return nil, "", false
}
}
}
return content, fields[len(fields)-1], true
}

func (l *loader) configFileMetaHasField(meta *K8sConfigFileMeta, path string) bool {
content, lastField, ok := l.getConfigFromPath(meta, path)
if ok {
_, hasField := content[lastField]
return hasField
}
return false
}

func (l *loader) loadKubeletConfigFileMeta(name string) *K8sConfigFileMeta {
meta := l.loadConfigFileMeta(name)
if meta == nil {
Expand Down Expand Up @@ -529,40 +561,53 @@ func (l *loader) pushError(err error) {
}
}

func (l *loader) parseBool(v string) bool {
func (l *loader) parseBool(v string) *bool {
if v == "" {
return true
return nil
}
b, err := strconv.ParseBool(v)
if err != nil {
l.pushError(err)
return nil
}
return b
return &b
}

//nolint:unused,deadcode
func (l *loader) parseFloat(v string) float64 {
func (l *loader) parseFloat(v string) *float64 {
if v == "" {
return nil
}
f, err := strconv.ParseFloat(v, 64)
if err != nil {
l.pushError(err)
return nil
}
return f
return &f
}

func (l *loader) parseInt(v string) int {
func (l *loader) parseInt(v string) *int {
if v == "" {
return nil
}
i, err := strconv.Atoi(v)
if err != nil {
l.pushError(err)
return nil
}
return i
return &i
}

func (l *loader) parseDuration(v string) time.Duration {
func (l *loader) parseDuration(v string) *time.Duration {
if v == "" {
return nil
}
d, err := time.ParseDuration(v)
if err != nil {
l.pushError(err)
return nil
}
return d
return &d
}

func buildProc(name string, cmdline []string) proc {
Expand Down
32 changes: 29 additions & 3 deletions pkg/compliance/k8sconfig/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ kubelet \
--cloud-provider=aws \
--container-runtime=remote \
--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=Sandbox,alpha.eksctl.io/nodegroup-name=standard,eks.amazonaws.com/nodegroup-image=ami-09f37ddb4a6ecc85e,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=standard,eks.amazonaws.com/sourceLaunchTemplateId=lt-0df2e04572534b928 \
--max-pods=17
--max-pods=17 \
--rotate-server-certificates=true
`

// TODO(jinroh): use testdata files
Expand Down Expand Up @@ -99,7 +100,6 @@ ARCH="aarch64"`,
},
"clusterDomain": "cluster.local",
"hairpinMode": "hairpin-veth",
"readOnlyPort": 0,
"cgroupDriver": "systemd",
"cgroupRoot": "/",
"featureGates": {
Expand Down Expand Up @@ -135,7 +135,8 @@ ARCH="aarch64"`,
"memory": "442Mi"
},
"systemReservedCgroup": "/system",
"kubeReservedCgroup": "/runtime"
"kubeReservedCgroup": "/runtime",
"maxPods": 18
}`,
},
{
Expand Down Expand Up @@ -337,6 +338,20 @@ func TestKubEksConfigLoader(t *testing.T) {
assert.NotNil(t, conf.Components.Kubelet.Kubeconfig)
assert.NotNil(t, conf.Components.Kubelet.Config.Content)

kubeletConfig := conf.Components.Kubelet.Config.Content.(map[string]interface{})

{
assert.Nil(t, conf.Components.Kubelet.AnonymousAuth)
assert.Equal(t, false, kubeletConfig["authentication"].(map[string]interface{})["anonymous"].(map[string]interface{})["enabled"])
}

{
v := 10255
assert.NotNil(t, conf.Components.Kubelet.ReadOnlyPort)
assert.Equal(t, &v, conf.Components.Kubelet.ReadOnlyPort)
assert.Nil(t, kubeletConfig["readOnlyPort"])
}

{
content, ok := conf.Components.Kubelet.Config.Content.(map[string]interface{})
assert.True(t, ok)
Expand All @@ -347,6 +362,17 @@ func TestKubEksConfigLoader(t *testing.T) {
clientCAFile, ok := x509["clientCAFile"].(*K8sCertFileMeta)
assert.True(t, ok)
assert.NotNil(t, clientCAFile)
assert.Nil(t, conf.Components.Kubelet.ClientCaFile)

assert.Equal(t, true, content["featureGates"].(map[string]interface{})["RotateKubeletServerCertificate"])

assert.Nil(t, conf.Components.Kubelet.AuthorizationMode)
assert.Equal(t, "Webhook", content["authorization"].(map[string]interface{})["mode"])

sevenTeen := 17
eigthTeen := 18
assert.Equal(t, &sevenTeen, conf.Components.Kubelet.MaxPods)
assert.Equal(t, float64(eigthTeen), content["maxPods"])
}
}

Expand Down
Loading

0 comments on commit 3584679

Please sign in to comment.