|
| 1 | +--- |
| 2 | +weight: 40 |
| 3 | +i18n: |
| 4 | + title: |
| 5 | + en: Comply with Pod Security Restricted Standard |
| 6 | + zh: 满足 Pod Security Restricted 安全规范 |
| 7 | +title: Comply with Pod Security Restricted Standard |
| 8 | +--- |
| 9 | + |
| 10 | +# Comply with Pod Security Restricted Standard |
| 11 | + |
| 12 | +## Feature Overview |
| 13 | + |
| 14 | +The `pod-security.kubernetes.io/enforce=restricted` standard is the most restrictive `Pod Security Standard`, enforcing current pod hardening best practices. When a namespace is labeled with this standard, all pods created in that namespace must comply with strict security requirements. |
| 15 | + |
| 16 | +This guide explains how to configure `Tekton Pipelines` to meet the `restricted` security standard, ensuring that all containers in your `Tasks` can run successfully in restricted namespaces. |
| 17 | + |
| 18 | +## Use Cases |
| 19 | + |
| 20 | +- Running `Tekton Pipelines` in namespaces with `pod-security.kubernetes.io/enforce=restricted` label |
| 21 | +- Meeting organizational security compliance requirements |
| 22 | +- Enhancing the security posture of your CI/CD pipelines |
| 23 | +- Running workloads in highly regulated environments |
| 24 | + |
| 25 | +## Prerequisites |
| 26 | + |
| 27 | +- `Tekton Pipelines` is installed via `TektonPipeline` or `TektonConfig` CR |
| 28 | +- You have permission to modify `TektonPipeline` or `TektonConfig` resources |
| 29 | +- You can create or edit `Task` definitions |
| 30 | +- For custom images, you have access to modify `Dockerfiles` and rebuild images |
| 31 | + |
| 32 | +## Understanding the Restricted Standard |
| 33 | + |
| 34 | +The `pod-security.kubernetes.io/enforce=restricted` standard requires all three types of containers in a `Pod` to meet the following security context requirements: |
| 35 | + |
| 36 | +- **Regular containers** (`containers`) |
| 37 | +- **Init containers** (`initContainers`) |
| 38 | +- **Ephemeral containers** (`ephemeralContainers`) |
| 39 | + |
| 40 | +Each container must have the following security context configuration: |
| 41 | + |
| 42 | +```yaml |
| 43 | +securityContext: |
| 44 | + allowPrivilegeEscalation: false |
| 45 | + runAsNonRoot: true |
| 46 | + capabilities: |
| 47 | + drop: |
| 48 | + - "ALL" |
| 49 | + seccompProfile: |
| 50 | + type: RuntimeDefault |
| 51 | +``` |
| 52 | +
|
| 53 | +**Configuration breakdown:** |
| 54 | +
|
| 55 | +| Field | Value | Purpose | Impact | |
| 56 | +|-------|-------|---------|--------| |
| 57 | +| `allowPrivilegeEscalation` | `false` | Prevents processes from gaining more privileges than their parent process | Blocks malicious code from escalating privileges through setuid binaries or file capabilities | |
| 58 | +| `runAsNonRoot` | `true` | Requires containers to run as a non-root user (UID ≠0) | Prevents containers from running as root, reducing the impact of container breakout vulnerabilities | |
| 59 | +| `capabilities.drop` | `["ALL"]` | Removes all Linux capabilities from the container | Limits the container's ability to perform privileged operations (e.g., network configuration, loading kernel modules) | |
| 60 | +| `seccompProfile.type` | `RuntimeDefault` | Applies the container runtime's default seccomp profile | Restricts the system calls available to the container, reducing the kernel attack surface | |
| 61 | + |
| 62 | +## Steps |
| 63 | + |
| 64 | +### 1. Configure Tekton to add security context to init containers |
| 65 | + |
| 66 | +`Tekton` creates init containers for each `Pod` it manages. To comply with the `restricted` standard, you need to enable `Tekton` to automatically add the required security context to these init containers. |
| 67 | + |
| 68 | +#### Option A: Configure via TektonPipeline |
| 69 | + |
| 70 | +If you manage `Tekton` directly through `TektonPipeline` CR: |
| 71 | + |
| 72 | +```yaml |
| 73 | +apiVersion: operator.tekton.dev/v1alpha1 |
| 74 | +kind: TektonPipeline |
| 75 | +spec: |
| 76 | + set-security-context: true |
| 77 | +``` |
| 78 | + |
| 79 | +Apply the configuration: |
| 80 | + |
| 81 | +```bash |
| 82 | +$ kubectl patch tektonpipeline tektonpipeline \ |
| 83 | + --type merge \ |
| 84 | + -p '{"spec":{"set-security-context":true}}' |
| 85 | +
|
| 86 | +tektonpipeline.operator.tekton.dev/tektonpipeline patched |
| 87 | +``` |
| 88 | + |
| 89 | +#### Option B: Configure via TektonConfig |
| 90 | + |
| 91 | +If you manage `Tekton` through `TektonConfig` CR: |
| 92 | + |
| 93 | +```yaml |
| 94 | +apiVersion: operator.tekton.dev/v1alpha1 |
| 95 | +kind: TektonConfig |
| 96 | +spec: |
| 97 | + pipeline: |
| 98 | + set-security-context: true |
| 99 | +``` |
| 100 | + |
| 101 | +Apply the configuration: |
| 102 | + |
| 103 | +```bash |
| 104 | +$ kubectl patch tektonconfig config \ |
| 105 | + --type merge \ |
| 106 | + -p '{"spec":{"pipeline":{"set-security-context":true}}}' |
| 107 | +
|
| 108 | +tektonconfig.operator.tekton.dev/config patched |
| 109 | +``` |
| 110 | + |
| 111 | +> **Note:** This configuration change takes effect immediately without requiring a restart of the `Tekton` controller. New `TaskRuns` and `PipelineRuns` created after this change will automatically have the required security context applied to init containers. |
| 112 | + |
| 113 | +### 2. Add security context to custom Task definitions |
| 114 | + |
| 115 | +For custom `Tasks` (not the built-in `Tasks` provided by the platform), you need to explicitly add the security context to each step. |
| 116 | + |
| 117 | +Example `Task` with security context: |
| 118 | + |
| 119 | +```yaml |
| 120 | +apiVersion: tekton.dev/v1 |
| 121 | +kind: Task |
| 122 | +metadata: |
| 123 | + name: custom-build-task |
| 124 | +spec: |
| 125 | + steps: |
| 126 | + - name: build |
| 127 | + image: registry.example.com/builder:latest |
| 128 | + securityContext: |
| 129 | + allowPrivilegeEscalation: false |
| 130 | + runAsNonRoot: true |
| 131 | + capabilities: |
| 132 | + drop: |
| 133 | + - "ALL" |
| 134 | + seccompProfile: |
| 135 | + type: RuntimeDefault |
| 136 | + script: | |
| 137 | + #!/bin/sh |
| 138 | + echo "Building application..." |
| 139 | +``` |
| 140 | + |
| 141 | +> **Important:** This step applies to custom `Tasks`. Built-in `Tasks` provided by the platform (except `buildah`, see Troubleshooting section) are compatible with these security constraints, but their `Task` definitions do not include explicit `securityContext` configurations since they are designed to work in various security contexts, not just restricted mode. |
| 142 | + |
| 143 | +### 3. Configure container images to use non-root users |
| 144 | + |
| 145 | +Container images must be configured to run as a non-root user. The user must be specified using a numeric UID rather than a username. |
| 146 | + |
| 147 | +In your `Dockerfile`, add a non-root user and set it as the default. Here's an example for Alpine-based images: |
| 148 | + |
| 149 | +```dockerfile |
| 150 | +# Add a non-root user with UID 65532 (Alpine syntax) |
| 151 | +RUN adduser -u 65532 -h /home/nonroot -D nonroot |
| 152 | +
|
| 153 | +# Set appropriate permissions for working directories |
| 154 | +RUN chown -R 65532:65532 /app |
| 155 | +
|
| 156 | +# Switch to the non-root user (use numeric UID) |
| 157 | +USER 65532 |
| 158 | +``` |
| 159 | + |
| 160 | +> **Note:** The `adduser` command syntax varies by base image. See the referenced documentation below for examples with other base images. |
| 161 | + |
| 162 | +Verify the image configuration: |
| 163 | + |
| 164 | +```bash |
| 165 | +# Check that the image runs as non-root |
| 166 | +$ podman run -it --rm ${registry} id |
| 167 | +
|
| 168 | +uid=65532(nonroot) gid=65532(nonroot) groups=65532(nonroot) |
| 169 | +``` |
| 170 | + |
| 171 | +For detailed guidance on adjusting `Dockerfiles`, see [Adjust Dockerfile for Building Task-Compatible Custom Images](./adjust_dockerfile_for_task_compatible_image.mdx). |
| 172 | + |
| 173 | +## Operation Results |
| 174 | + |
| 175 | +After completing the above steps: |
| 176 | + |
| 177 | +1. **Init Containers**: `Tekton`-created init containers will automatically comply with the `restricted` standard |
| 178 | +2. **Custom Tasks**: Your custom `Task` steps will have the required security context |
| 179 | +3. **Container Images**: Images will run as non-root users with minimal privileges |
| 180 | + |
| 181 | +You can verify compliance by creating a `TaskRun` in a restricted namespace: |
| 182 | + |
| 183 | +```bash |
| 184 | +# Label a namespace with the restricted standard |
| 185 | +$ kubectl label namespace test-ns pod-security.kubernetes.io/enforce=restricted |
| 186 | +
|
| 187 | +namespace/test-ns labeled |
| 188 | +
|
| 189 | +# Create a TaskRun in the restricted namespace |
| 190 | +$ kubectl -n test-ns create -f taskrun.yaml |
| 191 | +
|
| 192 | +taskrun.tekton.dev/example-taskrun created |
| 193 | +
|
| 194 | +# Verify the TaskRun succeeds |
| 195 | +$ kubectl -n test-ns get taskrun |
| 196 | +
|
| 197 | +NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME |
| 198 | +example-taskrun True Succeeded 2m ago 1m ago |
| 199 | +``` |
| 200 | + |
| 201 | +A successful `TaskRun` shows `SUCCEEDED` as `True` and `REASON` as `Succeeded`, indicating that all containers ran successfully with the required security constraints. |
| 202 | + |
| 203 | +## Using Policy Enforcement Tools |
| 204 | + |
| 205 | +For a more automated approach, you can use policy enforcement tools like `Kyverno` to automatically inject the required security context into all containers. By creating a `Kyverno` `Policy` (using `apiVersion: kyverno.io/v1` and `kind: Policy`), you can automatically mutate `Pods` to add the necessary security context configurations. |
| 206 | + |
| 207 | +For more info please refer to <ExternalSiteLink name="acp" href="/security/security_and_compliance/compliance/howto/security_context_enforcement.html" children="Scenario 4: Specified Namespace Security Context Enforcement" />. |
| 208 | + |
| 209 | +This approach eliminates the need to manually configure security context for each `Task`, simplifying compliance management. |
| 210 | + |
| 211 | +For detailed guidance on configuring `Kyverno` policies for this purpose, refer to: |
| 212 | +- [Add Default securityContext](https://kyverno.io/policies/other/add-default-securitycontext/add-default-securitycontext/) |
| 213 | +- [Restricted Pod Security Standards](https://kyverno.io/policies/pod-security/subrule/restricted/restricted-latest/restricted-latest/) |
| 214 | + |
| 215 | +## Troubleshooting |
| 216 | + |
| 217 | +### Built-in Tasks and the Restricted Standard |
| 218 | + |
| 219 | +Among the built-in `Tasks` provided by the platform, only the `buildah` `Task` cannot run under the `restricted` standard. This is because `buildah` requires elevated privileges to build container images. |
| 220 | + |
| 221 | +The `buildah` `Task` requires the following security context: |
| 222 | + |
| 223 | +```yaml |
| 224 | +securityContext: |
| 225 | + # allowPrivilegeEscalation: false # Cannot be set to false - buildah needs to escalate privileges to use the SETFCAP capability for setting file capabilities during container image builds; forcing false also blocks newuidmap/newgidmap, causing rootless to fall back to single UID/GID mapping with warnings and potentially incorrect file ownership |
| 226 | + runAsNonRoot: true |
| 227 | + capabilities: |
| 228 | + # drop: ["ALL"] # Cannot drop ALL capabilities - buildah requires SETFCAP capability to set file capabilities (e.g., cap_net_bind_service) on files within container images during the build process |
| 229 | + add: ["SETFCAP"] |
| 230 | + # seccompProfile: |
| 231 | + # type: RuntimeDefault # Cannot use RuntimeDefault - default seccomp blocks unshare/clone(CLONE_NEWUSER)/setns needed by buildah, leading to build failure; use Unconfined or a custom profile that allows these syscalls instead |
| 232 | +``` |
| 233 | + |
| 234 | +**Solutions:** |
| 235 | + |
| 236 | +1. Use the `buildah` `Task` in a separate namespace with `baseline` mode instead of `restricted` mode (e.g., `pod-security.kubernetes.io/enforce=baseline`) |
| 237 | +2. Explore alternative container image build methods that may have different security requirements |
| 238 | + |
| 239 | +### TaskRun fails with container user errors |
| 240 | + |
| 241 | +You may encounter one of the following errors: |
| 242 | + |
| 243 | +- **"container has runAsNonRoot and image will run as root"** - The container image has no `USER` directive in the `Dockerfile` (defaults to root) or explicitly sets `USER 0` or `USER root` |
| 244 | +- **"container has runAsNonRoot and image has non-numeric user"** - The container image uses a symbolic username (e.g., `USER appuser`) instead of a numeric UID |
| 245 | + |
| 246 | +**Solutions:** |
| 247 | + |
| 248 | +1. Rebuild the image with a numeric non-root user ID as described in Step 3. For example, use `USER 65532` instead of `USER appuser` or `USER root`. |
| 249 | + |
| 250 | +2. Specify the user in the `Task` `securityContext`: |
| 251 | + |
| 252 | + ```yaml |
| 253 | + apiVersion: tekton.dev/v1 |
| 254 | + kind: Task |
| 255 | + metadata: |
| 256 | + name: example-task |
| 257 | + spec: |
| 258 | + steps: |
| 259 | + - name: step1 |
| 260 | + image: registry.example.com/myimage:latest |
| 261 | + securityContext: |
| 262 | + runAsUser: 65532 |
| 263 | + runAsNonRoot: true |
| 264 | + allowPrivilegeEscalation: false |
| 265 | + capabilities: |
| 266 | + drop: |
| 267 | + - "ALL" |
| 268 | + seccompProfile: |
| 269 | + type: RuntimeDefault |
| 270 | + script: | |
| 271 | + #!/bin/sh |
| 272 | + echo "Running as user $(id -u)" |
| 273 | + ``` |
| 274 | + |
| 275 | +3. Specify the user in the `TaskRun` `podTemplate`: |
| 276 | + |
| 277 | + ```yaml |
| 278 | + apiVersion: tekton.dev/v1 |
| 279 | + kind: TaskRun |
| 280 | + metadata: |
| 281 | + name: example-taskrun |
| 282 | + spec: |
| 283 | + taskRef: |
| 284 | + name: example-task |
| 285 | + podTemplate: |
| 286 | + securityContext: |
| 287 | + runAsUser: 65532 |
| 288 | + runAsNonRoot: true |
| 289 | + fsGroup: 65532 |
| 290 | + ``` |
| 291 | + |
| 292 | +> **Note:** The `podTemplate.securityContext` sets Pod-level security context, which is inherited by all containers unless overridden at the container level. |
| 293 | + |
| 294 | +Options 2 and 3 are useful when you cannot modify the container image. |
| 295 | + |
| 296 | +### TaskRun fails with "Forbidden: cannot set securityContext.capabilities" |
| 297 | + |
| 298 | +This error occurs when the security context tries to add capabilities while dropping all capabilities. |
| 299 | + |
| 300 | +**Solution:** Ensure your `Task` does not add any capabilities. Only drop capabilities as shown in the examples. |
| 301 | + |
| 302 | +### Init containers fail with permission errors |
| 303 | + |
| 304 | +If init containers fail with permission errors after setting `set-security-context: true`, verify that: |
| 305 | + |
| 306 | +1. The namespace has appropriate security policies |
| 307 | +2. The container images used by `Tekton` are configured to run as non-root |
| 308 | +3. The `Tekton` installation is up to date |
| 309 | + |
| 310 | +## Learn More |
| 311 | + |
| 312 | +- [Kubernetes Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) |
| 313 | +- [Tekton Pipelines Additional Configuration Options](https://tekton.dev/vault/pipelines-main/additional-configs/) |
| 314 | +- [Adjust Dockerfile for Building Task-Compatible Custom Images](./adjust_dockerfile_for_task_compatible_image.mdx) |
| 315 | +- [Kyverno Policy Engine](https://kyverno.io/) |
0 commit comments