Back to Checks
kubernetes

Kubelet uses only strong TLS cipher suites

kubelet_strong_ciphers_only
Service: kubeletSeverity: medium
OfficialBuilt-inVerified
Categories:encryptioncluster-security
Resource Type:ConfigMap

Kubernetes Kubelet HTTPS configuration is assessed for use of strong TLS cipher suites. The presence of tlsCipherSuites is checked and its values are validated against an approved, modern allowlist (e.g., ECDHE with GCM/CHACHA20).

Prowler logoProwlerprowler-provider-kubernetes

Risk

Weak or unspecified ciphers enable downgrade and cryptographic attacks on kubelet traffic. Adversaries could read logs/exec streams, hijack sessions, or tamper with requests, undermining confidentiality and integrity and facilitating lateral movement across nodes.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler kubernetes --checks kubelet_strong_ciphers_only

Recommendation

Restrict tlsCipherSuites to a minimal set of modern suites (ECDHE with GCM or CHACHA20) and prefer TLS1.2+/TLS1.3. Remove deprecated CBC/RC4/3DES suites. Apply defense in depth: limit network access to the kubelet, rotate certificates, and review cipher policy regularly for deprecations.

Remediation

Other

1Identify the kubelet config ConfigMap name:
2- Run: kubectl -n kube-system get configmap | grep kubelet-config
3Edit that ConfigMap:
4- Run: kubectl -n kube-system edit configmap <kubelet-config-<version>>
5- In the data.kubelet YAML (KubeletConfiguration), add the following and save:
6tlsCipherSuites:
7- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
8- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
9- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
10- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
11- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
12- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
13- TLS_RSA_WITH_AES_256_GCM_SHA384
14- TLS_RSA_WITH_AES_128_GCM_SHA256
15Apply on each node (required for kubelets using local config):
16- SSH to the node, edit /var/lib/kubelet/config.yaml to include the same tlsCipherSuites list
17- Restart kubelet: sudo systemctl restart kubelet

Check Code

from prowler.lib.check.models import Check, Check_Report_Kubernetes
from prowler.providers.kubernetes.services.kubelet.kubelet_client import kubelet_client

default_kubelet_strong_ciphers = [
    "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",
    "TLS_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_RSA_WITH_AES_128_GCM_SHA256",
]


class kubelet_strong_ciphers_only(Check):
    def execute(self) -> Check_Report_Kubernetes:
        findings = []
        for cm in kubelet_client.kubelet_config_maps:
            report = Check_Report_Kubernetes(metadata=self.metadata(), resource=cm)
            if "tlsCipherSuites" not in cm.kubelet_args:
                report.status = "MANUAL"
                report.status_extended = f"Kubelet does not have the argument `tlsCipherSuites` in config file {cm.name}, verify it in the node's arguments."
            else:
                if cm.kubelet_args["tlsCipherSuites"].issubset(
                    kubelet_client.audit_config.get(
                        "kubelet_strong_ciphers", default_kubelet_strong_ciphers
                    )
                ):
                    report.status = "PASS"
                    report.status_extended = f"Kubelet is configured with strong cryptographic ciphers in config file {cm.name}."
                else:
                    report.status = "FAIL"
                    report.status_extended = f"Kubelet is not using only strong cryptographic ciphers in config file {cm.name}."
            findings.append(report)
        return findings