diff --git a/Makefile b/Makefile
index 6c38f130b3..9ddf378b42 100644
--- a/Makefile
+++ b/Makefile
@@ -1079,6 +1079,7 @@ kind/test: kind/cluster helm/repos $(addprefix local-dev/,$(KIND_TOOLS)) $(addpr
SKIP_INSTALL_REGISTRY=true \
LAGOON_FEATURE_FLAG_DEFAULT_ISOLATION_NETWORK_POLICY=enabled \
USE_CALICO_CNI=true \
+ LAGOON_FEATURE_FLAG_DEFAULT_ROOTLESS_WORKLOAD=enabled \
&& docker run --rm --network host --name ct-$(CI_BUILD_TAG) \
--volume "$$(pwd)/test-suite-run.ct.yaml:/etc/ct/ct.yaml" \
--volume "$$(pwd):/workdir" \
@@ -1202,6 +1203,7 @@ kind/retest:
SKIP_ALL_DEPS=true \
LAGOON_FEATURE_FLAG_DEFAULT_ISOLATION_NETWORK_POLICY=enabled \
USE_CALICO_CNI=true \
+ LAGOON_FEATURE_FLAG_DEFAULT_ROOTLESS_WORKLOAD=enabled \
&& docker run --rm --network host --name ct-$(CI_BUILD_TAG) \
--volume "$$(pwd)/test-suite-run.ct.yaml:/etc/ct/ct.yaml" \
--volume "$$(pwd):/workdir" \
diff --git a/docs/administering-lagoon/feature-flags.md b/docs/administering-lagoon/feature-flags.md
index 594d02142d..c6414f8aab 100644
--- a/docs/administering-lagoon/feature-flags.md
+++ b/docs/administering-lagoon/feature-flags.md
@@ -7,12 +7,10 @@ This is designed to assist users and administrators to roll out new platform fea
The following environment variables can be set on an environment or project to toggle feature flags.
-| Environment Variable Name | Active scope\* | Version introduced | Version removed | Default Value | Description |
-| --- | --- | --- | --- | --- | --- |
-| `LAGOON_FEATURE_FLAG_ROOTLESS_WORKLOAD` | `global` | 2.2.0 | - | `disabled` | Set to `enabled` to set a non-root pod security context on the pods in this environment or project.
This flag will eventually be deprecated, at which point non-root workloads will be enforced. |
-| `LAGOON_FEATURE_FLAG_ISOLATION_NETWORK_POLICY` | `global` | 2.2.0 | - | `disabled` | Set to `enabled` to add a default namespace isolation network policy to each environment on deployment.
This flag will eventually be deprecated, at which point the namespace isolation network policy will be enforced.
NOTE: enabling and then disabling this feature will _not_ remove any existing network policy from previous deployments. Those must be removed manually. |
-
-\* Active scope indicates whether the variable must be set as `build` or `runtime` scope to take effect. `global` sets the variable in both scopes, so that will work too.
+| Environment Variable Name | Active scope | Version introduced | Version removed | Default Value | Description |
+| --- | --- | --- | --- | --- | --- |
+| `LAGOON_FEATURE_FLAG_ROOTLESS_WORKLOAD` | `global` | 2.2.0 | - | `disabled` | Set to `enabled` to set a non-root pod security context on the pods in this environment or project.
This flag will eventually be deprecated, at which point non-root workloads will be enforced. |
+| `LAGOON_FEATURE_FLAG_ISOLATION_NETWORK_POLICY` | `global` | 2.2.0 | - | `disabled` | Set to `enabled` to add a default namespace isolation network policy to each environment on deployment.
This flag will eventually be deprecated, at which point the namespace isolation network policy will be enforced.
NOTE: enabling and then disabling this feature will _not_ remove any existing network policy from previous deployments. Those must be removed manually. |
## Cluster-level controls
diff --git a/images/kubectl-build-deploy-dind/Dockerfile b/images/kubectl-build-deploy-dind/Dockerfile
index 5e2e936240..a487756f75 100644
--- a/images/kubectl-build-deploy-dind/Dockerfile
+++ b/images/kubectl-build-deploy-dind/Dockerfile
@@ -13,6 +13,7 @@ WORKDIR /kubectl-build-deploy/git
COPY docker-entrypoint.sh /lagoon/entrypoints/100-docker-entrypoint.sh
COPY build-deploy.sh /kubectl-build-deploy/build-deploy.sh
COPY build-deploy-docker-compose.sh /kubectl-build-deploy/build-deploy-docker-compose.sh
+COPY rootless.values.yaml /kubectl-build-deploy/rootless.values.yaml
COPY scripts /kubectl-build-deploy/scripts
diff --git a/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh b/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh
index a041481802..4f695d4269 100755
--- a/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh
+++ b/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh
@@ -29,22 +29,23 @@ function contains() {
# and order:
#
# 1. The cluster-force feature flag, prefixed with LAGOON_FEATURE_FLAG_FORCE_,
-# in the build environment. This is set via a flag on the build-deploy
-# controller. This overrides the other variables and allows policy
-# enforcement at the cluster level.
+# as a build pod environment variable. This is set via a flag on the
+# build-deploy controller. This overrides the other variables and allows
+# policy enforcement at the cluster level.
#
# 2. The regular feature flag, prefixed with LAGOON_FEATURE_FLAG_, in the
-# Lagoon environment env-vars. This allows policy control at the environment
-# level.
+# Lagoon environment global scoped env-vars. This allows policy control at
+# the environment level.
#
# 3. The regular feature flag, prefixed with LAGOON_FEATURE_FLAG_, in the
-# Lagoon project env-vars. This allows policy control at the project level.
+# Lagoon project global scoped env-vars. This allows policy control at the
+# project level.
#
# 4. The cluster-default feature flag, prefixed with
-# LAGOON_FEATURE_FLAG_DEFAULT_, in the build environment. This is set via a
-# flag on the build-deploy controller. This allows default policy to be set
-# at the cluster level, but maintains the ability to selectively override at
-# the project or environment level.
+# LAGOON_FEATURE_FLAG_DEFAULT_, as a build pod environment variable. This is
+# set via a flag on the build-deploy controller. This allows default policy
+# to be set at the cluster level, but maintains the ability to selectively
+# override at the project or environment level.
#
# The value of the first variable found is printed to stdout. If the variable
# is not found, print an empty string. Additional arguments are ignored.
@@ -54,16 +55,16 @@ function featureFlag() {
local forceFlagVar defaultFlagVar flagVar
- # check build environment for the force policy first
+ # check build pod environment for the force policy first
forceFlagVar="LAGOON_FEATURE_FLAG_FORCE_$1"
[ "${!forceFlagVar}" ] && echo "${!forceFlagVar}" && return
flagVar="LAGOON_FEATURE_FLAG_$1"
# check Lagoon environment variables
- flagValue=$(jq -r '.[] | select((.scope as $scope | ["build", "global"] | index($scope)) and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_ENVIRONMENT_VARIABLES")
+ flagValue=$(jq -r '.[] | select(.scope == "global" and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_ENVIRONMENT_VARIABLES")
[ "$flagValue" ] && echo "$flagValue" && return
# check Lagoon project variables
- flagValue=$(jq -r '.[] | select((.scope as $scope | ["build", "global"] | index($scope)) and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_PROJECT_VARIABLES")
+ flagValue=$(jq -r '.[] | select(.scope == "global" and .name == "'"$flagVar"'") | .value' <<<"$LAGOON_PROJECT_VARIABLES")
[ "$flagValue" ] && echo "$flagValue" && return
# fall back to the default, if set.
@@ -610,6 +611,10 @@ yq write -i -- /kubectl-build-deploy/values.yaml 'routesAutogenerateShortSuffix'
for i in $ROUTES_AUTOGENERATE_PREFIXES; do yq write -i -- /kubectl-build-deploy/values.yaml 'routesAutogeneratePrefixes[+]' $i; done
yq write -i -- /kubectl-build-deploy/values.yaml 'kubernetes' $KUBERNETES
yq write -i -- /kubectl-build-deploy/values.yaml 'lagoonVersion' $LAGOON_VERSION
+# check for ROOTLESS_WORKLOAD feature flag, disabled by default
+if [ "$(featureFlag ROOTLESS_WORKLOAD)" = enabled ]; then
+ yq merge -ix -- /kubectl-build-deploy/values.yaml /kubectl-build-deploy/rootless.values.yaml
+fi
echo -e "\
diff --git a/images/kubectl-build-deploy-dind/helmcharts/kibana/templates/cronjob.yaml b/images/kubectl-build-deploy-dind/helmcharts/kibana/templates/cronjob.yaml
index b44c41de2b..78c810b63a 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/kibana/templates/cronjob.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/kibana/templates/cronjob.yaml
@@ -1,4 +1,5 @@
{{- range $cronjobName, $cronjobConfig := .Values.nativeCronjobs }}
+---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/cronjob.yaml b/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/cronjob.yaml
index 2429c9b116..c536545d9e 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/cronjob.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/cronjob.yaml
@@ -35,7 +35,7 @@ spec:
priorityClassName: {{ include "mariadb-single.lagoonPriority" $ }}
enableServiceLinks: false
securityContext:
- {{- toYaml $.Values.podSecurityContext | nindent 12 }}
+ {{- toYaml .Values.podSecurityContext | nindent 12 }}
volumes:
- name: {{ include "mariadb-single.fullname" $ }}
persistentVolumeClaim:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/deployment.yaml b/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/deployment.yaml
index 0943a6edfa..d287b965de 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/deployment.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/mariadb-single/templates/deployment.yaml
@@ -35,6 +35,8 @@ spec:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/cronjob.yaml b/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/cronjob.yaml
index 8859436802..efe91281ef 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/cronjob.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/cronjob.yaml
@@ -35,7 +35,7 @@ spec:
priorityClassName: {{ include "mongodb-single.lagoonPriority" $ }}
enableServiceLinks: false
securityContext:
- {{- toYaml $.Values.podSecurityContext | nindent 12 }}
+ {{- toYaml .Values.podSecurityContext | nindent 12 }}
volumes:
- name: {{ include "mongodb-single.fullname" $ }}
persistentVolumeClaim:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/deployment.yaml b/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/deployment.yaml
index 105523ad4c..f2f5689d0d 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/deployment.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/mongodb-single/templates/deployment.yaml
@@ -35,6 +35,8 @@ spec:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/nginx-php-persistent/templates/deployment.yaml b/images/kubectl-build-deploy-dind/helmcharts/nginx-php-persistent/templates/deployment.yaml
index 7405c91f7e..84ba73b949 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/nginx-php-persistent/templates/deployment.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/nginx-php-persistent/templates/deployment.yaml
@@ -34,6 +34,32 @@ spec:
enableServiceLinks: false
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
+ {{/* This is a test for "rootless" configuration. It will be true if the ROOTLESS_WORKLOAD feature flag is enabled. */}}
+ {{- if eq (int .Values.podSecurityContext.fsGroup) 10001 }}
+ # This initContainer sets permissions on the RWX storage compatible with
+ # the pod securityContext.
+ initContainers:
+ - command:
+ - "sh"
+ - "-c"
+ - |
+ set -e
+ SENTINEL="/storage/.lagoon-rootless-migration-complete"
+ if ! [ -f "$SENTINEL" ]; then
+ find /storage -mindepth 1 -exec chgrp $(stat -c "%g" /storage) {} +
+ find /storage -mindepth 1 -exec chmod g+rw {} +
+ find /storage -mindepth 1 -type d -exec chmod g+x {} +
+ fi
+ touch "$SENTINEL"
+ image: busybox:musl
+ imagePullPolicy: IfNotPresent
+ name: fix-storage-permissions
+ securityContext:
+ runAsUser: 0
+ volumeMounts:
+ - mountPath: /storage
+ name: {{ include "nginx-php-persistent.persistentStorageName" . }}
+ {{- end }}
containers:
- image: {{ .Values.images.nginx | quote }}
name: "nginx"
diff --git a/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/cronjob.yaml b/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/cronjob.yaml
index 2baf28c650..9060ea6d04 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/cronjob.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/cronjob.yaml
@@ -35,7 +35,7 @@ spec:
priorityClassName: {{ include "postgres-single.lagoonPriority" $ }}
enableServiceLinks: false
securityContext:
- {{- toYaml $.Values.podSecurityContext | nindent 12 }}
+ {{- toYaml .Values.podSecurityContext | nindent 12 }}
volumes:
- name: {{ include "postgres-single.fullname" $ }}
persistentVolumeClaim:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/deployment.yaml b/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/deployment.yaml
index c40b7c550a..7fab45e573 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/deployment.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/postgres-single/templates/deployment.yaml
@@ -35,6 +35,8 @@ spec:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
diff --git a/images/kubectl-build-deploy-dind/helmcharts/solr/templates/cronjob.yaml b/images/kubectl-build-deploy-dind/helmcharts/solr/templates/cronjob.yaml
index f68d583f2f..1ff5362c79 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/solr/templates/cronjob.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/solr/templates/cronjob.yaml
@@ -35,7 +35,7 @@ spec:
priorityClassName: {{ include "solr.lagoonPriority" $ }}
enableServiceLinks: false
securityContext:
- {{- toYaml $.Values.podSecurityContext | nindent 12 }}
+ {{- toYaml .Values.podSecurityContext | nindent 12 }}
containers:
- image: {{ $.Values.image | quote }}
name: cronjob-{{ $.Release.Name }}-{{ $cronjobName }}
diff --git a/images/kubectl-build-deploy-dind/helmcharts/solr/templates/deployment.yaml b/images/kubectl-build-deploy-dind/helmcharts/solr/templates/deployment.yaml
index 8a73f7eda0..2cb574f5aa 100644
--- a/images/kubectl-build-deploy-dind/helmcharts/solr/templates/deployment.yaml
+++ b/images/kubectl-build-deploy-dind/helmcharts/solr/templates/deployment.yaml
@@ -38,6 +38,8 @@ spec:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- image: {{ .Values.image | quote }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
name: {{ .Chart.Name }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
ports:
diff --git a/images/kubectl-build-deploy-dind/rootless.values.yaml b/images/kubectl-build-deploy-dind/rootless.values.yaml
new file mode 100644
index 0000000000..c7bba35fb4
--- /dev/null
+++ b/images/kubectl-build-deploy-dind/rootless.values.yaml
@@ -0,0 +1,6 @@
+# This is used in build-deploy-docker-compose.sh to specify the rootless
+# podSecurityContext for Lagoon helmcharts.
+podSecurityContext:
+ fsGroup: 10001
+ runAsGroup: 0
+ runAsUser: 10000