diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1fbf53b3..4ce8d8aca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ IMPROVEMENTS: * API Gateway: Allow controller to read MeshServices for use as a route backend. [[GH-1574](https://github.com/hashicorp/consul-k8s/pull/1574)] * API Gateway: Add `tolerations` to `apiGateway.managedGatewayClass` and `apiGateway.controller` [[GH-1650](https://github.com/hashicorp/consul-k8s/pull/1650)] * API Gateway: Create PodSecurityPolicy for controller when `global.enablePodSecurityPolicies=true`. [[GH-1656](https://github.com/hashicorp/consul-k8s/pull/1656)] + * API Gateway: Create PodSecurityPolicy and allow controller to bind it to ServiceAccounts that it creates for Gateway Deployments when `global.enablePodSecurityPolicies=true`. [[GH-1672](https://github.com/hashicorp/consul-k8s/pull/1672)] ## 0.49.0 (September 30, 2022) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index f84c5561c2..eac2bd1f69 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -245,11 +245,21 @@ rules: - patch - update {{- if .Values.global.enablePodSecurityPolicies }} -- apiGroups: ["policy"] - resources: ["podsecuritypolicies"] - resourceNames: - - {{ template "consul.fullname" . }}-api-gateway-controller +- apiGroups: + - policy + resources: + - podsecuritypolicies + verbs: + - use +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings verbs: - - use + - create + - get + - list + - watch {{- end }} {{- end }} diff --git a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml index 450357a773..f2fecba47e 100644 --- a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml +++ b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml @@ -15,6 +15,9 @@ spec: {{- if .Values.global.acls.manageSystemACLs }} managed: true method: {{ template "consul.fullname" . }}-k8s-auth-method + {{- if .Values.global.enablePodSecurityPolicies }} + podSecurityPolicy: {{ template "consul.fullname" . }}-api-gateway + {{- end }} {{- end }} {{- if .Values.global.tls.enabled }} scheme: https diff --git a/charts/consul/templates/api-gateway-podsecuritypolicy.yaml b/charts/consul/templates/api-gateway-podsecuritypolicy.yaml new file mode 100644 index 0000000000..48f826f995 --- /dev/null +++ b/charts/consul/templates/api-gateway-podsecuritypolicy.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.apiGateway.enabled .Values.global.enablePodSecurityPolicies }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "consul.fullname" . }}-api-gateway + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: api-gateway-controller +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + # This is redundant with non-root + disallow privilege escalation, + # but we can provide it for defense in depth. + requiredDropCapabilities: + - ALL + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + allowedCapabilities: + - NET_BIND_SERVICE + hostNetwork: false + hostIPC: false + hostPID: false + hostPorts: + - max: 65535 + min: 1025 + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: true +{{- end }} diff --git a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats index b69b6ac966..f26fdfeebd 100644 --- a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats +++ b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats @@ -20,7 +20,7 @@ load _helpers [ "${actual}" = "true" ] } -@test "apiGateway/ClusterRole: uses PodSecurityPolicy with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { +@test "apiGateway/ClusterRole: can use podsecuritypolicies with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { cd `chart_dir` local actual=$(helm template \ -s templates/api-gateway-controller-clusterrole.yaml \ @@ -28,6 +28,18 @@ load _helpers --set 'apiGateway.enabled=true' \ --set 'apiGateway.image=foo' \ . | tee /dev/stderr | - yq '.rules[] | select((.resourceNames[0] == "release-name-consul-api-gateway-controller") and (.resources[0] == "podsecuritypolicies")) | length > 0' | tee /dev/stderr) + yq '.rules[] | select((.resources[0] == "podsecuritypolicies") and (.verbs[0] == "use")) | length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "apiGateway/ClusterRole: can create roles and rolebindings with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-clusterrole.yaml \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + . | tee /dev/stderr | + yq '.rules[] | select((.resources[0] == "roles") and (.resources[1] == "rolebindings") and (.verbs | contains(["create","get","list","watch"]))) | length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] }