Skip to content

Commit d82c569

Browse files
authored
Make Restricted PSS security context work together with agent injection (#1624)
1 parent 3fdd064 commit d82c569

File tree

5 files changed

+163
-30
lines changed

5 files changed

+163
-30
lines changed

src/main/java/org/csanchez/jenkins/plugins/kubernetes/RestrictedPssSecurityContextInjector.java

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

3+
import edu.umd.cs.findbugs.annotations.CheckForNull;
34
import edu.umd.cs.findbugs.annotations.NonNull;
45
import hudson.Extension;
56
import io.fabric8.kubernetes.api.model.CapabilitiesBuilder;
7+
import io.fabric8.kubernetes.api.model.Container;
68
import io.fabric8.kubernetes.api.model.Pod;
79
import io.fabric8.kubernetes.api.model.SeccompProfileBuilder;
810
import io.fabric8.kubernetes.api.model.SecurityContext;
@@ -45,35 +47,41 @@ public Pod decorate(@NonNull KubernetesCloud kubernetesCloud, @NonNull Pod pod)
4547
LOGGER.warning("No spec found in the pod, skipping the security context update");
4648
return pod;
4749
}
48-
var containers = spec.getContainers();
49-
if (containers != null) {
50-
for (var container : containers) {
51-
var securityContext = container.getSecurityContext();
52-
if (securityContext == null) {
53-
securityContext = new SecurityContext();
54-
container.setSecurityContext(securityContext);
55-
}
56-
if (securityContext.getAllowPrivilegeEscalation() == null) {
57-
securityContext.setAllowPrivilegeEscalation(false);
58-
}
59-
if (securityContext.getRunAsNonRoot() == null) {
60-
securityContext.setRunAsNonRoot(true);
61-
}
62-
var seccompProfile = securityContext.getSeccompProfile();
63-
if (seccompProfile == null) {
64-
securityContext.setSeccompProfile(new SeccompProfileBuilder()
65-
.withType(SECCOMP_RUNTIME_DEFAULT)
66-
.build());
67-
}
68-
var capabilities = securityContext.getCapabilities();
69-
if (capabilities == null) {
70-
securityContext.setCapabilities(new CapabilitiesBuilder()
71-
.withDrop(List.of(CAPABILITIES_ALL))
72-
.build());
73-
}
74-
}
75-
}
50+
secure(spec.getInitContainers());
51+
secure(spec.getContainers());
7652
}
7753
return pod;
7854
}
55+
56+
private static void secure(@CheckForNull List<Container> containers) {
57+
if (containers != null) {
58+
containers.forEach(RestrictedPssSecurityContextInjector::secure);
59+
}
60+
}
61+
62+
private static void secure(@NonNull Container container) {
63+
var securityContext = container.getSecurityContext();
64+
if (securityContext == null) {
65+
securityContext = new SecurityContext();
66+
container.setSecurityContext(securityContext);
67+
}
68+
if (securityContext.getAllowPrivilegeEscalation() == null) {
69+
securityContext.setAllowPrivilegeEscalation(false);
70+
}
71+
if (securityContext.getRunAsNonRoot() == null) {
72+
securityContext.setRunAsNonRoot(true);
73+
}
74+
var seccompProfile = securityContext.getSeccompProfile();
75+
if (seccompProfile == null) {
76+
securityContext.setSeccompProfile(new SeccompProfileBuilder()
77+
.withType(SECCOMP_RUNTIME_DEFAULT)
78+
.build());
79+
}
80+
var capabilities = securityContext.getCapabilities();
81+
if (capabilities == null) {
82+
securityContext.setCapabilities(new CapabilitiesBuilder()
83+
.withDrop(List.of(CAPABILITIES_ALL))
84+
.build());
85+
}
86+
}
7987
}

src/test/java/org/csanchez/jenkins/plugins/kubernetes/AbstractGoldenFileTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ public void setUpCloud() {
2727
protected void test(String name) throws IOException {
2828
var beforeYAML = loadFileAsStream(name + "-before.yaml");
2929
var before = Serialization.unmarshal(beforeYAML, Pod.class);
30-
assertEquals(name + "-before.yaml is not normalized", beforeYAML, Serialization.asYaml(before));
30+
assertEquals(name + "-before.yaml is not normalized", Serialization.asYaml(before), beforeYAML);
3131
var afterYAML = loadFileAsStream(name + "-after.yaml");
3232
var after = decorator.decorate(cloud, before);
33-
assertEquals(name + "-after.yaml processed", afterYAML, Serialization.asYaml(after));
33+
assertEquals(name + "-after.yaml processed", Serialization.asYaml(after), afterYAML);
3434
}
3535

3636
@NonNull

src/test/java/org/csanchez/jenkins/plugins/kubernetes/RestrictedPssSecurityInjectorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,9 @@ public void multiContainer() throws IOException {
3030
public void existingSecurityContext() throws IOException {
3131
test("existingSecurityContext");
3232
}
33+
34+
@Test
35+
public void agentInjection() throws IOException {
36+
test("agentInjection");
37+
}
3338
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
apiVersion: "v1"
3+
kind: "Pod"
4+
metadata:
5+
name: "simple"
6+
namespace: "jenkins"
7+
spec:
8+
containers:
9+
- env:
10+
- name: "JENKINS_SECRET"
11+
value: "my-little-secret"
12+
- name: "JENKINS_AGENT_NAME"
13+
value: "my-lovely-agent"
14+
- name: "REMOTING_OPTS"
15+
value: "-noReconnectAfter 1d"
16+
- name: "JENKINS_NAME"
17+
value: "my-lovely-agent"
18+
- name: "JENKINS_AGENT_WORKDIR"
19+
value: "/home/jenkins/agent"
20+
- name: "JENKINS_URL"
21+
value: "http://localhost/"
22+
image: "jenkins/inbound-agent"
23+
name: "maven"
24+
resources:
25+
limits:
26+
cpu: "1"
27+
memory: "768Mi"
28+
requests:
29+
cpu: "1"
30+
memory: "768Mi"
31+
securityContext:
32+
allowPrivilegeEscalation: false
33+
capabilities:
34+
drop:
35+
- "ALL"
36+
runAsNonRoot: true
37+
seccompProfile:
38+
type: "RuntimeDefault"
39+
volumeMounts:
40+
- mountPath: "/jenkins-agent"
41+
name: "jenkins-agent"
42+
- mountPath: "/home/jenkins/agent"
43+
name: "workspace-volume"
44+
readOnly: false
45+
initContainers:
46+
- command:
47+
- "/bin/sh"
48+
- "-c"
49+
- "cp $(command -v jenkins-agent) /jenkins-agent/jenkins-agent;cp /usr/share/jenkins/agent.jar\
50+
\ /jenkins-agent/agent.jar;sed -i 's!-jar .*agent.jar!-jar /jenkins-agent\\\
51+
/agent.jar!' /jenkins-agent/jenkins-agent"
52+
image: "jenkins/inbound-agent:3261.v9c670a_4748a_9-1"
53+
name: "set-up-jenkins-agent"
54+
securityContext:
55+
allowPrivilegeEscalation: false
56+
capabilities:
57+
drop:
58+
- "ALL"
59+
runAsNonRoot: true
60+
seccompProfile:
61+
type: "RuntimeDefault"
62+
volumeMounts:
63+
- mountPath: "/jenkins-agent"
64+
name: "jenkins-agent"
65+
volumes:
66+
- emptyDir:
67+
medium: ""
68+
name: "workspace-volume"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
apiVersion: "v1"
3+
kind: "Pod"
4+
metadata:
5+
name: "simple"
6+
namespace: "jenkins"
7+
spec:
8+
containers:
9+
- env:
10+
- name: "JENKINS_SECRET"
11+
value: "my-little-secret"
12+
- name: "JENKINS_AGENT_NAME"
13+
value: "my-lovely-agent"
14+
- name: "REMOTING_OPTS"
15+
value: "-noReconnectAfter 1d"
16+
- name: "JENKINS_NAME"
17+
value: "my-lovely-agent"
18+
- name: "JENKINS_AGENT_WORKDIR"
19+
value: "/home/jenkins/agent"
20+
- name: "JENKINS_URL"
21+
value: "http://localhost/"
22+
image: "jenkins/inbound-agent"
23+
name: "maven"
24+
resources:
25+
limits:
26+
cpu: "1"
27+
memory: "768Mi"
28+
requests:
29+
cpu: "1"
30+
memory: "768Mi"
31+
volumeMounts:
32+
- mountPath: "/jenkins-agent"
33+
name: "jenkins-agent"
34+
- mountPath: "/home/jenkins/agent"
35+
name: "workspace-volume"
36+
readOnly: false
37+
initContainers:
38+
- command:
39+
- "/bin/sh"
40+
- "-c"
41+
- "cp $(command -v jenkins-agent) /jenkins-agent/jenkins-agent;cp /usr/share/jenkins/agent.jar\
42+
\ /jenkins-agent/agent.jar;sed -i 's!-jar .*agent.jar!-jar /jenkins-agent\\\
43+
/agent.jar!' /jenkins-agent/jenkins-agent"
44+
image: "jenkins/inbound-agent:3261.v9c670a_4748a_9-1"
45+
name: "set-up-jenkins-agent"
46+
volumeMounts:
47+
- mountPath: "/jenkins-agent"
48+
name: "jenkins-agent"
49+
volumes:
50+
- emptyDir:
51+
medium: ""
52+
name: "workspace-volume"

0 commit comments

Comments
 (0)