Skip to content

Commit

Permalink
Merge pull request #135 from anusha94/dockerfile-rem-docs
Browse files Browse the repository at this point in the history
Update Dockerfile policies
  • Loading branch information
anusha94 authored Jun 15, 2024
2 parents 4922d4c + 85ea85b commit e6a399a
Show file tree
Hide file tree
Showing 70 changed files with 665 additions and 64 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/chainsaw-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install kyverno-json
uses: kyverno/action-install-kyverno-json@4ac28215fd015ff6aa5525afc67f119f9f758957 # v0.0.1
with:
release: v0.0.3-alpha.2
release: main

- name: Prepare environment
run: |
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
- name: Install kyverno-json
uses: kyverno/action-install-kyverno-json@4ac28215fd015ff6aa5525afc67f119f9f758957 # v0.0.1
with:
release: v0.0.3-alpha.2
release: main

- name: Prepare environment
run: |
Expand Down
73 changes: 73 additions & 0 deletions dockerfile-best-practices/check-apt-command-force-yes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Imagine you're setting up a Docker image for a web server using Ubuntu as the base image. You want to install the Apache web server and PHP to run your website. Here's a simplified Dockerfile without the `--force-yes` option:

```
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y \
apache2 \
php
```

In this Dockerfile, we're updating the package index with apt-get update. We're then installing Apache (apache2) and PHP (php) using `apt-get install -y`, which automatically answers "yes" to any prompts.

Now, let's say you encounter a situation where you want to install a package that requires additional confirmation or conflicts with existing packages. For instance, you decide to install a package called 'example-package' that requires manual confirmation:

```
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y \
apache2 \
php \
example-package
```
Upon running the `docker build`, you might encounter a prompt asking for confirmation to install 'example-package'. This is where the `--force-yes` option comes into play. It allows you to bypass such prompts and force the installation without user confirmation.

However, using `--force-yes` can lead to unforeseen consequences. For instance, 'example-package' might conflict with another package already installed on the system. Without proper validation, `--force-yes` could potentially downgrade or overwrite critical packages, resulting in system instability or unexpected behavior.

This policy checks whether you're using the `--force-yes` option with the `apt-get` command. If you're using the option with `apt-get`, the policy will give you failing checks else passing checks.

**In order to test this policy, use the following commands:**

- 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 check-apt-command-force-yes.yaml
```
a. **Test Policy Against Valid Payload:**
```bash
kyverno-json scan --policy check-apt-command-force-yes.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 ) ...
- check-apt-command-force-yes / check-apt-command-force-yes / PASSED
Done
```

b. **Test Policy Against Invalid Payload:**
```bash
kyverno-json scan --policy check-at-command-force-yes.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 ) ...
- check-apt-command-force-yes / check-apt-command-force-yes / FAILED: refrain from using the '--force-yes' option with `apt-get` as it bypasses important package validation checks and can potentially compromise the stability and security of your system.: all[0].check.~.(Stages[].Commands[?Name=='RUN'].CmdLine[][])[0].((starts_with(@, 'apt-get ') || contains(@, ' apt-get ')) && contains(@, ' --force-yes')): Invalid value: true: Expected value: false
Done
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: json.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: check-apt-command-force-yes
annotations:
policies.kyverno.io/title: Check for overidding of safety checks in apt-get command
policies.kyverno.io/category: Dockerfile Best Practices
policies.kyverno.io/severity: medium
policies.nirmata.io/remediation-docs: "https://docs.nirmata.io/policysets/dockerfile_best_practices/check-apt-command-force-yes/"
policies.kyverno.io/description: >-
The --force-yes option in apt-get is used to override some safety checks
and prompts, allowing the installation or upgrade of packages even if
they require additional user confirmation or if they conflict with other
packages. This can potentially lead to system instability or unexpected
behavior, as it bypasses certain safeguards put in place to ensure the stability
and consistency of the system.
spec:
rules:
- name: check-apt-command-force-yes
match:
all:
- ($analyzer.resource.type): dockerfile
- (Stages[].Commands[?Name=='RUN'].CmdLine[][] | length(@) > `0`): true
assert:
all:
- message: refrain from using the '--force-yes' option with `apt-get` as it bypasses important package validation checks and can potentially compromise the stability and security of your system.
check:
~.(Stages[].Commands[?Name=='RUN'].CmdLine[][]):
((starts_with(@, 'apt-get ') || contains(@, ' apt-get ')) && contains(@, ' --force-yes')): false
- message: refrain from using the '--force-yes' option with `apt` as it bypasses important package validation checks and can potentially compromise the stability and security of your system.
check:
~.(Stages[].Commands[?Name=='RUN'].CmdLine[][]):
((starts_with(@, 'apt ') || contains(@, ' apt ')) && contains(@, ' --force-yes')): false
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM ubuntu:latest

RUN apt-get update && \
apt-get install --force-yes \
wget

RUN echo "Hello world"
Original file line number Diff line number Diff line change
@@ -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": [
{
"CmdLine": [
"apt update && apt install --force-yes wget"
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
},
{
"CmdLine": [
"echo \"Hello world\""
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -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": [
{
"CmdLine": [
"apt-get update && apt-get install --force-yes wget"
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
},
{
"CmdLine": [
"echo \"Hello world\""
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
analyzer:
resource:
type: dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
name: good-test
spec:
steps:
- name: kyverno-json
try:
- script:
content: |
set -e
kyverno-json scan --policy ../check-apt-command-force-yes.yaml --payload ./good-test/good-payload.json --output json --bindings ./binding.yaml
check:
($error): ~
(json_parse($stdout)):
- results:
- policy:
apiVersion: json.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: check-apt-command-force-yes
rules:
- rule:
name: check-apt-command-force-yes
error: ~
violations: ~
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
name: bad-test
spec:
steps:
- name: kyverno-json
try:
- script:
content: |
set -e
kyverno-json scan --policy ../check-apt-command-force-yes.yaml --payload ./bad-test/bad-payload.json --output json --bindings ./binding.yaml
check:
($error): ~
(json_parse($stdout)):
- results:
- policy:
apiVersion: json.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: check-apt-command-force-yes
rules:
- rule:
name: check-apt-command-force-yes
error: ~
violations:
- message: refrain from using the '--force-yes' option with `apt-get` as it bypasses important package validation checks and can potentially compromise the stability and security of your system.
errors:
- type: FieldValueInvalid
value: true
detail: 'Expected value: false'
---
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
name: bad-test-02
spec:
steps:
- name: kyverno-json
try:
- script:
content: |
set -e
kyverno-json scan --policy ../check-apt-command-force-yes.yaml --payload ./bad-test/bad-payload-02.json --output json --bindings ./binding.yaml
check:
($error): ~
(json_parse($stdout)):
- results:
- policy:
apiVersion: json.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: check-apt-command-force-yes
rules:
- rule:
name: check-apt-command-force-yes
error: ~
violations:
- message: refrain from using the '--force-yes' option with `apt` as it bypasses important package validation checks and can potentially compromise the stability and security of your system.
errors:
- type: FieldValueInvalid
value: true
detail: 'Expected value: false'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM ubuntu:latest

RUN apt-get update && \
apt-get install -y \
wget

RUN echo "Hello world"
Original file line number Diff line number Diff line change
@@ -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": [
{
"CmdLine": [
"apt-get update && apt-get install -y wget"
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
},
{
"CmdLine": [
"echo \"Hello world\""
],
"Files": null,
"FlagsUsed": [],
"Name": "RUN",
"PrependShell": true
}
]
}
]
}
Loading

0 comments on commit e6a399a

Please sign in to comment.