Skip to content

Commit 397cf8a

Browse files
authored
Merge pull request #188 from snyk/feat/update-secure-config
Feat/update secure config
2 parents 790b9b6 + 8381e79 commit 397cf8a

File tree

4 files changed

+78
-10
lines changed

4 files changed

+78
-10
lines changed

Dockerfile

+14-10
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,29 @@ LABEL maintainer="Snyk Ltd"
2929

3030
ENV NODE_ENV production
3131

32-
COPY --from=skopeo-build /usr/bin/skopeo /usr/bin/skopeo
33-
COPY --from=skopeo-build /etc/containers/registries.d/default.yaml /etc/containers/registries.d/default.yaml
34-
COPY --from=skopeo-build /etc/containers/policy.json /etc/containers/policy.json
35-
36-
RUN apk --no-cache add db
37-
COPY --from=rpmdb-build /go/src/github.com/snyk/go-rpmdb/rpmdb /usr/bin/rpmdb
38-
3932
RUN apk update
4033
RUN apk upgrade
34+
RUN apk --no-cache add db
35+
36+
RUN addgroup -S -g 10001 snyk
37+
RUN adduser -S -G snyk -h /srv/app -u 10001 snyk
38+
39+
WORKDIR /srv/app
40+
USER snyk:snyk
41+
42+
COPY --chown=snyk:snyk --from=skopeo-build /usr/bin/skopeo /usr/bin/skopeo
43+
COPY --chown=snyk:snyk --from=skopeo-build /etc/containers/registries.d/default.yaml /etc/containers/registries.d/default.yaml
44+
COPY --chown=snyk:snyk --from=skopeo-build /etc/containers/policy.json /etc/containers/policy.json
4145

42-
WORKDIR /root
46+
COPY --chown=snyk:snyk --from=rpmdb-build /go/src/github.com/snyk/go-rpmdb/rpmdb /usr/bin/rpmdb
4347

4448
# Add manifest files and install before adding anything else to take advantage of layer caching
45-
ADD package.json package-lock.json .snyk ./
49+
ADD --chown=snyk:snyk package.json package-lock.json .snyk ./
4650

4751
RUN npm install
4852

4953
# add the rest of the app files
50-
ADD . .
54+
ADD --chown=snyk:snyk . .
5155

5256
# Complete any `prepare` tasks (e.g. typescript), as this step ran automatically prior to app being copied
5357
RUN npm run prepare

snyk-monitor-deployment.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ spec:
5757
limits:
5858
cpu: '1'
5959
memory: '2Gi'
60+
securityContext:
61+
runAsUser: 10001
62+
runAsGroup: 10001
63+
privileged: false
64+
runAsNonRoot: true
65+
allowPrivilegeEscalation: false
66+
readOnlyRootFilesystem: false
67+
capabilities:
68+
drop:
69+
- ALL
6070
securityContext: {}
6171
volumes:
6272
- name: docker-config

snyk-monitor/templates/deployment.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ spec:
5151
limits:
5252
cpu: '1'
5353
memory: '2Gi'
54+
securityContext:
55+
runAsUser: 10001
56+
runAsGroup: 10001
57+
privileged: false
58+
runAsNonRoot: true
59+
allowPrivilegeEscalation: false
60+
readOnlyRootFilesystem: false
61+
capabilities:
62+
drop:
63+
- ALL
5464
volumes:
5565
- name: docker-config
5666
secret:

test/unit/deployment-files.test.ts

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as tap from 'tap';
2+
import { parse } from 'yaml';
3+
import { readFileSync } from 'fs';
4+
import { V1Deployment } from '@kubernetes/client-node';
5+
6+
tap.test('ensure the security properties of the deployment files are unchanged', async (t) => {
7+
const deploymentFiles = ['./snyk-monitor/templates/deployment.yaml', './snyk-monitor-deployment.yaml'];
8+
9+
for (const filePath of deploymentFiles) {
10+
const fileContent = readFileSync(filePath, 'utf8');
11+
const deployment: V1Deployment = parse(fileContent);
12+
13+
if (
14+
!deployment.spec ||
15+
!deployment.spec.template.spec ||
16+
!deployment.spec.template.spec.containers ||
17+
deployment.spec.template.spec.containers.length === 0 ||
18+
!deployment.spec.template.spec.containers[0].securityContext
19+
) {
20+
tap.fail('bad container spec or missing securityContext');
21+
return;
22+
}
23+
24+
const securityContext =
25+
deployment.spec.template.spec.containers[0].securityContext;
26+
27+
if (!securityContext.capabilities) {
28+
tap.fail('missing capabilities section in pod securityContext');
29+
return;
30+
}
31+
32+
tap.same(securityContext.capabilities, { drop: ['ALL'] }, 'all capabilities are dropped and none are added');
33+
tap.ok(securityContext.allowPrivilegeEscalation === false, 'must explicitly set allowPrivilegeEscalation to false');
34+
tap.ok(securityContext.privileged === false, 'must explicitly set privileged to false');
35+
tap.ok(securityContext.runAsNonRoot === true, 'must explicitly set runAsNonRoot to true');
36+
tap.ok(securityContext.runAsUser === 10001, 'must explicitly set runAsUser to 10001');
37+
tap.ok(securityContext.runAsGroup === 10001, 'must explicitly set runAsGroup to 10001');
38+
39+
// TODO: currently we do not set this to true because skopeo pulls
40+
// temporary files to /var/tmp and this behaviour is not configurable
41+
// To be secure, this value MUST be set to "true"!
42+
tap.ok(securityContext.readOnlyRootFilesystem === false, 'readOnlyRootFilesystem is not set ON PURPOSE');
43+
}
44+
});

0 commit comments

Comments
 (0)