diff --git a/charts/zalenium/README.md b/charts/zalenium/README.md index afb965c157..2e8beef632 100644 --- a/charts/zalenium/README.md +++ b/charts/zalenium/README.md @@ -79,6 +79,8 @@ See Zalenium's [usage examples](https://github.com/zalando/zalenium/blob/master/ | `hub.tag` | The zalenium hub image tag | `3` | | `hub.pullPolicy` | The pull policy for the hub image | `IfNotPresent` | | `hub.port` | The port the hub listens on | `4444` | +| `hub.podSecurityContext` | Pod Security Context used by hub and selenium grids | | +| `hub.containerSecurityContext` | Container Security Context used by hub and selenium grids | | | `hub.livenessTimeout` | Timeout for probe Hub liveness via HTTP request on Hub console | `1` | | `hub.readinessTimeout` | Timeout for probe Hub readiness via HTTP request on Hub console | `1` | | `hub.localVolumesRoot` | The root directory to store HostPath volumes (e.g. if running in minikube) | `/tmp` | diff --git a/charts/zalenium/templates/_pod-template.yaml b/charts/zalenium/templates/_pod-template.yaml index 439956c8ba..610be67ef1 100644 --- a/charts/zalenium/templates/_pod-template.yaml +++ b/charts/zalenium/templates/_pod-template.yaml @@ -4,11 +4,8 @@ metadata: {{- include "zalenium.labels" . | nindent 4 }} annotations: spec: - {{- if .Values.hub.securityContext.enabled }} securityContext: - fsGroup: {{ .Values.hub.securityContext.fsGroup }} - runAsUser: {{ .Values.hub.securityContext.runAsUser }} - {{- end }} + {{- toYaml .Values.hub.podSecurityContext | nindent 4 }} {{- if .Values.hub.pullSecrets }} imagePullSecrets: - name: {{ .Values.hub.imagePullSecret }} @@ -42,6 +39,8 @@ spec: - name: {{ .Chart.Name }} image: "{{ .Values.hub.image }}:{{ .Values.hub.tag }}" imagePullPolicy: {{ .Values.hub.pullPolicy }} + securityContext: + {{- toYaml .Values.hub.containerSecurityContext | nindent 8 }} ports: - containerPort: {{ .Values.hub.port }} protocol: TCP diff --git a/charts/zalenium/values.yaml b/charts/zalenium/values.yaml index aba08c77e6..617401a9d4 100644 --- a/charts/zalenium/values.yaml +++ b/charts/zalenium/values.yaml @@ -27,10 +27,17 @@ hub: ## Pod Security Context ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ ## in case it is running outside openshift, this should fix this https://github.com/zalando/zalenium/issues/631 - securityContext: - enabled: false - fsGroup: 0 - runAsUser: 1001 + podSecurityContext: + ## See all the options here https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#podsecuritycontext-v1-core + # fsGroup: 1000 + # runAsUser: 1000 + # runAsGroup: 1000 + + ## Container Security Context + containerSecurityContext: + ## See all the options here https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#securitycontext-v1-core + # capabilities: [] + # privileged: false ## Configure resource requests and limits ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ diff --git a/src/main/java/de/zalando/ep/zalenium/container/kubernetes/KubernetesContainerClient.java b/src/main/java/de/zalando/ep/zalenium/container/kubernetes/KubernetesContainerClient.java index 27c4c14be9..2fb12181cd 100644 --- a/src/main/java/de/zalando/ep/zalenium/container/kubernetes/KubernetesContainerClient.java +++ b/src/main/java/de/zalando/ep/zalenium/container/kubernetes/KubernetesContainerClient.java @@ -4,6 +4,7 @@ import de.zalando.ep.zalenium.container.ContainerClientRegistration; import de.zalando.ep.zalenium.container.ContainerCreationStatus; import de.zalando.ep.zalenium.util.Environment; +import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.ContainerStateTerminated; import io.fabric8.kubernetes.api.model.ContainerStatus; import io.fabric8.kubernetes.api.model.DoneablePod; @@ -14,6 +15,7 @@ import io.fabric8.kubernetes.api.model.PodList; import io.fabric8.kubernetes.api.model.PodSecurityContext; import io.fabric8.kubernetes.api.model.Quantity; +import io.fabric8.kubernetes.api.model.SecurityContext; import io.fabric8.kubernetes.api.model.Toleration; import io.fabric8.kubernetes.api.model.Volume; import io.fabric8.kubernetes.api.model.VolumeMount; @@ -53,6 +55,7 @@ public class KubernetesContainerClient implements ContainerClient { private static final Logger logger = LoggerFactory.getLogger(KubernetesContainerClient.class.getName()); + private static final String DEFAULT_ZALENIUM_CONTAINER_NAME = "zalenium"; private static final String ZALENIUM_KUBERNETES_TOLERATIONS = "ZALENIUM_KUBERNETES_TOLERATIONS"; private static final String ZALENIUM_KUBERNETES_NODE_SELECTOR = "ZALENIUM_KUBERNETES_NODE_SELECTOR"; @@ -71,7 +74,8 @@ public class KubernetesContainerClient implements ContainerClient { private List tolerations = new ArrayList<>(); private String imagePullPolicy; private List imagePullSecrets; - private PodSecurityContext configuredSecurityContext; + private PodSecurityContext configuredPodSecurityContext; + private SecurityContext configuredContainerSecurityContext; private final Map seleniumPodLimits = new HashMap<>(); private final Map seleniumPodRequests = new HashMap<>(); @@ -109,7 +113,8 @@ public KubernetesContainerClient(Environment environment, discoverNodeSelector(); discoverTolerations(); discoverImagePullSecrets(); - discoverSecurityContext(); + discoverPodSecurityContext(); + discoverContainerSecurityContext(); buildResourceMaps(); logger.info(String.format( @@ -221,8 +226,17 @@ private String findHostname() { return hostname; } - private void discoverSecurityContext() { - configuredSecurityContext = zaleniumPod.getSpec().getSecurityContext(); + private void discoverPodSecurityContext() { + configuredPodSecurityContext = zaleniumPod.getSpec().getSecurityContext(); + } + + private void discoverContainerSecurityContext() { + configuredContainerSecurityContext = zaleniumPod.getSpec().getContainers() + .stream() + .filter(c -> DEFAULT_ZALENIUM_CONTAINER_NAME.equals(c.getName())) + .map(Container::getSecurityContext) + .findFirst() + .orElse(null); } @Override @@ -353,7 +367,8 @@ public ContainerCreationStatus createContainer(String zaleniumContainerName, Str config.setPodLimits(seleniumPodLimits); config.setPodRequests(seleniumPodRequests); config.setOwner(zaleniumPod); - config.setPodSecurityContext(configuredSecurityContext); + config.setPodSecurityContext(configuredPodSecurityContext); + config.setContainerSecurityContext(configuredContainerSecurityContext); DoneablePod doneablePod = createDoneablePod.apply(config); @@ -584,6 +599,7 @@ public static DoneablePod createDoneablePodDefaultImpl(PodConfiguration config) .withImage(config.getImage()) .withImagePullPolicy(config.getImagePullPolicy()) .addAllToEnv(config.getEnvVars()) + .withSecurityContext(config.getContainerSecurityContext()) .addNewVolumeMount() .withName("dshm") .withMountPath("/dev/shm") diff --git a/src/main/java/de/zalando/ep/zalenium/container/kubernetes/PodConfiguration.java b/src/main/java/de/zalando/ep/zalenium/container/kubernetes/PodConfiguration.java index 0257bd20f5..8da02bd21e 100644 --- a/src/main/java/de/zalando/ep/zalenium/container/kubernetes/PodConfiguration.java +++ b/src/main/java/de/zalando/ep/zalenium/container/kubernetes/PodConfiguration.java @@ -5,6 +5,7 @@ import io.fabric8.kubernetes.api.model.HostAlias; import io.fabric8.kubernetes.api.model.LocalObjectReference; import io.fabric8.kubernetes.api.model.Quantity; +import io.fabric8.kubernetes.api.model.SecurityContext; import io.fabric8.kubernetes.api.model.Toleration; import io.fabric8.kubernetes.api.model.Volume; import io.fabric8.kubernetes.api.model.VolumeMount; @@ -34,6 +35,7 @@ public class PodConfiguration { private List tolerations; private OwnerReference ownerReference; private PodSecurityContext podSecurityContext; + private SecurityContext containerSecurityContext; public String getNodePort() { return nodePort; @@ -137,4 +139,11 @@ public void setPodSecurityContext(PodSecurityContext podSecurityContext) { this.podSecurityContext = podSecurityContext; } + public SecurityContext getContainerSecurityContext() { + return containerSecurityContext; + } + + public void setContainerSecurityContext(SecurityContext containerSecurityContext) { + this.containerSecurityContext = containerSecurityContext; + } } diff --git a/src/test/java/de/zalando/ep/zalenium/container/kubernetes/PodConfigurationTest.java b/src/test/java/de/zalando/ep/zalenium/container/kubernetes/PodConfigurationTest.java index d54a2fa4c3..1cb022d405 100644 --- a/src/test/java/de/zalando/ep/zalenium/container/kubernetes/PodConfigurationTest.java +++ b/src/test/java/de/zalando/ep/zalenium/container/kubernetes/PodConfigurationTest.java @@ -5,6 +5,7 @@ import io.fabric8.kubernetes.api.model.LocalObjectReference; import io.fabric8.kubernetes.api.model.PodSecurityContext; import io.fabric8.kubernetes.api.model.Quantity; +import io.fabric8.kubernetes.api.model.SecurityContext; import io.fabric8.kubernetes.api.model.Toleration; import io.fabric8.kubernetes.api.model.Volume; import io.fabric8.kubernetes.api.model.VolumeMount; @@ -155,4 +156,11 @@ public void testSetPodSecurityContext() { podConfiguration.setPodSecurityContext(securityContext); assertThat(podConfiguration.getPodSecurityContext(), is(securityContext)); } + + @Test + public void testSetContainerSecurityContext() { + SecurityContext securityContext = mock(SecurityContext.class); + podConfiguration.setContainerSecurityContext(securityContext); + assertThat(podConfiguration.getContainerSecurityContext(), is(securityContext)); + } }