diff --git a/staging/src/k8s.io/pod-security-admission/.gitignore b/staging/src/k8s.io/pod-security-admission/.gitignore new file mode 100644 index 00000000000..ec2ce3d4b0a --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/.gitignore @@ -0,0 +1,5 @@ +# Webhook binary +pod-security-webhook + +# Directory containing pki files +pki/ \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/Dockerfile b/staging/src/k8s.io/pod-security-admission/webhook/Dockerfile new file mode 100644 index 00000000000..9ddbac4a748 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/Dockerfile @@ -0,0 +1,19 @@ +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM gcr.io/distroless/static:latest + +COPY pod-security-webhook /pod-security-webhook + +ENTRYPOINT [ "/pod-security-webhook" ] \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/Makefile b/staging/src/k8s.io/pod-security-admission/webhook/Makefile new file mode 100644 index 00000000000..1e8587343ee --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/Makefile @@ -0,0 +1,66 @@ +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.PHONY: build container push clean + +ENTRYPOINT = "../cmd/webhook/webhook.go" +EXECUTABLE = "pod-security-webhook" + +# Relative to location in staging dir +KUBE_ROOT = "../../../../.." + +IMAGE_DOCKERFILE = "Dockerfile" +REGISTRY ?= "gcr.io/k8s-staging-sig-auth" +IMAGE ?= "$(REGISTRY)/pod-security-webhook" +TAG ?= "latest" + +OS ?= linux +ARCH ?= amd64 + +# Builds the PodSecurity webhook binary. +build: + @echo Building PodSecurity webhook... + @LDFLAGS=`cd -P . && /usr/bin/env bash -c '. $(KUBE_ROOT)/hack/lib/version.sh && KUBE_ROOT=$(KUBE_ROOT) KUBE_GO_PACKAGE=k8s.io/kubernetes kube::version::ldflags'`; \ + GOOS=$(OS) GOARCH=$(ARCH) CGO_ENABLED=0 go build -o $(EXECUTABLE) -ldflags "$$LDFLAGS" $(ENTRYPOINT) + @echo Done! + +# Builds the PodSecurity webhook Docker image. +container: build + @echo Building PodSecurity webhook image... + @docker build \ + -f $(IMAGE_DOCKERFILE) \ + -t $(IMAGE):$(TAG) . + @echo Done! + +# Creates a CA and serving certificate valid for webhook.pod-security-webhook.svc +certs: + rm -fr pki + mkdir -p pki + openssl genrsa -out pki/ca.key 2048 + openssl req -new -x509 -days 3650 -key pki/ca.key -subj "/CN=pod-security-webhook-ca-$(date +%s)" -out pki/ca.crt + + openssl req -newkey rsa:2048 -nodes -keyout pki/tls.key -subj "/CN=webhook.pod-security-webhook.svc" -out pki/tls.csr + + echo "subjectAltName=DNS:webhook.pod-security-webhook.svc" > pki/extensions.txt + echo "extendedKeyUsage=serverAuth" >> pki/extensions.txt + openssl x509 -req -extfile pki/extensions.txt -days 730 -in pki/tls.csr -CA pki/ca.crt -CAkey pki/ca.key -CAcreateserial -out pki/tls.crt + +# Publishes the PodSecurity webhook Docker image to the configured registry. +push: + @docker push $(IMAGE):$(TAG) + +# Removes Pod Security Webhook artifacts. +clean: + rm -f $(EXECUTABLE) + rm -fr pki diff --git a/staging/src/k8s.io/pod-security-admission/webhook/README.md b/staging/src/k8s.io/pod-security-admission/webhook/README.md new file mode 100644 index 00000000000..0bed2b98c83 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/README.md @@ -0,0 +1,33 @@ +# Pod Security Admission Webhook + +This directory contains files for a _Validating Admission Webhook_ that checks for conformance to the Pod Security Standards. It is built with the same Go package as the [Pod Security Admission Controller](https://kubernetes.io/docs/concepts/security/pod-security-admission/). The webhook is suitable for environments where the built-in PodSecurity admission controller cannot be used. + +For more information, see the [Dynamic Admission Control](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) documentation on the Kubernetes website. + +## Getting Started + +The webhook is available as a Docker image that lives within the SIG-Auth container registry. In addition to the `Dockerfile` for the webhook, this directory also contains sample Kubernetes manifests that can be used to deploy the webhook to a Kubernetes cluster. + +### Configuring the Webhook Certificate + +Run `make certs` to generate a CA and serving certificate valid for `https://webhook.pod-security-webhook.svc`. + +### Deploying the Webhook + +Apply the manifests to install the webhook in your cluster: + +```bash +kubectl apply -k . +``` + +This applies the manifests in the `manifests` subdirectory, +creates a secret containing the serving certificate, +and injects the CA bundle to the validating webhook. + +### Configuring the Webhook + +Similar to the Pod Security Admission Controller, the webhook requires a configuration file to determine how incoming resources are validated. For real-world deployments, we highly recommend reviewing our [documentation on selecting appropriate policy levels](https://kubernetes.io/docs/tasks/configure-pod-container/migrate-from-psp/#steps). + +## Contributing + +Please see the [contributing guidelines](../CONTRIBUTING.md) in the parent directory for general information about contributing to this project. diff --git a/staging/src/k8s.io/pod-security-admission/webhook/kustomization.yaml b/staging/src/k8s.io/pod-security-admission/webhook/kustomization.yaml new file mode 100644 index 00000000000..ac22d13e8ab --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/kustomization.yaml @@ -0,0 +1,33 @@ +# include the manifests +bases: +- ./manifests + +# generate the secret +# this depends on pki files, which can be created (or regenerated) with `make certs` +secretGenerator: +- name: pod-security-webhook + namespace: pod-security-webhook + type: kubernetes.io/tls + options: + disableNameSuffixHash: true + files: + - pki/ca.crt + - pki/tls.crt + - pki/tls.key + +# inject the CA into the validating webhook +replacements: +- source: + kind: Secret + name: pod-security-webhook + namespace: pod-security-webhook + fieldPath: data.ca\.crt + targets: + - select: + kind: ValidatingWebhookConfiguration + name: pod-security-webhook.kubernetes.io + fieldPaths: + - webhooks.0.clientConfig.caBundle + - webhooks.1.clientConfig.caBundle + options: + create: true diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/10-namespace.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/10-namespace.yaml new file mode 100644 index 00000000000..5a1d492060c --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/10-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: pod-security-webhook \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-configmap.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-configmap.yaml new file mode 100644 index 00000000000..4d1c73bf6d4 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-configmap.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: pod-security-webhook + namespace: pod-security-webhook +data: + podsecurityconfiguration.yaml: | + apiVersion: pod-security.admission.config.k8s.io/v1alpha1 + kind: PodSecurityConfiguration + # Defaults applied when a mode label is not set. + # + # Level label values must be one of: + # - "privileged" (default) + # - "baseline" + # - "restricted" + # + # Version label values must be one of: + # - "latest" (default) + # - specific version like "v1.22" + defaults: + enforce: "privileged" + enforce-version: "latest" + audit: "privileged" + audit-version: "latest" + warn: "privileged" + warn-version: "latest" + exemptions: + # Array of authenticated usernames to exempt. + usernames: [] + # Array of runtime class names to exempt. + runtimeClasses: [] + # Array of namespaces to exempt. + namespaces: [] diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-resourcequota.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-resourcequota.yaml new file mode 100644 index 00000000000..0c90bd22bda --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-resourcequota.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: pod-security-webhook + namespace: pod-security-webhook +spec: + hard: + pods: 3 + scopeSelector: + matchExpressions: + - operator: In + scopeName: PriorityClass + values: + - system-cluster-critical \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-serviceaccount.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-serviceaccount.yaml new file mode 100644 index 00000000000..3a353bc7303 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/20-serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: pod-security-webhook + namespace: pod-security-webhook \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/30-clusterrole.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/30-clusterrole.yaml new file mode 100644 index 00000000000..5d14e89013c --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/30-clusterrole.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: pod-security-webhook +rules: + - apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/40-clusterrolebinding.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/40-clusterrolebinding.yaml new file mode 100644 index 00000000000..2263986aac2 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/40-clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: pod-security-webhook +subjects: + - kind: ServiceAccount + name: pod-security-webhook + namespace: pod-security-webhook +roleRef: + kind: ClusterRole + name: pod-security-webhook + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/50-deployment.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/50-deployment.yaml new file mode 100644 index 00000000000..104321e2cf2 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/50-deployment.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pod-security-webhook + namespace: pod-security-webhook + labels: + app: pod-security-webhook +spec: + selector: + matchLabels: + app: pod-security-webhook + template: + metadata: + labels: + app: pod-security-webhook + spec: + serviceAccountName: pod-security-webhook + priorityClassName: system-cluster-critical + volumes: + - name: config + configMap: + name: pod-security-webhook + - name: pki + secret: + secretName: pod-security-webhook + containers: + - name: pod-security-webhook + image: k8s.gcr.io/sig-auth/pod-security-webhook:v1.22-alpha.0 + terminationMessagePolicy: FallbackToLogsOnError + ports: + - containerPort: 8443 + args: + [ + "--config", + "/etc/config/podsecurityconfiguration.yaml", + "--tls-cert-file", + "/etc/pki/tls.crt", + "--tls-private-key-file", + "/etc/pki/tls.key", + "--secure-port", + "8443", + ] + resources: + requests: + cpu: 100m + limits: + cpu: 500m + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: config + mountPath: "/etc/config" + readOnly: true + - name: pki + mountPath: "/etc/pki" + readOnly: true diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/60-service.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/60-service.yaml new file mode 100644 index 00000000000..0b5f66f4035 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/60-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: webhook + namespace: pod-security-webhook + labels: + app: pod-security-webhook +spec: + ports: + - port: 443 + targetPort: 8443 + protocol: TCP + name: https + selector: + app: pod-security-webhook \ No newline at end of file diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/70-validatingwebhookconfiguration.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/70-validatingwebhookconfiguration.yaml new file mode 100644 index 00000000000..c185c26c18e --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/70-validatingwebhookconfiguration.yaml @@ -0,0 +1,74 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: "pod-security-webhook.kubernetes.io" +webhooks: + # Audit annotations will be prefixed with this name + - name: "pod-security-webhook.kubernetes.io" + # Fail-closed admission webhooks can present operational challenges. + # You may want to consider using a failure policy of Ignore, but should + # consider the security tradeoffs. + failurePolicy: Fail + namespaceSelector: + # Exempt the webhook itself to avoid a circular dependency. + matchExpressions: + - key: kubernetes.io/metadata.name + operator: NotIn + values: ["pod-security-webhook"] + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: + - namespaces + - pods + - pods/ephemeralcontainers + clientConfig: + # Populate with the CA for the serving certificate + caBundle: "" + service: + namespace: "pod-security-webhook" + name: "webhook" + admissionReviewVersions: ["v1"] + sideEffects: None + timeoutSeconds: 5 + + # Audit annotations will be prefixed with this name + - name: "advisory.pod-security-webhook.kubernetes.io" + # Non-enforcing resources can safely fail-open. + failurePolicy: Ignore + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: NotIn + values: ["pod-security-webhook"] + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: + - podtemplates + - replicationcontrollers + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: + - daemonsets + - deployments + - replicasets + - statefulsets + - apiGroups: ["batch"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: + - cronjobs + - jobs + clientConfig: + # Populate with the CA for the serving certificate + caBundle: "" + service: + namespace: "pod-security-webhook" + name: "webhook" + admissionReviewVersions: ["v1"] + sideEffects: None + timeoutSeconds: 5 diff --git a/staging/src/k8s.io/pod-security-admission/webhook/manifests/kustomization.yaml b/staging/src/k8s.io/pod-security-admission/webhook/manifests/kustomization.yaml new file mode 100644 index 00000000000..8320af4a6d1 --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/webhook/manifests/kustomization.yaml @@ -0,0 +1,10 @@ +resources: +- 10-namespace.yaml +- 20-configmap.yaml +- 20-serviceaccount.yaml +- 20-resourcequota.yaml +- 30-clusterrole.yaml +- 40-clusterrolebinding.yaml +- 50-deployment.yaml +- 60-service.yaml +- 70-validatingwebhookconfiguration.yaml