documentation_complete: true


title: 'Ensure that the RotateKubeletServerCertificate argument is set'


{{% set default_jqfilter = '.data."config.yaml" | fromjson | .extendedArguments["feature-gates"]' %}}
{{% set default_api_path = '/api/v1/namespaces/openshift-kube-controller-manager/configmaps/config' %}}
{{% set hypershift_path = '/api/v1/namespaces/{{.hypershift_namespace_prefix}}-{{.hypershift_cluster}}/pods?labelSelector=app%3Dkube-controller-manager' %}}
{{% set hypershift_jqfilter = '.items[0].spec.containers[0].args' %}}
{{% set custom_api_path = '{{if ne .hypershift_cluster "None"}}' ~ hypershift_path ~ '{{else}}' ~  default_api_path ~ '{{end}}' %}}
{{% set custom_jqfilter = '{{if ne .hypershift_cluster "None"}}' ~ hypershift_jqfilter ~ '{{else}}' ~  default_jqfilter ~ '{{end}}' %}}
{{% set dump_path = default_api_path ~ ',' ~ default_jqfilter ~ ',' ~ custom_jqfilter %}}


description: |-
    To enforce kubelet server certificate rotation on the Controller Manager,
    set the <tt>RotateKubeletServerCertificate</tt> option to <tt>true</tt>
    in the <tt>openshift-kube-controller-manager</tt> configmap on the master
    node(s):
    <pre>
    "extendedArguments": {
    ...
      "feature-gates": [
      ...
        "RotateKubeletServerCertificate=true",
      ...
    ...
    </pre>

    This feature gate is enabled by default as of Kubernetes 1.12.

rationale: |-
    Enabling kubelet certificate rotation causes the kubelet to both request
    a serving certificate after bootstrapping its client credentials and rotate the
    certificate as its existing credentials expire. This automated periodic rotation
    ensures that there are no downtimes due to expired certificates and thus
    addressing the availability in the C/I/A security triad.

severity: medium

platform: not ocp4-on-hypershift-hosted and (ocp4.12 or ocp4.13)

ocil_clause: |-
    <tt>RotateKubeletServerCertificate</tt> argument is set to <tt>false</tt> in the
    <tt>controllerArguments</tt> options

ocil: |-
    To verify that <tt>RotateKubeletServerCertificate</tt> is configured correctly,
    run the following command:
    <pre>$ oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq -r '.extendedArguments["feature-gates"]'</pre>
    The output should return <tt>RotateKubeletServerCertificate=true</tt>

identifiers:
    cce@ocp4: CCE-83730-2

warnings:
- general: |-
    {{{ openshift_filtered_cluster_setting({custom_api_path: dump_path}) | indent(4) }}}
- functionality: |-
    In OpenShift 4, the kubelet certification rotation is enabled by default. 
    Openshift v4 automatically generates a new kube-apiserver-to-kubelet-signer CA certificates at 292
    days, removes old CA certificate after 365 days, and the kubelet-client, kubelet-server 
    certs are auto-rotated once every month. Hence, this rule is deprecated and not-applicable. 
    ref: https://docs.redhat.com/en/documentation/openshift_container_platform/4.15/html/security_and_compliance/certificate-types-and-descriptions#purpose-5
 
references:
    nerc-cip: CIP-003-8 R4.2,CIP-003-8 R6,CIP-004-6 R3,CIP-007-3 R5.1,CIP-007-3 R6.1
    nist: CM-6,CM-6(1),SC-8,SC-8(1)
    pcidss: Req-2.2
    srg: SRG-APP-000516-CTR-001325

# Since RotateKubeletServerCertificate is enabled by default, let's make sure
# it's not being disabled explicitly. If we only check for it to be enabled,
# we'll miss clusters that rely on the default and result in a false positive
# finding.
template:
  name: yamlfile_value
  vars:
    ocp_data: "true"
    entity_check: "at least one"
    filepath: {{{ openshift_filtered_path(default_api_path, default_jqfilter) }}}
    yamlpath: '[:]'
    values:
    - value: 'RotateKubeletServerCertificate=false'
      type: "string"
      operation: "pattern match"
      entity_check: "none satisfy"
