mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2024-12-23 15:18:07 +00:00
d2d3e72271
This approach becomes time-consuming for larger clusters. As kube-bench is executed as a job on every node in the cluster, To enhance performance, Streamlined the commands to execute directly on current node where kube-bench operates. This change ensures that the time complexity remains constant, regardless of the cluster size. By running the necessary commands only once per node, regardless of how many nodes are in the cluster, this approach significantly boosts performance and efficiency.
1446 lines
73 KiB
YAML
1446 lines
73 KiB
YAML
---
|
|
controls:
|
|
version: rh-1.0
|
|
id: 1
|
|
text: "Master Node Security Configuration"
|
|
type: "master"
|
|
groups:
|
|
- id: 1.1
|
|
text: "Master Node Configuration Files"
|
|
checks:
|
|
- id: 1.1.1
|
|
text: "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-apiserver namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/static-pod-resources/kube-apiserver-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.2
|
|
text: "Ensure that the API server pod specification file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-apiserver namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/static-pod-resources/kube-apiserver-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.3
|
|
text: "Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-controller-manager namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-controller-manager "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/static-pod-resources/kube-controller-manager-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.4
|
|
text: "Ensure that the controller manager pod specification file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-controller-manager namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-controller-manager "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/static-pod-resources/kube-controller-manager-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.5
|
|
text: "Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-scheduler namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-scheduler -l app=openshift-kube-scheduler --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-scheduler "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/static-pod-resources/kube-scheduler-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.6
|
|
text: "Ensure that the scheduler pod specification file ownership is set to root:root (Manual))"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-scheduler namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-scheduler -l app=openshift-kube-scheduler --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-scheduler "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/static-pod-resources/kube-scheduler-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.7
|
|
text: "Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Manual))"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-etcd namespace
|
|
POD_NAME=$(oc get pods -n openshift-etcd -l app=etcd --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc rsh -n openshift-etcd "$POD_NAME" stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/manifests/etcd-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.8
|
|
text: "Ensure that the etcd pod specification file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-etcd namespace
|
|
POD_NAME=$(oc get pods -n openshift-etcd -l app=etcd --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc rsh -n openshift-etcd "$POD_NAME" stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/manifests/etcd-pod.yaml
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.9
|
|
text: "Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
# For CNI multus
|
|
# Get the pod name in the openshift-multus namespace
|
|
POD_NAME=$(oc get pods -n openshift-multus -l app=multus --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-multus "$POD_NAME" -- /bin/bash -c "stat -c \"$i %n permissions=%a\" /host/etc/cni/net.d/*.conf"; 2>/dev/null
|
|
oc exec -n openshift-multus "$POD_NAME" -- /bin/bash -c "stat -c \"$i %n permissions=%a\" /host/var/run/multus/cni/net.d/*.conf"; 2>/dev/null
|
|
fi
|
|
# For SDN pods
|
|
POD_NAME=$(oc get pods -n openshift-sdn -l app=sdn --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/lib/cni/networks/openshift-sdn -type f -exec stat -c "$i %n permissions=%a" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/run/openshift-sdn -type f -exec stat -c "$i %n permissions=%a" {} \; 2>/dev/null
|
|
fi
|
|
|
|
# For OVS pods
|
|
POD_NAME=$(oc get pods -n openshift-sdn -l app=ovs --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/run/openvswitch -type f -exec stat -c "$i %n permissions=%a" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /etc/openvswitch -type f -exec stat -c "$i %n permissions=%a" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /run/openvswitch -type f -exec stat -c "$i %n permissions=%a" {} \; 2>/dev/null
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.10
|
|
text: "Ensure that the Container Network Interface file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
# For CNI multus
|
|
# Get the pod name in the openshift-multus namespace
|
|
POD_NAME=$(oc get pods -n openshift-multus -l app=multus --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-multus "$POD_NAME" -- /bin/bash -c "stat -c '$i %n %U:%G' /host/etc/cni/net.d/*.conf" 2>/dev/null
|
|
oc exec -n openshift-multus $i -- /bin/bash -c "stat -c '$i %n %U:%G' /host/var/run/multus/cni/net.d/*.conf" 2>/dev/null
|
|
fi
|
|
# For SDN pods
|
|
POD_NAME=$(oc get pods -n openshift-sdn -l app=sdn --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/lib/cni/networks/openshift-sdn -type f -exec stat -c "$i %n %U:%G" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/run/openshift-sdn -type f -exec stat -c "$i %n %U:%G" {} \; 2>/dev/null
|
|
fi
|
|
# For OVS pods in 4.5
|
|
POD_NAME=$(oc get pods -n openshift-sdn -l app=ovs --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /var/run/openvswitch -type f -exec stat -c "$i %n %U:%G" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /etc/openvswitch -type f -exec stat -c "$i %n %U:%G" {} \; 2>/dev/null
|
|
oc exec -n openshift-sdn "$POD_NAME" -- find /run/openvswitch -type f -exec stat -c "$i %n %U:%G" {} \; 2>/dev/null
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.11
|
|
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-etcd namespace
|
|
POD_NAME=$(oc get pods -n openshift-etcd -l app=etcd --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-etcd "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /var/lib/etcd/member
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "700"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.12
|
|
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-etcd namespace
|
|
POD_NAME=$(oc get pods -n openshift-etcd -l app=etcd --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-etcd "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /var/lib/etcd/member
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.13
|
|
text: "Ensure that the admin.conf file permissions are set to 644 or more restrictive (Manual))"
|
|
audit: |
|
|
NODE_NAME=$(oc get pod $HOSTNAME -o=jsonpath='{.spec.nodeName}')
|
|
oc debug node/$NODE_NAME -- chroot /host stat -c "$NODE_NAME %n permissions=%a" /etc/kubernetes/kubeconfig 2> /dev/null
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.14
|
|
text: "Ensure that the admin.conf file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
NODE_NAME=$(oc get pod $HOSTNAME -o=jsonpath='{.spec.nodeName}')
|
|
oc debug node/$NODE_NAME -- chroot /host stat -c "$NODE_NAME %n %U:%G" /etc/kubernetes/kubeconfig 2> /dev/null
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.15
|
|
text: "Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-scheduler namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-scheduler -l app=openshift-kube-scheduler --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-scheduler "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/static-pod-resources/configmaps/scheduler-kubeconfig/kubeconfig
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.16
|
|
text: "Ensure that the scheduler.conf file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-scheduler namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-scheduler -l app=openshift-kube-scheduler --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-scheduler "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/static-pod-resources/configmaps/scheduler-kubeconfig/kubeconfig
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.17
|
|
text: "Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-controller-manager namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-controller-manager "$POD_NAME" -- stat -c "$POD_NAME %n permissions=%a" /etc/kubernetes/static-pod-resources/configmaps/controller-manager-kubeconfig/kubeconfig
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.18
|
|
text: "Ensure that the controller-manager.conf file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-controller-manager namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-controller-manager "$POD_NAME" -- stat -c "$POD_NAME %n %U:%G" /etc/kubernetes/static-pod-resources/configmaps/controller-manager-kubeconfig/kubeconfig
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.19
|
|
text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Manual)"
|
|
audit: |
|
|
# Should return root:root for all files and directories
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-controller-manager namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# echo $i static-pod-certs
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-certs -type d -wholename '*/secrets*' -exec stat -c "$i %n %U:%G" {} \;
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-certs -type f -wholename '*/secrets*' -exec stat -c "$i %n %U:%G" {} \;
|
|
# echo $i static-pod-resources
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-resources -type d -wholename '*/secrets*' -exec stat -c "$i %n %U:%G" {} \;
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-resources -type f -wholename '*/secrets*' -exec stat -c "$i %n %U:%G" {} \;
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "root:root"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.20
|
|
text: "Ensure that the OpenShift PKI certificate file permissions are set to 644 or more restrictive (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-apiserver namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-certs -type f -wholename '*/secrets/*.crt' -exec stat -c "$POD_NAME %n permissions=%a" {} \;
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "644"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.1.21
|
|
text: "Ensure that the OpenShift PKI key file permissions are set to 600 (Manual)"
|
|
audit: |
|
|
# Get the node name where the pod is running
|
|
NODE_NAME=$(oc get pod "$HOSTNAME" -o=jsonpath='{.spec.nodeName}')
|
|
|
|
# Get the pod name in the openshift-kube-apiserver namespace
|
|
POD_NAME=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver --field-selector spec.nodeName="$NODE_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
|
|
|
if [ -z "$POD_NAME" ]; then
|
|
echo "No matching pods found on the current node."
|
|
else
|
|
# Execute the stat command
|
|
oc exec -n openshift-kube-apiserver "$POD_NAME" -c kube-apiserver -- find /etc/kubernetes/static-pod-certs -type f -wholename '*/secrets/*.key' -exec stat -c "$POD_NAME %n permissions=%a" {} \;
|
|
fi
|
|
use_multiple_values: true
|
|
tests:
|
|
test_items:
|
|
- flag: "permissions"
|
|
compare:
|
|
op: bitmask
|
|
value: "600"
|
|
remediation: |
|
|
No remediation required; file permissions are managed by the operator.
|
|
scored: false
|
|
|
|
- id: 1.2
|
|
text: "API Server"
|
|
checks:
|
|
- id: 1.2.1
|
|
text: "Ensure that anonymous requests are authorized (Manual)"
|
|
audit: |
|
|
# To verify that userGroups include system:unauthenticated
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]?'
|
|
# To verify that userGroups include system:unauthenticated
|
|
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]?.userGroups'
|
|
# To verify RBAC is enabled
|
|
oc get clusterrolebinding
|
|
oc get clusterrole
|
|
oc get rolebinding
|
|
oc get role
|
|
tests:
|
|
test_items:
|
|
- flag: "system:unauthenticated"
|
|
remediation: |
|
|
None required. The default configuration should not be modified.
|
|
scored: false
|
|
|
|
- id: 1.2.2
|
|
text: "Ensure that the --basic-auth-file argument is not set (Manual)"
|
|
audit: |
|
|
oc -n openshift-kube-apiserver get cm config -o yaml | grep --color "basic-auth"
|
|
oc -n openshift-apiserver get cm config -o yaml | grep --color "basic-auth"
|
|
# Add | awk '$3 != "AVAILABLE" { if ($3){print "available=true"}else{print "available=false"} }; to create AVAILABLE = true/false form
|
|
oc get clusteroperator authentication | awk '$3 != "AVAILABLE" { if ($3){print "available=true"}else{print "available=false"} }'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "basic-auth-file"
|
|
set: false
|
|
- flag: "available"
|
|
compare:
|
|
op: eq
|
|
value: true
|
|
remediation: |
|
|
None required. --basic-auth-file cannot be configured on OpenShift.
|
|
scored: false
|
|
|
|
- id: 1.2.3
|
|
text: "Ensure that the --token-auth-file parameter is not set (Manual)"
|
|
audit: |
|
|
# Verify that the token-auth-file flag is not present
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq '.spec.observedConfig.apiServerArguments'
|
|
#Verify that the authentication operator is running
|
|
oc get clusteroperator authentication | awk '$3 != "AVAILABLE" { if ($3){print "available=true"}else{print "available=false"} }'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "token-auth-file"
|
|
set: false
|
|
- flag: "available"
|
|
compare:
|
|
op: eq
|
|
value: true
|
|
remediation: |
|
|
None is required.
|
|
scored: false
|
|
|
|
- id: 1.2.4
|
|
text: "Use https for kubelet connections (Manual)"
|
|
audit: |
|
|
#for 4.5
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.kubeletClientInfo'
|
|
#for 4.6
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
#for both 4.5 and 4.6
|
|
oc -n openshift-apiserver describe secret serving-cert
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/kubelet-client/tls.crt"
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/kubelet-client/tls.key"
|
|
remediation: |
|
|
No remediation is required.
|
|
OpenShift platform components use X.509 certificates for authentication.
|
|
OpenShift manages the CAs and certificates for platform components. This is not configurable.
|
|
scored: false
|
|
|
|
- id: 1.2.5
|
|
text: "Ensure that the kubelet uses certificates to authenticate (Manual)"
|
|
audit: |
|
|
#for 4.5
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.kubeletClientInfo'
|
|
#for 4.6
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
#for both 4.5 and 4.6
|
|
oc -n openshift-apiserver describe secret serving-cert
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/kubelet-client/tls.crt"
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/kubelet-client/tls.key"
|
|
remediation: |
|
|
No remediation is required.
|
|
OpenShift platform components use X.509 certificates for authentication.
|
|
OpenShift manages the CAs and certificates for platform components.
|
|
This is not configurable.
|
|
scored: false
|
|
|
|
- id: 1.2.6
|
|
text: "Verify that the kubelet certificate authority is set as appropriate (Manual)"
|
|
audit: |
|
|
# for 4.5
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.kubeletClientInfo'
|
|
# for 4.6
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
tests:
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/configmaps/kubelet-serving-ca/ca-bundle.crt"
|
|
remediation: |
|
|
No remediation is required.
|
|
OpenShift platform components use X.509 certificates for authentication.
|
|
OpenShift manages the CAs and certificates for platform components.
|
|
This is not configurable.
|
|
scored: false
|
|
|
|
- id: 1.2.7
|
|
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Manual)"
|
|
audit: |
|
|
# To verify that the authorization-mode argument is not used
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
# To verify RBAC is configured:
|
|
oc get clusterrolebinding
|
|
oc get clusterrole
|
|
oc get rolebinding
|
|
oc get role
|
|
audit_config: |
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- path: "{.authorization-mode}"
|
|
compare:
|
|
op: nothave
|
|
value: "AlwaysAllow"
|
|
- path: "{.authorization-mode}"
|
|
flag: "authorization-mode"
|
|
set: false
|
|
remediation: |
|
|
None. RBAC is always on and the OpenShift API server does not use the values assigned to the flag authorization-mode.
|
|
scored: false
|
|
|
|
- id: 1.2.8
|
|
text: "Verify that the Node authorizer is enabled (Manual)"
|
|
audit: |
|
|
# For OCP 4.5 and earlier verify that authorization-mode is not used
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq '.spec.observedConfig.apiServerArguments'
|
|
# For OCP 4.5 and earlier verify that authorization-mode is not used
|
|
NODE_NAME=$(oc get pod $HOSTNAME -o=jsonpath='{.spec.nodeName}')
|
|
oc debug node/$NODE_NAME -- chroot /host cat /etc/kubernetes/kubelet.conf | grep authorization-mode 2> /dev/null
|
|
oc debug node/$NODE_NAME -- chroot /host ps -aux | grep kubelet | grep authorization-mode 2> /dev/null
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
audit_config: |
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- path: "{.authorization-mode}"
|
|
compare:
|
|
op: has
|
|
value: "Node"
|
|
- path: "{.authorization-mode}"
|
|
flag: "authorization-mode"
|
|
set: false
|
|
remediation: |
|
|
No remediation is required.
|
|
scored: false
|
|
|
|
- id: 1.2.9
|
|
text: "Verify that RBAC is enabled (Manual)"
|
|
audit: |
|
|
# For 4.5 To verify that the authorization-mode argument is not used
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
# To verify RBAC is used
|
|
oc get clusterrolebinding
|
|
oc get clusterrole
|
|
oc get rolebinding
|
|
oc get role
|
|
# For 4.6, verify that the authorization-mode argument includes RBAC
|
|
audit_config: |
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments'
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- path: "{.authorization-mode}"
|
|
compare:
|
|
op: has
|
|
value: "RBAC"
|
|
- path: "{.authorization-mode}"
|
|
flag: "authorization-mode"
|
|
set: false
|
|
remediation: |
|
|
None. It is not possible to disable RBAC.
|
|
scored: false
|
|
|
|
- id: 1.2.10
|
|
text: "Ensure that the APIPriorityAndFairness feature gate is enabled (Manual)"
|
|
audit: |
|
|
#Verify the APIPriorityAndFairness feature-gate
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq '.spec.observedConfig.apiServerArguments'
|
|
#Verify the set of admission-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "APIPriorityAndFairness=true"
|
|
- flag: "EventRateLimit"
|
|
set: false
|
|
remediation: |
|
|
No remediation is required
|
|
scored: false
|
|
|
|
- id: 1.2.11
|
|
text: "Ensure that the admission control plugin AlwaysAdmit is not set (Manual)"
|
|
audit: |
|
|
#Verify the set of admission-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
tests:
|
|
test_items:
|
|
- flag: "AlwaysAdmit"
|
|
set: false
|
|
remediation: |
|
|
No remediation is required. The AlwaysAdmit admission controller cannot be enabled in OpenShift.
|
|
scored: false
|
|
|
|
- id: 1.2.12
|
|
text: "Ensure that the admission control plugin AlwaysPullImages is set (Manual)"
|
|
audit: |
|
|
#Verify the set of admissi on-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
tests:
|
|
test_items:
|
|
- flag: "AlwaysPullImages"
|
|
set: false
|
|
remediation: |
|
|
None required.
|
|
scored: false
|
|
|
|
- id: 1.2.13
|
|
text: "Ensure that the admission control plugin SecurityContextDeny is not set (Manual)"
|
|
audit: |
|
|
#Verify the set of admission-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
output=$(oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has SecurityContextDeny and SecurityContextConstraint compiled" || echo $output
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
#Verify that SecurityContextConstraints are deployed
|
|
oc get scc
|
|
oc describe scc restricted
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "SecurityContextConstraint"
|
|
set: true
|
|
- flag: "anyuid"
|
|
- flag: "hostaccess"
|
|
- flag: "hostmount-anyuid"
|
|
- flag: "hostnetwork"
|
|
- flag: "node-exporter"
|
|
- flag: "nonroot"
|
|
- flag: "privileged"
|
|
- flag: "restricted"
|
|
remediation: |
|
|
None required. The Security Context Constraint admission controller cannot be disabled in OpenShift 4.
|
|
scored: false
|
|
|
|
- id: 1.2.14
|
|
text: "Ensure that the admission control plugin ServiceAccount is set (Manual)"
|
|
audit: |
|
|
#Verify the list of admission controllers for 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
output=$(oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has ServiceAccount compiled" || echo $output
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
#Verify that Service Accounts are present
|
|
oc get sa -A
|
|
tests:
|
|
test_items:
|
|
- flag: "ServiceAccount"
|
|
set: true
|
|
remediation: |
|
|
None required. OpenShift is configured to use service accounts by default.
|
|
scored: false
|
|
|
|
- id: 1.2.15
|
|
text: "Ensure that the admission control plugin NamespaceLifecycle is set (Manual)"
|
|
audit: |
|
|
#Verify the list of admission controllers for 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
output=$(oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has NamespaceLifecycle compiled" || echo $output
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
tests:
|
|
test_items:
|
|
- flag: "NamespaceLifecycle"
|
|
remediation: |
|
|
Ensure that the --disable-admission-plugins parameter does not include NamespaceLifecycle.
|
|
scored: false
|
|
|
|
- id: 1.2.16
|
|
text: "Ensure that the admission control plugin SecurityContextConstraint is set (Manual)"
|
|
audit: |
|
|
#Verify the set of admission-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
output=$(oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has SecurityContextConstraint compiled" || echo $output
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
#Verify that SecurityContextConstraints are deployed
|
|
oc get scc
|
|
oc describe scc restricted
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "SecurityContextConstraint"
|
|
- flag: "anyuid"
|
|
- flag: "hostaccess"
|
|
- flag: "hostmount-anyuid"
|
|
- flag: "hostnetwork"
|
|
- flag: "node-exporter"
|
|
- flag: "nonroot"
|
|
- flag: "privileged"
|
|
- flag: "restricted"
|
|
remediation: |
|
|
None required. Security Context Constraints are enabled by default in OpenShift and cannot be disabled.
|
|
scored: false
|
|
|
|
- id: 1.2.17
|
|
text: "Ensure that the admission control plugin NodeRestriction is set (Manual)"
|
|
audit: |
|
|
# For 4.5, review the control plane manifest https://github.com/openshift/origin/blob/release-4.5/vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane/manifests.go#L132
|
|
#Verify the set of admission-plugins for OCP 4.6 and higher
|
|
oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"'
|
|
output=$(oc -n openshift-kube-apiserver get configmap config -o json | jq -r '.data."config.yaml"' | jq '.apiServerArguments."enable-admission-plugins"')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has NodeRestriction compiled" || echo $output
|
|
#Check that no overrides are configured
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq -r '.spec.unsupportedConfigOverrides'
|
|
tests:
|
|
test_items:
|
|
- flag: "NodeRestriction"
|
|
remediation: |
|
|
The NodeRestriction plugin cannot be disabled.
|
|
scored: false
|
|
|
|
- id: 1.2.18
|
|
text: "Ensure that the --insecure-bind-address argument is not set (Manual)"
|
|
audit: |
|
|
# InsecureBindAddress=true should not be in the results
|
|
oc get kubeapiservers.operator.openshift.io cluster -o jsonpath='{range .spec.observedConfig.apiServerArguments.feature-gates[*]}{@}{"\n"}{end}'
|
|
# Result should be only 6443
|
|
oc -n openshift-kube-apiserver get endpoints -o jsonpath='{.items[*].subsets[*].ports[*].port}'
|
|
# Result should be only 8443
|
|
oc -n openshift-apiserver get endpoints -o jsonpath='{.items[*].subsets[*].ports[*].port}'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "insecure-bind-address"
|
|
set: false
|
|
- flag: 6443
|
|
- flag: 8443
|
|
remediation: |
|
|
None required.
|
|
scored: false
|
|
|
|
- id: 1.2.19
|
|
text: "Ensure that the --insecure-port argument is set to 0 (Manual)"
|
|
audit: |
|
|
# Should return 6443
|
|
oc -n openshift-kube-apiserver get endpoints -o jsonpath='{.items[*].subsets[*].ports[*].port}'
|
|
# For OCP 4.6 and above
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments["insecure-port"]'
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments["insecure-port"]')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has insecure-port set to \"0\" compiled" || echo $output
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "\"0\""
|
|
- flag: "6443"
|
|
remediation: |
|
|
None required. The configuration is managed by the API server operator.
|
|
scored: false
|
|
|
|
- id: 1.2.20
|
|
text: "Ensure that the --secure-port argument is not set to 0 (Manual)"
|
|
audit: |
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json | jq '.spec.observedConfig'
|
|
# Should return only 6443
|
|
echo ports=`oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver -o jsonpath='{.items[*].spec.containers[?(@.name=="kube-apiserver")].ports[*].containerPort}'`
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: '"bindAddress": "0.0.0.0:6443"'
|
|
- flag: "ports"
|
|
compare:
|
|
op: regex
|
|
value: '\s*(?:6443\s*){1,}$'
|
|
remediation: |
|
|
None required.
|
|
scored: false
|
|
|
|
- id: 1.2.21
|
|
text: "Ensure that the healthz endpoint is protected by RBAC (Manual)"
|
|
type: manual
|
|
audit: |
|
|
# Verify endpoints
|
|
oc -n openshift-kube-apiserver describe endpoints
|
|
# Check config for ports, livenessProbe, readinessProbe, healthz
|
|
oc -n openshift-kube-apiserver get cm kube-apiserver-pod -o json | jq -r '.data."pod.yaml"' | jq '.spec.containers'
|
|
# Test to validate RBAC enabled on the apiserver endpoint; check with non-admin role
|
|
oc project openshift-kube-apiserver POD=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver -o jsonpath='{.items[0].metadata.name}') PORT=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver -o jsonpath='{.items[0].spec.containers[0].ports[0].hostPort}')
|
|
# Following should return 403 Forbidden
|
|
oc rsh -n openshift-kube-apiserver ${POD} curl https://localhost:${PORT}/metrics -k
|
|
# Create a service account to test RBAC
|
|
oc create -n openshift-kube-apiserver sa permission-test-sa
|
|
# Should return 403 Forbidden
|
|
SA_TOKEN=$(oc sa -n openshift-kube-apiserver get-token permission-test-sa)
|
|
oc rsh -n openshift-kube-apiserver ${POD} curl https://localhost:${PORT}/metrics -H "Authorization: Bearer $SA_TOKEN" -k
|
|
# Cleanup
|
|
oc delete -n openshift-kube-apiserver sa permission-test-sa
|
|
# As cluster admin, should succeed
|
|
CLUSTER_ADMIN_TOKEN=$(oc whoami -t)
|
|
oc rsh -n openshift-kube-apiserver ${POD} curl https://localhost:${PORT}/metrics -H "Authorization: Bearer $CLUSTER_ADMIN_TOKEN" -k
|
|
remediation: |
|
|
None required as profiling data is protected by RBAC.
|
|
scored: false
|
|
|
|
- id: 1.2.22
|
|
text: "Ensure that the --audit-log-path argument is set (Manual)"
|
|
audit: |
|
|
# Should return “/var/log/kube-apiserver/audit.log"
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o jsonpath="{['.data.config\.yaml']}" | jq '.auditConfig.auditFilePath')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "$output" || true
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-path"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "$output" || true
|
|
POD=$(oc get pods -n openshift-kube-apiserver -l app=openshift-kube-apiserver -o jsonpath='{.items[0].metadata.name}')
|
|
oc rsh -n openshift-kube-apiserver -c kube-apiserver $POD ls /var/log/kube-apiserver/audit.log 2>/dev/null
|
|
# Should return 0
|
|
echo exit_code=$?
|
|
# Should return "/var/log/openshift-apiserver/audit.log"
|
|
output=$(oc get configmap config -n openshift-apiserver -o jsonpath="{['.data.config\.yaml']}" | jq '.auditConfig.auditFilePath')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "$output" || true
|
|
output=$(oc get configmap config -n openshift-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-path"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "$output" || true
|
|
POD=$(oc get pods -n openshift-apiserver -l apiserver=true -o jsonpath='{.items[0].metadata.name}')
|
|
oc rsh -n openshift-apiserver $POD ls /var/log/openshift-apiserver/audit.log 2>/dev/null
|
|
# Should return 0
|
|
echo exit_code=$?
|
|
use_multiple_values: true
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- flag: "/var/log/kube-apiserver/audit.log"
|
|
- flag: "/var/log/openshift-apiserver/audit.log"
|
|
- flag: "exit_code=0"
|
|
- flag: "null"
|
|
remediation: |
|
|
None required. This is managed by the cluster apiserver operator.
|
|
scored: false
|
|
|
|
- id: 1.2.23
|
|
text: "Ensure that the audit logs are forwarded off the cluster for retention (Manual)"
|
|
type: "manual"
|
|
remediation: |
|
|
Follow the documentation for log forwarding. Forwarding logs to third party systems
|
|
https://docs.openshift.com/container-platform/4.5/logging/cluster-logging-external.html
|
|
scored: false
|
|
|
|
- id: 1.2.24
|
|
text: "Ensure that the maximumRetainedFiles argument is set to 10 or as appropriate (Manual)"
|
|
audit: |
|
|
#NOTICE
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r .auditConfig.maximumRetainedFiles)
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "maximumRetainedFiles=$output" || true
|
|
output=$(oc get configmap config -n openshift-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r .auditConfig.maximumRetainedFiles)
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "maximumRetainedFiles=$output" || true
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-maxbackup"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "audit-log-maxbackup=$output" || true
|
|
output=$(oc get configmap config -n openshift-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-maxbackup"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "audit-log-maxbackup=$output" || true
|
|
use_multiple_values: true
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- flag: "maximumRetainedFiles"
|
|
compare:
|
|
op: gte
|
|
value: 10
|
|
- flag: "audit-log-maxbackup"
|
|
compare:
|
|
op: gte
|
|
value: 10
|
|
remediation: |
|
|
Set the maximumRetainedFiles parameter to 10 or as an appropriate number of files. maximumRetainedFiles: 10
|
|
scored: false
|
|
|
|
- id: 1.2.25
|
|
text: "Ensure that the maximumFileSizeMegabytes argument is set to 100 or as appropriate (Manual)"
|
|
audit: |
|
|
#NOTICE
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r .auditConfig.maximumFileSizeMegabytes)
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "maximumFileSizeMegabytes=$output" || true
|
|
output=$(oc get configmap config -n openshift-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r .auditConfig.maximumFileSizeMegabytes)
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "maximumFileSizeMegabytes=$output" || true
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-maxsize"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "audit-log-maxsize=$output" || true
|
|
output=$(oc get configmap config -n openshift-apiserver -o json | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["audit-log-maxsize"][]?')
|
|
[ "$output" != "" ] && [ "$output" != "null" ] && echo "audit-log-maxsize=$output" || true
|
|
use_multiple_values: true
|
|
tests:
|
|
bin_op: or
|
|
test_items:
|
|
- flag: "maximumFileSizeMegabytes"
|
|
compare:
|
|
op: gte
|
|
value: 100
|
|
- flag: "audit-log-maxsize"
|
|
compare:
|
|
op: gte
|
|
value: 100
|
|
remediation: |
|
|
Set the audit-log-maxsize parameter to 100 or as an appropriate number.
|
|
maximumFileSizeMegabytes: 100
|
|
scored: false
|
|
|
|
- id: 1.2.26
|
|
text: "Ensure that the --request-timeout argument is set as appropriate (Manual)"
|
|
audit: |
|
|
echo requestTimeoutSeconds=`oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .servingInfo.requestTimeoutSeconds`
|
|
tests:
|
|
test_items:
|
|
- flag: "requestTimeoutSeconds"
|
|
remediation: |
|
|
TBD
|
|
scored: false
|
|
|
|
- id: 1.2.27
|
|
text: "Ensure that the --service-account-lookup argument is set to true (Manual)"
|
|
audit: |
|
|
# For OCP 4.5
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.apiServerArguments' | grep service-account-lookup
|
|
# For OCP 4.6 and above
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["service-account-lookup"]'
|
|
output=$(oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["service-account-lookup"][0]')
|
|
[ "$output" == "null" ] && echo "ocp 4.5 has service-account-lookup=true compiled" || echo service-account-lookup=$output
|
|
tests:
|
|
test_items:
|
|
- flag: "service-account-lookup=true"
|
|
remediation: |
|
|
TBD
|
|
scored: false
|
|
|
|
- id: 1.2.28
|
|
text: "Ensure that the --service-account-key-file argument is set as appropriate (Manual)"
|
|
audit: |
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .serviceAccountPublicKeyFiles[]
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/configmaps/sa-token-signing-certs"
|
|
- flag: "/etc/kubernetes/static-pod-resources/configmaps/bound-sa-token-signing-certs"
|
|
remediation: |
|
|
The OpenShift API server does not use the service-account-key-file argument.
|
|
The ServiceAccount token authenticator is configured with serviceAccountConfig.publicKeyFiles.
|
|
OpenShift does not reuse the apiserver TLS key. This is not configurable.
|
|
scored: false
|
|
|
|
- id: 1.2.29
|
|
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Manual)"
|
|
audit: |
|
|
# etcd Certificate File
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .storageConfig.certFile
|
|
# etcd Key File
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .storageConfig.keyFile
|
|
# NOTICE 4.6 extention
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["etcd-certfile"]'
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["etcd-keyfile"]'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/etcd-client/tls.crt"
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/etcd-client/tls.key"
|
|
remediation: |
|
|
OpenShift automatically manages TLS and client certificate authentication for etcd.
|
|
This is not configurable.
|
|
scored: false
|
|
|
|
- id: 1.2.30
|
|
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Manual)"
|
|
audit: |
|
|
# TLS Cert File - openshift-kube-apiserver
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .servingInfo.certFile
|
|
# TLS Key File
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.servingInfo.keyFile'
|
|
# NOTECI 4.6 extention
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["tls-cert-file"]'
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["tls-private-key-file"]'
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-certs/secrets/service-network-serving-certkey/tls.crt"
|
|
- flag: "/etc/kubernetes/static-pod-certs/secrets/service-network-serving-certkey/tls.key"
|
|
remediation: |
|
|
OpenShift automatically manages TLS authentication for the API server communication with the node/kublet.
|
|
This is not configurable. You may optionally set a custom default certificate to be used by the API server
|
|
when serving content in order to enable clients to access the API server at a different host name or without
|
|
the need to distribute the cluster-managed certificate authority (CA) certificates to the clients.
|
|
Follow the directions in the OpenShift documentation User-provided certificates for the API server
|
|
scored: false
|
|
|
|
- id: 1.2.31
|
|
text: "Ensure that the --client-ca-file argument is set as appropriate (Manual)"
|
|
audit: |
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .servingInfo.clientCA
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["client-ca-file"]'
|
|
tests:
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-certs/configmaps/client-ca/ca-bundle.crt"
|
|
remediation: |
|
|
OpenShift automatically manages TLS authentication for the API server communication with the node/kublet.
|
|
This is not configurable. You may optionally set a custom default certificate to be used by the API
|
|
server when serving content in order to enable clients to access the API server at a different host name
|
|
or without the need to distribute the cluster-managed certificate authority (CA) certificates to the clients.
|
|
|
|
User-provided certificates must be provided in a kubernetes.io/tls type Secret in the openshift-config namespace.
|
|
Update the API server cluster configuration,
|
|
the apiserver/cluster resource, to enable the use of the user-provided certificate.
|
|
scored: false
|
|
|
|
- id: 1.2.32
|
|
text: "Ensure that the --etcd-cafile argument is set as appropriate (Manual)"
|
|
audit: |
|
|
#etcd CA File
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r .storageConfig.ca
|
|
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq -r '.apiServerArguments["etcd-cafile"]'
|
|
tests:
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/configmaps/etcd-serving-ca/ca-bundle.crt"
|
|
remediation: |
|
|
None required. OpenShift generates the etcd-cafile and sets the arguments appropriately in the API server. Communication with etcd is secured by the etcd serving CA.
|
|
scored: false
|
|
|
|
- id: 1.2.33
|
|
text: "Ensure that the --encryption-provider-config argument is set as appropriate (Manual)"
|
|
audit: |
|
|
# encrypt the etcd datastore
|
|
oc get openshiftapiserver -o=jsonpath='{range.items[0].status.conditions[?(@.type=="Encrypted")]}{.reason}{"\n"}{.message}{"\n"}'
|
|
tests:
|
|
test_items:
|
|
- flag: "EncryptionCompleted"
|
|
remediation: |
|
|
Follow the OpenShift documentation for Encrypting etcd data | Authentication | OpenShift Container Platform 4.5
|
|
https://docs.openshift.com/container-platform/4.5/security/encrypting-etcd.html
|
|
scored: false
|
|
|
|
- id: 1.2.34
|
|
text: "Ensure that encryption providers are appropriately configured (Manual)"
|
|
audit: |
|
|
# encrypt the etcd datastore
|
|
oc get openshiftapiserver -o=jsonpath='{range.items[0].status.conditions[?(@.type=="Encrypted")]}{.reason}{"\n"}{.message}{"\n"}'
|
|
tests:
|
|
test_items:
|
|
- flag: "EncryptionCompleted"
|
|
remediation: |
|
|
Follow the Kubernetes documentation and configure a EncryptionConfig file.
|
|
In this file, choose aescbc, kms or secretbox as the encryption provider.
|
|
scored: false
|
|
|
|
- id: 1.2.35
|
|
text: "Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Manual)"
|
|
type: manual
|
|
audit: |
|
|
# verify cipher suites
|
|
oc get cm -n openshift-authentication v4-0-config-system-cliconfig -o jsonpath='{.data.v4\-0\-config\-system\-cliconfig}' | jq .servingInfo
|
|
oc get kubeapiservers.operator.openshift.io cluster -o json |jq.spec.observedConfig.servingInfo
|
|
oc get openshiftapiservers.operator.openshift.io cluster -o json |jq.spec.observedConfig.servingInfo
|
|
oc describe --namespace=openshift-ingress-operator ingresscontroller/default
|
|
remediation: |
|
|
Verify that the tlsSecurityProfile is set to the value you chose.
|
|
Note: The HAProxy Ingress controller image does not support TLS 1.3
|
|
and because the Modern profile requires TLS 1.3, it is not supported.
|
|
The Ingress Operator converts the Modern profile to Intermediate.
|
|
The Ingress Operator also converts the TLS 1.0 of an Old or Custom profile to 1.1,
|
|
and TLS 1.3 of a Custom profile to 1.2.
|
|
scored: false
|
|
|
|
- id: 1.3
|
|
text: "Controller Manager"
|
|
checks:
|
|
- id: 1.3.1
|
|
text: "Ensure that garbage collection is configured as appropriate (Manual)"
|
|
type: manual
|
|
remediation: |
|
|
To configure, follow the directions in Configuring garbage collection for containers and images
|
|
https://docs.openshift.com/container-platform/4.5/nodes/nodes/nodes-nodes-garbage-collection.html#nodes-nodes-garbage-collection-configuring_nodes-nodes-configuring
|
|
scored: false
|
|
|
|
- id: 1.3.2
|
|
text: "Ensure that controller manager healthz endpoints are protected by RBAC (Manual)"
|
|
type: manual
|
|
audit: |
|
|
# Verify configuration for ports, livenessProbe, readinessProbe, healthz
|
|
oc -n openshift-kube-controller-manager get cm kube-controller-manager-pod -o json | jq -r '.data."pod.yaml"' | jq '.spec.containers'
|
|
# Verify endpoints
|
|
oc -n openshift-kube-controller-manager describe endpoints
|
|
# Test to validate RBAC enabled on the controller endpoint; check with non-admin role
|
|
oc project openshift-kube-controller-manage
|
|
POD=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager -o jsonpath='{.items[0].metadata.name}')
|
|
PORT=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager -o jsonpath='{.items[0].spec.containers[0].ports[0].hostPort}')
|
|
# Following should return 403 Forbidden
|
|
oc rsh -n openshift-kube-controller-manager ${POD} curl https://localhost:${PORT}/metrics -k
|
|
# Create a service account to test RBAC
|
|
oc create -n openshift-kube-controller-manager sa permission-test-sa
|
|
# Should return 403 Forbidden
|
|
SA_TOKEN=$(oc sa -n openshift-kube-controller-manager get-token permission-test-sa)
|
|
oc rsh -n openshift-kube-controller-manager ${POD} curl https://localhost:${PORT}/metrics -H "Authorization: Bearer $SA_TOKEN" -k
|
|
# Cleanup
|
|
oc delete -n openshift-kube-controller-manager sa permission-test-sa
|
|
# As cluster admin, should succeed
|
|
CLUSTER_ADMIN_TOKEN=$(oc whoami -t)
|
|
oc rsh -n openshift-kube-controller-manager ${POD} curl https://localhost:${PORT}/metrics -H "Authorization: Bearer $CLUSTER_ADMIN_TOKEN" -k
|
|
remediation: |
|
|
None required; profiling is protected by RBAC.
|
|
scored: false
|
|
|
|
- id: 1.3.3
|
|
text: "Ensure that the --use-service-account-credentials argument is set to true (Manual)"
|
|
audit: |
|
|
echo use-service-account-credentials=`oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq -r '.extendedArguments["use-service-account-credentials"][]'`
|
|
tests:
|
|
test_items:
|
|
- flag: "use-service-account-credentials"
|
|
compare:
|
|
op: eq
|
|
value: true
|
|
remediation: |
|
|
The OpenShift Controller Manager operator manages and updates the OpenShift Controller Manager.
|
|
The Kubernetes Controller Manager operator manages and updates the Kubernetes Controller Manager deployed on top of OpenShift.
|
|
This operator is configured via KubeControllerManager custom resource.
|
|
scored: false
|
|
|
|
- id: 1.3.4
|
|
text: "Ensure that the --service-account-private-key-file argument is set as appropriate (Manual)"
|
|
audit: |
|
|
oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq -r '.extendedArguments["service-account-private-key-file"][]'
|
|
tests:
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/secrets/service-account-private-key/service-account.key"
|
|
remediation: |
|
|
None required.
|
|
OpenShift manages the service account credentials for the scheduler automatically.
|
|
scored: false
|
|
|
|
- id: 1.3.5
|
|
text: "Ensure that the --root-ca-file argument is set as appropriate (Manual)"
|
|
audit: |
|
|
oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq -r '.extendedArguments["root-ca-file"][]'
|
|
tests:
|
|
test_items:
|
|
- flag: "/etc/kubernetes/static-pod-resources/configmaps/serviceaccount-ca/ca-bundle.crt"
|
|
remediation: |
|
|
None required.
|
|
Certificates for OpenShift platform components are automatically created and rotated by the OpenShift Container Platform.
|
|
scored: false
|
|
|
|
- id: 1.3.6
|
|
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
|
audit: |
|
|
oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq -r '.extendedArguments["feature-gates"][]'
|
|
tests:
|
|
test_items:
|
|
- flag: "RotateKubeletServerCertificate"
|
|
compare:
|
|
op: eq
|
|
value: "true"
|
|
remediation: |
|
|
None required.
|
|
Certificates for OpenShift platform components are automatically created and rotated by the OpenShift Container Platform.
|
|
scored: false
|
|
|
|
- id: 1.3.7
|
|
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Manual)"
|
|
audit: |
|
|
echo port=`oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq '.extendedArguments["port"][]'`
|
|
echo secure-port=`oc get configmaps config -n openshift-kube-controller-manager -ojson | jq -r '.data["config.yaml"]' | jq '.extendedArguments["secure-port"][]'`
|
|
#Following should fail with a http code 403
|
|
POD=$(oc get pods -n openshift-kube-controller-manager -l app=kube-controller-manager -o jsonpath='{.items[0].metadata.name}')
|
|
oc rsh -n openshift-kube-controller-manager -c kube-controller-manager $POD curl https://localhost:10257/metrics -k
|
|
tests:
|
|
bin_op: and
|
|
test_items:
|
|
- flag: "secure-port"
|
|
compare:
|
|
op: eq
|
|
value: "\"10257\""
|
|
- flag: "port"
|
|
compare:
|
|
op: eq
|
|
value: "\"0\""
|
|
- flag: "\"code\": 403"
|
|
remediation: |
|
|
Edit the Controller Manager pod specification file $controllermanagerconf
|
|
on the master node and ensure the correct value for the --bind-address parameter
|
|
scored: false
|
|
|
|
- id: 1.4
|
|
text: "Scheduler"
|
|
checks:
|
|
- id: 1.4.1
|
|
text: "Ensure that the healthz endpoints for the scheduler are protected by RBAC (Manual)"
|
|
type: manual
|
|
audit: |
|
|
# check configuration for ports, livenessProbe, readinessProbe, healthz
|
|
oc -n openshift-kube-scheduler get cm kube-scheduler-pod -o json | jq -r '.data."pod.yaml"' | jq '.spec.containers'
|
|
# Test to verify endpoints
|
|
oc -n openshift-kube-scheduler describe endpoints
|
|
# Test to validate RBAC enabled on the scheduler endpoint; check with non-admin role
|
|
oc project openshift-kube-scheduler
|
|
POD=$(oc get pods -l app=openshift-kube-scheduler -o jsonpath='{.items[0].metadata.name}')
|
|
PORT=$(oc get pod $POD -o jsonpath='{.spec.containers[0].livenessProbe.httpGet.port}')
|
|
# Should return 403 Forbidden
|
|
oc rsh ${POD} curl http://localhost:${PORT}/metrics -k
|
|
# Create a service account to test RBAC
|
|
oc create sa permission-test-sa
|
|
# Should return 403 Forbidden
|
|
SA_TOKEN=$(oc sa get-token permission-test-sa)
|
|
oc rsh ${POD} curl http://localhost:${PORT}/metrics -H "Authorization: Bearer $SA_TOKEN" -k
|
|
# Cleanup
|
|
oc delete sa permission-test-sa
|
|
# As cluster admin, should succeed
|
|
CLUSTER_ADMIN_TOKEN=$(oc whoami -t)
|
|
oc rsh ${POD} curl http://localhost:${PORT}/metrics -H "Authorization: Bearer $CLUSTER_ADMIN_TOKEN" -k
|
|
remediation: |
|
|
A fix to this issue: https://bugzilla.redhat.com/show_bug.cgi?id=1889488 None required.
|
|
Profiling is protected by RBAC and cannot be disabled.
|
|
scored: false
|
|
|
|
- id: 1.4.2
|
|
text: "Verify that the scheduler API service is protected by authentication and authorization (Manual)"
|
|
type: manual
|
|
audit: |
|
|
# To verify endpoints
|
|
oc -n openshift-kube-scheduler describe endpoints
|
|
# To verify that bind-adress is not used in the configuration and that port is set to 0
|
|
oc -n openshift-kube-scheduler get cm kube-scheduler-pod -o json | jq -r '.data."pod.yaml"' | jq '.spec.containers'
|
|
# To test for RBAC:
|
|
oc project openshift-kube-scheduler
|
|
POD=$(oc get pods -l app=openshift-kube-scheduler -o jsonpath='{.items[0].metadata.name}')
|
|
POD_IP=$(oc get pods -l app=openshift-kube-scheduler -o jsonpath='{.items[0].status.podIP}')
|
|
PORT=$(oc get pod $POD -o jsonpath='{.spec.containers[0].livenessProbe.httpGet.port}')
|
|
# Should return a 403
|
|
oc rsh ${POD} curl http://${POD_IP}:${PORT}/metrics
|
|
# Create a service account to test RBAC
|
|
oc create sa permission-test-sa
|
|
# Should return 403 Forbidden
|
|
SA_TOKEN=$(oc sa get-token permission-test-sa)
|
|
oc rsh ${POD} curl http://localhost:${PORT}/metrics -H "Authorization: Bearer $SA_TOKEN" -k
|
|
# Cleanup
|
|
oc delete sa permission-test-sa
|
|
# As cluster admin, should succeed
|
|
CLUSTER_ADMIN_TOKEN=$(oc whoami -t)
|
|
oc rsh ${POD} curl http://localhost:${PORT}/metrics -H "Authorization: Bearer $CLUSTER_ADMIN_TOKEN" -k
|
|
remediation: |
|
|
By default, the --bind-address argument is not present,
|
|
the readinessProbe and livenessProbe arguments are set to 10251 and the port argument is set to 0.
|
|
Check the status of this issue: https://bugzilla.redhat.com/show_bug.cgi?id=1889488
|
|
scored: false
|