diff --git a/helm/psa-restricted-patcher/Chart.yaml b/helm/psa-restricted-patcher/Chart.yaml index 16b1a53..a688c63 100644 --- a/helm/psa-restricted-patcher/Chart.yaml +++ b/helm/psa-restricted-patcher/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: psa-restricted-patcher description: Automatically patches pods on creation to conform to the pod security restricted profile type: application -version: 0.10.0 -appVersion: "0.4.0" +version: 0.10.1 +appVersion: "0.4.1" maintainers: - name: bryopsida \ No newline at end of file diff --git a/helm/psa-restricted-patcher/README.md b/helm/psa-restricted-patcher/README.md index 7063912..3b93583 100644 --- a/helm/psa-restricted-patcher/README.md +++ b/helm/psa-restricted-patcher/README.md @@ -1,6 +1,6 @@ # psa-restricted-patcher -![Version: 0.10.0](https://img.shields.io/badge/Version-0.10.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.4.0](https://img.shields.io/badge/AppVersion-0.4.0-informational?style=flat-square) +![Version: 0.10.1](https://img.shields.io/badge/Version-0.10.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.4.1](https://img.shields.io/badge/AppVersion-0.4.1-informational?style=flat-square) Automatically patches pods on creation to conform to the pod security restricted profile diff --git a/package.json b/package.json index c27d4ee..0372366 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "psa-restricted-patcher", - "version": "0.4.0", + "version": "0.4.1", "description": "Automatically patches pods on creation to comply with the restricted pod security admission policy", "main": "dist/app.js", "scripts": { diff --git a/src/services/admission.ts b/src/services/admission.ts index 0a1dc47..3856441 100644 --- a/src/services/admission.ts +++ b/src/services/admission.ts @@ -1,7 +1,12 @@ import { inject, injectable } from 'inversify' import { TYPES } from '../types' import { Logger } from 'pino' -import { V1Capabilities, V1Pod, V1PodSpec } from '@kubernetes/client-node' +import { + V1Capabilities, + V1Container, + V1Pod, + V1PodSpec +} from '@kubernetes/client-node' import * as jsonpatch from 'fast-json-patch' export interface IAdmission { @@ -38,6 +43,39 @@ export class Admission implements IAdmission { this.seccompProfile = seccompProfile } + /** + * + * @param {V1Container} c container object whose securityContext will be enhanced + * @returns {V1Container} enhanced container + */ + private patchContainer(c: V1Container): V1Container { + if (!c.securityContext) c.securityContext = {} + if ( + c.securityContext.allowPrivilegeEscalation == null || + c.securityContext.allowPrivilegeEscalation + ) + c.securityContext.allowPrivilegeEscalation = false + if (c.securityContext.privileged == null || c.securityContext.privileged) + c.securityContext.privileged = false + if (!c.securityContext.readOnlyRootFilesystem) + c.securityContext.readOnlyRootFilesystem = true + if (!c.securityContext.runAsNonRoot) c.securityContext.runAsNonRoot = true + if (!c.securityContext.runAsGroup) + c.securityContext.runAsGroup = this.defaultGid ?? 1001 + if (!c.securityContext.runAsUser) + c.securityContext.runAsUser = this.defaultUid ?? 1001 + if (!c.securityContext.capabilities) + c.securityContext.capabilities = new V1Capabilities() + if (!c.securityContext.capabilities.drop) + c.securityContext.capabilities.drop = ['ALL'] + return c + } + + /** + * Patch the pod level and container level securityContext's of a pod + * @param {V1Pod} pod + * @returns {string} JSON Patch string that will be returned to the API server + */ async admit(pod: V1Pod): Promise { const observer = jsonpatch.observe(pod) const spec = pod.spec as V1PodSpec @@ -51,28 +89,7 @@ export class Admission implements IAdmission { type: this.seccompProfile } } - spec.containers = spec.containers.map((c) => { - if (!c.securityContext) c.securityContext = {} - if ( - c.securityContext.allowPrivilegeEscalation == null || - c.securityContext.allowPrivilegeEscalation - ) - c.securityContext.allowPrivilegeEscalation = false - if (c.securityContext.privileged == null || c.securityContext.privileged) - c.securityContext.privileged = false - if (!c.securityContext.readOnlyRootFilesystem) - c.securityContext.readOnlyRootFilesystem = true - if (!c.securityContext.runAsNonRoot) c.securityContext.runAsNonRoot = true - if (!c.securityContext.runAsGroup) - c.securityContext.runAsGroup = this.defaultGid ?? 1001 - if (!c.securityContext.runAsUser) - c.securityContext.runAsUser = this.defaultUid ?? 1001 - if (!c.securityContext.capabilities) - c.securityContext.capabilities = new V1Capabilities() - if (!c.securityContext.capabilities.drop) - c.securityContext.capabilities.drop = ['ALL'] - return c - }) + spec.containers = spec.containers.map(this.patchContainer.bind(this)) return Promise.resolve(JSON.stringify(jsonpatch.generate(observer))) } }