Skip to content

Commit 799eebb

Browse files
author
Jonathan Yu
authored
feat: add container security context settings (#183)
* Apply security context settings to containers as well as pod, so that users can safely override the pod security context without losing security of container security context (useful when using sidecar containers with different privileges) * Add a default runAsGroup set to gid 1000 * Remove custom security context values data types in favor of built-in Kubernetes types
1 parent e87fe09 commit 799eebb

File tree

5 files changed

+33
-33
lines changed

5 files changed

+33
-33
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,30 @@ View [our docs](https://coder.com/docs/setup/installation) for detailed installa
2525
| certs | object | Certificate that will be mounted inside Coder services. | `{"secret":{"key":"","name":""}}` |
2626
| certs.secret.key | string | Key pointing to a certificate in the secret. | `""` |
2727
| certs.secret.name | string | Name of the secret. | `""` |
28-
| coderd | object | Primary service responsible for all things Coder! | `{"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"In","values":["coderd"]}]},"topologyKey":"kubernetes.io/hostname"},"weight":1}]}},"builtinProviderServiceAccount":{"annotations":{},"labels":{}},"devurlsHost":"","image":"","oidc":{"enableRefresh":false,"redirectOptions":{}},"podSecurityContext":{"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}},"replicas":1,"resources":{"limits":{"cpu":"250m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"512Mi"}},"satellite":{"accessURL":"","enable":false,"primaryURL":""},"securityContext":{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}},"serviceAnnotations":{},"serviceNodePorts":{"http":null,"https":null},"serviceSpec":{"externalTrafficPolicy":"Local","loadBalancerIP":"","loadBalancerSourceRanges":[],"type":"LoadBalancer"},"superAdmin":{"passwordSecret":{"key":"password","name":""}},"tls":{"devurlsHostSecretName":"","hostSecretName":""},"trustProxyIP":false}` |
28+
| coderd | object | Primary service responsible for all things Coder! | `{"affinity":{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"In","values":["coderd"]}]},"topologyKey":"kubernetes.io/hostname"},"weight":1}]}},"builtinProviderServiceAccount":{"annotations":{},"labels":{}},"devurlsHost":"","image":"","oidc":{"enableRefresh":false,"redirectOptions":{}},"podSecurityContext":{"runAsGroup":1000,"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}},"replicas":1,"resources":{"limits":{"cpu":"250m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"512Mi"}},"satellite":{"accessURL":"","enable":false,"primaryURL":""},"securityContext":{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"runAsGroup":1000,"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}},"serviceAnnotations":{},"serviceNodePorts":{"http":null,"https":null},"serviceSpec":{"externalTrafficPolicy":"Local","loadBalancerIP":"","loadBalancerSourceRanges":[],"type":"LoadBalancer"},"superAdmin":{"passwordSecret":{"key":"password","name":""}},"tls":{"devurlsHostSecretName":"","hostSecretName":""},"trustProxyIP":false}` |
2929
| coderd.affinity | object | Allows specifying an affinity rule for the `coderd` deployment. The default rule prefers to schedule coderd pods on different nodes, which is only applicable if coderd.replicas is greater than 1. | `{"podAntiAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"In","values":["coderd"]}]},"topologyKey":"kubernetes.io/hostname"},"weight":1}]}}` |
3030
| coderd.builtinProviderServiceAccount | object | Customize the built-in Kubernetes provider service account. | `{"annotations":{},"labels":{}}` |
3131
| coderd.builtinProviderServiceAccount.annotations | object | A KV mapping of annotations. See: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ | `{}` |
3232
| coderd.builtinProviderServiceAccount.labels | object | Add labels to the service account used for the built-in provider. | `{}` |
3333
| coderd.devurlsHost | string | Wildcard hostname to allow matching against custom-created dev URLs. Leaving as an empty string results in DevURLs being disabled. | `""` |
3434
| coderd.image | string | Injected by Coder during release. | `""` |
35-
| coderd.podSecurityContext | object | Fields related to the pod's security context (as opposed to the container). Some fields are also present in the container security context, which will take precedence over these values. | `{"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}}` |
36-
| coderd.podSecurityContext.runAsNonRoot | bool | Requires that containers in the pod run as a non-privileged user. | `true` |
37-
| coderd.podSecurityContext.runAsUser | int | Sets the user id of the pod. This must not be set to root (uid 0). | `1000` |
35+
| coderd.podSecurityContext | object | Fields related to the pod's security context (as opposed to the container). Some fields are also present in the container security context, which will take precedence over these values. | `{"runAsGroup":1000,"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}}` |
36+
| coderd.podSecurityContext.runAsGroup | int | Sets the group id of the pod. For security reasons, we recommend using a non-root group. | `1000` |
37+
| coderd.podSecurityContext.runAsNonRoot | bool | Requires that containers in the pod run as an unprivileged user. If setting runAsUser to 0 (root), this will need to be set to false. | `true` |
38+
| coderd.podSecurityContext.runAsUser | int | Sets the user id of the pod. For security reasons, we recommend using a non-root user. | `1000` |
3839
| coderd.podSecurityContext.seccompProfile | object | Sets the seccomp profile for the pod. If set, the container security context setting will take precedence over this value. | `{"type":"RuntimeDefault"}` |
3940
| coderd.replicas | int | The number of Kubernetes Pod replicas. | `1` |
4041
| coderd.resources | object | Kubernetes resource specification for coderd pods. To unset a value, set it to "". To unset all values, set resources to nil. | `{"limits":{"cpu":"250m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"512Mi"}}` |
4142
| coderd.satellite | object | Deploy a satellite to geodistribute access to workspaces for lower latency. | `{"accessURL":"","enable":false,"primaryURL":""}` |
4243
| coderd.satellite.accessURL | string | URL of the satellite that clients will connect to. e.g. https://sydney.coder.myorg.com | `""` |
4344
| coderd.satellite.enable | bool | Run coderd as a satellite pointing to a primary deployment. Satellite enable low-latency access to workspaces all over the world. Read more: TODO: Link to docs. | `false` |
4445
| coderd.satellite.primaryURL | string | URL of the primary Coder deployment. Must be accessible from the satellite and clients. eg. https://coder.myorg.com | `""` |
45-
| coderd.securityContext | object | Fields related to the container's security context (as opposed to the pod). Some fields are also present in the pod security context, in which case these values will take precedence. | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"seccompProfile":{"type":"RuntimeDefault"}}` |
46+
| coderd.securityContext | object | Fields related to the container's security context (as opposed to the pod). Some fields are also present in the pod security context, in which case these values will take precedence. | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"runAsGroup":1000,"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}}` |
4647
| coderd.securityContext.allowPrivilegeEscalation | bool | Controls whether the container can gain additional privileges, such as escalating to root. It is recommended to leave this setting disabled in production. | `false` |
4748
| coderd.securityContext.readOnlyRootFilesystem | bool | Mounts the container's root filesystem as read-only. It is recommended to leave this setting enabled in production. This will override the same setting in the pod | `true` |
49+
| coderd.securityContext.runAsGroup | int | Sets the group id of the pod. For security reasons, we recommend using a non-root group. | `1000` |
50+
| coderd.securityContext.runAsNonRoot | bool | Requires that the coderd and migrations containers run as an unprivileged user. If setting runAsUser to 0 (root), this will need to be set to false. | `true` |
51+
| coderd.securityContext.runAsUser | int | Sets the user id of the pod. For security reasons, we recommend using a non-root user. | `1000` |
4852
| coderd.securityContext.seccompProfile | object | Sets the seccomp profile for the migration and runtime containers. | `{"type":"RuntimeDefault"}` |
4953
| coderd.serviceAnnotations | object | Extra annotations to apply to the coderd service. | `{}` |
5054
| coderd.serviceNodePorts | object | Allows manually setting static node ports for the coderd service. This is only helpful if static ports are required, and usually should be left alone. By default these are dynamically chosen. | `{"http":null,"https":null}` |

examples/kind/kind.values.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,6 @@ coderd:
44
# Avoid provisioning a LoadBalancer
55
type: ClusterIP
66

7-
# Set the container security context (by default, this inherits
8-
# the settings from the pod security context)
9-
securityContext:
10-
runAsNonRoot: true
11-
runAsUser: 1000
12-
runAsGroup: 1000
13-
147
# Reduce resource requirements for deployments using kind, which
158
# we typically use for development and test purposes only.
169
resources:

tests/examples_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func TestExamples(t *testing.T) {
4646
ContainerSecurityContext: &corev1.SecurityContext{
4747
RunAsUser: nil,
4848
RunAsGroup: nil,
49-
RunAsNonRoot: nil,
49+
RunAsNonRoot: pointer.Bool(true),
5050
Capabilities: nil,
5151
Privileged: nil,
5252
SELinuxOptions: nil,
@@ -62,6 +62,7 @@ func TestExamples(t *testing.T) {
6262
Values: exampleKind,
6363
PodSecurityContext: &corev1.PodSecurityContext{
6464
RunAsUser: pointer.Int64(1000),
65+
RunAsGroup: pointer.Int64(1000),
6566
RunAsNonRoot: pointer.Bool(true),
6667
SeccompProfile: &corev1.SeccompProfile{
6768
Type: corev1.SeccompProfileTypeRuntimeDefault,
@@ -89,13 +90,17 @@ func TestExamples(t *testing.T) {
8990
var (
9091
defaultPsp = &corev1.PodSecurityContext{
9192
RunAsUser: pointer.Int64(1000),
93+
RunAsGroup: pointer.Int64(1000),
9294
RunAsNonRoot: pointer.Bool(true),
9395
SeccompProfile: &corev1.SeccompProfile{
9496
Type: corev1.SeccompProfileTypeRuntimeDefault,
9597
},
9698
}
9799

98100
defaultCsc = &corev1.SecurityContext{
101+
RunAsUser: pointer.Int64(1000),
102+
RunAsGroup: pointer.Int64(1000),
103+
RunAsNonRoot: pointer.Bool(true),
99104
ReadOnlyRootFilesystem: pointer.Bool(true),
100105
AllowPrivilegeEscalation: pointer.Bool(false),
101106
SeccompProfile: &corev1.SeccompProfile{

tests/values.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ type CoderdValues struct {
8282
DevURLsHost *string `json:"devurlsHost" yaml:"devurlsHost"`
8383
TLS *CoderdTLSValues `json:"tls" yaml:"tls"`
8484
Satellite *CoderdSatelliteValues `json:"satellite" yaml:"satellite"`
85-
PodSecurityContext *CoderdPodSecurityContextValues `json:"podSecurityContext" yaml:"podSecurityContext"`
86-
SecurityContext *CoderdSecurityContextValues `json:"securityContext" yaml:"securityContext"`
85+
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext" yaml:"podSecurityContext"`
86+
SecurityContext *corev1.SecurityContext `json:"securityContext" yaml:"securityContext"`
8787
Resources *corev1.ResourceRequirements `json:"resources" yaml:"resources"`
8888
BuiltinProviderServiceAccount *CoderdBuiltinProviderServiceAccountValues `json:"builtinProviderServiceAccount" yaml:"builtinProviderServiceAccount"`
8989
OIDC *CoderdOIDCValues `json:"oidc" yaml:"oidc"`
@@ -147,22 +147,6 @@ type CoderdServiceSpecValues struct {
147147
LoadBalancerSourceRanges *[]string `json:"loadBalancerSourceRanges" yaml:"loadBalancerSourceRanges"`
148148
}
149149

150-
// CoderdPodSecurityContextValues reflect values from
151-
// coderd.podSecurityContext.
152-
type CoderdPodSecurityContextValues struct {
153-
RunAsNonRoot *bool `json:"runAsNonRoot" yaml:"runAsNonRoot"`
154-
RunAsUser *int `json:"runAsUser" yaml:"runAsUser"`
155-
SeccompProfile *corev1.SeccompProfile `json:"seccompProfile" yaml:"seccompProfile"`
156-
}
157-
158-
// CoderdSecurityContextValues reflect values from
159-
// coderd.securityContext.
160-
type CoderdSecurityContextValues struct {
161-
ReadOnlyRootFilesystem *bool `json:"readOnlyRootFilesystem" yaml:"readOnlyRootFilesystem"`
162-
AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation" yaml:"allowPrivilegeEscalation"`
163-
SeccompProfile *corev1.SeccompProfile `json:"seccompProfile" yaml:"seccompProfile"`
164-
}
165-
166150
// EnvboxValues reflect values from envbox.
167151
type EnvboxValues struct {
168152
Image *string `json:"image" yaml:"image"`

values.yaml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,15 @@ coderd:
7676
# container security context, which will take precedence over these values.
7777
podSecurityContext:
7878
# coderd.podSecurityContext.runAsNonRoot -- Requires that containers in
79-
# the pod run as a non-privileged user.
79+
# the pod run as an unprivileged user. If setting runAsUser to 0 (root),
80+
# this will need to be set to false.
8081
runAsNonRoot: true
8182
# coderd.podSecurityContext.runAsUser -- Sets the user id of the pod.
82-
# This must not be set to root (uid 0).
83+
# For security reasons, we recommend using a non-root user.
8384
runAsUser: 1000
85+
# coderd.podSecurityContext.runAsGroup -- Sets the group id of the pod.
86+
# For security reasons, we recommend using a non-root group.
87+
runAsGroup: 1000
8488
# coderd.podSecurityContext.seccompProfile -- Sets the seccomp profile
8589
# for the pod. If set, the container security context setting will take
8690
# precedence over this value.
@@ -91,6 +95,16 @@ coderd:
9195
# context (as opposed to the pod). Some fields are also present in the pod
9296
# security context, in which case these values will take precedence.
9397
securityContext:
98+
# coderd.securityContext.runAsNonRoot -- Requires that the coderd and
99+
# migrations containers run as an unprivileged user. If setting
100+
# runAsUser to 0 (root), this will need to be set to false.
101+
runAsNonRoot: true
102+
# coderd.securityContext.runAsUser -- Sets the user id of the pod.
103+
# For security reasons, we recommend using a non-root user.
104+
runAsUser: 1000
105+
# coderd.securityContext.runAsGroup -- Sets the group id of the pod.
106+
# For security reasons, we recommend using a non-root group.
107+
runAsGroup: 1000
94108
# coderd.securityContext.readOnlyRootFilesystem -- Mounts the container's
95109
# root filesystem as read-only. It is recommended to leave this setting
96110
# enabled in production. This will override the same setting in the pod

0 commit comments

Comments
 (0)