diff --git a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/aws-cluster-class.yaml b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/aws-cluster-class.yaml index 04be532d9..004ffab64 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/aws-cluster-class.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/aws-cluster-class.yaml @@ -84,24 +84,73 @@ spec: clusterConfiguration: apiServer: extraArgs: + admission-control-config-file: /etc/kubernetes/admission.yaml + enable-admission-plugins: DenyServiceExternalIPs,EventRateLimit,NodeRestriction profiling: "false" + service-account-lookup: "true" + extraVolumes: + - hostPath: /etc/kubernetes/admission.yaml + mountPath: /etc/kubernetes/admission.yaml + name: admission-config + pathType: File + readOnly: true + - hostPath: /etc/kubernetes/eventratelimit-config.yaml + mountPath: /etc/kubernetes/eventratelimit-config.yaml + name: eventratelimit-config + pathType: File + readOnly: true controllerManager: extraArgs: cloud-provider: external profiling: "false" + terminated-pod-gc-threshold: "10000" scheduler: extraArgs: profiling: "false" + files: + - content: | + apiVersion: apiserver.config.k8s.io/v1 + kind: AdmissionConfiguration + plugins: + - name: EventRateLimit + path: /etc/kubernetes/eventratelimit-config.yaml + path: /etc/kubernetes/admission.yaml + permissions: "0600" + - content: | + apiVersion: eventratelimit.admission.k8s.io/v1alpha1 + kind: Configuration + limits: + - type: Server + qps: 10000 + burst: 40000 + path: /etc/kubernetes/eventratelimit-config.yaml + permissions: "0600" initConfiguration: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 name: '{{ ds.meta_data.local_hostname }}' joinConfiguration: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 name: '{{ ds.meta_data.local_hostname }}' + postKubeadmCommands: + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: AWSMachineTemplate @@ -140,4 +189,13 @@ spec: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 name: '{{ ds.meta_data.local_hostname }}' + postKubeadmCommands: + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml diff --git a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/docker-cluster-class.yaml b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/docker-cluster-class.yaml index d924b1017..3f95c1da7 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/docker-cluster-class.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/docker-cluster-class.yaml @@ -83,17 +83,68 @@ spec: clusterConfiguration: apiServer: extraArgs: + admission-control-config-file: /etc/kubernetes/admission.yaml + enable-admission-plugins: DenyServiceExternalIPs,EventRateLimit,NodeRestriction profiling: "false" + service-account-lookup: "true" + extraVolumes: + - hostPath: /etc/kubernetes/admission.yaml + mountPath: /etc/kubernetes/admission.yaml + name: admission-config + pathType: File + readOnly: true + - hostPath: /etc/kubernetes/eventratelimit-config.yaml + mountPath: /etc/kubernetes/eventratelimit-config.yaml + name: eventratelimit-config + pathType: File + readOnly: true controllerManager: extraArgs: profiling: "false" + terminated-pod-gc-threshold: "10000" scheduler: extraArgs: profiling: "false" + files: + - content: | + apiVersion: apiserver.config.k8s.io/v1 + kind: AdmissionConfiguration + plugins: + - name: EventRateLimit + path: /etc/kubernetes/eventratelimit-config.yaml + path: /etc/kubernetes/admission.yaml + permissions: "0600" + - content: | + apiVersion: eventratelimit.admission.k8s.io/v1alpha1 + kind: Configuration + limits: + - type: Server + qps: 10000 + burst: 40000 + path: /etc/kubernetes/eventratelimit-config.yaml + permissions: "0600" initConfiguration: - nodeRegistration: {} + nodeRegistration: + kubeletExtraArgs: + event-qps: "5" + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 joinConfiguration: - nodeRegistration: {} + nodeRegistration: + kubeletExtraArgs: + event-qps: "5" + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + postKubeadmCommands: + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: DockerMachineTemplate @@ -131,4 +182,14 @@ spec: template: spec: joinConfiguration: - nodeRegistration: {} + nodeRegistration: + kubeletExtraArgs: + event-qps: "5" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + postKubeadmCommands: + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml diff --git a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/nutanix-cluster-class.yaml b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/nutanix-cluster-class.yaml index 79ff86bb2..549c623a0 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/nutanix-cluster-class.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/defaultclusterclasses/nutanix-cluster-class.yaml @@ -11,10 +11,17 @@ spec: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" eviction-hard: nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%,memory.available<100Mi,imagefs.inodesFree<10% - tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 postKubeadmCommands: - echo "after kubeadm call" > /var/log/postkubeadm.log + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml preKubeadmCommands: - echo "before kubeadm call" > /var/log/prekubeadm.log - hostnamectl set-hostname "{{ ds.meta_data.hostname }}" @@ -123,12 +130,27 @@ spec: clusterConfiguration: apiServer: extraArgs: + admission-control-config-file: /etc/kubernetes/admission.yaml + enable-admission-plugins: DenyServiceExternalIPs,EventRateLimit,NodeRestriction profiling: "false" + service-account-lookup: "true" tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + extraVolumes: + - hostPath: /etc/kubernetes/admission.yaml + mountPath: /etc/kubernetes/admission.yaml + name: admission-config + pathType: File + readOnly: true + - hostPath: /etc/kubernetes/eventratelimit-config.yaml + mountPath: /etc/kubernetes/eventratelimit-config.yaml + name: eventratelimit-config + pathType: File + readOnly: true controllerManager: extraArgs: cloud-provider: external profiling: "false" + terminated-pod-gc-threshold: "10000" tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 scheduler: extraArgs: @@ -199,21 +221,49 @@ spec: path: /etc/kubernetes/admin.conf name: kubeconfig path: /etc/kubernetes/manifests/kube-vip.yaml + - content: | + apiVersion: apiserver.config.k8s.io/v1 + kind: AdmissionConfiguration + plugins: + - name: EventRateLimit + path: /etc/kubernetes/eventratelimit-config.yaml + path: /etc/kubernetes/admission.yaml + permissions: "0600" + - content: | + apiVersion: eventratelimit.admission.k8s.io/v1alpha1 + kind: Configuration + limits: + - type: Server + qps: 10000 + burst: 40000 + path: /etc/kubernetes/eventratelimit-config.yaml + permissions: "0600" initConfiguration: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" eviction-hard: nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%,memory.available<100Mi,imagefs.inodesFree<10% - tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 joinConfiguration: nodeRegistration: kubeletExtraArgs: cloud-provider: external + event-qps: "5" eviction-hard: nodefs.available<10%,nodefs.inodesFree<5%,imagefs.available<15%,memory.available<100Mi,imagefs.inodesFree<10% - tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + make-iptables-util-chains: "true" + pod-max-pids: "4096" + read-only-port: "0" + streaming-connection-idle-timeout: 5m + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 postKubeadmCommands: - - echo export KUBECONFIG=/etc/kubernetes/admin.conf >> /root/.bashrc - - echo "after kubeadm call" > /var/log/postkubeadm.log + - chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" + - chmod 600 $(systemctl show -P DropInPaths kubelet.service) + - chmod 600 /var/lib/kubelet/config.yaml preKubeadmCommands: - echo "before kubeadm call" > /var/log/prekubeadm.log - hostnamectl set-hostname "{{ ds.meta_data.hostname }}" diff --git a/hack/examples/overlays/clusterclasses/aws/kustomization.yaml.tmpl b/hack/examples/overlays/clusterclasses/aws/kustomization.yaml.tmpl index 682bc2c53..3d8f4f008 100644 --- a/hack/examples/overlays/clusterclasses/aws/kustomization.yaml.tmpl +++ b/hack/examples/overlays/clusterclasses/aws/kustomization.yaml.tmpl @@ -68,5 +68,29 @@ patches: # BEGIN CIS patches - target: kind: KubeadmControlPlaneTemplate - path: ../../../patches/disable-kubeadmcontrolplane-profiling.yaml + path: ../../../patches/cis-kubeadmcontrolplanetemplate.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/initialize-kubeadmconfigtemplate-postkubeadmcommands.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-files.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-extravolumes.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-admissionconfiguration.yaml # END CIS patches diff --git a/hack/examples/overlays/clusterclasses/docker/kustomization.yaml.tmpl b/hack/examples/overlays/clusterclasses/docker/kustomization.yaml.tmpl index d2706f020..f8cfb46e0 100644 --- a/hack/examples/overlays/clusterclasses/docker/kustomization.yaml.tmpl +++ b/hack/examples/overlays/clusterclasses/docker/kustomization.yaml.tmpl @@ -29,5 +29,29 @@ patches: # BEGIN CIS patches - target: kind: KubeadmControlPlaneTemplate - path: ../../../patches/disable-kubeadmcontrolplane-profiling.yaml + path: ../../../patches/cis-kubeadmcontrolplanetemplate.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/initialize-kubeadmconfigtemplate-postkubeadmcommands.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-files.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-extravolumes.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-admissionconfiguration.yaml # END CIS patches diff --git a/hack/examples/overlays/clusterclasses/nutanix/kustomization.yaml.tmpl b/hack/examples/overlays/clusterclasses/nutanix/kustomization.yaml.tmpl index 90c13c876..ca16d8749 100644 --- a/hack/examples/overlays/clusterclasses/nutanix/kustomization.yaml.tmpl +++ b/hack/examples/overlays/clusterclasses/nutanix/kustomization.yaml.tmpl @@ -29,5 +29,23 @@ patches: # BEGIN CIS patches - target: kind: KubeadmControlPlaneTemplate - path: ../../../patches/disable-kubeadmcontrolplane-profiling.yaml + path: ../../../patches/cis-kubeadmcontrolplanetemplate.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmConfigTemplate + path: ../../../patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/initialize-extravolumes.yaml + - target: + kind: KubeadmControlPlaneTemplate + path: ../../../patches/cis-admissionconfiguration.yaml # END CIS patches diff --git a/hack/examples/patches/cis-admissionconfiguration.yaml b/hack/examples/patches/cis-admissionconfiguration.yaml new file mode 100644 index 000000000..71f4e5c79 --- /dev/null +++ b/hack/examples/patches/cis-admissionconfiguration.yaml @@ -0,0 +1,47 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- op: add + path: /spec/template/spec/kubeadmConfigSpec/files/- + value: + path: /etc/kubernetes/admission.yaml + permissions: "0600" + content: | + apiVersion: apiserver.config.k8s.io/v1 + kind: AdmissionConfiguration + plugins: + - name: EventRateLimit + path: /etc/kubernetes/eventratelimit-config.yaml +- op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/- + value: + name: admission-config + hostPath: /etc/kubernetes/admission.yaml + mountPath: /etc/kubernetes/admission.yaml + readOnly: true + pathType: File +- op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs/admission-control-config-file + value: /etc/kubernetes/admission.yaml + +# 1.2.9 Ensure that the EventRateLimit admission controller is enabled +- op: add + path: /spec/template/spec/kubeadmConfigSpec/files/- + value: + path: /etc/kubernetes/eventratelimit-config.yaml + permissions: "0600" + content: | + apiVersion: eventratelimit.admission.k8s.io/v1alpha1 + kind: Configuration + limits: + - type: Server + qps: 10000 + burst: 40000 +- op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes/- + value: + name: eventratelimit-config + hostPath: /etc/kubernetes/eventratelimit-config.yaml + mountPath: /etc/kubernetes/eventratelimit-config.yaml + readOnly: true + pathType: File diff --git a/hack/examples/patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml b/hack/examples/patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml new file mode 100644 index 000000000..b0a6f9b58 --- /dev/null +++ b/hack/examples/patches/cis-kubeadmconfigtemplate-kubelet-file-permissions.yaml @@ -0,0 +1,14 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# 4.1.1 Ensure that the kubelet service file has appropriate permissions. +- op: add + path: /spec/template/spec/postKubeadmCommands/- + value: chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" +- op: add + path: /spec/template/spec/postKubeadmCommands/- + value: chmod 600 $(systemctl show -P DropInPaths kubelet.service) +# 4.1.9 Ensure that the kubelet configuration file has appropriate permissions. +- op: add + path: /spec/template/spec/postKubeadmCommands/- + value: chmod 600 /var/lib/kubelet/config.yaml diff --git a/hack/examples/patches/cis-kubeadmconfigtemplate.yaml b/hack/examples/patches/cis-kubeadmconfigtemplate.yaml new file mode 100644 index 000000000..e6ef33586 --- /dev/null +++ b/hack/examples/patches/cis-kubeadmconfigtemplate.yaml @@ -0,0 +1,24 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 +kind: KubeadmConfigTemplate +metadata: + name: not-used +spec: + template: + spec: + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + # 4.2.4 Ensure that the --read-only-port argument is set to 0 + read-only-port: "0" + # 4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 + # Recommendation: Set to 5m instead of 4h as per CIS guidelines + streaming-connection-idle-timeout: "5m" + # 4.2.8 Ensure that the event-qps argument is set to a level which ensures appropriate event capture + event-qps: "5" + # 4.2.12 Updated with recommended strong cipher suites + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + # 4.2.13 Ensure that a limit is set on pod PIDs + pod-max-pids: "4096" diff --git a/hack/examples/patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml b/hack/examples/patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml new file mode 100644 index 000000000..06a84e2a5 --- /dev/null +++ b/hack/examples/patches/cis-kubeadmcontrolplanetemplate-kubelet-file-permissions.yaml @@ -0,0 +1,14 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# 4.1.1 Ensure that the kubelet service file has appropriate permissions. +- op: add + path: /spec/template/spec/kubeadmConfigSpec/postKubeadmCommands/- + value: chmod 600 "$(systemctl show -P FragmentPath kubelet.service)" +- op: add + path: /spec/template/spec/kubeadmConfigSpec/postKubeadmCommands/- + value: chmod 600 $(systemctl show -P DropInPaths kubelet.service) +# 4.1.9 Ensure that the kubelet configuration file has appropriate permissions. +- op: add + path: /spec/template/spec/kubeadmConfigSpec/postKubeadmCommands/- + value: chmod 600 /var/lib/kubelet/config.yaml diff --git a/hack/examples/patches/cis-kubeadmcontrolplanetemplate.yaml b/hack/examples/patches/cis-kubeadmcontrolplanetemplate.yaml new file mode 100644 index 000000000..07f8cbc15 --- /dev/null +++ b/hack/examples/patches/cis-kubeadmcontrolplanetemplate.yaml @@ -0,0 +1,64 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: controlplane.cluster.x-k8s.io/v1beta1 +kind: KubeadmControlPlaneTemplate +metadata: + name: not-used +spec: + template: + spec: + kubeadmConfigSpec: + initConfiguration: + nodeRegistration: + kubeletExtraArgs: + # 4.2.4 Ensure that the --read-only-port argument is set to 0 + read-only-port: "0" + # 4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 + # Recommendation: Set to 5m instead of 4h as per CIS guidelines + streaming-connection-idle-timeout: "5m" + # 4.2.6 Ensure that the --make-iptables-util-chains argument is set to true + make-iptables-util-chains: "true" + # 4.2.8 Ensure that the event-qps argument is set to a level which ensures appropriate event capture + event-qps: "5" + # 4.2.12 Updated with recommended strong cipher suites + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + # 4.2.13 Ensure that a limit is set on pod PIDs + pod-max-pids: "4096" + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + # 4.2.4 Ensure that the --read-only-port argument is set to 0 + read-only-port: "0" + # 4.2.5 Ensure that the --streaming-connection-idle-timeout argument is not set to 0 + # Recommendation: Set to 5m instead of 4h as per CIS guidelines + streaming-connection-idle-timeout: "5m" + # 4.2.6 Ensure that the --make-iptables-util-chains argument is set to true + make-iptables-util-chains: "true" + # 4.2.8 Ensure that the event-qps argument is set to a level which ensures appropriate event capture + event-qps: "5" + # 4.2.12 Updated with recommended strong cipher suites + tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + # 4.2.13 Ensure that a limit is set on pod PIDs + pod-max-pids: "4096" + clusterConfiguration: + apiServer: + extraArgs: + # 1.2.15 Ensure that the --profiling argument is set to false + profiling: "false" + # 1.2.21 Ensure that the --service-account-lookup argument is set to true + service-account-lookup: "true" + # 1.2.3 Ensure that the DenyServiceExternalIPs is set + # 1.2.9 Ensure that the admission control plugin EventRateLimit is set + # 1.2.14 Ensure that the admission control plugin NodeRestriction is set + enable-admission-plugins: DenyServiceExternalIPs,EventRateLimit,NodeRestriction + controllerManager: + extraArgs: + #1.3.1 Ensure that the --terminated-pod-gc-threshold argument is set as appropriate + terminated-pod-gc-threshold: "10000" + #1.3.2 Ensure that the --profiling argument is set to false + profiling: "false" + scheduler: + extraArgs: + #1.4.1 Ensure that the --profiling argument is set to false + profiling: "false" diff --git a/hack/examples/patches/disable-kubeadmcontrolplane-profiling.yaml b/hack/examples/patches/disable-kubeadmcontrolplane-profiling.yaml deleted file mode 100644 index e86828dc8..000000000 --- a/hack/examples/patches/disable-kubeadmcontrolplane-profiling.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2025 Nutanix. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -apiVersion: controlplane.cluster.x-k8s.io/v1beta1 -kind: KubeadmControlPlaneTemplate -metadata: - name: not-used -spec: - template: - spec: - kubeadmConfigSpec: - clusterConfiguration: - apiServer: - extraArgs: - profiling: "false" - controllerManager: - extraArgs: - profiling: "false" - scheduler: - extraArgs: - profiling: "false" diff --git a/hack/examples/patches/initialize-extravolumes.yaml b/hack/examples/patches/initialize-extravolumes.yaml new file mode 100644 index 000000000..014fe5418 --- /dev/null +++ b/hack/examples/patches/initialize-extravolumes.yaml @@ -0,0 +1,6 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes + value: [] diff --git a/hack/examples/patches/initialize-files.yaml b/hack/examples/patches/initialize-files.yaml new file mode 100644 index 000000000..a00a6c2ee --- /dev/null +++ b/hack/examples/patches/initialize-files.yaml @@ -0,0 +1,6 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- op: add + path: /spec/template/spec/kubeadmConfigSpec/files + value: [] diff --git a/hack/examples/patches/initialize-kubeadmconfigtemplate-postkubeadmcommands.yaml b/hack/examples/patches/initialize-kubeadmconfigtemplate-postkubeadmcommands.yaml new file mode 100644 index 000000000..9da1fd703 --- /dev/null +++ b/hack/examples/patches/initialize-kubeadmconfigtemplate-postkubeadmcommands.yaml @@ -0,0 +1,6 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- op: add + path: /spec/template/spec/postKubeadmCommands + value: [] diff --git a/hack/examples/patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml b/hack/examples/patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml new file mode 100644 index 000000000..658306b67 --- /dev/null +++ b/hack/examples/patches/initialize-kubeadmcontrolplanetemplate-postkubeadmcommands.yaml @@ -0,0 +1,6 @@ +# Copyright 2025 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +- op: add + path: /spec/template/spec/kubeadmConfigSpec/postKubeadmCommands + value: [] diff --git a/pkg/handlers/generic/mutation/auditpolicy/inject.go b/pkg/handlers/generic/mutation/auditpolicy/inject.go index 14ea4d969..32b9f634f 100644 --- a/pkg/handlers/generic/mutation/auditpolicy/inject.go +++ b/pkg/handlers/generic/mutation/auditpolicy/inject.go @@ -7,6 +7,7 @@ import ( "context" _ "embed" + corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" @@ -25,7 +26,7 @@ type auditPolicyPatchHandler struct{} //go:embed embedded/apiserver-audit-policy.yaml var auditPolicy string -const auditPolicyPath = "/etc/kubernetes/audit-policy/apiserver-audit-policy.yaml" +const auditPolicyPath = "/etc/kubernetes/audit-policy.yaml" func NewPatch() *auditPolicyPatchHandler { return &auditPolicyPatchHandler{} @@ -82,14 +83,16 @@ func (h *auditPolicyPatchHandler) Mutate( apiServer.ExtraVolumes, bootstrapv1.HostPathMount{ Name: "audit-policy", - HostPath: "/etc/kubernetes/audit-policy/", - MountPath: "/etc/kubernetes/audit-policy/", + HostPath: auditPolicyPath, + MountPath: auditPolicyPath, ReadOnly: true, + PathType: corev1.HostPathFile, }, bootstrapv1.HostPathMount{ Name: "audit-logs", HostPath: "/var/log/kubernetes/audit", MountPath: "/var/log/audit/", + PathType: corev1.HostPathDirectoryOrCreate, }, ) diff --git a/pkg/handlers/generic/mutation/auditpolicy/inject_test.go b/pkg/handlers/generic/mutation/auditpolicy/inject_test.go index 352e0da63..224a06ca2 100644 --- a/pkg/handlers/generic/mutation/auditpolicy/inject_test.go +++ b/pkg/handlers/generic/mutation/auditpolicy/inject_test.go @@ -37,7 +37,7 @@ var _ = Describe("Generate Audit Policy patches", func() { Path: "/spec/template/spec/kubeadmConfigSpec/files", ValueMatcher: gomega.ContainElements( gomega.HaveKeyWithValue( - "path", "/etc/kubernetes/audit-policy/apiserver-audit-policy.yaml", + "path", "/etc/kubernetes/audit-policy.yaml", ), ), }, { @@ -52,7 +52,7 @@ var _ = Describe("Generate Audit Policy patches", func() { "audit-log-maxbackup": "10", "audit-log-maxsize": "100", "audit-log-path": "/var/log/audit/kube-apiserver-audit.log", - "audit-policy-file": "/etc/kubernetes/audit-policy/apiserver-audit-policy.yaml", + "audit-policy-file": "/etc/kubernetes/audit-policy.yaml", "audit-log-maxage": "30", }, ), @@ -60,15 +60,17 @@ var _ = Describe("Generate Audit Policy patches", func() { "extraVolumes", []interface{}{ map[string]interface{}{ - "hostPath": "/etc/kubernetes/audit-policy/", - "mountPath": "/etc/kubernetes/audit-policy/", + "hostPath": "/etc/kubernetes/audit-policy.yaml", + "mountPath": "/etc/kubernetes/audit-policy.yaml", "name": "audit-policy", "readOnly": true, + "pathType": "File", }, map[string]interface{}{ "name": "audit-logs", "hostPath": "/var/log/kubernetes/audit", "mountPath": "/var/log/audit/", + "pathType": "DirectoryOrCreate", }, }, ),