16 KiB
Task 1
A pod has been created in the omni namespace, but it has a few issues that need to be addressed.
The pod has been created with more permissions than it needs. It allows read access to the /usr/share/nginx/html/internal directory, making the Internal Site publicly accessible. To verify this, click the Site button (above the terminal) and add /internal/ to the end of the URL.
Use the below recommendations to resolve this.
Use the AppArmor profile created at /etc/apparmor.d/frontend to restrict access to the internal site. The omni namespace has several service accounts. Apply the principle of least privilege and use the service account with the minimum privileges (excluding the default service account). Once the pod is recreated with the correct service account, delete the other unused service accounts in the omni namespace (excluding the default service account). Do not create a new service account or use the default service account.
Is the correct service account used? Are obsolete service accounts deleted? Is the internal-site restricted? Is the pod running?
Solution
apparmor_parser /etc/apparmor.d/frontend
apparmor_status | grep frontend
cat p.yaml
apiVersion: v1
kind: Pod
metadata:
generation: 1
labels:
run: nginx
name: frontend-site
namespace: omni
spec:
containers:
- image: nginx:alpine
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: controlplane
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: restricted-frontend
serviceAccount: frontend-default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- hostPath:
path: /data/pages
type: Directory
name: test-volume
- name: kube-api-access-z88t9
projected:
defaultMode: 420
sources:
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
k auth can-i --list --as=system:serviceaccount:omni:frontend-default
Task 2
A pod has been created in the orion namespace. It uses secrets as environment variables. Extract the decoded secret for the CONNECTOR_PASSWORD and place it under /root/CKS/secrets/CONNECTOR_PASSWORD.
You are not yet done; instead of using secrets as an environment variable, mount the secret as a read-only volume at the path /mnt/connector/password, which the application can then use.
Is the pod secured? Is the secret mounted as read-only? Is the existing secret extracted to file?
Task 3
The Release Engineering Team has shared some YAML manifests and Dockerfiles with you for review. These files are located under /opt/course/.
As a container security expert, your task is to perform a manual static analysis and identify possible security issues related to unwanted credential exposure. Note that running processes as root is not a concern in this task.
Record the filenames containing issues in /opt/course/security-issues.txt.
Note: Assume that all referenced files, folders, secrets, and volume mounts are present in the Dockerfiles and YAML manifests. You can ignore any syntax or logic errors.
Are the filenames containing issues written in /opt/course/security-issues.txt?
Task 4
Create a new pod named audit-nginx in the default namespace using the nginx:alpine image. Secure the syscalls that this pod can use by using the audit.json seccomp profile in the pod's security context.
The audit.json file is provided at the /root/CKS directory. Move it into the profiles directory inside the default seccomp directory before creating the pod.
Does audit-nginx use the right image? Is the pod running? Does the pod use the correct seccomp profile?
Task 5
We have identified a few issues with our kubernetes setup and need your help in fixing them.
Fix the following issues on kubelet:
Kubelet service file permission issues Kubelet config.yaml permission issues Fix the following issues on etcd:
Incorrect ownership of the etcd directory Fix the following issues on the controlplane node:
Incorrect value of the profiling argument for: kube-controller-manager kube-scheduler Kube-bench is installed, and its config files are available under /opt/kube-bench. Use the cis-1.10 benchmark with the current Kubernetes version.
Note: Only fix issues that have the status FAIL, except issue number 1.2.5. Also, ignore the issues with policies.
Is the apiserver working? Are the issues fixed for the controller and scheduler on the controlplane node? Is the issue pertaining to the etcd data directory fixed? Is the kubelet service file issue fixed? Is the kubelet config file issue fixed?
Task 6
There is suspicious activity in the cluster involving one of the pods running the httpd:2.4-alpine image.
Falco generates frequent alerts that start with: File below a known binary directory opened for writing.
Identify the rule causing this alert and update it as per the below requirements:
Set the rule priority to CRITICAL (Note: Falco will format this as "Critical" in log output)
The rule output must be: File below a known binary directory opened for writing (user_id=%user.uid file_updated=%fd.name command=%proc.cmdline)
Configure alerts to be logged to: /opt/security_incidents/alerts.log.
Do not update the default rules file directly. Instead, use the falco_rules.local.yaml file to override.
Expected log format:
: Critical File below a known binary directory opened for writing (user_id=0 file_updated=/bin/sleep command=tar -xmf - -C /bin)
Note: After updating the alert rule, it may take up to a minute for the alerts to appear in the new log location.
Task 7
A deployment named fruits in the namespace salad has three containers:
apple banana, and kiwi One of these containers has the package curl installed. Identify which container has that package from the running containers, and create an SBOM SPDX for the container's image.
Use the tarball archive of that particular image stored under /root/ImageTarballs directory for generating the SPDX JSON. The archives have names matching their images.
Save the output in ~/bugged-fruit.spdx. Save the container name in ~/bugged-container.txt.
Note: bom as well as all its required dependencies have already been installed.
Is the SPDX JSON SBOM for the image with curl installed stored at ~/bugged-fruit.spdx? Is the container name stored in ~/bugged-container.txt?
Task 8
Create a service account named bot-sa in the namespace automated. Make sure that this service account does not get automatically mounted to workloads.
A workload named sweeper is also in the automated namespace. Set the deployment's service account to the newly created service account, and mount the service account token as a projected volume. Do not change any other fields in the deployment.
Has the service account bot-sa been created without auto-mount? Has the bot-sa service account been set as the deployment's service account? Has the bot-sa service account token been mounted to the deployment as a projected volume? No default auto-mount on the Pod ?
Task 9
A deployment named web-server is running in the restricted namespace.
Identify the reason why the deployment is not in a running state; fix the issue so that it can be in a running state.
Do not change the namespace labels or container image.
Has the deployment been fixed, and is the pod in a running state? Namespace still enforces restricted ?
Task 10
Deployment web-app is running in the products namespace.
Database product-db is running in the database namespace.
Create a network policy named allow-traffic-to-products that allows traffic from product-db to the web-app workload, as well as all traffic originating from the payments namespace.
Utilize the labels applied on the relevant resources.
Has the network policy allow-traffic-to-products been created? Is traffic allowed from product-db to web-app? Is traffic allowed from payments-app to web-app? Is traffic not allowed from a test app in the database namespace? Is traffic not allowed from a test app in the default namespace?
Task 11
Edit the gamma deployment in the galaxy namespace to ensure that all containers meet the following requirements:
Run as user 1001 Do not allow privilege escalation Mount their file systems as read-only
Is the deployment edited to enable both containers to run as user 1001? Is the deployment edited to deny privilege escalation on both containers? Is the deployment edited to mount read-only file systems on both containers?
Task 12
A deployment rocket-server is exposed using the service of the same name in the space namespace.
Create an ingress resource named rocket-ingress to load balance the incoming traffic to the workload on path /.
Use the hostname rocket-server.local in the Ingress rules.
Utilize the TLS certificate stored in a secret named rocket-tls in the space namespace so that it enables TLS traffic on that ingress resource.
Is the ingress resource correctly created? Has the ingress TLS secret been attached? Does the ingress route to the correct path and port? Is curl working for the HTTPS connection via the ingress?
Task 13
A developer named martin needs access to work on the dev-a, dev-b, and dev-z namespaces. He should have the ability to carry out any operation on any pod in the dev-a and dev-b namespaces. However, on the dev-z namespace, he should only have the permission to get and list the pods.
The current setup is too permissive and violates the above condition. Use the above requirement and secure martin's access in the cluster. You may re-create objects; however, ensure to use the same names as the ones in currently in effect.
Does martin have unrestricted access to all pods in dev-a? Does martin have unrestricted access to all pods in dev-b? Can martin only list and get pods in dev-z?
Task 14
You need to enable auditing on this cluster. A basic policy file is available at /etc/kubernetes/cluster-policy.yaml.
The logs should be stored at /var/log/cluster-audit.log. The logs should be retained for 10 days and should not exceed 10MB. A maximum of 3 files should be kept at a time.
After you enable auditing on the cluster, update the basic policy file to track the following:
Delete activity on secrets in the kube-system namespace at the Metadata level Changes to deployments in the default namespace at the Request level All other requests at the Metadata level Make sure your changes to the policy file are in effect.
Note: A copy of the kube-apiserver.yaml is kept in ~/ so that you can revert if the configuration goes wrong. Make sure kube-apiserver is working fine for the sake of grading the exam.
Does /var/log/cluster-audit.log exist with the logs written to it?
Does auditing follow the mentioned parameters as specified in the question?
Is the delete activity on secrets tracked at the Metadata level in the kube-system namespace?
Is the edit activity on deployments tracked at the Request level in the default namespace?
Task 15
We need to ensure that when pods are created in this cluster, they cannot use the latest image tag, irrespective of the repository being used.
To achieve this, a simple Admission Webhook Server has been developed and deployed. A service called image-bouncer-webhook is deployed in the cluster. This Webhook server ensures that the developers of the team cannot use the latest image tag. Use the following specs to integrate it with the cluster using an ImagePolicyWebhook:
Create a new admission configuration file at /etc/admission-controllers/admission-configuration.yaml
The kubeconfig file with the credentials to connect to the webhook server is located at /root/CKS/ImagePolicy/admission-kubeconfig.yaml. Note: The /root/CKS/ImagePolicy/ directory is already mounted on the kube-apiserver at path /etc/admission-controllers, so reference that path in reference the admission configuration.
Ensure that if the latest tag is used, the request must be rejected at all times.
Enable the Admission Controller.
Finally, delete the existing pod in the magnum namespace that violates the policy and recreate it, ensuring the same image but using tag 1.27.
NOTE: If the kube-apiserver becomes unresponsive, this can affect the validation of this exam. In such a case, restore the kube-apiserver using the backup file created at: /root/backup/kube-apiserver.yaml. Wait for the API to be available again and proceed.
Is the ImagePolicyWebhook enabled and the API server running? Is the policy implemented? Is the pod recreated with the correct image? Is the pod running?
Solution
Create the below admission-configuration.yaml inside /root/CKS/ImagePolicy directory in the controlplane node:
apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins:
- name: ImagePolicyWebhook configuration: imagePolicy: kubeConfigFile: /etc/admission-controllers/admission-kubeconfig.yaml allowTTL: 50 denyTTL: 50 retryBackoff: 500 defaultAllow: false
The /root/CKS/ImagePolicy is mounted at the path /etc/admission-controllers directory in the kube-apiserver. So, you can directly place the files under /root/CKS/ImagePolicy.
Here is a snippet of the volume and volumeMounts (already added to apiserver config, you don't need to do anything here):
containers: . . . volumeMounts:
- mountPath: /etc/admission-controllers name: admission-controllers readOnly: true
volumes:
- hostPath: path: /root/CKS/ImagePolicy/ type: DirectoryOrCreate name: admission-controllers
Next, update the kube-apiserver command flags and add ImagePolicyWebhook to the enable-admission-plugins flag. Use the configuration file that was created in the previous step as the value of admission-control-config-file.
Note: Remember, this command will be run inside the kube-apiserver container, so the path must be /etc/admission-controllers/admission-configuration.yaml (mounted from /root/CKS/ImagePolicy in controlplane).
Edit the kube-apiserver manifest file:
vi /etc/kubernetes/manifests/kube-apiserver.yaml
to add the following flags under spec.containers.command:
- --admission-control-config-file=/etc/admission-controllers/admission-configuration.yaml
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
In case we mess up while solving the question, API server could become unresponsive. For example:
The connection to the server controlplane:6443 was refused - did you specify the right host or port?
In such case scenario restore kube-apiserver to it's default state using the backup provided at /root/backup/kube-apiserver.yaml Run the below command to restore the kube-apiserver initial state:
cp -v /root/backup/kube-apiserver.yaml /etc/kubernetes/manifests
Remediate the Non-Compliant Pod After the ImagePolicyWebhook is active, you must fix the existing app-0403 pod in the magnum namespace, as it violates the new policy, and , Admission controllers only check new requests; they don't affect pods that are already running.
Get the Pod's Definition First, get the YAML definition of the running pod and save it to a file. kubectl get pod app-0403 -n magnum -o yaml > app-0403-fix.yaml
Clean and Edit the YAML Now, edit the file. The YAML you just saved contains live, system-managed fields. You must clean it up before you can re-apply it. vi app-0403-fix.yaml
Change:
image: gcr.io/google-containers/busybox
to:
image: gcr.io/google-containers/busybox:1.27
Save and exit the file.
Delete the Old Pod You must delete the running pod before you can create a new one with the same name. kubectl delete pod app-0403 -n magnum
Apply the Fixed Manifest Finally, create the new, compliant pod from your corrected YAML file. The webhook will inspect this request and allow it. kubectl apply -f app-0403-fix.yaml