Back to Checks
kubernetes

Etcd pod uses a unique Certificate Authority distinct from the Kubernetes API server CA

etcd_unique_ca
Service: etcdSeverity: high
OfficialBuilt-inVerified
Categories:encryptioncluster-securitytrust-boundaries
Resource Type:Pod

Etcd configuration is assessed to ensure it trusts a unique Certificate Authority via --trusted-ca-file, distinct from the API server's --client-ca-file. If the same CA file is used, etcd shares the cluster CA; differing files imply separation, though CA content should still be verified.

Risk

Using the Kubernetes CA for etcd allows any cert signed by that CA to authenticate to the datastore. Theft or mis-issuance enables unauthorized reads/writes, causing secret exposure (confidentiality), state tampering (integrity), and potential control-plane disruption (availability).

Run this check with Prowler

Run in Prowler Cloud
Run
prowler kubernetes --checks etcd_unique_ca

Recommendation

Adopt a separate PKI for etcd: issue client and peer certs from an etcd-only CA and trust only that CA. Enforce mTLS (--client-cert-auth, --peer-client-cert-auth), avoid --auto-tls, rotate keys independently, and apply least privilege to CA issuance with regular certificate audits.

Remediation

Other

1SSH to a control-plane node that runs etcd
2Open the API server manifest: sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml and note the value of --client-ca-file=<APISERVER_CA_PATH>
3Ensure an etcd-specific CA file exists at a different path (for example: /etc/kubernetes/pki/etcd/ca.crt) and is readable by the etcd container
4Edit the etcd manifest: sudo vi /etc/kubernetes/manifests/etcd.yaml
5- In the etcd container command/args, add or update: --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt (this path must NOT equal <APISERVER_CA_PATH>)
6- Save the file; the kubelet will restart the etcd pod automatically
7Verify the change: kubectl -n kube-system get pods -o wide | grep etcd, then describe the etcd pod and confirm --trusted-ca-file points to a different path than the API server --client-ca-file

Check Code

from prowler.lib.check.models import Check, Check_Report_Kubernetes
from prowler.providers.kubernetes.services.apiserver.apiserver_client import (
    apiserver_client,
)
from prowler.providers.kubernetes.services.etcd.etcd_client import etcd_client


class etcd_unique_ca(Check):
    def execute(self) -> Check_Report_Kubernetes:
        findings = []
        # Get first the CA Files of the apiserver pods
        apiserver_ca_files = []
        for pod in apiserver_client.apiserver_pods:
            for container in pod.containers.values():
                for command in container.command:
                    if command.startswith("--client-ca-file"):
                        apiserver_ca_files.append(command.split("=")[1])
        for pod in etcd_client.etcd_pods:
            etcd_ca_files = []
            report = Check_Report_Kubernetes(metadata=self.metadata(), resource=pod)
            report.status = "MANUAL"
            report.status_extended = f"Etcd uses a different CA file from the Kubernetes cluster CA in pod {pod.name}, but verify if the content is the same."
            for container in pod.containers.values():
                for command in container.command:
                    if command.startswith("--trusted-ca-file"):
                        etcd_ca_files.append(command.split("=")[1])
            if any(ca in etcd_ca_files for ca in apiserver_ca_files):
                report.status = "FAIL"
                report.status_extended = f"Etcd does not use a unique CA file, which could compromise its security in pod {pod.name}."
            findings.append(report)
        return findings