From 35b3b14fb19139ca02e5d42e8fd65e104052dd71 Mon Sep 17 00:00:00 2001 From: fykaa Date: Wed, 7 Feb 2024 16:11:39 +0530 Subject: [PATCH] add: kyverno-json-policies for dockerfile-best-practices --- .../detect-multiple-instructions/README.md | 79 +++++++++++++++++ .../detect-multiple-instructions.yaml | 22 +++++ .../test/bad-test/Dockerfile | 13 +++ .../test/bad-test/bad-payload.json | 69 +++++++++++++++ .../test/good-test/Dockerfile | 13 +++ .../test/good-test/good-payload.json | 71 ++++++++++++++++ .../prefer-copy-over-add/README.md | 76 +++++++++++++++++ .../prefer-copy-over-add.yaml | 21 +++++ .../test/bad-test/Dockerfile | 14 ++++ .../test/bad-test/bad-payload.json | 84 +++++++++++++++++++ .../test/good-test/Dockerfile | 13 +++ .../test/good-test/good-payload.json | 71 ++++++++++++++++ .../validate-expose-port-22/README.md | 70 ++++++++++++++++ .../test/bad-test/Dockerfile | 5 ++ .../test/bad-test/bad-payload.json | 44 ++++++++++ .../test/bad-test1/Dockerfile | 5 ++ .../test/bad-test1/bad-payload.json | 47 +++++++++++ .../test/bad-test2/Dockerfile | 5 ++ .../test/bad-test2/bad-payload.json | 44 ++++++++++ .../test/good-test/Dockerfile | 3 + .../test/good-test/good-payload.json | 35 ++++++++ .../validate-expose-port-22.yaml | 23 +++++ 22 files changed, 827 insertions(+) create mode 100644 dockerfile-best-practices/detect-multiple-instructions/README.md create mode 100644 dockerfile-best-practices/detect-multiple-instructions/detect-multiple-instructions.yaml create mode 100644 dockerfile-best-practices/detect-multiple-instructions/test/bad-test/Dockerfile create mode 100644 dockerfile-best-practices/detect-multiple-instructions/test/bad-test/bad-payload.json create mode 100644 dockerfile-best-practices/detect-multiple-instructions/test/good-test/Dockerfile create mode 100644 dockerfile-best-practices/detect-multiple-instructions/test/good-test/good-payload.json create mode 100644 dockerfile-best-practices/prefer-copy-over-add/README.md create mode 100644 dockerfile-best-practices/prefer-copy-over-add/prefer-copy-over-add.yaml create mode 100644 dockerfile-best-practices/prefer-copy-over-add/test/bad-test/Dockerfile create mode 100644 dockerfile-best-practices/prefer-copy-over-add/test/bad-test/bad-payload.json create mode 100644 dockerfile-best-practices/prefer-copy-over-add/test/good-test/Dockerfile create mode 100644 dockerfile-best-practices/prefer-copy-over-add/test/good-test/good-payload.json create mode 100644 dockerfile-best-practices/validate-expose-port-22/README.md create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test/Dockerfile create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test/bad-payload.json create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test1/Dockerfile create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test1/bad-payload.json create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test2/Dockerfile create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/bad-test2/bad-payload.json create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/good-test/Dockerfile create mode 100644 dockerfile-best-practices/validate-expose-port-22/test/good-test/good-payload.json create mode 100644 dockerfile-best-practices/validate-expose-port-22/validate-expose-port-22.yaml diff --git a/dockerfile-best-practices/detect-multiple-instructions/README.md b/dockerfile-best-practices/detect-multiple-instructions/README.md new file mode 100644 index 00000000..cc7a2e33 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/README.md @@ -0,0 +1,79 @@ +# Detect if there are any multiple instructions in a single line + +This policy is implemented to ensure that container images are built with minimal cached layers. It specifically focuses on detecting and preventing the use of multiple instructions in a single line within Dockerfiles. An example of such a scenario is using '&&' to combine two commands. + +## Policy Details: + +- **Policy Name:** detect-multiple-instructions +- **Check Description:** This policy ensures that Dockerfile Container Image Should Be Built with Minimal Cached Layers +- **Policy Category:** Dockerfile Best Practices + +## How It Works: + +### Validation Criteria: + +**Key** : CmdLine[0] +**Valid Values** : executables of the command +**Type** : string + +- **Condition:** `CmdLine[0]` contains ` && ` + - **Result:** FAIL + - **Reason:** Multiple instructions in a single line detected. + + +- **Condition:** `CmdLine[0]` doesn't contains ` && ` + - **Result:** PASS + - **Reason:** Single instruction per line, complying with best practices. + +### Policy Validation Testing Instructions + +To evaluate and test the policy ensuring dockerfile meets poliy requirements: + +For testing this policy you will need to: +- Make sure you have `kyverno-json` installed on the machine +- Make sure you have [nctl `v3.4.0`](https://downloads.nirmata.io/nctl/downloads/) or above. + + +1. **Extract JSON equivalent of the dockerfile:** + ```bash + nctl scan dockerfile -r test/good-test/Dockerfile --show-json > payload.json + ``` + +2. **Test the Policy with Kyverno:** + ```bash + kyverno-json scan --payload payload.json --policy detect-multiple-instructions.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --policy detect-multiple-instructions.yaml --payload test/good-test/good-payload.json + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - detect-multiple-instructions / detect-multiple-instructions / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ```bash + kyverno-json scan --policy detect-multiple-instructions.yaml --payload test/bad-test/bad-payload.json + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - detect-multiple-instructions / detect-multiple-instructions / FAILED: Found multiple instructions in a single line: any[0].check.~.(Stages[].Commands[].CmdLine[0].contains(@, ' && '))[0]: Invalid value: true: Expected value: false + Done + ``` + +--- + +This way you can ensure that your dockerfile adhere to policy. \ No newline at end of file diff --git a/dockerfile-best-practices/detect-multiple-instructions/detect-multiple-instructions.yaml b/dockerfile-best-practices/detect-multiple-instructions/detect-multiple-instructions.yaml new file mode 100644 index 00000000..8256db78 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/detect-multiple-instructions.yaml @@ -0,0 +1,22 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: detect-multiple-instructions + annotations: + policies.kyverno.io/title: Detect Multiple Instructions in Single Line + policies.kyverno.io/category: Dockerfile Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that Dockerfile Container Image Should Be Built with Minimal Cached Layers +spec: + rules: + - name: detect-multiple-instructions + match: + any: + - (Stages[].Commands[?Name=='RUN'].CmdLine[][] | length(@) > `0`): true + assert: + all: + - message: Found multiple instructions in a single line + check: + ~.(Stages[].Commands[?Name=='RUN'].CmdLine[][]): + (contains(@, ' && ')): false diff --git a/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/Dockerfile b/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/Dockerfile new file mode 100644 index 00000000..905049c4 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:latest + +# Update the package repository +RUN apt-get update && apt-get install -y nano + +WORKDIR /app + +COPY . /app + +EXPOSE 8080 + +# Example: Run a command when the container starts +CMD ["echo", "Container is running!"] diff --git a/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/bad-payload.json b/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/bad-payload.json new file mode 100644 index 00000000..08441995 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/test/bad-test/bad-payload.json @@ -0,0 +1,69 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "CmdLine": [ + "apt-get update && apt-get install -y nano" + ], + "Files": null, + "FlagsUsed": [], + "Name": "RUN", + "PrependShell": true + }, + { + "Name": "WORKDIR", + "Path": "/app" + }, + { + "Chmod": "", + "Chown": "", + "DestPath": "/app", + "From": "", + "Link": false, + "Name": "COPY", + "SourceContents": null, + "SourcePaths": [ + "." + ] + }, + { + "Name": "EXPOSE", + "Ports": [ + "8080" + ] + }, + { + "CmdLine": [ + "echo", + "Container is running!" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] + } diff --git a/dockerfile-best-practices/detect-multiple-instructions/test/good-test/Dockerfile b/dockerfile-best-practices/detect-multiple-instructions/test/good-test/Dockerfile new file mode 100644 index 00000000..05b92868 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/test/good-test/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:latest + +# Update the package repository +RUN apt-get update + +WORKDIR /app + +COPY . /app + +EXPOSE 8080 + +# Example: Run a command when the container starts +CMD ["echo", "&& is not present"] diff --git a/dockerfile-best-practices/detect-multiple-instructions/test/good-test/good-payload.json b/dockerfile-best-practices/detect-multiple-instructions/test/good-test/good-payload.json new file mode 100644 index 00000000..917c8949 --- /dev/null +++ b/dockerfile-best-practices/detect-multiple-instructions/test/good-test/good-payload.json @@ -0,0 +1,71 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "CmdLine": [ + "apt-get update" + ], + "Files": null, + "FlagsUsed": [ + + ], + "Name": "RUN", + "PrependShell": true + }, + { + "Name": "WORKDIR", + "Path": "/app" + }, + { + "Chmod": "", + "Chown": "", + "DestPath": "/app", + "From": "", + "Link": false, + "Name": "COPY", + "SourceContents": null, + "SourcePaths": [ + "." + ] + }, + { + "Name": "EXPOSE", + "Ports": [ + "8080" + ] + }, + { + "CmdLine": [ + "echo", + "&& is not present" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] + } diff --git a/dockerfile-best-practices/prefer-copy-over-add/README.md b/dockerfile-best-practices/prefer-copy-over-add/README.md new file mode 100644 index 00000000..295d6b9f --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/README.md @@ -0,0 +1,76 @@ +# Prefer COPY over ADD Instructions in Dockerfile + +This policy ensures that container images are built using commands that result in known outcomes. Specifically, it advocates for the preference of using the `COPY` instruction over `ADD` in Dockerfiles. By adhering to this policy, you enhance the predictability and transparency of the image-building process. + +## Policy Details: + +- **Policy Name:** prefer-copy-over-add +- **Check Description:** This policy checks whether Dockerfiles use the ADD instructions for copying files into the container image. +- **Policy Category:** Dockerfile Best Practices + +## How It Works: + +### Validation Criteria: + +**Key** : ADD + +- **Condition:** If `ADD` exists + - **Result:** FAIL + - **Reason:** Using `ADD` can introduce unnecessary complexity and ambiguity, potentially leading to unintended consequences. The policy recommends preferring COPY for explicit file copying. + +- **Condition:** If `ADD` doesn't exist + - **Result:** PASS + - **Reason:** This indicates compliance with the policy, as the absence of ADD aligns with the best practice of using COPY for file operations. + +### Policy Validation Testing Instructions + +To evaluate and test the policy ensuring dockerfile meets poliy requirements: + +For testing this policy you will need to: +- Make sure you have `kyverno-json` installed on the machine +- Make sure you have [nctl `v3.4.0`](https://downloads.nirmata.io/nctl/downloads/) or above. + + +1. **Extract JSON equivalent of the dockerfile:** + ```bash + nctl scan dockerfile -r test/good-test/Dockerfile --show-json > payload.json + ``` + +2. **Test the Policy with Kyverno:** + ```bash + kyverno-json scan --payload payload.json --policy prefer-copy-over-add.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --policy prefer-copy-over-add.yaml --payload test/good-test/good-payload.json + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - prefer-copy-over-add / prefer-copy-over-add / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ```bash + kyverno-json scan --policy prefer-copy-over-add.yaml --payload test/bad-test/bad-payload.json + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - prefer-copy-over-add / prefer-copy-over-add / FAILED: Avoid the use of ADD instructions in Dockerfiles: any[0].check.(Stages[].Commands[?Name=='ADD'].Link[] | length(@) > `0`): Invalid value: true: Expected value: false + Done + ``` + +--- + +By following this policy, you can ensure that your Dockerfile adopts a more straightforward and transparent approach to file copying, promoting better image building practices. \ No newline at end of file diff --git a/dockerfile-best-practices/prefer-copy-over-add/prefer-copy-over-add.yaml b/dockerfile-best-practices/prefer-copy-over-add/prefer-copy-over-add.yaml new file mode 100644 index 00000000..d54eb771 --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/prefer-copy-over-add.yaml @@ -0,0 +1,21 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: prefer-copy-over-add + annotations: + policies.kyverno.io/title: Prefer COPY over ADD in Dockerfile + policies.kyverno.io/category: Dockerfile Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that COPY instructions are used instead of ADD instructions in Dockerfiles. +spec: + rules: + - name: prefer-copy-over-add + match: + any: + - (Stages[].Commands[] | length(@) > `0`): true + assert: + any: + - message: Avoid the use of ADD instructions in Dockerfiles + check: + (Stages[].Commands[?Name=='ADD'].Link[] | length(@) > `0`): false diff --git a/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/Dockerfile b/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/Dockerfile new file mode 100644 index 00000000..fb42d4f9 --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:latest + +WORKDIR /app + +ADD . /app/ + +RUN apt-get update && apt-get install -y nano + +COPY . /app + +EXPOSE 8080 + +# Example: Run a command when the container starts +CMD ["echo", "ADD is present in the Dockerfile"] diff --git a/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/bad-payload.json b/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/bad-payload.json new file mode 100644 index 00000000..7aaf63ee --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/test/bad-test/bad-payload.json @@ -0,0 +1,84 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "Name": "WORKDIR", + "Path": "/app" + }, + { + "Checksum": "", + "Chmod": "", + "Chown": "", + "DestPath": "/app/", + "KeepGitDir": false, + "Link": false, + "Name": "ADD", + "SourceContents": null, + "SourcePaths": [ + "." + ] + }, + { + "CmdLine": [ + "apt-get update && apt-get install -y nano" + ], + "Files": null, + "FlagsUsed": [ + + ], + "Name": "RUN", + "PrependShell": true + }, + { + "Chmod": "", + "Chown": "", + "DestPath": "/app", + "From": "", + "Link": false, + "Name": "COPY", + "SourceContents": null, + "SourcePaths": [ + "." + ] + }, + { + "Name": "EXPOSE", + "Ports": [ + "8080" + ] + }, + { + "CmdLine": [ + "echo", + "ADD is present in the Dockerfile" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] +} diff --git a/dockerfile-best-practices/prefer-copy-over-add/test/good-test/Dockerfile b/dockerfile-best-practices/prefer-copy-over-add/test/good-test/Dockerfile new file mode 100644 index 00000000..d0c13e8c --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/test/good-test/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:latest + +# Update the package repository +RUN apt-get update + +WORKDIR /app + +COPY . /app + +EXPOSE 8080 + +# Example: Run a command when the container starts +CMD ["echo", "ADD Instruction is not present"] \ No newline at end of file diff --git a/dockerfile-best-practices/prefer-copy-over-add/test/good-test/good-payload.json b/dockerfile-best-practices/prefer-copy-over-add/test/good-test/good-payload.json new file mode 100644 index 00000000..32a66bdf --- /dev/null +++ b/dockerfile-best-practices/prefer-copy-over-add/test/good-test/good-payload.json @@ -0,0 +1,71 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "CmdLine": [ + "apt-get update" + ], + "Files": null, + "FlagsUsed": [ + + ], + "Name": "RUN", + "PrependShell": true + }, + { + "Name": "WORKDIR", + "Path": "/app" + }, + { + "Chmod": "", + "Chown": "", + "DestPath": "/app", + "From": "", + "Link": false, + "Name": "COPY", + "SourceContents": null, + "SourcePaths": [ + "." + ] + }, + { + "Name": "EXPOSE", + "Ports": [ + "8080" + ] + }, + { + "CmdLine": [ + "echo", + "ADD Instruction is not present" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] + } diff --git a/dockerfile-best-practices/validate-expose-port-22/README.md b/dockerfile-best-practices/validate-expose-port-22/README.md new file mode 100644 index 00000000..6ad4b3e8 --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/README.md @@ -0,0 +1,70 @@ +# Validating Exposed Port 22 in Dockerfile + +Exposing port 22 in a Dockerfile can pose security risks by potentially allowing unauthorized access to the containerized system. This policy aims to validate whether port 22 is exposed in Dockerfiles to enhance security practices. + +## Policy Details: + +- **Policy Name:** validate-expose-port-22 +- **Check Description:** This policy checks whether Dockerfiles exposes port 22. +- **Policy Category:** Dockerfile Security Best Practices + +## How It Works: + +### Validation Criteria:_____ + +**Key** : Ports + +- **Condition:** If `Ports` under EXPOSE has 22 or 22/tcp + - **Result:** FAIL + - **Reason:** Exposing port 22 could lead to security vulnerabilities, as it is commonly associated with SSH and remote access. + +- **Condition:** If `Port` doesn't exposes 22 or 22/tcp + - **Result:** PASS + - **Reason:** Compliance with the policy is achieved when port 22 is not exposed, aligning with best security practices to mitigate potential risks. + +### Policy Validation Testing Instructions + +To evaluate and test the policy ensuring Dockerfile compliance: + +For testing this policy, follow these steps: +- Ensure you have `kyverno-json` installed on your machine. +- Ensure you have [nctl `v3.4.0`](https://downloads.nirmata.io/nctl/downloads/) or a higher version installed. + +1. **Extract JSON equivalent of the Dockerfile:** + ```bash + nctl scan dockerfile -r test/good-test/Dockerfile --show-json > payload.json + ``` + +2. **Test the Policy with Kyverno:** + ```bash + kyverno-json scan --payload payload.json --policy validate-expose-port-22.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --policy validate-expose-port-22.yaml --payload test/good-test/good-payload.json + ``` + + This produces the output: + ``` + + ``` + + b. **Test Against Invalid Payload:** + ```bash + kyverno-json scan --policy validate-expose-port-22.yaml --payload test/bad-test/bad-payload.json + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - validate-expose-port-22 / validate-expose-port-22 / FAILED: Exposing port 22 in Dockerfile: any[0].check.(Stages[].ExposedPorts | contains("22/tcp")): Invalid value: false: Expected value: true + Done + ``` + +--- + +By adhering to this policy, you bolster the security of your Dockerized applications by minimizing the exposure of port 22, thereby reducing the risk of unauthorized access. \ No newline at end of file diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test/Dockerfile b/dockerfile-best-practices/validate-expose-port-22/test/bad-test/Dockerfile new file mode 100644 index 00000000..e967ebb5 --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test/Dockerfile @@ -0,0 +1,5 @@ +FROM ubuntu:latest + +EXPOSE 22 + +CMD ["echo", "Port 22 is exposed for SSH access"] diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test/bad-payload.json b/dockerfile-best-practices/validate-expose-port-22/test/bad-test/bad-payload.json new file mode 100644 index 00000000..3a3b7c4b --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test/bad-payload.json @@ -0,0 +1,44 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "Name": "EXPOSE", + "Ports": [ + "22" + ] + }, + { + "CmdLine": [ + "echo", + "Port 22 is exposed for SSH access" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] +} diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/Dockerfile b/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/Dockerfile new file mode 100644 index 00000000..e8246f06 --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/Dockerfile @@ -0,0 +1,5 @@ +FROM ubuntu:latest + +EXPOSE 3000 80 443 22 + +CMD ["echo", "Port 22 is exposed for SSH access"] diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/bad-payload.json b/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/bad-payload.json new file mode 100644 index 00000000..98f760fd --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test1/bad-payload.json @@ -0,0 +1,47 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "Name": "EXPOSE", + "Ports": [ + "22", + "3000", + "443", + "80" + ] + }, + { + "CmdLine": [ + "echo", + "Port 22 is exposed for SSH access" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] +} diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/Dockerfile b/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/Dockerfile new file mode 100644 index 00000000..0c9265eb --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/Dockerfile @@ -0,0 +1,5 @@ +FROM ubuntu:latest + +EXPOSE 22/tcp + +CMD ["echo", "Port 22 is exposed for SSH access"] diff --git a/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/bad-payload.json b/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/bad-payload.json new file mode 100644 index 00000000..d3d7d65c --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/bad-test2/bad-payload.json @@ -0,0 +1,44 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "Name": "EXPOSE", + "Ports": [ + "22/tcp" + ] + }, + { + "CmdLine": [ + "echo", + "Port 22 is exposed for SSH access" + ], + "Files": null, + "Name": "CMD", + "PrependShell": false + } + ] + } + ] +} diff --git a/dockerfile-best-practices/validate-expose-port-22/test/good-test/Dockerfile b/dockerfile-best-practices/validate-expose-port-22/test/good-test/Dockerfile new file mode 100644 index 00000000..952a10dd --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/good-test/Dockerfile @@ -0,0 +1,3 @@ +FROM ubuntu:latest + +EXPOSE 8080 \ No newline at end of file diff --git a/dockerfile-best-practices/validate-expose-port-22/test/good-test/good-payload.json b/dockerfile-best-practices/validate-expose-port-22/test/good-test/good-payload.json new file mode 100644 index 00000000..9f35f9b9 --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/test/good-test/good-payload.json @@ -0,0 +1,35 @@ +{ + "MetaArgs": null, + "Stages": [ + { + "Name": "", + "BaseName": "ubuntu:latest", + "Platform": "", + "Comment": "", + "SourceCode": "FROM ubuntu:latest", + "Location": [ + { + "Start": { + "Line": 1, + "Character": 0 + }, + "End": { + "Line": 1, + "Character": 0 + } + } + ], + "From": { + "Image": "ubuntu:latest" + }, + "Commands": [ + { + "Name": "EXPOSE", + "Ports": [ + "8080" + ] + } + ] + } + ] +} diff --git a/dockerfile-best-practices/validate-expose-port-22/validate-expose-port-22.yaml b/dockerfile-best-practices/validate-expose-port-22/validate-expose-port-22.yaml new file mode 100644 index 00000000..23b82ed3 --- /dev/null +++ b/dockerfile-best-practices/validate-expose-port-22/validate-expose-port-22.yaml @@ -0,0 +1,23 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: validate-expose-port-22 + annotations: + policies.kyverno.io/title: Validating Exposed Port 22 in Dockerfile + policies.kyverno.io/category: Dockerfile Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether Dockerfiles exposes port 22. +spec: + rules: + - name: prefer-copy-over-add + match: + any: + - (Stages[].Commands[?Name=='EXPOSE'][] | length(@) > `0`): true + assert: + any: + - message: Port 22 should not be exposed + check: + (Stages[].Commands[?Name=='EXPOSE'].Ports[][]): + (contains(@, '22')): false + (contains(@, '22/tcp')): false