diff --git a/charts/pega/README.md b/charts/pega/README.md index 71fb2d6e1..2997e298e 100644 --- a/charts/pega/README.md +++ b/charts/pega/README.md @@ -308,7 +308,7 @@ requestor: ### Security context By default, security context for your Pega pod deployments `pegasystems/pega` image uses `pegauser`(9001) as the user and volume mounts uses `root`(0) as the group. To configure an alternative user for your custom image, set value for `runAsUser` and to configure an alternative group for volume mounts, set value for `fsGroup`. Note that pegasystems/pega image works only with pegauser(9001). -`runAsUser` and `fsGroup` must be configured in `securityContext` under each tier block and will be applied to Deployments/Statefulsets, see the [Kubernetes Documentation](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +`runAsUser` and `fsGroup` must be configured in `securityContext` under each tier block and will be applied to Deployments/Statefulsets, along with these settings other allowed configuration can also be supplied here, see the [Kubernetes Documentation](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). Example: diff --git a/charts/pega/charts/hazelcast/templates/clustering-service-deployment.yaml b/charts/pega/charts/hazelcast/templates/clustering-service-deployment.yaml index 289ba7db1..789dfbeb3 100644 --- a/charts/pega/charts/hazelcast/templates/clustering-service-deployment.yaml +++ b/charts/pega/charts/hazelcast/templates/clustering-service-deployment.yaml @@ -22,6 +22,10 @@ spec: {{- include "generatedClusteringServicePodAnnotations" . | indent 8 }} spec: terminationGracePeriodSeconds: {{ .Values.server.graceful_shutdown_max_wait_seconds }} +{{- if .Values.securityContext }} + securityContext: +{{ toYaml .Values.securityContext | indent 8 }} +{{- end }} containers: - name: hazelcast image: {{ .Values.clusteringServiceImage }} diff --git a/charts/pega/charts/hazelcast/values.yaml b/charts/pega/charts/hazelcast/values.yaml index f7d7cad8e..a130095cb 100644 --- a/charts/pega/charts/hazelcast/values.yaml +++ b/charts/pega/charts/hazelcast/values.yaml @@ -58,3 +58,7 @@ server: diagnostics_metric_level: "info" diagnostic_log_file_size_mb: "50" diagnostics_file_count: "3" + +# Apply securityContext to clustering service pods. For example to set `runAsUser: 1000`: +# securityContext: +# runAsUser: 1000 diff --git a/charts/pega/templates/_pega-deployment.tpl b/charts/pega/templates/_pega-deployment.tpl index a14e212f5..a43ca4d89 100644 --- a/charts/pega/templates/_pega-deployment.tpl +++ b/charts/pega/templates/_pega-deployment.tpl @@ -112,23 +112,13 @@ spec: nodeSelector: {{ toYaml .node.nodeSelector | indent 8 }} {{- end }} -{{- if (ne .root.Values.global.provider "openshift") }} securityContext: -{{- if .node.securityContext }} -{{- if .node.securityContext.runAsUser }} - runAsUser: {{ .node.securityContext.runAsUser }} -{{- else }} - runAsUser: 9001 -{{- end }} -{{- if .node.securityContext.fsGroup }} - fsGroup: {{ .node.securityContext.fsGroup }} -{{- else }} - fsGroup: 0 -{{- end }} -{{- else }} +{{- if (ne .root.Values.global.provider "openshift") }} runAsUser: 9001 fsGroup: 0 {{- end }} +{{- if .node.securityContext }} +{{ toYaml .node.securityContext | indent 8 }} {{- end }} {{- if .node.topologySpreadConstraints }} topologySpreadConstraints: diff --git a/terratest/src/test/pega/clustering-service-deployment_test.go b/terratest/src/test/pega/clustering-service-deployment_test.go index fcb8930ca..5d772a92a 100644 --- a/terratest/src/test/pega/clustering-service-deployment_test.go +++ b/terratest/src/test/pega/clustering-service-deployment_test.go @@ -2,13 +2,14 @@ package pega import ( "fmt" + "path/filepath" + "strings" + "testing" + "github.com/gruntwork-io/terratest/modules/helm" "github.com/stretchr/testify/require" appsv1beta2 "k8s.io/api/apps/v1beta2" "k8s.io/apimachinery/pkg/util/intstr" - "path/filepath" - "strings" - "testing" ) func TestClusteringServiceDeployment(t *testing.T) { @@ -64,3 +65,36 @@ func VerifyClusteringServiceDeployment(t *testing.T, yamlContent string) { } } } + +func TestClusteringServiceDeploymentSecurityContext(t *testing.T) { + var supportedVendors = []string{"k8s", "openshift", "eks", "gke", "aks", "pks"} + var supportedOperations = []string{"deploy", "install-deploy"} + + helmChartPath, err := filepath.Abs(PegaHelmChartPath) + require.NoError(t, err) + + for _, vendor := range supportedVendors { + + for _, operation := range supportedOperations { + + fmt.Println(vendor + "-" + operation) + + var options = &helm.Options{ + SetValues: map[string]string{ + "global.provider": vendor, + "global.actions.execute": operation, + "hazelcast.clusteringServiceEnabled": "true", + "hazelcast.securityContext.runAsUser": "1000", + }, + } + + yamlContent := RenderTemplate(t, options, helmChartPath, []string{"charts/hazelcast/templates/clustering-service-deployment.yaml"}) + yamlSplit := strings.Split(yamlContent, "---") + var statefulsetObj appsv1beta2.StatefulSet + UnmarshalK8SYaml(t, yamlSplit[1], &statefulsetObj) + + require.Equal(t, int64(1000), *statefulsetObj.Spec.Template.Spec.SecurityContext.RunAsUser) + + } + } +} diff --git a/terratest/src/test/pega/pega-tier-deployment_security_context_test.go b/terratest/src/test/pega/pega-tier-deployment_security_context_test.go new file mode 100644 index 000000000..65c16f430 --- /dev/null +++ b/terratest/src/test/pega/pega-tier-deployment_security_context_test.go @@ -0,0 +1,147 @@ +package pega + +import ( + "fmt" + "path/filepath" + "strings" + "testing" + + "github.com/gruntwork-io/terratest/modules/helm" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" +) + +func TestPegaTierDeploymentSecurityContextDefaults(t *testing.T) { + var supportedVendors = []string{"k8s", "openshift", "eks", "gke", "aks", "pks"} + var supportedOperations = []string{"deploy"} + var deploymentNames = []string{"myapp-dev"} + + helmChartPath, err := filepath.Abs(PegaHelmChartPath) + require.NoError(t, err) + + for _, vendor := range supportedVendors { + + var depObj appsv1.Deployment + + for _, operation := range supportedOperations { + + for _, depName := range deploymentNames { + + fmt.Println(vendor + "-" + operation) + + var options = &helm.Options{ + SetValues: map[string]string{ + "global.provider": vendor, + "global.actions.execute": operation, + "global.deployment.name": depName, + }, + } + + yamlContent := RenderTemplate(t, options, helmChartPath, []string{"templates/pega-tier-deployment.yaml"}) + yamlSplit := strings.Split(yamlContent, "---") + UnmarshalK8SYaml(t, yamlSplit[1], &depObj) + + if vendor != "openshift" { + // for openshift and for others + require.Equal(t, int64(0), *depObj.Spec.Template.Spec.SecurityContext.FSGroup) + require.Equal(t, int64(9001), *depObj.Spec.Template.Spec.SecurityContext.RunAsUser) + } else { + require.Nil(t, depObj.Spec.Template.Spec.SecurityContext) + } + + } + } + } +} + +func TestPegaTierDeploymentSecurityContextAdditional(t *testing.T) { + var supportedVendors = []string{"k8s", "openshift"} + var supportedOperations = []string{"deploy"} + var deploymentNames = []string{"myapp-dev"} + + helmChartPath, err := filepath.Abs(PegaHelmChartPath) + require.NoError(t, err) + + for _, vendor := range supportedVendors { + + var depObj appsv1.Deployment + + for _, operation := range supportedOperations { + + for _, depName := range deploymentNames { + + fmt.Println(vendor + "-" + operation) + + var options = &helm.Options{ + SetValues: map[string]string{ + "global.provider": vendor, + "global.actions.execute": operation, + "global.deployment.name": depName, + "global.tier[0].securityContext.runAsNonRoot": "true", + "global.tier[0].securityContext.supplementalGroups[0]": "2000", + }, + } + + yamlContent := RenderTemplate(t, options, helmChartPath, []string{"templates/pega-tier-deployment.yaml"}) + yamlSplit := strings.Split(yamlContent, "---") + UnmarshalK8SYaml(t, yamlSplit[1], &depObj) + + require.Equal(t, bool(true), *depObj.Spec.Template.Spec.SecurityContext.RunAsNonRoot) + require.Equal(t, int64(2000), *&depObj.Spec.Template.Spec.SecurityContext.SupplementalGroups[0]) + + if vendor != "openshift" { + // for openshift and for others + require.Equal(t, int64(0), *depObj.Spec.Template.Spec.SecurityContext.FSGroup) + require.Equal(t, int64(9001), *depObj.Spec.Template.Spec.SecurityContext.RunAsUser) + } else { + require.Nil(t, depObj.Spec.Template.Spec.SecurityContext.FSGroup) + require.Nil(t, depObj.Spec.Template.Spec.SecurityContext.RunAsUser) + } + + } + } + } +} + +func TestPegaTierDeploymentSecurityContextOverrideDefault(t *testing.T) { + var supportedVendors = []string{"k8s", "eks", "gke"} + var supportedOperations = []string{"deploy"} + var deploymentNames = []string{"myapp-dev"} + + helmChartPath, err := filepath.Abs(PegaHelmChartPath) + require.NoError(t, err) + + for _, vendor := range supportedVendors { + var depObj appsv1.Deployment + + for _, operation := range supportedOperations { + + for _, depName := range deploymentNames { + + fmt.Println(vendor + "-" + operation) + + var options = &helm.Options{ + SetValues: map[string]string{ + "global.provider": vendor, + "global.actions.execute": operation, + "global.deployment.name": depName, + "global.tier[0].securityContext.fsGroup": "2", + }, + } + + yamlContent := RenderTemplate(t, options, helmChartPath, []string{"templates/pega-tier-deployment.yaml"}) + yamlSplit := strings.Split(yamlContent, "---") + UnmarshalK8SYaml(t, yamlSplit[1], &depObj) + + if vendor != "openshift" { + // for openshift and for others + require.Equal(t, int64(2), *depObj.Spec.Template.Spec.SecurityContext.FSGroup) + require.Equal(t, int64(9001), *depObj.Spec.Template.Spec.SecurityContext.RunAsUser) + } else { + require.Equal(t, int64(2), *depObj.Spec.Template.Spec.SecurityContext.FSGroup) + require.Nil(t, depObj.Spec.Template.Spec.SecurityContext.RunAsUser) + } + } + } + } +}