{"id":21145360,"url":"https://github.com/jsa2/akspodsecurity","last_synced_at":"2025-06-30T03:36:28.015Z","repository":{"id":45892921,"uuid":"432956788","full_name":"jsa2/AKSPodSecurity","owner":"jsa2","description":"Increase workload security by aligning the use of Azure Policy and resource specification together. First with audit controls, and then with deny controls.","archived":false,"fork":false,"pushed_at":"2021-11-29T09:46:52.000Z","size":861,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-14T13:43:09.201Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsa2.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-29T08:15:18.000Z","updated_at":"2023-03-16T14:26:15.000Z","dependencies_parsed_at":"2022-09-05T18:20:36.290Z","dependency_job_id":null,"html_url":"https://github.com/jsa2/AKSPodSecurity","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jsa2/AKSPodSecurity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsa2%2FAKSPodSecurity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsa2%2FAKSPodSecurity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsa2%2FAKSPodSecurity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsa2%2FAKSPodSecurity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsa2","download_url":"https://codeload.github.com/jsa2/AKSPodSecurity/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsa2%2FAKSPodSecurity/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262705169,"owners_count":23351199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T08:39:43.767Z","updated_at":"2025-06-30T03:36:27.990Z","avatar_url":"https://github.com/jsa2.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Azure Kubernetes Service - Enhanced Kubernetes cluster pod security baseline standards for Linux-based workloads\r\n\r\nThis example builds upon existing Pod Security baseline with enhancements, and provides means to manage the initiative as code using GitHub actions.\r\n(You can also create manually the initiative, but this guide does not have instructions for manual workflow)\r\n\r\n**Scope** of this guide is to increase workload security by aligning the use of Azure Policy and resource specification together. First with audit controls, and then with deny controls.\r\n\r\n**Original policy baseline policy** \r\n\r\nDescription| source\r\n-|-\r\n|This initiative includes the policies for the Kubernetes cluster pod security baseline standards. This policy is generally available for Kubernetes Service (AKS), and preview for AKS Engine and Azure Arc enabled Kubernetes. For instructions on using this policy, visit https://aka.ms/kubepolicydoc.|Kubernetes cluster pod security baseline standards for Linux-based workloads\r\n\r\n\r\n**Enhanced policy**\r\n\r\n![img](img/front.png)\r\n\r\n- [Azure Kubernetes Service - Enhanced Kubernetes cluster pod security baseline standards for Linux-based workloads](#azure-kubernetes-service---enhanced-kubernetes-cluster-pod-security-baseline-standards-for-linux-based-workloads)\r\n  - [Differences compared to the built-in initiative:](#differences-compared-to-the-built-in-initiative)\r\n  - [Disclaimer](#disclaimer)\r\n  - [Utilizing the initiative](#utilizing-the-initiative)\r\n    - [Example of which policy affects which specification in resource](#example-of-which-policy-affects-which-specification-in-resource)\r\n    - [Example of healthy podspec](#example-of-healthy-podspec)\r\n  - [Deployment guide:](#deployment-guide)\r\n    - [Express installation with password based SPN (recommended only for testing)](#express-installation-with-password-based-spn-recommended-only-for-testing)\r\n    - [Advanced with Workload federation (recommended for enterprise use)](#advanced-with-workload-federation-recommended-for-enterprise-use)\r\n  - [References](#references)\r\n\r\n\r\n\r\n---\r\n\r\n## Differences compared to the built-in initiative:\r\n\r\n\r\n✔️ Adds \"debug\" namespace to exclusions, so you don't have to run debugging workloads in the namespaces  ``[\"kube-system\" \"gatekeeper-system\", \"azure-arc\"] ``\r\n\r\n- Typical example of debug namespace use would be the SSH to AKS node\r\n\r\n```bash\r\nkubectl create namespace 'debug'\r\nnode=$(kubectl get nodes -o=jsonpath='{.items[0].metadata.name}')\r\nval=$(echo $node | sed 's/\"//g')\r\nkubectl debug node/$val -it --image=mcr.microsoft.com/aks/fundamental/base-ubuntu:v0.0.11 --namespace=\"debug\"\r\n```\r\n\r\n✔️ Adds ``Kubernetes cluster containers should only use allowed AppArmor profiles`` -policy \r\n\r\n- Configuration is compliant with the \"runtime/default\" out-of-the-box AKS node installed profile. Creates initiative parameter for \"runtime/default\" appArmor profile, which is the default profile installed in AKS nodes\r\n\r\n✔️ Adds  `` Kubernetes cluster containers should run with a read only root file system `` \r\n\r\n✔️ Allows switching state for allow policies from audit to deny in single setting using Initiative parameters\r\n\r\n![img](img/init.png)\r\n\r\n---\r\n## Disclaimer\r\n[Read license](LICENSE)\r\n## Utilizing the initiative \r\n\r\n- Target the Policy to scope you want to apply it (Recommendation for testing is to target it to single AKS cluster)\r\n- Review audit results produced by the policy\r\n- Implement healthy podSpec / deployment \r\n\r\n\r\n### Example of which policy affects which specification in resource \r\n\r\nMS Docs features good example of complete healthy and unhealthy specifications\r\n\r\n[Unhealthy specification ](https://docs.microsoft.com/en-us/azure/defender-for-cloud/kubernetes-workload-protections#unhealthy-deployment-example-yaml-file)\r\n\r\n[healthy specification ](https://docs.microsoft.com/en-us/azure/defender-for-cloud/kubernetes-workload-protections#healthy-deployment-example-yaml-file)\r\n\r\n---\r\n\r\n**Mapping to Azure Policy and specification**\r\n\r\nThe below table highlights healthy, and un-healthy settings examples spec\r\n\r\nitem|status | YAML \r\n-|-|-\r\nPods should run as non-root /non-privileged|✔ | **spec.securityContext** \u003cbr\u003e ``privileged: false``  \u003cbr\u003e       ``runAsNonRoot:true`` \u003cbr\u003e ``allowPrivilegeEscalation: false``\r\nPod Filesystem access should be read-only or limited only for specifed writes | ✔ | **spec.securityContext** \u003cbr\u003e ``readOnlyRootFilesystem: true`` \r\nPod actions should be limited with appArmor |✔| **metadata.annotations** \u003cbr\u003e ``container.apparmor.security.beta.kubernetes.io/v5: runtime/default`` \r\nPod should be disabled for automation of API credentials |✔| **spec** \u003cbr\u003e `` automountServiceAccountToken: false `` \r\nPod hostPath mounts should only allow predefined mounts, and preferably not used at all (By default Azure Policy audits all hostPath mounts as non compliant, to block hostPath mounts the policy needs to be changed) | ✔ | **spec.Volumes** \u003cbr\u003e `` hostPath: \u003cOnly allowed values here defined in Azure Policy\u003e `` \r\n**MS direct reference** *To protect against privilege escalation outside the container, avoid pod access to sensitive host namespaces (host process ID and host IPC) in a Kubernetes cluster*.   |❌| Should not define use of 'true' in following settings **spec.hostPID** \u003cbr\u003e `` hostPID:   `` \u003cbr\u003e **spec.hostIPC** \u003cbr\u003e ``hostIPC: `` \r\n**MS direct reference**  *Pods created with the hostNetwork attribute enabled will share the node’s network space. To avoid compromised container from sniffing network traffic, we recommend not putting your pods on the host network*|❌|  Should not define use of 'true' in following settings \u003cbr\u003e **spec** \u003cbr\u003e `` hostNetwork:  `` \r\n\r\n\r\n### Example of healthy podspec\r\n- For testing replace the image with any image you want to test the POD deployment against\r\n- The example assumes keyVault integration with secrets store driver. If you don't have such integration configured, remove ``volumes`` and ``volumeMounts``  \r\n\r\n```YAML\r\napiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: demorce\r\n  annotations:\r\n    container.apparmor.security.beta.kubernetes.io/v5: runtime/default\r\nspec:\r\n  automountServiceAccountToken: false\r\n  containers:\r\n    - name: nginxHealthy\r\n      image: nginx:1.14.2\r\n      ports:\r\n        - containerPort: 8443\r\n      resources:\r\n          limits:\r\n            cpu: 100m\r\n            memory: 250Mi\r\n      securityContext:\r\n        privileged: false\r\n        readOnlyRootFilesystem: true\r\n        allowPrivilegeEscalation: false\r\n        runAsNonRoot: true\r\n        runAsUser: 1000\r\n      volumeMounts:\r\n        - name: secrets-store01-inline\r\n          mountPath: /mnt/secrets-store\r\n          readOnly: true\r\n  volumes:\r\n      - name: secrets-store01-inline\r\n        csi:\r\n          driver: secrets-store.csi.k8s.io\r\n          readOnly: true\r\n          volumeAttributes:\r\n            secretProviderClass: azure-kvname-user-msi \r\n``` \r\n\r\n\r\n\r\n## Deployment guide:\r\n\r\n### Express installation with password based SPN (recommended only for testing)\r\n\r\nFollowing this method creates SPN with required permissions ``Resource Policy Contributor``  to the subscription defined in cli script\r\n\r\n- References https://github.com/marketplace/actions/manage-azure-policy#configure-credentials-for-azure-login-action \r\n1.  Create SPN\r\n\r\n```bash\r\n## Set subscription\r\nSUB=\"3539c2a2-cd25-48c6-b295-14e59334ef1c\"\r\naz account set --subscription $SUB\r\naz ad sp create-for-rbac --name PodSecurityPolicySPN --role 'Resource Policy Contributor' --scopes \"/subscriptions/$SUB\"\r\n\r\n# If you are running Azure Cloud Shell, you can automatically do step 2 here \r\n# node replacesub.js $SUB\r\n```\r\n\r\nTake note of the output, as it is used in step 5.\r\n\r\n![img](img/output.png)\r\n\r\n2. Replace subscription ``SUBID`` ID in [policyset.json](initiatives/AKSREF_-_Kubernetes_cluster_pod_security_baseline_standards_for_Linux-based_workloads_1f01afd98f33414e995e3ad5/policyset.json)\r\n  ```\r\n    \"id\": \"/subscriptions/SUBID/providers/Microsoft.Authorization/policySetDefinitions/1f01afd98f33414e995e3ad5\",\r\n    \"type\": \"Microsoft.Authorization/policySetDefinitions\",\r\n    \"name\": \"1f01afd98f33414e995e3ad5\"\r\n  ```\r\n\r\n\r\n3. After this Create **new** Github repo, and force push the contents of this repo to the just created repo\r\n\r\n```\r\n git remote add myTestRepo git@github.com:you/yourTestRepo.git\r\n git add .; git commit -m \"init to myTestRepo\"\r\n git push myTestRepo --force\r\n```\r\n\r\n4. replace the credentials in action.yml wit the secret listed in the throwaway repo *(the ID for credential needs to match that of the one listed in secrets)*\r\n```yaml\r\nwith:\r\n        creds: ${{secrets.policySecret}}\r\n        allow-no-subscriptions: true\r\n```\r\n5. Add the password to the repo you created. The secret name needs to match \"creds\" as defined in previous step\r\n\r\n- replace as follows AppId = clientID, password = clientSecret\r\n\r\n![img](img/secret.png)\r\n\r\n6. From actions start the workflow manually\r\n\r\n![img](img/wf.png)\r\n\r\n7. After update you should see the following output in actions and at azure policy\r\n\r\n![img](img/assign.png)\r\n\r\n![img](img/deployed.png)\r\n\r\n8.  Assign the policy to test cluster\r\n\r\n![img](img/assingment.png)\r\n\r\n9. Review results and determine which resources need to be fixed, or excluded from policy\r\n![img](img/compl.png)\r\n\r\n![img](img/details.png)\r\n10. If you feel that everything works correctly, turn the policy initative to deny\r\n\r\n![img](img/init.png)\r\n\r\n### Advanced with Workload federation (recommended for enterprise use)\r\n\r\n- To be tested!\r\n\r\n[documentation](https://docs.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication)\r\n\r\n## References\r\nhttps://kubernetes.io/docs/concepts/policy/pod-security-policy/\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsa2%2Fakspodsecurity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsa2%2Fakspodsecurity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsa2%2Fakspodsecurity/lists"}