Compare commits

...

37 Commits

Author SHA1 Message Date
Yoav Rotem
75fe5d0048 Fix ocp job issues (#893)
* Fix openshift missing glibc

Fixing issues #891  #890

* Update goreleaser

Change release to build, no need to release while building (when pushed to main) but only when publishing (release new version)

* Update goreleaser version to 0.169.0

* Change from release to build

* Try day run on release

It used to be released to docker hub each push, the issue was that docker hub had a automation for it, now test if its not releasing every git push.
2021-06-09 15:34:39 +03:00
Yoav Rotem
fdf0bbd960 Fixing typos (#899) 2021-06-09 15:11:05 +03:00
Yoav Rotem
dd68e8f000 Change files names to start with lowercase (#898) 2021-06-09 14:55:28 +03:00
Yoav Rotem
0d1bd2bbd9 mkdocs support and update docs (#884)
* Delete README.md

* Edit readme and separate into different files

* Update README.md

* Update Running.md

* Update CONTRIBUTING.md

* Create Contributing.md

* Add files via upload

* Update Index.md

* Rename Flags and Commands.md to Flags_and_commands.md

* Rename Index.md to index.md

* Create mkdocs.yml

* Delete images directory

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Create mkdocs-dev.yaml

* Create mkdocs-latest.yaml

* Update mkdocs.yml

* Update mkdocs.yml

* Update mkdocs.yml

Add yamllint ---

* Make it yamllint comply

* Make Yamllint comply

* Make Yamllint comply

* Change description

Co-authored-by: Itay Shakury <itay@itaysk.com>

* Fix syntax

Co-authored-by: Itay Shakury <itay@itaysk.com>

* Update docs/Architecture.md

Co-authored-by: Itay Shakury <itay@itaysk.com>

* Update docs/Architecture.md

Co-authored-by: Itay Shakury <itay@itaysk.com>

* Update example for test files

* Update contributing

* Delete Contributing.md

* Update Flags_and_commands.md

* Change syntax and add source

* Update Platforms.md

* lower case file names

* lower case file names

* Lower case file names

* Lower case file names

* Lower case file names

* Lower case file names

* Add note about inspect master in some platforms

* Add quick start

* Lower case files names

* Lower case files names

* Fixing typo

* Remove section about old ocp

* Fix typos

Co-authored-by: Itay Shakury <itay@itaysk.com>
2021-06-09 11:17:16 +03:00
Ed Robinson
4b28c84b97 Allow kube-bench to scan Bottlerocket OS (#889) 2021-06-08 12:23:43 +03:00
tonyqui
6605ff8844 False positive when running rh-0.7 benchmarks (#886) 2021-06-07 12:18:59 +03:00
Dave Hay
fb92680702 Issue 867: Updating CIS 1.1.9 and 1.1.10 (#877)
Mitigating "No such file or directory" related to CNI config directory

Signed-off by: Dave Hay <david_hay@uk.ibm.com>
2021-05-23 11:46:36 +03:00
Yoav Rotem
62d9045ec6 Fix issue with missing 'Maintainer' field (#875)
Issue #840 missing 'Maintainer' field in package
2021-05-20 11:21:04 +03:00
Yoav Rotem
1f4b941c51 Fix test request timeout (#874)
* Test 1.2.24 should be manual

* Test 1.2.26 should be manual

* Test 1.2.26 should be manual

* Change test 1.2.26

* Change test 1.2.26

* Change test 1.2.26

* Change test 1.2.26

* Change test 1.2.26
2021-05-18 16:53:50 +03:00
Yoav Rotem
9820da9579 Update gke-1.0 (#873)
* Create controlplane.yaml

* Update and tidy yaml

* Update and tidy yaml

* Update and tidy yaml
2021-05-18 16:37:55 +03:00
hbc
e4d9455820 cfg: add /etc/default/kubeletconfig.json for AKS (#865)
* cfg: add `/etc/default/kubeletconfig.json`

* fix(cfg): search kubeletconfig.json first

* feat: mount `/etc/default` from host for AKS cluster

Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>
2021-05-11 12:37:25 +03:00
Huang Huang
47c2494728 Support CIS ACK 1.0.0 benchmark (#841)
* Support CIS ACK 1.0.0 benchmark

* fix yaml lint

* Fix TestMakeSubsitutions may failed when order of map changed

* Support auto-detect platform when running on ACK

* Apply suggestions from code review

Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>

Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>
2021-05-11 11:52:24 +03:00
Yoav Rotem
887965d31f Add detected kubernetes version (#869)
* Add detected kubernetes version to controls

* Refactore NewControls function

Now new Control function is expecting detected version argument.

* Refactore NewControls function

Now new Control function is expecting detected version argument.

* Refactore NewControls function

New Control function is expecting detected version argument.

* Add detected kube version

* add detecetedKubeVersion

* Add detecetedKubeVersion

* Add detectedKubeVersion

* Add detecetedKubeVersion

* Fix missing version

* Change version

Change version from 3.10 to rh-0.7

* fix version: "cis-1.5"

* fix version: "cis-1.5"

* fix version: "cis-1.5"

* Fix version: "cis-1.5"

* Fix version: "cis-1.5"

* Fix version: "cis-1.6"

* Fix version: "cis-1.6"

* Fix version: "cis-1.6"

* Fix version: "cis-1.6"

* Fix version: "cis-1.6"
2021-05-09 14:48:34 +03:00
Huang Huang
182e64753e mount /etc/passwd and /etc/group for etcd ownership related checks (#868) 2021-05-09 14:25:14 +03:00
Yoav Rotem
a1bd51db99 Add rh-1.0 (#863) 2021-05-02 19:31:03 +03:00
Gábor Lipták
af4999ac0e Bring Go to 1.16 (#859)
* Bring Go to 1.16

* Bring Go to 1.16

* Bump actions/setup-go to v2

* Bump actions/setup-go to v2
2021-05-02 12:47:30 +03:00
Yoav Rotem
68c2ee2ebf Add support for Redhat openshift 4.0 cis 1.1.0 (#860) 2021-04-29 17:08:41 +03:00
Dmytro Oboznyi
d528400881 Fix file permissions false positive (#800)
* Fix file permissions false positive

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Added kops files to config path list

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Automated CNI files checks

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Fixed linting

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Fixed to right folder CNI test

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Changed Automated to manual

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Removed changes from remediation

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Added path to config files

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Update cfg/cis-1.6/master.yaml

Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>
Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Fix

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Fix to job.yaml

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Add extra mountpoints

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Revert audit scripts changes

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

Co-authored-by: Yoav Rotem <yoavrotems97@gmail.com>
2021-04-08 17:02:27 +03:00
Yoav Rotem
f2386c0386 Update ocp 3.11 (#849)
* Add OCP auto-detection

* Add test for openshift

* update and fix bugs

update file to match with new kube-bench features and fix bugs

* Update file and fix bugs

update file to match with new kube-bench features and fix bugs

* Remove specific configs

Those configs could be set in main config.yaml

* Update to include openshift files

* fix typos

* fix typo

* Remove trailing spaces

* Update util.go

* Add tests for getOcpValidVersion
2021-03-24 18:06:54 +02:00
Yoav Rotem
0cb302761c Add logging (#822)
* Add more logging

The old logging could was lacking and in some cases misleading

* Add Logging

Add more logs and change some old messages, the important part is make each test log more readable by adding ------ test id ------ section in logs

* Fix typos

* more info

add more info in comment about the function and it use cases

Co-authored-by: Liz Rice <liz@lizrice.com>

* Use switch case

Change the logic from if to switch and tidy up the code
2021-03-22 17:33:53 +02:00
Neha Viswanathan
9030532263 upgrade base image versions in Dockerfile (#831) 2021-03-21 22:53:39 +02:00
Yoav Rotem
50fce51da7 Fix fallback to default version (#834)
* Fix fallback to default version

In some cases kube-bench will crush instead of fallback to default version. 
Fix it to only log that couldn't auto-detect version and used default.

* Fix case with fallback to default version
2021-03-02 16:27:34 +02:00
Yoav Rotem
e308bc1eba Add version logging (#817)
* Add more logging

issue #816  add more logging for better debug and information about version auto-detection and fix typo

* Fix typo

* Add more logging

issue #816  add more logging for better debug and information about version auto-detection and fix typo

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* tidy logging output

Co-authored-by: Liz Rice <liz@lizrice.com>

* Remove extra logging

Co-authored-by: Liz Rice <liz@lizrice.com>
2021-02-23 14:24:14 +00:00
Neha Viswanathan
b2d481812f deprecate master and node subcommands (#812)
* deprecate master and node subcommands

* deprecate master and node subcommands
2021-02-23 14:23:55 +00:00
Naoki Oketani
bc21212980 chore: fix an invalid markdown syntax (#815) 2021-02-23 14:23:38 +00:00
Takahiro Tsuruda
4d6de1e2a5 chore: fix defer func in for-loop (#825)
* chore: call defer func for each iteration

Signed-off-by: TakahiroTsuruda <isrgnoe@gmail.com>

* chore: error check
2021-02-23 14:22:15 +00:00
Liz Rice
baf05eca3b docs: remove deprecated subcommands master / node (#827)
* docs: remove references to deprecated subcommands

Removing master / node since it's better to autodetect, or to use
--target

Signed-off-by: Liz Rice <liz@lizrice.com>

* docs: specifying kubernetes or benchmark version

Signed-off-by: Liz Rice <liz@lizrice.com>
2021-02-23 14:05:34 +00:00
Liz Rice
92ebc493ac chore: fix YAML lint errors (#826)
* chore: fix YAML lint

* chore: fix YAML lint
2021-02-23 14:04:45 +00:00
Michael Kandelaars
3e9b5a7b49 Refactor of EKS and ASFF integration Job and instructions (#794)
* Refactor to use Configmap for EKS and ASFF integration

* newline

* markdown fix

* formatting fix

* Update docs/asff.md

Co-authored-by: Liz Rice <liz@lizrice.com>

* typo

* docs: remove section about rebuilding

* docs: reminder to specify kube-bench image for ASFF

Co-authored-by: Liz Rice <liz@lizrice.com>
2021-02-22 14:28:36 +00:00
Liz Rice
ade7fb0759 chore: improve bug report template (#821)
Ask for more details that we usually need to request anyway, like the
list of currently running processes

Signed-off-by: Liz Rice <liz@lizrice.com>
2021-02-22 11:00:59 +02:00
Thorsten Schifferdecker
2b3f036959 (fix) add config.yaml to releases, see #811 (#813)
Signed-off-by: Thorsten Schifferdecker <ts@systs.org>
2021-02-11 12:56:49 +02:00
Dmytro Oboznyi
6262bc79ec Automated testing 1.2.34 (#801)
* Automated testing 1.2.34

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Changed automation status in test

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Changed one more test

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>

* Changed Automated to manual

Signed-off-by: Dmytro Oboznyi <dmytro.oboznyi@syncier.com>
2021-02-11 11:54:41 +02:00
Felipe Augusto de Castro
ed53e56356 Allow kube-bench to scan Bottlerocket OS (#809) 2021-02-10 16:56:11 +02:00
Giuseppe Ingoglia
773b3e6f79 add new proxy path (#820)
Solving issue raised in #819
2021-02-10 12:14:25 +02:00
Liz Rice
95905fb5c2 Publish to aquasec org on Docker Hub 2021-01-21 10:27:46 +00:00
Liz Rice
a96ffc2e16 Publish to the aquasec org on Docker Hub (#805)
* Publish to the aquasec org on Docker Hub

* chore: remove spaces
2021-01-21 10:22:28 +00:00
Liz Rice
5ae42ebd82 Add manual workflow dispatch to Publish (#804)
So we can trigger publish manually
2021-01-21 11:48:48 +02:00
86 changed files with 5792 additions and 1181 deletions

View File

@@ -3,15 +3,35 @@ name: Bug report
about: Tell us about a problem you are experiencing
---
**What steps did you take and what happened:**
**Overview**
[A clear and concise description of what the bug is, and what commands you ran. If possible please supply logs generated with the `-v 3` parameter.)
[A clear and concise description of what the bug is]
**How did you run kube-bench?**
[Please specify exactly how you ran kube-bench, including details of command parameters and/or job file that you used to run it]
**What happened?**
[Please include output from the report to illustrate the problem. If possible please supply logs generated with the `-v 3` parameter.]
**What did you expect to happen:**
[Please describe what you expected to happen differently.]
**Environment**
[Please specify the version of kube-bench and Kubernetes]
[What is your version of kube-bench? (run `kube-bench version`)]
[What is your version of Kubernetes? (run `kubectl version` or `oc version` on OpenShift.)]
**Running processes**
[Please include the output from running `ps -eaf | grep kube` on the affected node. This will allow us to check what Kubernetes processes are running, and how this compares to what kube-bench detected.]
**Configuration files**
[If kube-bench is reporting an issue related to the settings defined in a config file, please attach the file, or include an extract showing the settings that are being detected incorrectly.]
**Anything else you would like to add:**

View File

@@ -1,3 +1,4 @@
---
name: Build
on:
push:
@@ -18,9 +19,9 @@ jobs:
runs-on: ubuntu-18.04
steps:
- name: Setup Go
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.13
go-version: 1.16
- name: Checkout code
uses: actions/checkout@v2
- name: yaml-lint
@@ -36,5 +37,5 @@ jobs:
- name: Dry-run release snapshot
uses: goreleaser/goreleaser-action@v2
with:
version: v0.148.0
version: v0.169.0
args: release --snapshot --skip-publish --rm-dist

35
.github/workflows/mkdocs-dev.yaml vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Deploy the dev documentation
on:
push:
paths:
- 'docs/**'
- mkdocs.yml
branches:
- main
jobs:
deploy:
name: Deploy the dev documentation
runs-on: ubuntu-18.04
steps:
- name: Checkout main
uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: true
- uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Install dependencies
run: |
pip install git+https://${GH_TOKEN}@github.com/squidfunk/mkdocs-material-insiders.git
pip install mike
pip install mkdocs-macros-plugin
env:
GH_TOKEN: ${{ secrets.MKDOCS_AQUA_BOT }}
- name: Setup Git
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
- name: Deploy the dev documents
run: mike deploy --push dev

30
.github/workflows/mkdocs-latest.yaml vendored Normal file
View File

@@ -0,0 +1,30 @@
---
name: Deploy the latest documentation
on:
push:
tags:
- "v*"
jobs:
deploy:
name: Deploy the latest documentation
runs-on: ubuntu-18.04
steps:
- name: Checkout main
uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: true
- uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Install dependencies
run: |
pip install git+https://${GH_TOKEN}@github.com/squidfunk/mkdocs-material-insiders.git
pip install mike
pip install mkdocs-macros-plugin
env:
GH_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }}
- name: Deploy the latest documents
run: |
VERSION=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
mike deploy --push --update-aliases $VERSION latest

View File

@@ -1,11 +1,13 @@
---
name: Publish
on:
workflow_dispatch:
push:
tags:
- "v*"
env:
ALIAS: aquasecurity
DOCKERHUB_ALIAS: aquasec
REP: kube-bench
jobs:
publish:
@@ -54,9 +56,9 @@ jobs:
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: |
${{ secrets.DOCKERHUB_USER }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}
${{ env.DOCKERHUB_ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}
public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}
${{ secrets.DOCKERHUB_USER }}/${{ env.REP }}:latest
${{ env.DOCKERHUB_ALIAS }}/${{ env.REP }}:latest
public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:latest
cache-from: type=local,src=/tmp/.buildx-cache/release
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache/release

View File

@@ -1,3 +1,4 @@
---
name: Release
on:
push:
@@ -9,9 +10,9 @@ jobs:
runs-on: ubuntu-18.04
steps:
- name: Setup Go
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.13
go-version: 1.16
- name: Checkout code
uses: actions/checkout@v2
- name: Run unit tests
@@ -21,7 +22,7 @@ jobs:
- name: Release
uses: goreleaser/goreleaser-action@v2
with:
version: v0.148.0
version: v0.169.0
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -24,14 +24,17 @@ archives:
name_template: '{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{.Arm }}{{ end }}'
files:
- "cfg/**/*"
- "cfg/config.yaml"
nfpms:
-
vendor: Aqua Security
maintainer: Yoav Rotem <yoav.rotem@aquasec.com>
description: "The Kubernetes Bench for Security is a Go application that checks whether Kubernetes is deployed according to security best practices"
license: Apache-2.0
homepage: https://github.com/aquasecurity/kube-bench
files:
"cfg/**/*": "/etc/kube-bench/cfg"
"cfg/config.yaml": "/etc/kube-bench/cfg"
formats:
- deb
- rpm

View File

@@ -1,6 +1,8 @@
Thank you for taking an interest in contributing to kube-bench !
## Issues
## Contributing, bug reporting, openning issues and starting discussions
### Issues
- Feel free to open an issue for any reason as long as you make it clear if the issue is about a bug/feature/question/comment.
- Please spend some time giving due diligence to the issue tracker. Your issue might be a duplicate. If it is, please add your comment to the existing issue.
@@ -9,16 +11,69 @@ Thank you for taking an interest in contributing to kube-bench !
- For questions and bug reports, please include the following information:
- version of kube-bench you are running (from kube-bench version) along with the command line options you are using.
- version of Kubernetes you are running (from kubectl version or oc version for Openshift).
- Verbose log output, by setting the `-v 10` command line option.
- Verbose log output, by setting the `-v 3` command line option.
## Pull Requests
### Bugs
If you think you have found a bug please follow the instructions below.
- Open a [new bug](https://github.com/aquasecurity/kube-bench/issues/new?assignees=&labels=&template=bug_report.md) if a duplicate doesn't already exist.
- Make sure to give as much information as possible in the following questions
- Overview
- How did you run kube-bench?
- What happened?
- What did you expect to happen
- Environment
- Running processes
- Configuration files
- Anything else you would like to add
- Set `-v 3` command line option and save the log output. Please paste this into your issue.
### Features
We also use the GitHub discussions to track feature requests. If you have an idea to make kube-bench even more awesome follow the steps below.
- Open a [new discussion](https://github.com/aquasecurity/kube-bench/discussions/new?category_id=19113743) if a duplicate doesn't already exist.
- Remember users might be searching for your discussion in the future, so please give it a meaningful title to helps others.
- Clearly define the use case, using concrete examples. For example, I type `this` and kube-bench does `that`.
- If you would like to include a technical design for your feature please feel free to do so.
### Questions
We also use the GitHub discussions to Q&A.
- Open a [new discussion](https://github.com/aquasecurity/kube-bench/discussions/new) if a duplicate doesn't already exist.
- Remember users might be searching for your discussion in the future, so please give it a meaningful title to helps others.
### Pull Requests
We welcome pull requests!
- Every Pull Request should have an associated Issue, unless you are fixing a trivial documentation issue.
- We will not accept changes to LICENSE, NOTICE or CONTRIBUTING from outside the Aqua Security team. Please raise an Issue if you believe there is a problem with any of these files.
- Your PR is more likely to be accepted if it focuses on just one change.
- Describe what the PR does. There's no convention enforced, but please try to be concise and descriptive. Treat the PR description as a commit message. Titles that start with "fix"/"add"/"improve"/"remove" are good examples.
- Please add the associated Issue in the PR description.
- Please include a comment with the results before and after your change.
- There's no need to add or tag reviewers.
- If a reviewer commented on your code or asked for changes, please remember to mark the discussion as resolved after you address it. PRs with unresolved issues should not be merged (even if the comment is unclear or requires no action from your side).
- Please include a comment with the results before and after your change.
- Your PR is more likely to be accepted if it includes tests (We have not historically been very strict about tests, but we would like to improve this!).
- You're welcome to submit a draft PR if you would like early feedback on an idea or an approach.
- Happy coding!
## Testing locally with kind
Our makefile contains targets to test your current version of kube-bench inside a [Kind](https://kind.sigs.k8s.io/) cluster. This can be very handy if you don't want to run a real Kubernetes cluster for development purposes.
First, you'll need to create the cluster using `make kind-test-cluster` this will create a new cluster if it cannot be found on your machine. By default, the cluster is named `kube-bench` but you can change the name by using the environment variable `KIND_PROFILE`.
*If kind cannot be found on your system the target will try to install it using `go get`*
Next, you'll have to build the kube-bench docker image using `make build-docker`, then we will be able to push the docker image to the cluster using `make kind-push`.
Finally, we can use the `make kind-run` target to run the current version of kube-bench in the cluster and follow the logs of pods created. (Ctrl+C to exit)
Every time you want to test a change, you'll need to rebuild the docker image and push it to cluster before running it again. ( `make build-docker kind-push kind-run` )
1. Every Pull Request should have an associated Issue, unless you are fixing a trivial documentation issue.
1. We will not accept changes to LICENSE, NOTICE or CONTRIBUTING from outside the Aqua Security team. Please raise an Issue if you believe there is a problem with any of these files.
1. Your PR is more likely to be accepted if it focuses on just one change.
1. Describe what the PR does. There's no convention enforced, but please try to be concise and descriptive. Treat the PR description as a commit message. Titles that start with "fix"/"add"/"improve"/"remove" are good examples.
1. Please add the associated Issue in the PR description.
1. There's no need to add or tag reviewers.
1. If a reviewer commented on your code or asked for changes, please remember to mark the discussion as resolved after you address it. PRs with unresolved issues should not be merged (even if the comment is unclear or requires no action from your side).
1. Please include a comment with the results before and after your change.
1. Your PR is more likely to be accepted if it includes tests (We have not historically been very strict about tests, but we would like to improve this!).

View File

@@ -1,4 +1,4 @@
FROM golang:1.15 AS build
FROM golang:1.16 AS build
WORKDIR /go/src/github.com/aquasecurity/kube-bench/
COPY go.mod go.sum ./
COPY main.go .
@@ -10,7 +10,7 @@ ARG GOOS=linux
ARG GOARCH=amd64
RUN GO111MODULE=on CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH go build -a -ldflags "-X github.com/aquasecurity/kube-bench/cmd.KubeBenchVersion=${KUBEBENCH_VERSION} -w" -o /go/bin/kube-bench
FROM alpine:3.12 AS run
FROM alpine:3.13 AS run
WORKDIR /opt/kube-bench/
# add GNU ps for -C, -o cmd, and --no-headers support
# https://github.com/aquasecurity/kube-bench/issues/109
@@ -20,6 +20,12 @@ RUN apk --no-cache add procps
# https://github.com/aquasecurity/kube-bench/issues/535
RUN apk --no-cache add openssl
# Add glibc for running oc command
RUN wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
RUN wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk
RUN apk add glibc-2.33-r0.apk
RUN apk add jq
ENV PATH=$PATH:/usr/local/mount-from-host/bin
COPY --from=build /go/bin/kube-bench /usr/local/bin/kube-bench

404
README.md
View File

@@ -17,159 +17,20 @@
[report-card-img]: https://goreportcard.com/badge/github.com/aquasecurity/kube-bench
[report-card]: https://goreportcard.com/report/github.com/aquasecurity/kube-bench
<img src="images/kube-bench.png" width="200" alt="kube-bench logo">
<img src="docs/images/kube-bench.png" width="200" alt="kube-bench logo">
kube-bench is a Go application that checks whether Kubernetes is deployed securely by running the checks documented in the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/).
kube-bench is tool that checks whether Kubernetes is deployed securely by running the checks documented in the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/).
Tests are configured with YAML files, making this tool easy to update as test specifications evolve.
### Please Note
![Kubernetes Bench for Security](/docs/images/output.png "Kubernetes Bench for Security")
1. kube-bench implements the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/) as closely as possible. Please raise issues here if kube-bench is not correctly implementing the test as described in the Benchmark. To report issues in the Benchmark itself (for example, tests that you believe are inappropriate), please join the [CIS community](https://cisecurity.org).
1. There is not a one-to-one mapping between releases of Kubernetes and releases of the CIS benchmark. See [CIS Kubernetes Benchmark support](#cis-kubernetes-benchmark-support) to see which releases of Kubernetes are covered by different releases of the benchmark.
1. It is impossible to inspect the master nodes of managed clusters, e.g. GKE, EKS and AKS, using kube-bench as one does not have access to such nodes, although it is still possible to use kube-bench to check worker node configuration in these environments.
![Kubernetes Bench for Security](https://raw.githubusercontent.com/aquasecurity/kube-bench/main/images/output.png "Kubernetes Bench for Security")
Table of Contents
=================
- [CIS Kubernetes Benchmark support](#cis-kubernetes-benchmark-support)
- [Installation](#installation)
- [Running kube-bench](#running-kube-bench)
- [Running inside a container](#running-inside-a-container)
- [Running in a Kubernetes cluster](#running-in-a-kubernetes-cluster)
- [Running in an AKS cluster](#running-in-an-aks-cluster)
- [Running in an EKS cluster](#running-in-an-eks-cluster)
- [Running on OpenShift](#running-on-openshift)
- [Running in an GKE cluster](#running-in-a-gke-cluster)
- [Installing from a container](#installing-from-a-container)
- [Download and Install binaries](#download-and-install-binaries)
- [Installing from sources](#installing-from-sources)
- [Output](#output)
- [Configuration](#configuration)
- [Troubleshooting](#troubleshooting)
- [Test config YAML representation](#test-config-yaml-representation)
- [Omitting checks](#omitting-checks)
- [Roadmap](#roadmap)
- [Testing locally with kind](#testing-locally-with-kind)
- [Contributing](#contributing)
- [Bugs](#bugs)
- [Features](#features)
- [Pull Requests](#pull-requests)
## CIS Kubernetes Benchmark support
kube-bench supports the tests for Kubernetes as defined in the [CIS Kubernetes Benchmarks](https://www.cisecurity.org/benchmark/kubernetes/).
| CIS Kubernetes Benchmark | kube-bench config | Kubernetes versions |
|---|---|---|
| [1.5.1](https://workbench.cisecurity.org/benchmarks/4892) | cis-1.5 | 1.15- |
| [1.6.0](https://workbench.cisecurity.org/benchmarks/4834) | cis-1.6 | 1.16- |
| [GKE 1.0.0](https://workbench.cisecurity.org/benchmarks/4536) | gke-1.0 | GKE |
| [EKS 1.0.0](https://workbench.cisecurity.org/benchmarks/5190) | eks-1.0 | EKS |
| Red Hat OpenShift hardening guide | rh-0.7 | OCP 3.10-3.11 |
By default, kube-bench will determine the test set to run based on the Kubernetes version running on the machine, but please note that kube-bench does not automatically detect OpenShift and GKE - see the section below on [Running kube-bench](https://github.com/aquasecurity/kube-bench#running-kube-bench).
## Installation
You can choose to
* Run kube-bench from inside a container (sharing PID namespace with the host). See [Running inside a container](#running-inside-a-container) for additional details.
* Run a container that installs kube-bench on the host, and then run kube-bench directly on the host. See [Installing from a container](#installing-from-a-container) for additional details.
* install the latest binaries from the [Releases page](https://github.com/aquasecurity/kube-bench/releases), though please note that you also need to download the config and test files from the `cfg` directory. See [Download and Install binaries](#download-and-install-binaries) for details.
* Compile it from source. See [Installing from sources](#installing-from-sources) for details.
## Running kube-bench
If you run kube-bench directly from the command line you may need to be root / sudo to have access to all the config files.
kube-bench automatically selects which `controls` to use based on the detected
node type and the version of Kubernetes a cluster is running. This behavior
can be overridden by specifying the `master` or `node` subcommand and the
`--version` flag on the command line.
The Kubernetes version can also be set with the `KUBE_BENCH_VERSION` environment variable.
The value of `--version` takes precedence over the value of `KUBE_BENCH_VERSION`.
For example, run kube-bench against a master with version auto-detection:
```
kube-bench master
```
Or run kube-bench against a worker node using the tests for Kubernetes version 1.13:
```
kube-bench node --version 1.13
```
`kube-bench` will map the `--version` to the corresponding CIS Benchmark version as indicated by the mapping table above. For example, if you specify `--version 1.15`, this is mapped to CIS Benchmark version `cis-1.15`.
Alternatively, you can specify `--benchmark` to run a specific CIS Benchmark version:
```
kube-bench node --benchmark cis-1.5
```
If you want to target specific CIS Benchmark `target` (i.e master, node, etcd, etc...)
you can use the `run --targets` subcommand.
```
kube-bench --benchmark cis-1.5 run --targets master,node
```
or
```
kube-bench --benchmark cis-1.5 run --targets master,node,etcd,policies
```
The following table shows the valid targets based on the CIS Benchmark version.
| CIS Benchmark | Targets |
|---|---|
| cis-1.5| master, controlplane, node, etcd, policies |
| cis-1.6| master, controlplane, node, etcd, policies |
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
| eks-1.0| controlplane, node, policies, managedservices |
If no targets are specified, `kube-bench` will determine the appropriate targets based on the CIS Benchmark version.
`controls` for the various versions of CIS Benchmark can be found in directories
with same name as the CIS Benchmark versions under `cfg/`, for example `cfg/cis-1.5`.
**Note:** **`It is an error to specify both --version and --benchmark flags together`**
### Running inside a container
You can avoid installing kube-bench on the host by running it inside a container using the host PID namespace and mounting the `/etc` and `/var` directories where the configuration and other files are located on the host so that kube-bench can check their existence and permissions.
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t aquasec/kube-bench:latest [master|node] --version 1.13
```
> Note: the tests require either the kubelet or kubectl binary in the path in order to auto-detect the Kubernetes version. You can pass `-v $(which kubectl):/usr/local/mount-from-host/bin/kubectl` to resolve this. You will also need to pass in kubeconfig credentials. For example:
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -v $(which kubectl):/usr/local/mount-from-host/bin/kubectl -v ~/.kube:/.kube -e KUBECONFIG=/.kube/config -t aquasec/kube-bench:latest [master|node]
```
You can use your own configs by mounting them over the default ones in `/opt/kube-bench/cfg/`
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v path/to/my-config.yaml:/opt/kube-bench/cfg/config.yam -v $(which kubectl):/usr/local/mount-from-host/bin/kubectl -v ~/.kube:/.kube -e KUBECONFIG=/.kube/config aquasec/kube-bench:latest [master|node]
```
### Running in a Kubernetes cluster
### Quick start
There are multiple ways to run kube-bench.
You can run kube-bench inside a pod, but it will need access to the host's PID namespace in order to check the running processes, as well as access to some directories on the host where config files and other files are stored.
Master nodes are automatically detected by kube-bench and will run master checks when possible.
The detection is done by verifying that mandatory components for master, as defined in the config files, are running (see [Configuration](#configuration)).
The supplied `job.yaml` file can be applied to run the tests as a job. For example:
The supplied `job.yaml` [file](job.yaml) can be applied to run the tests as a job. For example:
```bash
$ kubectl apply -f job.yaml
@@ -190,257 +51,22 @@ kubectl logs kube-bench-j76s9
[INFO] 1.1 API Server
...
```
For more information and different ways to run kube-bench see [documentation](docs/running.md)
### Please Note
You can still force to run specific master or node checks using respectively `job-master.yaml` and `job-node.yaml`.
1. kube-bench implements the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/) as closely as possible. Please raise issues here if kube-bench is not correctly implementing the test as described in the Benchmark. To report issues in the Benchmark itself (for example, tests that you believe are inappropriate), please join the [CIS community](https://cisecurity.org).
To run the tests on the master node, the pod needs to be scheduled on that node. This involves setting a nodeSelector and tolerations in the pod spec.
The default labels applied to master nodes has changed since Kubernetes 1.11, so if you are using an older version you may need to modify the nodeSelector and tolerations to run the job on the master node.
1. There is not a one-to-one mapping between releases of Kubernetes and releases of the CIS benchmark. See [CIS Kubernetes Benchmark support](docs/platforms.md#cis-kubernetes-benchmark-support) to see which releases of Kubernetes are covered by different releases of the benchmark.
### Running in an AKS cluster
By default, kube-bench will determine the test set to run based on the Kubernetes version running on the machine.
- see the following documentation on [Running kube-bench](docs/running.md#running-kube-bench) for more details.
1. Create an AKS cluster(e.g. 1.13.7) with RBAC enabled, otherwise there would be 4 failures
1. Use the [kubectl-enter plugin] (https://github.com/kvaps/kubectl-enter) to shell into a node
`
kubectl-enter {node-name}
`
or ssh to one agent node
could open nsg 22 port and assign a public ip for one agent node (only for testing purpose)
1. Run CIS benchmark to view results:
```
docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
./kube-bench node
```
kube-bench cannot be run on AKS master nodes
### Running in an EKS cluster
There is a `job-eks.yaml` file for running the kube-bench node checks on an EKS cluster. The significant difference on EKS is that it's not possible to schedule jobs onto the master node, so master checks can't be performed
1. To create an EKS Cluster refer to [Getting Started with Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html) in the *Amazon EKS User Guide*
- Information on configuring `eksctl`, `kubectl` and the AWS CLI is within
2. Create an [Amazon Elastic Container Registry (ECR)](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) repository to host the kube-bench container image
```
aws ecr create-repository --repository-name k8s/kube-bench --image-tag-mutability MUTABLE
```
3. Download, build and push the kube-bench container image to your ECR repo
```
git clone https://github.com/aquasecurity/kube-bench.git
cd kube-bench
aws ecr get-login-password --region <AWS_REGION> | docker login --username AWS --password-stdin <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com
docker build -t k8s/kube-bench .
docker tag k8s/kube-bench:latest <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
docker push <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
```
4. Copy the URI of your pushed image, the URI format is like this: `<AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest`
5. Replace the `image` value in `job-eks.yaml` with the URI from Step 4
6. Run the kube-bench job on a Pod in your Cluster: `kubectl apply -f job-eks.yaml`
7. Find the Pod that was created, it *should* be in the `default` namespace: `kubectl get pods --all-namespaces`
8. Retrieve the value of this Pod and output the report, note the Pod name will vary: `kubectl logs kube-bench-<value>`
- You can save the report for later reference: `kubectl logs kube-bench-<value> > kube-bench-report.txt`
#### Report kube-bench findings to AWS Security Hub
You can configure kube-bench with the `--asff` option to send findings to AWS Security Hub for any benchmark tests that fail or that generate a warning. See [this page][kube-bench-aws-security-hub] for more information on how to enable the kube-bench integration with AWS Security Hub.
### Running on OpenShift
| OpenShift Hardening Guide | kube-bench config |
|---|---|
| ocp-3.10| rh-0.7 |
| ocp-3.11| rh-0.7 |
| ocp-4.* | Not supported |
kube-bench includes a set of test files for Red Hat's OpenShift hardening guide for OCP 3.10 and 3.11. To run this you will need to specify `--benchmark rh-07`, or `--version ocp-3.10` or `--version ocp-3.11`
when you run the `kube-bench` command (either directly or through YAML).
There is work in progress on a [CIS Red Hat OpenShift Container Platform Benchmark](https://workbench.cisecurity.org/benchmarks/5248) which we believe should cover OCP 4.* and we intend to add support in kube-bench when it's published.
### Running in a GKE cluster
| CIS Benchmark | Targets |
|---|---|
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
kube-bench includes benchmarks for GKE. To run this you will need to specify `--benchmark gke-1.0` when you run the `kube-bench` command.
To run the benchmark as a job in your GKE cluster apply the included `job-gke.yaml`.
```
kubectl apply -f job-gke.yaml
```
### Installing from a container
This command copies the kube-bench binary and configuration files to your host from the Docker container:
**binaries compiled for linux-x86-64 only (so they won't run on macOS or Windows)**
```
docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
```
You can then run `./kube-bench [master|node]`.
### Download and Install binaries
It is possible to manually install and run kube-bench release binaries. In order to do that, you must have access to your Kubernetes cluster nodes. Note that if you're using one of the managed Kubernetes services (e.g. EKS, AKS, GKE), you will not have access to the master nodes of your cluster and you cant perform any tests on the master nodes.
First, log into one of the nodes using SSH.
Install kube-bench binary for your platform using the commands below. Note that there may be newer releases available. See [releases page](https://github.com/aquasecurity/kube-bench/releases).
Ubuntu/Debian:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.3.1/kube-bench_0.3.1_linux_amd64.deb -o kube-bench_0.3.1_linux_amd64.deb
sudo apt install ./kube-bench_0.3.1_linux_amd64.deb -f
```
RHEL:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.3.1/kube-bench_0.3.1_linux_amd64.rpm -o kube-bench_0.3.1_linux_amd64.rpm
sudo yum install kube-bench_0.3.1_linux_amd64.rpm -y
```
Alternatively, you can manually download and extract the kube-bench binary:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.3.1/kube-bench_0.3.1_linux_amd64.tar.gz -o kube-bench_0.3.1_linux_amd64.tar.gz
tar -xvf kube-bench_0.3.1_linux_amd64.tar.gz
```
You can then run kube-bench directly:
```
kube-bench [master|node]
```
If you manually downloaded the kube-bench binary (using curl command above), you have to specify the location of configuration directory and file. For example:
```
./kube-bench --config-dir `pwd`/cfg --config `pwd`/cfg/config.yaml [master|node]
```
See previous section on [Running kube-bench](#running-kube-bench) for further details on using the kube-bench binary.
### Installing from sources
If Go is installed on the target machines, you can simply clone this repository and run as follows (assuming your [`GOPATH` is set](https://github.com/golang/go/wiki/GOPATH)):
```shell
go get github.com/aquasecurity/kube-bench
cd $GOPATH/src/github.com/aquasecurity/kube-bench
go build -o kube-bench .
# See all supported options
./kube-bench --help
# Run all checks
./kube-bench
```
## Output
There are four output states:
- [PASS] indicates that the test was run successfully, and passed.
- [FAIL] indicates that the test was run successfully, and failed. The remediation output describes how to correct the configuration, or includes an error message describing why the test could not be run.
- [WARN] means this test needs further attention, for example it is a test that needs to be run manually. Check the remediation output for further information.
- [INFO] is informational output that needs no further action.
Note:
- If the test is Manual, this always generates WARN (because the user has to run it manually)
- If the test is Scored, and kube-bench was unable to run the test, this generates FAIL (because the test has not been passed, and as a Scored test, if it doesn't pass then it must be considered a failure).
- If the test is Not Scored, and kube-bench was unable to run the test, this generates WARN.
- If the test is Scored, type is empty, and there are no `test_items` present, it generates a WARN. This is to highlight tests that appear to be incompletely defined.
## Configuration
Kubernetes configuration and binary file locations and names can vary from installation to installation, so these are configurable in the `cfg/config.yaml` file.
Any settings in the version-specific config file `cfg/<version>/config.yaml` take precedence over settings in the main `cfg/config.yaml` file.
You can read more about `kube-bench` configuration in our [documentation](docs/README.md#configuration-and-variables).
## Troubleshooting
Running `kube-bench` with the `-v 3` parameter will generate debug logs that can be very helpful for debugging problems.
If you are using one of the example `job*.yaml` files, you will need to edit the `command` field, for example `["kube-bench", "-v", "3"]`. Once the job has run, the logs can be retrieved using `kubectl logs` on the job's pod.
## Test config YAML representation
The tests (or "controls") are represented as YAML documents (installed by default into `./cfg`). There are different versions of these test YAML files reflecting different versions of the CIS Kubernetes Benchmark. You will find more information about the test file YAML definitions in our [documentation](docs/README.md).
### Omitting checks
If you decide that a recommendation is not appropriate for your environment, you can choose to omit it by editing the test YAML file to give it the check type `skip` as in this example:
```yaml
checks:
- id: 2.1.1
text: "Ensure that the --allow-privileged argument is set to false (Scored)"
type: "skip"
scored: true
```
No tests will be run for this check and the output will be marked [INFO].
## Contributing
Kindly read [Contributing](CONTRIBUTING.md) before contributing.
We welcome PRs and issue reports.
## Roadmap
Going forward we plan to release updates to kube-bench to add support for new releases of the CIS Benchmark. Note that these are not released as frequently as Kubernetes releases.
We welcome PRs and issue reports.
## Testing locally with kind
Our makefile contains targets to test your current version of kube-bench inside a [Kind](https://kind.sigs.k8s.io/) cluster. This can be very handy if you don't want to run a real Kubernetes cluster for development purposes.
First, you'll need to create the cluster using `make kind-test-cluster` this will create a new cluster if it cannot be found on your machine. By default, the cluster is named `kube-bench` but you can change the name by using the environment variable `KIND_PROFILE`.
*If kind cannot be found on your system the target will try to install it using `go get`*
Next, you'll have to build the kube-bench docker image using `make build-docker`, then we will be able to push the docker image to the cluster using `make kind-push`.
Finally, we can use the `make kind-run` target to run the current version of kube-bench in the cluster and follow the logs of pods created. (Ctrl+C to exit)
Every time you want to test a change, you'll need to rebuild the docker image and push it to cluster before running it again. ( `make build-docker kind-push kind-run` )
## Contributing
Kindly read [Contributing.md](CONTRIBUTING.md) before contributing. Some instructions for the common contributions are stated below.
### Bugs
If you think you have found a bug please follow the instructions below.
- Please spend a small amount of time giving due diligence to the issue tracker. Your issue might be a duplicate.
- Open a [new issue](https://github.com/aquasecurity/kube-bench/issues/new) if a duplicate doesn't already exist.
- Note the version of kube-bench you are running (from `kube-bench version`) and the command line options you are using.
- Note the version of Kubernetes you are running (from `kubectl version` or `oc version` for OpenShift).
- Set `-v 10` command line option and save the log output. Please paste this into your issue.
- Remember users might be searching for your issue in the future, so please give it a meaningful title to help others.
### Features
We also use the GitHub issue tracker to track feature requests. If you have an idea to make kube-bench even more awesome follow the steps below.
- Open a [new issue](https://github.com/aquasecurity/kube-bench/issues/new).
- Remember users might be searching for your issue in the future, so please give it a meaningful title to helps others.
- Clearly define the use case, using concrete examples. For example, I type `this` and kube-bench does `that`.
- If you would like to include a technical design for your feature please feel free to do so.
### Pull Requests
We welcome pull requests!
- Your PR is more likely to be accepted if it focuses on just one change.
- Please include a comment with the results before and after your change.
- Your PR is more likely to be accepted if it includes tests. (We have not historically been very strict about tests, but we would like to improve this!).
- You're welcome to submit a draft PR if you would like early feedback on an idea or an approach.
- Happy coding!
[kube-bench-aws-security-hub]: ./docs/asff.md

2
cfg/ack-1.0/config.yaml Normal file
View File

@@ -0,0 +1,2 @@
---
## Version-specific settings that override the values in cfg/config.yaml

View File

@@ -0,0 +1,39 @@
---
controls:
version: "ack-1.0"
id: 3
text: "Control Plane Configuration"
type: "controlplane"
groups:
- id: 3.1
text: "Authentication and Authorization"
checks:
- id: 3.1.1
text: "Revoke client certificate when possible leakage (Manual)"
type: "manual"
remediation: |
Kubernetes provides the option to use client certificates for user authentication.
ACK issues kubeconfig with its client certificates as the user credentials for connecing to target cluster.
User should revoke his/her issued kubeconfig when possible leakage.
scored: false
- id: 3.2
text: "Logging"
checks:
- id: 3.2.1
text: "Ensure that a minimal audit policy is created (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--audit-policy-file"
remediation: |
Create an audit policy file for your cluster.
scored: false
- id: 3.2.2
text: "Ensure that the audit policy covers key security concerns (Manual)"
type: "manual"
remediation: |
Consider modification of the audit policy in use on the cluster to include these items, at a
minimum.
scored: false

135
cfg/ack-1.0/etcd.yaml Normal file
View File

@@ -0,0 +1,135 @@
---
controls:
version: "ack-1.0"
id: 2
text: "Etcd Node Configuration"
type: "etcd"
groups:
- id: 2
text: "Etcd Node Configuration Files"
checks:
- id: 2.1
text: "Ensure that the --cert-file and --key-file arguments are set as appropriate (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
bin_op: and
test_items:
- flag: "--cert-file"
env: "ETCD_CERT_FILE"
- flag: "--key-file"
env: "ETCD_KEY_FILE"
remediation: |
Follow the etcd service documentation and configure TLS encryption.
Then, edit the etcd pod specification file /etc/kubernetes/manifests/etcd.yaml
on the master node and set the below parameters.
--cert-file=</path/to/ca-file>
--key-file=</path/to/key-file>
scored: true
- id: 2.2
text: "Ensure that the --client-cert-auth argument is set to true (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
test_items:
- flag: "--client-cert-auth"
env: "ETCD_CLIENT_CERT_AUTH"
compare:
op: eq
value: true
remediation: |
Edit the etcd pod specification file $etcdconf on the master
node and set the below parameter.
--client-cert-auth="true"
scored: true
- id: 2.3
text: "Ensure that the --auto-tls argument is not set to true (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--auto-tls"
env: "ETCD_AUTO_TLS"
set: false
- flag: "--auto-tls"
env: "ETCD_AUTO_TLS"
compare:
op: eq
value: false
remediation: |
Edit the etcd pod specification file $etcdconf on the master
node and either remove the --auto-tls parameter or set it to false.
--auto-tls=false
scored: true
- id: 2.4
text: "Ensure that the --peer-cert-file and --peer-key-file arguments are
set as appropriate (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
bin_op: and
test_items:
- flag: "--peer-cert-file"
env: "ETCD_PEER_CERT_FILE"
- flag: "--peer-key-file"
env: "ETCD_PEER_KEY_FILE"
remediation: |
Follow the etcd service documentation and configure peer TLS encryption as appropriate
for your etcd cluster.
Then, edit the etcd pod specification file $etcdconf on the
master node and set the below parameters.
--peer-client-file=</path/to/peer-cert-file>
--peer-key-file=</path/to/peer-key-file>
scored: true
- id: 2.5
text: "Ensure that the --peer-client-cert-auth argument is set to true (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
test_items:
- flag: "--peer-client-cert-auth"
env: "ETCD_PEER_CLIENT_CERT_AUTH"
compare:
op: eq
value: true
remediation: |
Edit the etcd pod specification file $etcdconf on the master
node and set the below parameter.
--peer-client-cert-auth=true
scored: true
- id: 2.6
text: "Ensure that the --peer-auto-tls argument is not set to true (Automated)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--peer-auto-tls"
env: "ETCD_PEER_AUTO_TLS"
set: false
- flag: "--peer-auto-tls"
env: "ETCD_PEER_AUTO_TLS"
compare:
op: eq
value: false
remediation: |
Edit the etcd pod specification file $etcdconf on the master
node and either remove the --peer-auto-tls parameter or set it to false.
--peer-auto-tls=false
scored: true
- id: 2.7
text: "Ensure that a unique Certificate Authority is used for etcd (Manual)"
audit: "/bin/ps -ef | /bin/grep $etcdbin | /bin/grep -v grep"
tests:
test_items:
- flag: "--trusted-ca-file"
env: "ETCD_TRUSTED_CA_FILE"
remediation: |
[Manual test]
Follow the etcd documentation and create a dedicated certificate authority setup for the
etcd service.
Then, edit the etcd pod specification file $etcdconf on the
master node and set the below parameter.
--trusted-ca-file=</path/to/ca-file>
scored: false

View File

@@ -0,0 +1,127 @@
---
controls:
version: "ack-1.0"
id: 6
text: "Managed Services"
type: "managedservices"
groups:
- id: 6.1
text: "Image Registry and Image Scanning"
checks:
- id: 6.1.1
text: "Ensure Image Vulnerability Scanning using ACR image scanning or a third party provider (Manual)"
type: "manual"
remediation: |
Ensure Image Vulnerability Scanning using ACR image scanning or a third party provider by follow the ACR document: https://www.alibabacloud.com/help/doc-detail/160146.htm
scored: false
- id: 6.1.2
text: "Minimize user access to ACR (Manual)"
type: "manual"
remediation: |
Minimize user access to ACR by follow the ACR document to setup network access control: https://www.alibabacloud.com/help/doc-detail/142179.htm
And follow the ACR document to setup Resource Access Management (RAM) policies for ACR: https://www.alibabacloud.com/help/doc-detail/144229.htm
scored: false
- id: 6.1.3
text: "Minimize cluster access to read-only for ACR (Manual)"
type: "manual"
remediation: Minimize cluster access to read-only for ACR
scored: false
- id: 6.1.4
text: "Minimize Container Registries to only those approved (Manual)"
type: "manual"
remediation: Minimize Container Registries to only those approved
scored: false
- id: 6.2
text: "Key Management Service (KMS)"
checks:
- id: 6.2.1
text: "Ensure Kubernetes Secrets are encrypted using keys managed in KMS (Manual)"
type: "manual"
remediation: |
Ensure Kubernetes Secrets are encrypted using keys managed in KMS by follow The ACK document: https://www.alibabacloud.com/help/zh/doc-detail/177372.htm
scored: false
- id: 6.3
text: "Cluster Networking"
checks:
- id: 6.3.1
text: "Restrict Access to the Control Plane Endpoint (Manual)"
type: "manual"
remediation: Restrict Access to the Control Plane Endpoint
scored: false
- id: 6.3.2
text: "Ensure clusters are created with Private Endpoint Enabled and Public Access Disabled (Manual)"
type: "manual"
remediation: Ensure clusters are created with Private Endpoint Enabled and Public Access Disabled
scored: false
- id: 6.3.3
text: "Ensure clusters are created with Private Nodes (Manual)"
type: "manual"
remediation: Ensure clusters are created with Private Nodes
scored: false
- id: 6.3.4
text: "Ensure Network Policy is Enabled and set as appropriate (Manual)"
type: "manual"
remediation: Ensure Network Policy is Enabled and set as appropriate
scored: false
- id: 6.3.5
text: "Encrypt traffic to HTTPS load balancers with TLS certificates (Manual)"
type: "manual"
remediation: Encrypt traffic to HTTPS load balancers with TLS certificates
scored: false
- id: 6.4
text: "Storage"
checks:
- id: 6.4.1
text: "Enable data disk encryption for Alibaba Cloud Disks (Manual)"
type: "manual"
remediation: Enable data disk encryption for Alibaba Cloud Disks
scored: false
- id: 6.5
text: "Logging"
checks:
- id: 6.5.1
text: "Ensure Cluster Auditing is Enabled (Manual)"
type: "manual"
remediation: Ensure Cluster Auditing is Enabled
scored: false
- id: 6.6
text: "Other Cluster Configurations"
checks:
- id: 6.6.1
text: "Ensure Pod Security Policy is Enabled and set as appropriate (Manual)"
type: "manual"
remediation: Ensure Pod Security Policy is Enabled and set as appropriate
scored: false
- id: 6.6.2
text: "Enable Cloud Security Center (Manual)"
type: "manual"
remediation: Enable Cloud Security Center
scored: false
- id: 6.6.3
text: "Consider ACK Sandboxed-Container for running untrusted workloads (Manual)"
type: "manual"
remediation: Consider ACK Sandboxed-Container for running untrusted workloads
- id: 6.6.4
text: "Consider ACK TEE-based when running confidential computing (Manual)"
type: "manual"
remediation: Consider ACK TEE-based when running confidential computing
- id: 6.6.5
text: "Consider use service account token volume projection (Manual)"
type: "manual"
remediation: Consider use service account token volume projection

968
cfg/ack-1.0/master.yaml Normal file
View File

@@ -0,0 +1,968 @@
---
controls:
version: "ack-1.0"
id: 1
text: "Master Node Security Configuration"
type: "master"
groups:
- id: 1.1
text: "Master Node Configuration Files"
checks:
- id: 1.1.1
text: "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c permissions=%a $apiserverconf; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the
master node.
For example, chmod 644 $apiserverconf
scored: true
- id: 1.1.2
text: "Ensure that the API server pod specification file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e $apiserverconf; then stat -c %U:%G $apiserverconf; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $apiserverconf
scored: true
- id: 1.1.3
text: "Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c permissions=%a $controllermanagerconf; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 $controllermanagerconf
scored: true
- id: 1.1.4
text: "Ensure that the controller manager pod specification file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e $controllermanagerconf; then stat -c %U:%G $controllermanagerconf; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $controllermanagerconf
scored: true
- id: 1.1.5
text: "Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c permissions=%a $schedulerconf; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 $schedulerconf
scored: true
- id: 1.1.6
text: "Ensure that the scheduler pod specification file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e $schedulerconf; then stat -c %U:%G $schedulerconf; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $schedulerconf
scored: true
- id: 1.1.7
text: "Ensure that the etcd service file permissions are set to 644 or more restrictive (Automated)"
audit: |
stat -c permissions=%a /usr/lib/systemd/system/etcd.service || \
if test -e $etcdconf; then find $etcdconf -name '*etcd*' | xargs stat -c permissions=%a; fi
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 $etcdconf
scored: true
- id: 1.1.8
text: "Ensure that the etcd service file ownership is set to root:root (Automated)"
audit: |
stat -c %U:%G /usr/lib/systemd/system/etcd.service || \
if test -e $etcdconf; then find $etcdconf -name '*etcd*' | xargs stat -c %U:%G; fi
use_multiple_values: true
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $etcdconf
scored: true
- id: 1.1.9
text: "Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Manual)"
audit: "stat -c permissions=%a <path/to/cni/files>"
type: "manual"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 <path/to/cni/files>
scored: false
- id: 1.1.10
text: "Ensure that the Container Network Interface file ownership is set to root:root (Manual)"
audit: "stat -c %U:%G <path/to/cni/files>"
type: "manual"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root <path/to/cni/files>
scored: false
- id: 1.1.11
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)"
audit: |
stat -c permissions=%a /var/lib/etcd/data.etcd || \
ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c permissions=%a
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "700"
remediation: |
On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the below command:
ps -ef | grep etcd
Run the below command (based on the etcd data directory found above). For example,
chmod 700 /var/lib/etcd
scored: true
- id: 1.1.12
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)"
audit: |
stat -c %U:%G /var/lib/etcd/data.etcd || \
ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G
tests:
test_items:
- flag: "etcd:etcd"
remediation: |
On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the below command:
ps -ef | grep etcd
Run the below command (based on the etcd data directory found above).
For example, chown etcd:etcd /var/lib/etcd
scored: true
- id: 1.1.13
text: "Ensure that the admin.conf file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e /etc/kubernetes/admin.conf; then stat -c permissions=%a /etc/kubernetes/admin.conf; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 /etc/kubernetes/admin.conf
scored: true
- id: 1.1.14
text: "Ensure that the admin.conf file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e /etc/kubernetes/admin.conf; then stat -c %U:%G /etc/kubernetes/admin.conf; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root /etc/kubernetes/admin.conf
scored: true
- id: 1.1.15
text: "Ensure that the scheduler.conf file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c permissions=%a $schedulerkubeconfig; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 $schedulerkubeconfig
scored: true
- id: 1.1.16
text: "Ensure that the scheduler.conf file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e $schedulerkubeconfig; then stat -c %U:%G $schedulerkubeconfig; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $schedulerkubeconfig
scored: true
- id: 1.1.17
text: "Ensure that the controller-manager.conf file permissions are set to 644 or more restrictive (Automated)"
audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c permissions=%a $controllermanagerkubeconfig; fi'"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod 644 $controllermanagerkubeconfig
scored: true
- id: 1.1.18
text: "Ensure that the controller-manager.conf file ownership is set to root:root (Automated)"
audit: "/bin/sh -c 'if test -e $controllermanagerkubeconfig; then stat -c %U:%G $controllermanagerkubeconfig; fi'"
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown root:root $controllermanagerkubeconfig
scored: true
- id: 1.1.19
text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Automated)"
audit: "find /etc/kubernetes/pki/ | xargs stat -c %U:%G"
use_multiple_values: true
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chown -R root:root /etc/kubernetes/pki/
scored: true
- id: 1.1.20
text: "Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Manual)"
audit: "find /etc/kubernetes/pki -name '*.crt' | xargs stat -c permissions=%a"
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod -R 644 /etc/kubernetes/pki/*.crt
scored: false
- id: 1.1.21
text: "Ensure that the Kubernetes PKI key file permissions are set to 600 (Manual)"
audit: "find /etc/kubernetes/pki -name '*.key' | xargs stat -c permissions=%a"
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "600"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
chmod -R 600 /etc/kubernetes/pki/*.key
scored: false
- id: 1.2
text: "API Server"
checks:
- id: 1.2.1
text: "Ensure that the --basic-auth-file argument is not set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--basic-auth-file"
set: false
remediation: |
Follow the documentation and configure alternate mechanisms for authentication. Then,
edit the API server pod specification file $apiserverconf
on the master node and remove the --basic-auth-file=<filename> parameter.
scored: true
- id: 1.2.2
text: "Ensure that the --token-auth-file parameter is not set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--token-auth-file"
set: false
remediation: |
Follow the documentation and configure alternate mechanisms for authentication. Then,
edit the API server pod specification file $apiserverconf
on the master node and remove the --token-auth-file=<filename> parameter.
scored: true
- id: 1.2.3
text: "Ensure that the --kubelet-https argument is set to true (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--kubelet-https"
compare:
op: eq
value: true
- flag: "--kubelet-https"
set: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and remove the --kubelet-https parameter.
scored: true
- id: 1.2.4
text: "Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: and
test_items:
- flag: "--kubelet-client-certificate"
- flag: "--kubelet-client-key"
remediation: |
Follow the Kubernetes documentation and set up the TLS connection between the
apiserver and kubelets. Then, edit API server pod specification file
$apiserverconf on the master node and set the
kubelet client certificate and key parameters as below.
--kubelet-client-certificate=<path/to/client-certificate-file>
--kubelet-client-key=<path/to/client-key-file>
scored: true
- id: 1.2.5
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--authorization-mode"
compare:
op: nothave
value: "AlwaysAllow"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --authorization-mode parameter to values other than AlwaysAllow.
One such example could be as below.
--authorization-mode=RBAC
scored: true
- id: 1.2.6
text: "Ensure that the --authorization-mode argument includes Node (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--authorization-mode"
compare:
op: has
value: "Node"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --authorization-mode parameter to a value that includes Node.
--authorization-mode=Node,RBAC
scored: true
- id: 1.2.7
text: "Ensure that the --authorization-mode argument includes RBAC (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--authorization-mode"
compare:
op: has
value: "RBAC"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --authorization-mode parameter to a value that includes RBAC,
for example:
--authorization-mode=Node,RBAC
scored: true
- id: 1.2.8
text: "Ensure that the admission control plugin EventRateLimit is set (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--enable-admission-plugins"
compare:
op: has
value: "EventRateLimit"
remediation: |
Follow the Kubernetes documentation and set the desired limits in a configuration file.
Then, edit the API server pod specification file $apiserverconf
and set the below parameters.
--enable-admission-plugins=...,EventRateLimit,...
--admission-control-config-file=<path/to/configuration/file>
scored: false
- id: 1.2.9
text: "Ensure that the admission control plugin AlwaysAdmit is not set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--enable-admission-plugins"
compare:
op: nothave
value: AlwaysAdmit
- flag: "--enable-admission-plugins"
set: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and either remove the --enable-admission-plugins parameter, or set it to a
value that does not include AlwaysAdmit.
scored: true
- id: 1.2.10
text: "Ensure that the admission control plugin AlwaysPullImages is set (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--enable-admission-plugins"
compare:
op: has
value: "AlwaysPullImages"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --enable-admission-plugins parameter to include
AlwaysPullImages.
--enable-admission-plugins=...,AlwaysPullImages,...
scored: false
- id: 1.2.11
text: "Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--enable-admission-plugins"
compare:
op: has
value: "SecurityContextDeny"
- flag: "--enable-admission-plugins"
compare:
op: has
value: "PodSecurityPolicy"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --enable-admission-plugins parameter to include
SecurityContextDeny, unless PodSecurityPolicy is already in place.
--enable-admission-plugins=...,SecurityContextDeny,...
scored: false
- id: 1.2.12
text: "Ensure that the admission control plugin ServiceAccount is set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--disable-admission-plugins"
compare:
op: nothave
value: "ServiceAccount"
- flag: "--disable-admission-plugins"
set: false
remediation: |
Follow the documentation and create ServiceAccount objects as per your environment.
Then, edit the API server pod specification file $apiserverconf
on the master node and ensure that the --disable-admission-plugins parameter is set to a
value that does not include ServiceAccount.
scored: true
- id: 1.2.13
text: "Ensure that the admission control plugin NamespaceLifecycle is set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--disable-admission-plugins"
compare:
op: nothave
value: "NamespaceLifecycle"
- flag: "--disable-admission-plugins"
set: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --disable-admission-plugins parameter to
ensure it does not include NamespaceLifecycle.
scored: true
- id: 1.2.14
text: "Ensure that the admission control plugin PodSecurityPolicy is set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--enable-admission-plugins"
compare:
op: has
value: "PodSecurityPolicy"
remediation: |
Follow the documentation and create Pod Security Policy objects as per your environment.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the --enable-admission-plugins parameter to a
value that includes PodSecurityPolicy:
--enable-admission-plugins=...,PodSecurityPolicy,...
Then restart the API Server.
scored: true
- id: 1.2.15
text: "Ensure that the admission control plugin NodeRestriction is set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--enable-admission-plugins"
compare:
op: has
value: "NodeRestriction"
remediation: |
Follow the Kubernetes documentation and configure NodeRestriction plug-in on kubelets.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the --enable-admission-plugins parameter to a
value that includes NodeRestriction.
--enable-admission-plugins=...,NodeRestriction,...
scored: true
- id: 1.2.16
text: "Ensure that the --insecure-bind-address argument is not set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--insecure-bind-address"
set: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and remove the --insecure-bind-address parameter.
scored: true
- id: 1.2.17
text: "Ensure that the --insecure-port argument is set to 0 (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--insecure-port"
compare:
op: eq
value: 0
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the below parameter.
--insecure-port=0
scored: true
- id: 1.2.18
text: "Ensure that the --secure-port argument is not set to 0 (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--secure-port"
compare:
op: gt
value: 0
- flag: "--secure-port"
set: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and either remove the --secure-port parameter or
set it to a different (non-zero) desired port.
scored: true
- id: 1.2.19
text: "Ensure that the --profiling argument is set to false (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--profiling"
compare:
op: eq
value: false
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the below parameter.
--profiling=false
scored: true
- id: 1.2.20
text: "Ensure that the --audit-log-path argument is set (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--audit-log-path"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --audit-log-path parameter to a suitable path and
file where you would like audit logs to be written, for example:
--audit-log-path=/var/log/apiserver/audit.log
scored: true
- id: 1.2.21
text: "Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--audit-log-maxage"
compare:
op: gte
value: 30
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --audit-log-maxage parameter to 30 or as an appropriate number of days:
--audit-log-maxage=30
scored: true
- id: 1.2.22
text: "Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--audit-log-maxbackup"
compare:
op: gte
value: 10
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
value.
--audit-log-maxbackup=10
scored: true
- id: 1.2.23
text: "Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--audit-log-maxsize"
compare:
op: gte
value: 100
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --audit-log-maxsize parameter to an appropriate size in MB.
For example, to set it as 100 MB:
--audit-log-maxsize=100
scored: true
- id: 1.2.24
text: "Ensure that the --request-timeout argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
type: manual
remediation: |
Edit the API server pod specification file $apiserverconf
and set the below parameter as appropriate and if needed.
For example,
--request-timeout=300s
scored: true
- id: 1.2.25
text: "Ensure that the --service-account-lookup argument is set to true (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--service-account-lookup"
set: false
- flag: "--service-account-lookup"
compare:
op: eq
value: true
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the below parameter.
--service-account-lookup=true
Alternatively, you can delete the --service-account-lookup parameter from this file so
that the default takes effect.
scored: true
- id: 1.2.26
text: "Ensure that the --service-account-key-file argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--service-account-key-file"
remediation: |
Edit the API server pod specification file $apiserverconf
on the master node and set the --service-account-key-file parameter
to the public key file for service accounts:
--service-account-key-file=<filename>
scored: true
- id: 1.2.27
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: and
test_items:
- flag: "--etcd-certfile"
- flag: "--etcd-keyfile"
remediation: |
Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the etcd certificate and key file parameters.
--etcd-certfile=<path/to/client-certificate-file>
--etcd-keyfile=<path/to/client-key-file>
scored: true
- id: 1.2.28
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: and
test_items:
- flag: "--tls-cert-file"
- flag: "--tls-private-key-file"
remediation: |
Follow the Kubernetes documentation and set up the TLS connection on the apiserver.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the TLS certificate and private key file parameters.
--tls-cert-file=<path/to/tls-certificate-file>
--tls-private-key-file=<path/to/tls-key-file>
scored: true
- id: 1.2.29
text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--client-ca-file"
remediation: |
Follow the Kubernetes documentation and set up the TLS connection on the apiserver.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the client certificate authority file.
--client-ca-file=<path/to/client-ca-file>
scored: true
- id: 1.2.30
text: "Ensure that the --etcd-cafile argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--etcd-cafile"
remediation: |
Follow the Kubernetes documentation and set up the TLS connection between the apiserver and etcd.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the etcd certificate authority file parameter.
--etcd-cafile=<path/to/ca-file>
scored: true
- id: 1.2.31
text: "Ensure that the --encryption-provider-config argument is set as appropriate (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--encryption-provider-config"
remediation: |
Follow the Kubernetes documentation and configure a EncryptionConfig file.
Then, edit the API server pod specification file $apiserverconf
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
scored: false
- id: 1.2.32
text: "Ensure that encryption providers are appropriately configured (Manual)"
audit: |
ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep $apiserverbin | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
if test -e $ENCRYPTION_PROVIDER_CONFIG; then grep -A1 'providers:' $ENCRYPTION_PROVIDER_CONFIG | tail -n1 | grep -o "[A-Za-z]*" | sed 's/^/provider=/'; fi
tests:
test_items:
- flag: "provider"
compare:
op: valid_elements
value: "aescbc,kms,secretbox"
remediation: |
Follow the Kubernetes documentation and configure a EncryptionConfig file.
In this file, choose aescbc, kms or secretbox as the encryption provider.
scored: false
- id: 1.2.33
text: "Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
test_items:
- flag: "--tls-cipher-suites"
compare:
op: valid_elements
value: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256"
remediation: |
Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the below parameter.
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM
_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM
_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM
_SHA384
scored: false
- id: 1.3
text: "Controller Manager"
checks:
- id: 1.3.1
text: "Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Manual)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
test_items:
- flag: "--terminated-pod-gc-threshold"
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and set the --terminated-pod-gc-threshold to an appropriate threshold,
for example:
--terminated-pod-gc-threshold=10
scored: false
- id: 1.3.2
text: "Ensure that the --profiling argument is set to false (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
test_items:
- flag: "--profiling"
compare:
op: eq
value: false
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and set the below parameter.
--profiling=false
scored: true
- id: 1.3.3
text: "Ensure that the --use-service-account-credentials argument is set to true (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
test_items:
- flag: "--use-service-account-credentials"
compare:
op: noteq
value: false
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node to set the below parameter.
--use-service-account-credentials=true
scored: true
- id: 1.3.4
text: "Ensure that the --service-account-private-key-file argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
test_items:
- flag: "--service-account-private-key-file"
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and set the --service-account-private-key-file parameter
to the private key file for service accounts.
--service-account-private-key-file=<filename>
scored: true
- id: 1.3.5
text: "Ensure that the --root-ca-file argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
test_items:
- flag: "--root-ca-file"
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and set the --root-ca-file parameter to the certificate bundle file`.
--root-ca-file=<path/to/file>
scored: true
- id: 1.3.6
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--feature-gates"
compare:
op: nothave
value: "RotateKubeletServerCertificate=false"
set: true
- flag: "--feature-gates"
set: false
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and set the --feature-gates parameter to include RotateKubeletServerCertificate=true.
--feature-gates=RotateKubeletServerCertificate=true
scored: true
- id: 1.3.7
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
audit: "/bin/ps -ef | grep $controllermanagerbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--bind-address"
compare:
op: eq
value: "127.0.0.1"
- flag: "--bind-address"
set: false
remediation: |
Edit the Controller Manager pod specification file $controllermanagerconf
on the master node and ensure the correct value for the --bind-address parameter
scored: true
- id: 1.4
text: "Scheduler"
checks:
- id: 1.4.1
text: "Ensure that the --profiling argument is set to false (Automated)"
audit: "/bin/ps -ef | grep $schedulerbin | grep -v grep"
tests:
test_items:
- flag: "--profiling"
compare:
op: eq
value: false
remediation: |
Edit the Scheduler pod specification file $schedulerconf file
on the master node and set the below parameter.
--profiling=false
scored: true
- id: 1.4.2
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
audit: "/bin/ps -ef | grep $schedulerbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--bind-address"
compare:
op: eq
value: "127.0.0.1"
- flag: "--bind-address"
set: false
remediation: |
Edit the Scheduler pod specification file $schedulerconf
on the master node and ensure the correct value for the --bind-address parameter
scored: true

392
cfg/ack-1.0/node.yaml Normal file
View File

@@ -0,0 +1,392 @@
---
controls:
version: "ack-1.0"
id: 4
text: "Worker Node Security Configuration"
type: "node"
groups:
- id: 4.1
text: "Worker Node Configuration Files"
checks:
- id: 4.1.1
text: "Ensure that the kubelet service file permissions are set to 644 or more restrictive (Automated)"
audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c permissions=%a $kubeletsvc; fi'' '
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example,
chmod 644 $kubeletsvc
scored: true
- id: 4.1.2
text: "Ensure that the kubelet service file ownership is set to root:root (Automated)"
audit: '/bin/sh -c ''if test -e $kubeletsvc; then stat -c %U:%G $kubeletsvc; fi'' '
tests:
test_items:
- flag: root:root
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example,
chown root:root $kubeletsvc
scored: true
- id: 4.1.3
text: "If proxy kubeconfig file exists ensure permissions are set to 644 or more restrictive (Manual)"
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c permissions=%a $proxykubeconfig; fi'' '
tests:
bin_op: or
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
- flag: "$proxykubeconfig"
set: false
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example,
chmod 644 $proxykubeconfig
scored: false
- id: 4.1.4
text: "If proxy kubeconfig file exists ensure ownership is set to root:root (Manual)"
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c %U:%G $proxykubeconfig; fi'' '
tests:
bin_op: or
test_items:
- flag: root:root
- flag: "$proxykubeconfig"
set: false
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example, chown root:root $proxykubeconfig
scored: false
- id: 4.1.5
text: "Ensure that the --kubeconfig kubelet.conf file permissions are set to 644 or more restrictive (Automated)"
audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c permissions=%a $kubeletkubeconfig; fi'' '
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example,
chmod 644 $kubeletkubeconfig
scored: true
- id: 4.1.6
text: "Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root (Manual)"
audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'' '
tests:
test_items:
- flag: root:root
remediation: |
Run the below command (based on the file location on your system) on the each worker node.
For example,
chown root:root $kubeletkubeconfig
scored: false
- id: 4.1.7
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Manual)"
audit: |
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
if test -e $CAFILE; then stat -c permissions=%a $CAFILE; fi
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the following command to modify the file permissions of the
--client-ca-file chmod 644 <filename>
scored: false
- id: 4.1.8
text: "Ensure that the client certificate authorities file ownership is set to root:root (Manual)"
audit: |
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
tests:
test_items:
- flag: root:root
compare:
op: eq
value: root:root
remediation: |
Run the following command to modify the ownership of the --client-ca-file.
chown root:root <filename>
scored: false
- id: 4.1.9
text: "Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive (Automated)"
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c permissions=%a $kubeletconf; fi'' '
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the following command (using the config file location identified in the Audit step)
chmod 644 $kubeletconf
scored: true
- id: 4.1.10
text: "Ensure that the kubelet --config configuration file ownership is set to root:root (Automated)"
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c %U:%G $kubeletconf; fi'' '
tests:
test_items:
- flag: root:root
remediation: |
Run the following command (using the config file location identified in the Audit step)
chown root:root $kubeletconf
scored: true
- id: 4.2
text: "Kubelet"
checks:
- id: 4.2.1
text: "Ensure that the anonymous-auth argument is set to false (Automated)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: "--anonymous-auth"
path: '{.authentication.anonymous.enabled}'
compare:
op: eq
value: false
remediation: |
If using a Kubelet config file, edit the file to set authentication: anonymous: enabled to
false.
If using executable arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
--anonymous-auth=false
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: true
- id: 4.2.2
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --authorization-mode
path: '{.authorization.mode}'
compare:
op: nothave
value: AlwaysAllow
remediation: |
If using a Kubelet config file, edit the file to set authorization: mode to Webhook. If
using executable arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_AUTHZ_ARGS variable.
--authorization-mode=Webhook
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: true
- id: 4.2.3
text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --client-ca-file
path: '{.authentication.x509.clientCAFile}'
remediation: |
If using a Kubelet config file, edit the file to set authentication: x509: clientCAFile to
the location of the client CA file.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_AUTHZ_ARGS variable.
--client-ca-file=<path/to/client-ca-file>
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: true
- id: 4.2.4
text: "Ensure that the --read-only-port argument is set to 0 (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
bin_op: or
test_items:
- flag: "--read-only-port"
path: '{.readOnlyPort}'
compare:
op: eq
value: 0
- flag: "--read-only-port"
path: '{.readOnlyPort}'
set: false
remediation: |
If using a Kubelet config file, edit the file to set readOnlyPort to 0.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
--read-only-port=0
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false
- id: 4.2.5
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --streaming-connection-idle-timeout
path: '{.streamingConnectionIdleTimeout}'
compare:
op: noteq
value: 0
- flag: --streaming-connection-idle-timeout
path: '{.streamingConnectionIdleTimeout}'
set: false
bin_op: or
remediation: |
If using a Kubelet config file, edit the file to set streamingConnectionIdleTimeout to a
value other than 0.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
--streaming-connection-idle-timeout=5m
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false
- id: 4.2.6
text: "Ensure that the --protect-kernel-defaults argument is set to true (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --protect-kernel-defaults
path: '{.protectKernelDefaults}'
compare:
op: eq
value: true
remediation: |
If using a Kubelet config file, edit the file to set protectKernelDefaults: true.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
--protect-kernel-defaults=true
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false
- id: 4.2.7
text: "Ensure that the --make-iptables-util-chains argument is set to true (Automated)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --make-iptables-util-chains
path: '{.makeIPTablesUtilChains}'
compare:
op: eq
value: true
- flag: --make-iptables-util-chains
path: '{.makeIPTablesUtilChains}'
set: false
bin_op: or
remediation: |
If using a Kubelet config file, edit the file to set makeIPTablesUtilChains: true.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
remove the --make-iptables-util-chains argument from the
KUBELET_SYSTEM_PODS_ARGS variable.
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: true
- id: 4.2.8
text: "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --event-qps
path: '{.eventRecordQPS}'
compare:
op: eq
value: 0
remediation: |
If using a Kubelet config file, edit the file to set eventRecordQPS: to an appropriate level.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameter in KUBELET_SYSTEM_PODS_ARGS variable.
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false
- id: 4.2.9
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --tls-cert-file
path: '{.tlsCertFile}'
- flag: --tls-private-key-file
path: '{.tlsPrivateKeyFile}'
remediation: |
If using a Kubelet config file, edit the file to set tlsCertFile to the location
of the certificate file to use to identify this Kubelet, and tlsPrivateKeyFile
to the location of the corresponding private key file.
If using command line arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the below parameters in KUBELET_CERTIFICATE_ARGS variable.
--tls-cert-file=<path/to/tls-certificate-file>
--tls-private-key-file=<path/to/tls-key-file>
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false
- id: 4.2.10
text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Manual)"
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
test_items:
- flag: --tls-cipher-suites
path: '{range .tlsCipherSuites[:]}{}{'',''}{end}'
compare:
op: valid_elements
value: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
remediation: |
If using a Kubelet config file, edit the file to set TLSCipherSuites: to
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
or to a subset of these values.
If using executable arguments, edit the kubelet service file
$kubeletsvc on each worker node and
set the --tls-cipher-suites parameter as follows, or to a subset of these values.
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256
Based on your system, restart the kubelet service. For example:
systemctl daemon-reload
systemctl restart kubelet.service
scored: false

239
cfg/ack-1.0/policies.yaml Normal file
View File

@@ -0,0 +1,239 @@
---
controls:
version: "ack-1.0"
id: 5
text: "Kubernetes Policies"
type: "policies"
groups:
- id: 5.1
text: "RBAC and Service Accounts"
checks:
- id: 5.1.1
text: "Ensure that the cluster-admin role is only used where required (Manual)"
type: "manual"
remediation: |
Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
if they need this role or if they could use a role with fewer privileges.
Where possible, first bind users to a lower privileged role and then remove the
clusterrolebinding to the cluster-admin role :
kubectl delete clusterrolebinding [name]
scored: false
- id: 5.1.2
text: "Minimize access to secrets (Manual)"
type: "manual"
remediation: |
Where possible, remove get, list and watch access to secret objects in the cluster.
scored: false
- id: 5.1.3
text: "Minimize wildcard use in Roles and ClusterRoles (Manual)"
type: "manual"
remediation: |
Where possible replace any use of wildcards in clusterroles and roles with specific
objects or actions.
scored: false
- id: 5.1.4
text: "Minimize access to create pods (Manual)"
type: "manual"
remediation: |
Where possible, remove create access to pod objects in the cluster.
scored: false
- id: 5.1.5
text: "Ensure that default service accounts are not actively used. (Manual)"
type: "manual"
remediation: |
Create explicit service accounts wherever a Kubernetes workload requires specific access
to the Kubernetes API server.
Modify the configuration of each default service account to include this value
automountServiceAccountToken: false
scored: false
- id: 5.1.6
text: "Ensure that Service Account Tokens are only mounted where necessary (Manual)"
type: "manual"
remediation: |
Modify the definition of pods and service accounts which do not need to mount service
account tokens to disable it.
scored: false
- id: 5.2
text: "Pod Security Policies"
checks:
- id: 5.2.1
text: "Minimize the admission of privileged containers (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that
the .spec.privileged field is omitted or set to false.
scored: false
- id: 5.2.2
text: "Minimize the admission of containers wishing to share the host process ID namespace (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.hostPID field is omitted or set to false.
scored: false
- id: 5.2.3
text: "Minimize the admission of containers wishing to share the host IPC namespace (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.hostIPC field is omitted or set to false.
scored: false
- id: 5.2.4
text: "Minimize the admission of containers wishing to share the host network namespace (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.hostNetwork field is omitted or set to false.
scored: false
- id: 5.2.5
text: "Minimize the admission of containers with allowPrivilegeEscalation (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.allowPrivilegeEscalation field is omitted or set to false.
scored: false
- id: 5.2.6
text: "Minimize the admission of root containers (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.runAsUser.rule is set to either MustRunAsNonRoot or MustRunAs with the range of
UIDs not including 0.
scored: false
- id: 5.2.7
text: "Minimize the admission of containers with the NET_RAW capability (Manual)"
type: "manual"
remediation: |
Create a PSP as described in the Kubernetes documentation, ensuring that the
.spec.requiredDropCapabilities is set to include either NET_RAW or ALL.
scored: false
- id: 5.2.8
text: "Minimize the admission of containers with added capabilities (Manual)"
type: "manual"
remediation: |
Ensure that allowedCapabilities is not present in PSPs for the cluster unless
it is set to an empty array.
scored: false
- id: 5.2.9
text: "Minimize the admission of containers with capabilities assigned (Manual)"
type: "manual"
remediation: |
Review the use of capabilites in applications runnning on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
scored: false
- id: 5.3
text: "Network Policies and CNI"
checks:
- id: 5.3.1
text: "Ensure that the CNI in use supports Network Policies (Manual)"
type: "manual"
remediation: |
If the CNI plugin in use does not support network policies, consideration should be given to
making use of a different plugin, or finding an alternate mechanism for restricting traffic
in the Kubernetes cluster.
scored: false
- id: 5.3.2
text: "Ensure that all Namespaces have Network Policies defined (Manual)"
type: "manual"
remediation: |
Follow the documentation and create NetworkPolicy objects as you need them.
scored: false
- id: 5.4
text: "Secrets Management"
checks:
- id: 5.4.1
text: "Prefer using secrets as files over secrets as environment variables (Manual)"
type: "manual"
remediation: |
if possible, rewrite application code to read secrets from mounted secret files, rather than
from environment variables.
scored: false
- id: 5.4.2
text: "Consider external secret storage (Manual)"
type: "manual"
remediation: |
Refer to the secrets management options offered by your cloud provider or a third-party
secrets management solution.
scored: false
- id: 5.5
text: "Extensible Admission Control"
checks:
- id: 5.5.1
text: "Configure Image Provenance using ImagePolicyWebhook admission controller (Manual)"
type: "manual"
remediation: |
Follow the Kubernetes documentation and setup image provenance.
scored: false
- id: 5.6
text: "General Policies"
checks:
- id: 5.6.1
text: "Create administrative boundaries between resources using namespaces (Manual)"
type: "manual"
remediation: |
Follow the documentation and create namespaces for objects in your deployment as you need
them.
scored: false
- id: 5.6.2
text: "Ensure that the seccomp profile is set to docker/default in your pod definitions (Manual)"
type: "manual"
remediation: |
Seccomp is an alpha feature currently. By default, all alpha features are disabled. So, you
would need to enable alpha features in the apiserver by passing "--feature-
gates=AllAlpha=true" argument.
Edit the /etc/kubernetes/apiserver file on the master node and set the KUBE_API_ARGS
parameter to "--feature-gates=AllAlpha=true"
KUBE_API_ARGS="--feature-gates=AllAlpha=true"
Based on your system, restart the kube-apiserver service. For example:
systemctl restart kube-apiserver.service
Use annotations to enable the docker/default seccomp profile in your pod definitions. An
example is as below:
apiVersion: v1
kind: Pod
metadata:
name: trustworthy-pod
annotations:
seccomp.security.alpha.kubernetes.io/pod: docker/default
spec:
containers:
- name: trustworthy-container
image: sotrustworthy:latest
scored: false
- id: 5.6.3
text: "Apply Security Context to Your Pods and Containers (Manual)"
type: "manual"
remediation: |
Follow the Kubernetes documentation and apply security contexts to your pods. For a
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
Containers.
scored: false
- id: 5.6.4
text: "The default namespace should not be used (Manual)"
type: "manual"
remediation: |
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
resources and that all new resources are created in a specific namespace.
scored: false

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.5
version: "cis-1.5"
id: 3
text: "Control Plane Configuration"
type: "controlplane"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.15
version: "cis-1.5"
id: 2
text: "Etcd Node Configuration"
type: "etcd"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.5
version: "cis-1.5"
id: 1
text: "Master Node Security Configuration"
type: "master"
@@ -766,13 +766,7 @@ groups:
- id: 1.2.26
text: "Ensure that the --request-timeout argument is set as appropriate (Scored)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--request-timeout"
set: false
- flag: "--request-timeout"
set: true
type: manual
remediation: |
Edit the API server pod specification file $apiserverconf
and set the below parameter as appropriate and if needed.

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.5
version: "cis-1.5"
id: 4
text: "Worker Node Security Configuration"
type: "node"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.5
version: "cis-1.5"
id: 5
text: "Kubernetes Policies"
type: "policies"
@@ -131,7 +131,7 @@ groups:
text: "Minimize the admission of containers with capabilities assigned (Not Scored)"
type: "manual"
remediation: |
Review the use of capabilites in applications runnning on your cluster. Where a namespace
Review the use of capabilites in applications running on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
scored: false

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.6
version: "cis-1.6"
id: 3
text: "Control Plane Configuration"
type: "controlplane"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.6
version: "cis-1.6"
id: 2
text: "Etcd Node Configuration"
type: "etcd"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.6
version: "cis-1.6"
id: 1
text: "Master Node Security Configuration"
type: "master"
@@ -120,8 +120,16 @@ groups:
- id: 1.1.9
text: "Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Manual)"
audit: "stat -c permissions=%a <path/to/cni/files>"
type: "manual"
audit: |
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs stat -c permissions=%a
find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c permissions=%a
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
@@ -130,8 +138,13 @@ groups:
- id: 1.1.10
text: "Ensure that the Container Network Interface file ownership is set to root:root (Manual)"
audit: "stat -c %U:%G <path/to/cni/files>"
type: "manual"
audit: |
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs stat -c %U:%G
find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c %U:%G
use_multiple_values: true
tests:
test_items:
- flag: "root:root"
remediation: |
Run the below command (based on the file location on your system) on the master node.
For example,
@@ -701,12 +714,7 @@ groups:
- id: 1.2.26
text: "Ensure that the --request-timeout argument is set as appropriate (Automated)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
tests:
bin_op: or
test_items:
- flag: "--request-timeout"
set: false
- flag: "--request-timeout"
type: manual
remediation: |
Edit the API server pod specification file $apiserverconf
and set the below parameter as appropriate and if needed.
@@ -819,8 +827,15 @@ groups:
- id: 1.2.34
text: "Ensure that encryption providers are appropriately configured (Manual)"
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
type: "manual"
audit: |
ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep $apiserverbin | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
if test -e $ENCRYPTION_PROVIDER_CONFIG; then grep -A1 'providers:' $ENCRYPTION_PROVIDER_CONFIG | tail -n1 | grep -o "[A-Za-z]*" | sed 's/^/provider=/'; fi
tests:
test_items:
- flag: "provider"
compare:
op: valid_elements
value: "aescbc,kms,secretbox"
remediation: |
Follow the Kubernetes documentation and configure a EncryptionConfig file.
In this file, choose aescbc, kms or secretbox as the encryption provider.

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.6
version: "cis-1.6"
id: 4
text: "Worker Node Security Configuration"
type: "node"

View File

@@ -1,6 +1,6 @@
---
controls:
version: 1.6
version: "cis-1.6"
id: 5
text: "Kubernetes Policies"
type: "policies"
@@ -131,7 +131,7 @@ groups:
text: "Minimize the admission of containers with capabilities assigned (Manual)"
type: "manual"
remediation: |
Review the use of capabilites in applications runnning on your cluster. Where a namespace
Review the use of capabilites in applications running on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
scored: false

View File

@@ -15,6 +15,7 @@ master:
- flanneld
# kubernetes is a component to cover the config file /etc/kubernetes/config that is referred to in the benchmark
- kubernetes
- kubelet
kubernetes:
defaultconf: /etc/kubernetes/config
@@ -25,12 +26,15 @@ master:
- "hyperkube apiserver"
- "hyperkube kube-apiserver"
- "apiserver"
- "openshift start master api"
- "hypershift openshift-kube-apiserver"
confs:
- /etc/kubernetes/manifests/kube-apiserver.yaml
- /etc/kubernetes/manifests/kube-apiserver.yml
- /etc/kubernetes/manifests/kube-apiserver.manifest
- /var/snap/kube-apiserver/current/args
- /var/snap/microk8s/current/args/kube-apiserver
- /etc/origin/master/master-config.yaml
defaultconf: /etc/kubernetes/manifests/kube-apiserver.yaml
scheduler:
@@ -39,15 +43,19 @@ master:
- "hyperkube scheduler"
- "hyperkube kube-scheduler"
- "scheduler"
- "openshift start master controllers"
confs:
- /etc/kubernetes/manifests/kube-scheduler.yaml
- /etc/kubernetes/manifests/kube-scheduler.yml
- /etc/kubernetes/manifests/kube-scheduler.manifest
- /var/snap/kube-scheduler/current/args
- /var/snap/microk8s/current/args/kube-scheduler
- /etc/origin/master/scheduler.json
defaultconf: /etc/kubernetes/manifests/kube-scheduler.yaml
kubeconfig:
- /etc/kubernetes/scheduler.conf
- /var/lib/kube-scheduler/kubeconfig
- /var/lib/kube-scheduler/config.yaml
defaultkubeconfig: /etc/kubernetes/scheduler.conf
controllermanager:
@@ -57,6 +65,8 @@ master:
- "hyperkube controller-manager"
- "hyperkube kube-controller-manager"
- "controller-manager"
- "openshift start master controllers"
- "hypershift openshift-controller-manager"
confs:
- /etc/kubernetes/manifests/kube-controller-manager.yaml
- /etc/kubernetes/manifests/kube-controller-manager.yml
@@ -66,12 +76,14 @@ master:
defaultconf: /etc/kubernetes/manifests/kube-controller-manager.yaml
kubeconfig:
- /etc/kubernetes/controller-manager.conf
- /var/lib/kube-controller-manager/kubeconfig
defaultkubeconfig: /etc/kubernetes/controller-manager.conf
etcd:
optional: true
bins:
- "etcd"
- "openshift start etcd"
confs:
- /etc/kubernetes/manifests/etcd.yaml
- /etc/kubernetes/manifests/etcd.yml
@@ -81,7 +93,6 @@ master:
- /var/snap/etcd/common/etcd.conf.yaml
- /var/snap/microk8s/current/args/etcd
- /usr/lib/systemd/system/etcd.service
- /etc/kubernetes/manifests
defaultconf: /etc/kubernetes/manifests/etcd.yaml
flanneld:
@@ -90,6 +101,12 @@ master:
- flanneld
defaultconf: /etc/sysconfig/flanneld
kubelet:
optional: true
bins:
- "hyperkube kubelet"
- "kubelet"
node:
components:
- kubelet
@@ -114,6 +131,8 @@ node:
- "/lib/systemd/system/kubelet.service"
- "/etc/systemd/system/snap.kubelet.daemon.service"
- "/etc/systemd/system/snap.microk8s.daemon-kubelet.service"
- "/etc/systemd/system/atomic-openshift-node.service"
- "/etc/systemd/system/origin-node.service"
bins:
- "hyperkube kubelet"
- "kubelet"
@@ -121,13 +140,16 @@ node:
- "/etc/kubernetes/kubelet.conf"
- "/var/lib/kubelet/kubeconfig"
- "/etc/kubernetes/kubelet-kubeconfig"
- "/etc/kubernetes/kubelet/kubeconfig"
- "/var/snap/microk8s/current/credentials/kubelet.config"
confs:
- "/var/lib/kubelet/config.yaml"
- "/var/lib/kubelet/config.yml"
- "/etc/kubernetes/kubelet/kubelet-config.json"
- "/etc/kubernetes/kubelet/config"
- "/home/kubernetes/kubelet-config.yaml"
- "/home/kubernetes/kubelet-config.yml"
- "/etc/default/kubeletconfig.json"
- "/etc/default/kubelet"
- "/var/lib/kubelet/kubeconfig"
- "/var/snap/kubelet/current/args"
@@ -154,6 +176,7 @@ node:
- "hyperkube proxy"
- "hyperkube kube-proxy"
- "proxy"
- "openshift start network"
confs:
- /etc/kubernetes/proxy
- /etc/kubernetes/addons/kube-proxy-daemonset.yaml
@@ -162,6 +185,7 @@ node:
- /var/snap/microk8s/current/args/kube-proxy
kubeconfig:
- "/etc/kubernetes/kubelet-kubeconfig"
- "/etc/kubernetes/kubelet/config"
- "/var/lib/kubelet/kubeconfig"
- "/var/snap/microk8s/current/credentials/proxy.config"
svc:
@@ -215,7 +239,9 @@ version_mapping:
"gke-1.0": "gke-1.0"
"ocp-3.10": "rh-0.7"
"ocp-3.11": "rh-0.7"
"ocp-4.0": "rh-1.0"
"aks-1.0": "aks-1.0"
"ack-1.0": "ack-1.0"
target_mapping:
"cis-1.5":
@@ -252,3 +278,16 @@ target_mapping:
- "controlplane"
- "policies"
- "managedservices"
"ack-1.0":
- "master"
- "node"
- "controlplane"
- "etcd"
- "policies"
- "managedservices"
"rh-1.0":
- "master"
- "node"
- "controlplane"
- "policies"
- "etcd"

View File

@@ -20,6 +20,7 @@ groups:
- id: 3.2
text: "Logging"
type: skip
checks:
- id: 3.2.1
text: "Ensure that a minimal audit policy is created (Not Scored)"

View File

@@ -7,6 +7,7 @@ type: "etcd"
groups:
- id: 2
text: "Etcd Node Configuration Files"
type: skip
checks:
- id: 2.1
text: "Ensure that the --cert-file and --key-file arguments are set as appropriate (Not Scored)"

View File

@@ -7,6 +7,7 @@ type: "master"
groups:
- id: 1.1
text: "Master Node Configuration Files "
type: skip
checks:
- id: 1.1.1
text: "Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Not Scored)"
@@ -115,6 +116,7 @@ groups:
- id: 1.2
text: "API Server"
type: skip
checks:
- id: 1.2.1
text: "Ensure that the --anonymous-auth argument is set to false (Not Scored)"
@@ -298,6 +300,7 @@ groups:
- id: 1.3
text: "Controller Manager"
type: skip
checks:
- id: 1.3.1
text: "Ensure that the --terminated-pod-gc-threshold argument is set as appropriate (Not Scored)"
@@ -336,6 +339,7 @@ groups:
- id: 1.4
text: "Scheduler"
type: skip
checks:
- id: 1.4.1
text: "Ensure that the --profiling argument is set to false (Not Scored)"

View File

@@ -10,55 +10,25 @@ groups:
checks:
- id: 4.1.1
text: "Ensure that the kubelet service file permissions are set to 644 or more restrictive (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.2
text: "Ensure that the kubelet service file ownership is set to root:root (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.3
text: "Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)"
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c %a $proxykubeconfig; fi'' '
audit: '/bin/sh -c ''if test -e $proxykubeconfig; then stat -c permissions=%a $proxykubeconfig; fi'' '
tests:
test_items:
- flag: "644"
- flag: "permissions"
compare:
op: eq
op: bitmask
value: "644"
set: true
- flag: "640"
compare:
op: eq
value: "640"
set: true
- flag: "600"
compare:
op: eq
value: "600"
set: true
- flag: "444"
compare:
op: eq
value: "444"
set: true
- flag: "440"
compare:
op: eq
value: "440"
set: true
- flag: "400"
compare:
op: eq
value: "400"
set: true
- flag: "000"
compare:
op: eq
value: "000"
set: true
bin_op: or
remediation: |
Run the below command (based on the file location on your system) on each worker node.
For example,
@@ -71,7 +41,6 @@ groups:
tests:
test_items:
- flag: root:root
set: true
remediation: |
Run the below command (based on the file location on your system) on each worker node.
For example, chown root:root $proxykubeconfig
@@ -79,65 +48,38 @@ groups:
- id: 4.1.5
text: "Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.6
text: "Ensure that the kubelet.conf file ownership is set to root:root (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.7
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.8
text: "Ensure that the client certificate authorities file ownership is set to root:root (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false
- id: 4.1.9
text: "Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Scored)"
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c %a $kubeletconf; fi'' '
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c permissions=%a $kubeletconf; fi'' '
tests:
test_items:
- flag: "644"
- flag: "permissions"
set: true
compare:
op: eq
value: "644"
- flag: "640"
set: true
compare:
op: eq
value: "640"
- flag: "600"
set: true
compare:
op: eq
value: "600"
- flag: "444"
compare:
op: eq
value: "444"
set: true
- flag: "440"
compare:
op: eq
value: "440"
set: true
- flag: "400"
compare:
op: eq
value: "400"
set: true
- flag: "000"
compare:
op: eq
value: "000"
set: true
bin_op: or
remediation: |
Run the following command (using the config file location identified in the Audit step)
chmod 644 $kubeletconf
@@ -149,7 +91,6 @@ groups:
tests:
test_items:
- flag: root:root
set: true
remediation: |
Run the following command (using the config file location identified in the Audit step)
chown root:root $kubeletconf
@@ -166,7 +107,6 @@ groups:
test_items:
- flag: "--anonymous-auth"
path: '{.authentication.anonymous.enabled}'
set: true
compare:
op: eq
value: false
@@ -190,7 +130,6 @@ groups:
test_items:
- flag: --authorization-mode
path: '{.authorization.mode}'
set: true
compare:
op: nothave
value: AlwaysAllow
@@ -234,7 +173,6 @@ groups:
test_items:
- flag: "--read-only-port"
path: '{.readOnlyPort}'
set: true
compare:
op: eq
value: 0
@@ -257,7 +195,6 @@ groups:
test_items:
- flag: --streaming-connection-idle-timeout
path: '{.streamingConnectionIdleTimeout}'
set: true
compare:
op: noteq
value: 0
@@ -285,7 +222,6 @@ groups:
test_items:
- flag: --protect-kernel-defaults
path: '{.protectKernelDefaults}'
set: true
compare:
op: eq
value: true
@@ -308,7 +244,6 @@ groups:
test_items:
- flag: --make-iptables-util-chains
path: '{.makeIPTablesUtilChains}'
set: true
compare:
op: eq
value: true
@@ -329,9 +264,6 @@ groups:
- id: 4.2.8
text: "Ensure that the --hostname-override argument is not set (Scored)"
# This is one of those properties that can only be set as a command line argument.
# To check if the property is set as expected, we need to parse the kubelet command
# instead reading the Kubelet Configuration file.
audit: "/bin/ps -fC $kubeletbin "
tests:
test_items:
@@ -373,13 +305,12 @@ groups:
audit: "/bin/ps -fC $kubeletbin"
audit_config: "/bin/cat $kubeletconf"
tests:
bin_op: and
test_items:
- flag: --tls-cert-file
path: '{.tlsCertFile}'
set: true
- flag: --tls-private-key-file
path: '{.tlsPrivateKeyFile}'
set: true
remediation: |
If using a Kubelet config file, edit the file to set tlsCertFile to the location
of the certificate file to use to identify this Kubelet, and tlsPrivateKeyFile
@@ -402,7 +333,6 @@ groups:
test_items:
- flag: --rotate-certificates
path: '{.rotateCertificates}'
set: true
compare:
op: eq
value: true
@@ -430,7 +360,6 @@ groups:
test_items:
- flag: RotateKubeletServerCertificate
path: '{.featureGates.RotateKubeletServerCertificate}'
set: true
compare:
op: eq
value: true
@@ -445,5 +374,6 @@ groups:
- id: 4.2.13
text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Scored)"
type: skip
remediation: "This control cannot be modified in GKE."
scored: false

View File

@@ -131,7 +131,7 @@ groups:
text: "Minimize the admission of containers with capabilities assigned (Scored) "
type: "manual"
remediation: |
Review the use of capabilites in applications runnning on your cluster. Where a namespace
Review the use of capabilites in applications running on your cluster. Where a namespace
contains applications which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
scored: true

View File

@@ -1,32 +1,2 @@
---
## Version-specific settings that override the values in cfg/config.yaml
master:
apiserver:
bins:
- openshift start master api
- hypershift openshift-kube-apiserver
scheduler:
bins:
- "openshift start master controllers"
- "hyperkube kube-scheduler"
confs:
- /etc/origin/master/scheduler.json
controllermanager:
bins:
- "openshift start master controllers"
- "hypershift openshift-controller-manager"
etcd:
bins:
- openshift start etcd
node:
svcs:
- /etc/systemd/system/atomic-openshift-node.service
- /etc/systemd/system/origin-node.service
proxy:
bins:
- openshift start network

View File

@@ -1,6 +1,6 @@
---
controls:
version: 3.10
version: "rh-0.7"
id: 1
text: "Securing the OpenShift Master"
type: "master"
@@ -16,13 +16,10 @@ groups:
- id: 1.2
text: "Verify that the basic-auth-file method is not enabled"
audit: "grep -A2 basic-auth-file /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "--basic-auth-file"
compare:
op: eq
value: ""
- path: "{.kubernetesMasterConfig.apiServerArguments.basic-auth-file}"
set: false
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml and
@@ -41,35 +38,27 @@ groups:
- id: 1.4
text: "Secure communications between the API server and master nodes"
audit: "grep -A4 kubeletClientInfo /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "kubeletClientInfo:"
compare:
op: eq
value: "kubeletClientInfo:"
set: true
- flag: "ca"
- path: "{.kubeletClientInfo.ca}"
compare:
op: has
value: "ca-bundle.crt"
set: true
- flag: "certFile"
- path: "{.kubeletClientInfo.certFile}"
compare:
op: has
value: "master.kubelet-client.crt"
set: true
- flag: "keyFile"
- path: "{.kubeletClientInfo.keyFile}"
compare:
op: has
value: "master.kubelet-client.key"
set: true
- flag: "port: 10250"
- path: "{.kubeletClientInfo.port}"
compare:
op: eq
value: "port: 10250"
set: true
value: "10250"
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
and change it to match the below.
@@ -83,10 +72,10 @@ groups:
- id: 1.5
text: "Prevent insecure bindings"
audit: "grep -A2 insecure-bind-address /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "insecure-bind-address"
- path: "{.kubernetesMasterConfig.insecure-bind-address}"
set: false
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
@@ -100,10 +89,10 @@ groups:
- id: 1.6
text: "Prevent insecure port access"
audit: "grep -A2 insecure-port /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "insecure-port"
- path: "{.kubernetesMasterConfig.apiServerArguments.insecure-port}"
set: false
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
@@ -117,17 +106,16 @@ groups:
- id: 1.7
text: "Use Secure Ports for API Server Traffic"
audit: "grep -A2 secure-port /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "secure-port"
- path: "{.kubernetesMasterConfig.apiServerArguments.secure-port}"
set: false
- flag: "secure-port"
- path: "{.kubernetesMasterConfig.apiServerArguments.secure-port}"
compare:
op: nothave
op: noteq
value: "0"
set: true
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
and either remove the secure-port parameter or set it to a different (non-zero)
@@ -146,17 +134,16 @@ groups:
- id: 1.9
text: "Verify repair-malformed-updates argument for API compatibility"
audit: "grep -A2 repair-malformed-updates /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "repair-malformed-updates"
- path: "{.repair-malformed-updates}"
set: false
- flag: "repair-malformed-updates"
- path: "{.repair-malformed-updates}"
compare:
op: has
op: eq
value: "true"
set: true
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
and remove the repair-malformed-updates entry or set repair-malformed-updates=true.
@@ -164,10 +151,10 @@ groups:
- id: 1.10
text: "Verify that the AlwaysAdmit admission controller is disabled"
audit: "grep -A4 AlwaysAdmit /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "AlwaysAdmit"
- path: "{.AlwaysAdmit}"
set: false
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
@@ -182,14 +169,13 @@ groups:
- id: 1.11
text: "Manage the AlwaysPullImages admission controller"
audit: "grep -A4 AlwaysPullImages /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "disable"
- path: "{.admissionConfig.pluginConfig.configuration.disable}"
compare:
op: has
op: eq
value: "false"
set: true
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
and add the entry below.
@@ -215,10 +201,10 @@ groups:
- id: 1.14
text: "Manage the NamespaceLifecycle admission controller"
audit: "grep -A4 NamespaceLifecycle /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "NamespaceLifecycle"
- path: "{.NamespaceLifecycle}"
set: false
remediation: |
Edit the kubernetes master config file /etc/origin/master/master-config.yaml
@@ -233,14 +219,13 @@ groups:
- id: 1.15
text: "Configure API server auditing - audit log file path"
audit: "grep -A5 auditConfig /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "enabled"
- path: "{.auditConfig.enabled}"
compare:
op: has
op: eq
value: "true"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml, update the following entry and restart the API server.
@@ -257,14 +242,13 @@ groups:
- id: 1.16
text: "Configure API server auditing - audit log retention"
audit: "grep -A5 auditConfig /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "maximumFileRetentionDays: 30"
- path: "{.auditConfig.maximumFileRetentionDays}"
compare:
op: has
value: "maximumFileRetentionDays"
set: true
op: gte
value: 30
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml,
update the maximumFileRetentionDays entry and restart the API server.
@@ -282,14 +266,13 @@ groups:
- id: 1.17
text: "Configure API server auditing - audit log backup retention"
audit: "grep -A5 auditConfig /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "maximumRetainedFiles: 10"
- path: "{.auditConfig.maximumRetainedFiles}"
compare:
op: has
value: "maximumRetainedFiles"
set: true
op: eq
value: "10"
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml, update the maximumRetainedFiles entry,
set enabled to true and restart the API server.
@@ -307,14 +290,13 @@ groups:
- id: 1.18
text: "Configure audit log file size"
audit: "grep -A5 auditConfig /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "maximumFileSizeMegabytes: 30"
- path: "{.auditConfig.maximumFileSizeMegabytes}"
compare:
op: has
value: "maximumFileSizeMegabytes"
set: true
op: eq
value: "30"
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml, update the maximumFileSizeMegabytes entry,
set enabled to true and restart the API server.
@@ -332,10 +314,10 @@ groups:
- id: 1.19
text: "Verify that authorization-mode is not set to AlwaysAllow"
audit: "grep -A1 authorization-mode /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "authorization-mode"
- path: "{.kubernetesMasterConfig.apiServerArguments.authorization-mode}"
set: false
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and remove the authorization-mode
@@ -349,10 +331,10 @@ groups:
- id: 1.20
text: "Verify that the token-auth-file flag is not set"
audit: "grep token-auth-file /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "token-auth-file"
- path: "{.kubernetesMasterConfig.apiServerArguments.token-auth-file}"
set: false
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and remove the token-auth-file
@@ -366,10 +348,10 @@ groups:
- id: 1.21
text: "Verify the API server certificate authority"
audit: "grep -A1 kubelet-certificate-authority /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "kubelet-certificate-authority"
- path: "{.kubernetesMasterConfig.apiServerArguments.kubelet-certificat-authority}"
set: false
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and remove the following
@@ -383,20 +365,18 @@ groups:
- id: 1.22
text: "Verify the API server client certificate and client key"
audit: "grep -A4 kubeletClientInfo /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "keyFile"
- path: "{.kubeletClientInfo.keyFile}"
compare:
op: has
op: eq
value: "master.kubelet-client.key"
set: true
- flag: "certFile"
- path: "{.kubeletClientInfo.certFile}"
compare:
op: has
op: eq
value: "master.kubelet-client.crt"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and add the following
configuration under kubeletClientInfo
@@ -420,20 +400,18 @@ groups:
- id: 1.25
text: "Verify that the service account key file argument is not set"
audit: "grep -A9 serviceAccountConfig /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "privateKeyFile"
- path: "{.serviceAccountConfig.privateKeyFile}"
compare:
op: has
op: eq
value: "serviceaccounts.private.key"
set: true
- flag: "serviceaccounts.public.key"
- path: "{.serviceAccountConfig.publicKeyFiles}"
compare:
op: has
value: "serviceaccounts.public.key"
set: true
remediation: |
OpenShift API server does not use the service-account-key-file argument.
Even if value is set in master-config.yaml, it will not be used to verify
@@ -460,20 +438,18 @@ groups:
- id: 1.26
text: "Verify the certificate and key used for communication with etcd"
audit: "grep -A3 etcdClientInfo /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "certFile"
- path: "{.etcdClientInfo.certFile}"
compare:
op: has
op: eq
value: "master.etcd-client.crt"
set: true
- flag: "keyFile"
- path: "{.etcdClientInfo.keyFile}"
compare:
op: has
op: eq
value: "master.etcd-client.key"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set keyFile and certFile
under etcdClientInfo like below.
@@ -486,17 +462,16 @@ groups:
- id: 1.27
text: "Verify that the ServiceAccount admission controller is enabled"
audit: "grep -A4 ServiceAccount /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "ServiceAccount"
- path: "{.ServiceAccount.configuration.disable}"
set: false
- flag: "disable"
- path: "{.ServiceAccount.configuration.disable}"
compare:
op: has
op: eq
value: "false"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and enable ServiceAccount
admission control policy.
@@ -510,20 +485,18 @@ groups:
- id: 1.28
text: "Verify the certificate and key used to encrypt API server traffic"
audit: "grep -A7 servingInfo /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "certFile"
- path: "{.servingInfo.certFile}"
compare:
op: has
op: eq
value: "master.server.crt"
set: true
- flag: "keyFile"
- path: "{.servingInfo.keyFile}"
compare:
op: has
op: eq
value: "master.server.key"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set keyFile and certFile under servingInfo.
@@ -539,10 +512,10 @@ groups:
- id: 1.29
text: "Verify that the --client-ca-file argument is not set"
audit: "grep client-ca-file /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "clientCA: ca.crt"
- path: "{.servingInfo.clientCA}"
set: false
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set clientCA under servingInfo.
@@ -559,14 +532,13 @@ groups:
- id: 1.30
text: "Verify the CA used for communication with etcd"
audit: "grep -A3 etcdClientInfo /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "ca"
- path: "{.etcdClientInfo.ca}"
compare:
op: has
op: eq
value: "master.etcd-ca.crt"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set ca under etcdClientInfo.
@@ -583,17 +555,16 @@ groups:
- id: 1.32
text: "Verify that the NodeRestriction admission controller is enabled"
audit: "grep -A4 NodeRestriction /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "NodeRestriction"
- path: "{.NodeRestriction.configuration.disable}"
set: false
- flag: "disable"
- path: "{.NodeRestriction.configuration.disable}"
compare:
op: has
op: eq
value: "false"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and enable NodeRestriction ca under etcdClientInfo.
@@ -606,14 +577,10 @@ groups:
- id: 1.33
text: "Configure encryption of data at rest in etcd datastore"
audit: "grep -A1 experimental-encryption-provider-config /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "experimental-encryption-provider-config:"
compare:
op: has
value: "experimental-encryption-provider-config:"
set: true
- path: "{.kubernetesMasterConfig.apiServerArguments.experimental-encryption-provider-config}"
remediation: |
Follow the instructions in the documentation to configure encryption.
https://docs.openshift.com/container-platform/3.10/admin_guide/encrypting_data.html
@@ -621,14 +588,14 @@ groups:
- id: 1.34
text: "Set the encryption provider to aescbc for etcd data at rest"
audit: "grep -A1 experimental-encryption-provider-config /etc/origin/master/master-config.yaml | sed -n '2p' | awk '{ print $2 }' | xargs grep -A1 providers"
audit_config: "grep -A1 experimental-encryption-provider-config /etc/origin/master/master-config.yaml | sed -n '2p' | awk '{ print $2 }' | xargs cat"
tests:
test_items:
- flag: "aescbc:"
- path: "{.providers.aescbc.experimental-encryption-provider-config}"
compare:
op: has
value: "aescbc:"
set: true
value: "aescbc"
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set aescbc as the first provider in encryption provider config.
See https://docs.openshift.com/container-platform/3.10/admin_guide/encrypting_data.html.
@@ -636,14 +603,13 @@ groups:
- id: 1.35
text: "Enable the EventRateLimit plugin"
audit: "grep -A4 EventRateLimit /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "disable"
- path: "{.admissionConfig.pluginConfig.AlwaysPullImages.configuration.disable}"
compare:
op: has
op: eq
value: "false"
set: true
remediation: |
Follow the documentation to enable the EventRateLimit plugin.
https://docs.openshift.com/container-platform/3.10/architecture/additional_concepts/admission_controllers.html#admission-controllers-general-admission-rules
@@ -651,16 +617,15 @@ groups:
- id: 1.36
text: "Configure advanced auditing"
audit: "grep AdvancedAuditing /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "AdvancedAuditing"
- path: "{.kubernetesMasterConfig.apiServerArguments.feature-gates.AdvancedAuditing}"
compare:
op: eq
value: "true"
set: true
- flag: "AdvancedAuditing"
- path: "{.kubernetesMasterConfig.apiServerArguments.feature-gates.AdvancedAuditing}"
set: false
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and enable AdvancedAuditing,
@@ -696,14 +661,13 @@ groups:
checks:
- id: 3.1
text: "Adjust the terminated-pod-gc-threshold argument as needed"
audit: "grep terminated-pod-gc-threshold -A1 /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "terminated-pod-gc-threshold:"
- path: "{.kubernetesMasterConfig.controllerArguments.terminated-pod-gc-threshold}"
compare:
op: has
op: eq
value: "12500"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and enable terminated-pod-gc-threshold.
@@ -722,17 +686,16 @@ groups:
- id: 3.3
text: "Verify that the --use-service-account-credentials argument is set to true"
audit: "grep -A2 use-service-account-credentials /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: or
test_items:
- flag: "use-service-account-credentials"
- path: "{.kubernetesMasterConfig.controllerArguments.use-service-account-credentials}"
set: false
- flag: "true"
- path: "{.kubernetesMasterConfig.controllerArguments.use-service-account-credentials}"
compare:
op: has
op: eq
value: "true"
set: true
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and set use-service-account-credentials
to true under controllerArguments section.
@@ -743,45 +706,45 @@ groups:
    - true
scored: true
# Review 3.4
- id: 3.4
text: "Verify that the --service-account-private-key-file argument is set as appropriate"
audit: |
grep -A9 serviceAccountConfig /etc/origin/master/master-config.yaml | grep privateKeyFile;
grep -A2 service-account-private-key-file /etc/origin/master/master-config.yaml
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "privateKeyFile: serviceaccounts.private.key"
path: "{.serviceAccountConfig.privateKeyFile}"
compare:
op: has
value: "privateKeyFile"
op: eq
value: "serviceaccounts.private.key"
- flag: "service-account-private-key-file"
set: false
remediation:
remediation: |
Edit the Openshift master config file /etc/origin/master/master-config.yaml and remove service-account-private-key-file
scored: true
# Review 3.5
- id: 3.5
text: "Verify that the --root-ca-file argument is set as appropriate"
audit: "/bin/sh -c 'grep root-ca-file /etc/origin/master/master-config.yaml; grep -A9 serviceAccountConfig /etc/origin/master/master-config.yaml'"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
bin_op: and
test_items:
- flag: "root-ca-file=/etc/origin/master/ca-bundle.crt"
- path: "{.serviceAccountConfig.root-ca-file}"
compare:
op: has
op: eq
value: "/etc/origin/master/ca-bundle.crt"
set: true
- flag: "masterCA"
- path: "{.serviceAccountConfig.masterCA}"
compare:
op: has
op: eq
value: "ca-bundle.crt"
set: true
remediation:
remediation: |
Reset to OpenShift defaults OpenShift starts kube-controller-manager with
root-ca-file=/etc/origin/master/ca-bundle.crt by default.  OpenShift Advanced
root-ca-file=/etc/origin/master/ca-bundle.crt by default. OpenShift Advanced
Installation creates this certificate authority and configuration without any
configuration required.
@@ -795,15 +758,14 @@ groups:
- id: 3.7
text: "Manage certificate rotation"
audit: "grep -B3 RotateKubeletServerCertificate=true /etc/origin/master/master-config.yaml"
audit_config: "cat /etc/origin/master/master-config.yaml"
tests:
test_items:
- flag: "RotateKubeletServerCertificate"
- path: "{.kubeletArguments.feature-gates.RotateKubeletServerCertificate}"
compare:
op: eq
value: "true"
set: true
remediation:
remediation: |
If you decide not to enable the RotateKubeletServerCertificate feature,
be sure to use the Ansible playbooks provided with the OpenShift installer to
automate re-deploying certificates.
@@ -822,7 +784,6 @@ groups:
compare:
op: bitmask
value: "600"
set: true
remediation: |
Run the below command.
@@ -835,10 +796,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -854,7 +811,6 @@ groups:
compare:
op: bitmask
value: "600"
set: true
remediation: |
Run the below command on the master node.
@@ -867,10 +823,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -886,7 +838,6 @@ groups:
compare:
op: bitmask
value: "600"
set: true
remediation: |
Run the below command.
@@ -899,10 +850,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -918,7 +865,6 @@ groups:
compare:
op: bitmask
value: "600"
set: true
remediation: |
Run the below command.
@@ -931,10 +877,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -944,13 +886,13 @@ groups:
- id: 4.9
text: "Verify the default OpenShift Container Network Interface file permissions"
audit: "stat -c permissions=%a /etc/origin/openvswitch/ /etc/cni/net.d/"
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command.
@@ -960,13 +902,10 @@ groups:
- id: 4.10
text: "Verify the default OpenShift Container Network Interface file ownership"
audit: "stat -c %U:%G /etc/origin/openvswitch/ /etc/cni/net.d/"
use_multiple_values: true
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -982,7 +921,6 @@ groups:
compare:
op: bitmask
value: "700"
set: true
remediation: |
On the etcd server node, get the etcd data directory, passed as an argument --data-dir ,
from the below command:
@@ -997,10 +935,6 @@ groups:
tests:
test_items:
- flag: "etcd:etcd"
compare:
op: eq
value: "etcd:etcd"
set: true
remediation: |
Run the below command on the master node.
@@ -1016,7 +950,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command.
@@ -1029,10 +962,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -1048,7 +977,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command.
@@ -1061,10 +989,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: "root:root"
set: true
remediation: |
Run the below command on the master node.
@@ -1080,7 +1004,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command.
@@ -1109,45 +1032,34 @@ groups:
checks:
- id: 5.1
text: "Verify the default OpenShift cert-file and key-file configuration"
audit: "/bin/sh -c '/usr/local/bin/master-exec etcd etcd grep ETCD_CERT_FILE=/etc/etcd/server.crt /proc/1/environ; /usr/local/bin/master-exec etcd etcd grep etcd_key_file=/etc/etcd/server.key /proc/1/environ; grep ETCD_CERT_FILE=/etc/etcd/server.crt /etc/etcd/etcd.conf; grep ETCD_KEY_FILE=/etc/etcd/server.key /etc/etcd/etcd.conf'"
audit: "/bin/sh -c '/usr/local/bin/master-exec etcd etcd grep ETCD_CERT_FILE=/etc/etcd/server.crt /proc/1/environ; /usr/local/bin/master-exec etcd etcd grep ETCD_KEY_FILE=/etc/etcd/server.key /proc/1/environ; grep ETCD_CERT_FILE=/etc/etcd/server.crt /etc/etcd/etcd.conf; grep ETCD_KEY_FILE=/etc/etcd/server.key /etc/etcd/etcd.conf'"
tests:
bin_op: and
test_items:
- flag: "Binary file /proc/1/environ matches"
- flag: "ETCD_CERT_FILE"
compare:
op: has
value: "Binary file /proc/1/environ matches"
set: true
- flag: "ETCD_CERT_FILE=/etc/etcd/server.crt"
op: eq
value: "/etc/etcd/server.crt"
- flag: "ETCD_KEY_FILE"
compare:
op: has
value: "ETCD_CERT_FILE=/etc/etcd/server.crt"
set: true
- flag: "ETCD_KEY_FILE=/etc/etcd/server.key"
compare:
op: has
value: "ETCD_KEY_FILE=/etc/etcd/server.key"
set: true
op: eq
value: "/etc/etcd/server.key"
remediation: |
Reset to the OpenShift default configuration.
scored: true
- id: 5.2
text: "Verify the default OpenShift setting for the client-cert-auth argument"
audit: "/bin/sh -c'/usr/local/bin/master-exec etcd etcd grep ETCD_CLIENT_CERT_AUTH=true /proc/1/environ; grep ETCD_CLIENT_CERT_AUTH /etc/etcd/etcd.conf'"
audit: "/bin/sh -c '/usr/local/bin/master-exec etcd etcd grep ETCD_CLIENT_CERT_AUTH=true /proc/1/environ; grep ETCD_CLIENT_CERT_AUTH /etc/etcd/etcd.conf'"
tests:
bin_op: and
test_items:
- flag: "Binary file /proc/1/environ matches"
- flag: "ETCD_CLIENT_CERT_AUTH"
compare:
op: has
value: "Binary file /proc/1/environ matches"
set: true
- flag: "ETCD_CLIENT_CERT_AUTH=true"
compare:
op: has
value: "ETCD_CLIENT_CERT_AUTH=true"
set: true
op: eq
value: "true"
remediation: |
Reset to the OpenShift default configuration.
scored: true
@@ -1158,41 +1070,29 @@ groups:
tests:
bin_op: or
test_items:
- flag: "ETCD_AUTO_TLS=false"
- flag: "ETCD_AUTO_TLS"
compare:
op: has
value: "ETCD_AUTO_TLS=false"
set: true
- flag: "#ETCD_AUTO_TLS"
compare:
op: has
value: "#ETCD_AUTO_TLS"
set: true
op: eq
value: "false"
remediation: |
Reset to the OpenShift default configuration.
scored: true
- id: 5.4
text: "Verify the OpenShift default peer-cert-file and peer-key-file arguments for etcd"
audit: "/bin/sh -c'/usr/local/bin/master-exec etcd etcd grep ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt /proc/1/environ; /usr/local/bin/master-exec etcd etcd grep ETCD_PEER_KEY_FILE=/etc/etcd/peer.key /proc/1/environ; grep ETCD_PEER_CERT_FILE /etc/etcd/etcd.conf; grep ETCD_PEER_KEY_FILE /etc/etcd/etcd.conf'"
audit: "/bin/sh -c '/usr/local/bin/master-exec etcd etcd grep ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt /proc/1/environ; /usr/local/bin/master-exec etcd etcd grep ETCD_PEER_KEY_FILE=/etc/etcd/peer.key /proc/1/environ; grep ETCD_PEER_CERT_FILE /etc/etcd/etcd.conf; grep ETCD_PEER_KEY_FILE /etc/etcd/etcd.conf'"
tests:
bin_op: and
test_items:
- flag: "Binary file /proc/1/environ matches"
- flag: "ETCD_PEER_CERT_FILE"
compare:
op: has
value: "Binary file /proc/1/environ matches"
set: true
- flag: "ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt"
op: eq
value: "/etc/etcd/peer.crt"
- flag: "ETCD_PEER_KEY_FILE"
compare:
op: has
value: "ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt"
set: true
- flag: "ETCD_PEER_KEY_FILE=/etc/etcd/peer.key"
compare:
op: has
value: "ETCD_PEER_KEY_FILE=/etc/etcd/peer.key"
set: true
op: eq
value: "/etc/etcd/peer.key"
remediation: |
Reset to the OpenShift default configuration.
scored: true
@@ -1204,15 +1104,10 @@ groups:
bin_op: and
test_items:
- flag: "Binary file /proc/1/environ matches"
- flag: "ETCD_PEER_CLIENT_CERT_AUTH"
compare:
op: has
value: "Binary file /proc/1/environ matches"
set: true
- flag: "ETCD_PEER_CLIENT_CERT_AUTH=true"
compare:
op: has
value: "ETCD_PEER_CLIENT_CERT_AUTH=true"
set: true
op: eq
value: "true"
remediation: |
Reset to the OpenShift default configuration.
scored: true
@@ -1221,18 +1116,11 @@ groups:
text: "Verify the OpenShift default configuration for the peer-auto-tls argument"
audit: "/bin/sh -c '/usr/local/bin/master-exec etcd etcd grep ETCD_PEER_AUTO_TLS /proc/1/environ; grep ETCD_PEER_AUTO_TLS /etc/etcd/etcd.conf'"
tests:
bin_op: and
test_items:
- flag: "Binary file /proc/1/environ matches"
- flag: "ETCD_PEER_AUTO_TLS"
compare:
op: has
value: "Binary file /proc/1/environ matches"
set: true
- flag: "#ETCD_PEER_AUTO_TLS=false"
compare:
op: has
value: "#ETCD_PEER_AUTO_TLS=false"
set: true
op: noteq
value: "true"
remediation: |
Reset to the OpenShift default configuration.
scored: true
@@ -1253,10 +1141,6 @@ groups:
tests:
test_items:
- flag: "issuer= /CN=etcd-signer"
compare:
op: has
value: "issuer= /CN=etcd-signer"
set: true
remediation: |
Reset to the OpenShift default configuration.
scored: false

View File

@@ -1,5 +1,6 @@
---
controls:
version: "rh-0.7"
id: 2
text: "Worker Node Security Configuration"
type: "node"
@@ -19,17 +20,16 @@ groups:
- id: 7.3
text: "Verify that the --authorization-mode argument is set to WebHook"
audit: "grep -A1 authorization-mode /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "authorization-mode"
- path: "{.kubeletArguments.authorization-mode}"
set: false
- flag: "authorization-mode"
- path: "{.kubeletArguments.authorization-mode}"
compare:
op: has
value: "Webhook"
set: true
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and remove authorization-mode under
kubeletArguments in /etc/origin/node/node-config.yaml or set it to "Webhook".
@@ -37,10 +37,10 @@ groups:
- id: 7.4
text: "Verify the OpenShift default for the client-ca-file argument"
audit: "grep -A1 client-ca-file /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
test_items:
- flag: "client-ca-file"
- path: "{.PodManifestConfig.client-ca-file}"
set: false
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and remove any configuration returned by the following:
@@ -53,31 +53,32 @@ groups:
- id: 7.5
text: "Verify the OpenShift default setting for the read-only-port argument"
audit: "grep -A1 read-only-port /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "read-only-port"
- path: "{.kubeletArguments.read-only-port}"
set: false
- flag: "read-only-port"
- path: "{.kubeletArguments.read-only-port}"
compare:
op: has
op: eq
value: "0"
set: true
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and removed so that the OpenShift default is applied.
scored: true
- id: 7.6
text: "Adjust the streaming-connection-idle-timeout argument"
audit: "grep -A1 streaming-connection-idle-timeout /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "streaming-connection-idle-timeout"
set: false
- flag: "5m"
- path: "{.kubeletArguments.streaming-connection-idle-timeout}"
set: false
- path: "{.kubeletArguments.streaming-connection-idle-timeout}"
compare:
op: eq
value: "5m"
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and set the streaming-connection-timeout
value like the following in node-config.yaml.
@@ -94,17 +95,16 @@ groups:
- id: 7.8
text: "Verify the OpenShift default value of true for the make-iptables-util-chains argument"
audit: "grep -A1 make-iptables-util-chains /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "make-iptables-util-chains"
- path: "{.kubeletArguments.make-iptables-util-chains}"
set: false
- flag: "make-iptables-util-chains"
- path: "{.kubeletArguments.make-iptables-util-chains}"
compare:
op: has
op: eq
value: "true"
set: true
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and reset make-iptables-util-chains to the OpenShift
default value of true.
@@ -112,14 +112,16 @@ groups:
- id: 7.9
text: "Verify that the --keep-terminated-pod-volumes argument is set to false"
audit: "grep -A1 keep-terminated-pod-volumes /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "keep-terminated-pod-volumes"
- path: "{.kubeletArguments.keep-terminated-pod-volumes}"
set: false
- path: "{.kubeletArguments.keep-terminated-pod-volumes}"
compare:
op: has
op: eq
value: "false"
set: true
remediation: |
Reset to the OpenShift defaults
scored: true
@@ -131,17 +133,16 @@ groups:
- id: 7.11
text: "Set the --event-qps argument to 0"
audit: "grep -A1 event-qps /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "event-qps"
- path: "{.kubeletArguments.event-qps}"
set: false
- flag: "event-qps"
- path: "{.kubeletArguments.event-qps}"
compare:
op: has
op: eq
value: "0"
set: true
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml set the event-qps argument to 0 in
the kubeletArguments section of.
@@ -149,31 +150,29 @@ groups:
- id: 7.12
text: "Verify the OpenShift cert-dir flag for HTTPS traffic"
audit: "grep -A1 cert-dir /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
test_items:
- flag: "/etc/origin/node/certificates"
- path: "{.kubeletArguments.cert-dir}"
compare:
op: has
value: "/etc/origin/node/certificates"
set: true
remediation: |
Reset to the OpenShift default values.
scored: true
- id: 7.13
text: "Verify the OpenShift default of 0 for the cadvisor-port argument"
audit: "grep -A1 cadvisor-port /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
bin_op: or
test_items:
- flag: "cadvisor-port"
- path: "{.kubeletArguments.cadvisor-port}"
set: false
- flag: "cadvisor-port"
- path: "{.kubeletArguments.cadvisor-port}"
compare:
op: has
op: eq
value: "0"
set: true
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and remove the cadvisor-port flag
if it is set in the kubeletArguments section.
@@ -181,28 +180,26 @@ groups:
- id: 7.14
text: "Verify that the RotateKubeletClientCertificate argument is set to true"
audit: "grep -B1 RotateKubeletClientCertificate=true /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
test_items:
- flag: "RotateKubeletClientCertificate=true"
- path: "{.kubeletArguments.feature-gates}"
compare:
op: has
value: "true"
set: true
value: "RotateKubeletClientCertificate=true"
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and set RotateKubeletClientCertificate to true.
scored: true
- id: 7.15
text: "Verify that the RotateKubeletServerCertificate argument is set to true"
audit: "grep -B1 RotateKubeletServerCertificate=true /etc/origin/node/node-config.yaml"
audit_config: "cat /etc/origin/node/node-config.yaml"
tests:
test_items:
- flag: "RotateKubeletServerCertificate=true"
- path: "{.kubeletArguments.feature-gates}"
compare:
op: has
value: "true"
set: true
value: "RotateKubeletServerCertificate=true"
remediation: |
Edit the Openshift node config file /etc/origin/node/node-config.yaml and set RotateKubeletServerCertificate to true.
scored: true
@@ -220,7 +217,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command on each worker node.
chmod 644 /etc/origin/node/node.kubeconfig
@@ -232,10 +228,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: root:root
set: true
remediation: |
Run the below command on each worker node.
chown root:root /etc/origin/node/node.kubeconfig
@@ -243,32 +235,27 @@ groups:
- id: 8.3
text: "Verify the kubelet service file permissions of 644"
audit: "stat -c permissions=%a $nodesvc"
audit: "stat -c permissions=%a $kubeletsvc"
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command on each worker node.
chmod 644 $nodesvc
chmod 644 $kubeletsvc
scored: true
- id: 8.4
text: "Verify the kubelet service file ownership of root:root"
audit: "stat -c %U:%G $nodesvc"
audit: "stat -c %U:%G $kubeletsvc"
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: root:root
set: true
remediation: |
Run the below command on each worker node.
chown root:root $nodesvc
chown root:root $kubeletsvc
scored: true
- id: 8.5
@@ -280,7 +267,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command on each worker node.
chmod 644 /etc/origin/node/node.kubeconfig
@@ -292,10 +278,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: root:root
set: true
remediation: |
Run the below command on each worker node.
chown root:root /etc/origin/node/node.kubeconfig
@@ -310,7 +292,6 @@ groups:
compare:
op: bitmask
value: "644"
set: true
remediation: |
Run the below command on each worker node.
chmod 644 /etc/origin/node/client-ca.crt
@@ -322,10 +303,6 @@ groups:
tests:
test_items:
- flag: "root:root"
compare:
op: eq
value: root:root
set: true
remediation: |
Run the below command on each worker node.
chown root:root /etc/origin/node/client-ca.crt

2
cfg/rh-1.0/config.yaml Normal file
View File

@@ -0,0 +1,2 @@
---
## Version-specific settings that override the values in cfg/config.yaml

View File

@@ -0,0 +1,62 @@
---
controls:
version: rh-1.0
id: 3
text: "Control Plane Configuration"
type: "controlplane"
groups:
- id: 3.1
text: "Authentication and Authorization"
checks:
- id: 3.1.1
text: "Client certificate authentication should not be used for users (Manual)"
audit: |
# To verify user authentication is enabled
oc describe authentication
# To verify that an identity provider is configured
oc get identity
# To verify that a custom cluster-admin user exists
oc get clusterrolebindings -o=custom-columns=NAME:.metadata.name,ROLE:.roleRef.name,SUBJECT:.subjects[*].kind | grep cluster-admin | grep User
# To verity that kbueadmin is removed, no results should be returned
oc get secrets kubeadmin -n kube-system
type: manual
remediation: |
Configure an identity provider for the OpenShift cluster.
Understanding identity provider configuration | Authentication | OpenShift
Container Platform 4.5. Once an identity provider has been defined,
you can use RBAC to define and apply permissions.
After you define an identity provider and create a new cluster-admin user,
remove the kubeadmin user to improve cluster security.
scored: false
- id: 3.2
text: "Logging"
checks:
- id: 3.2.1
text: "Ensure that a minimal audit policy is created (Manual)"
audit: |
#To view kube apiserver log files
oc adm node-logs --role=master --path=kube-apiserver/
#To view openshift apiserver log files
oc adm node-logs --role=master --path=openshift-apiserver/
#To verify kube apiserver audit config
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig[]'
#To verify openshift apiserver audit config
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig[]'
type: manual
remediation: |
No remediation required.
scored: false
- id: 3.2.2
text: "Ensure that the audit policy covers key security concerns (Manual)"
audit: |
#To verify openshift apiserver audit config
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]'
#To verify kube apiserver audit config
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]'
type: manual
remediation: |
In OpenShift 4.6 and higher, if appropriate for your needs,
modify the audit policy.
scored: false

154
cfg/rh-1.0/etcd.yaml Normal file
View File

@@ -0,0 +1,154 @@
---
controls:
version: rh-1.0
id: 2
text: "Etcd Node Configuration"
type: "etcd"
groups:
- id: 2
text: "Etcd Node Configuration Files"
checks:
- id: 2.1
text: "Ensure that the --cert-file and --key-file arguments are set as appropriate (Manual)"
audit: |
# For --cert-file
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--cert-file=[^ ]*\).*/\1/'
done 2>/dev/null
# For --key-file
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--key-file=[^ ]*\).*/\1/'
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "file"
compare:
op: regex
value: '\/etc\/kubernetes\/static-pod-certs\/secrets\/etcd-all-serving\/etcd-serving-.*\.(?:crt|key)'
remediation: |
OpenShift does not use the etcd-certfile or etcd-keyfile flags.
Certificates for etcd are managed by the etcd cluster operator.
scored: false
- id: 2.2
text: "Ensure that the --client-cert-auth argument is set to true (Manual)"
audit: |
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--client-cert-auth=[^ ]*\).*/\1/'
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "--client-cert-auth"
compare:
op: eq
value: true
remediation: |
This setting is managed by the cluster etcd operator. No remediation required."
scored: false
- id: 2.3
text: "Ensure that the --auto-tls argument is not set to true (Manual)"
audit: |
# Returns 0 if found, 1 if not found
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | grep -- --auto-tls=true 2>&1>/dev/null ; echo exit_code=$?
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "exit_code"
compare:
op: eq
value: "1"
remediation: |
This setting is managed by the cluster etcd operator. No remediation required.e
scored: false
- id: 2.4
text: "Ensure that the --peer-cert-file and --peer-key-file arguments are set as appropriate (Manual)"
audit: |
# For --peer-cert-file
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--peer-cert-file=[^ ]*\).*/\1/'
done 2>/dev/null
# For --peer-key-file
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--peer-key-file=[^ ]*\).*/\1/'
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "file"
compare:
op: regex
value: '\/etc\/kubernetes\/static-pod-certs\/secrets\/etcd-all-peer\/etcd-peer-.*\.(?:crt|key)'
remediation: |
None. This configuration is managed by the etcd operator.
scored: false
- id: 2.5
text: "Ensure that the --peer-client-cert-auth argument is set to true (Manual)"
audit: |
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--peer-client-cert-auth=[^ ]*\).*/\1/'
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "--peer-client-cert-auth"
compare:
op: eq
value: true
remediation: |
This setting is managed by the cluster etcd operator. No remediation required.
scored: false
- id: 2.6
text: "Ensure that the --peer-auto-tls argument is not set to true (Manual)"
audit: |
# Returns 0 if found, 1 if not found
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | grep -- --peer-auto-tls=true 2>&1>/dev/null ; echo exit_code=$?
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "exit_code"
compare:
op: eq
value: "1"
remediation: |
This setting is managed by the cluster etcd operator. No remediation required.
scored: false
- id: 2.7
text: "Ensure that a unique Certificate Authority is used for etcd (Manual)"
audit: |
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--trusted-ca-file=[^ ]*\).*/\1/'
done 2>/dev/null
for i in $(oc get pods -oname -n openshift-etcd)
do
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | sed 's/.*\(--peer-trusted-ca-file=[^ ]*\).*/\1/'
done 2>/dev/null
use_multiple_values: true
tests:
test_items:
- flag: "file"
compare:
op: regex
value: '\/etc\/kubernetes\/static-pod-certs\/configmaps\/etcd-(?:serving|peer-client)-ca\/ca-bundle\.(?:crt|key)'
remediation: |
None required. Certificates for etcd are managed by the OpenShift cluster etcd operator.
scored: false

1262
cfg/rh-1.0/master.yaml Normal file

File diff suppressed because it is too large Load Diff

453
cfg/rh-1.0/node.yaml Normal file
View File

@@ -0,0 +1,453 @@
---
controls:
version: rh-1.0
id: 4
text: "Worker Node Security Configuration"
type: "node"
groups:
- id: 4.1
text: "Worker Node Configuration Files"
checks:
- id: 4.1.1
text: "Ensure that the kubelet service file permissions are set to 644 or more restrictive (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n permissions=%a" /etc/systemd/system/kubelet.service
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
By default, the kubelet service file has permissions of 644.
scored: true
- id: 4.1.2
text: "Ensure that the kubelet service file ownership is set to root:root (Automated)"
audit: |
# Should return root:root for each node
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n %U:%G" /etc/systemd/system/kubelet.service
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: root:root
remediation: |
By default, the kubelet service file has ownership of root:root.
scored: true
- id: 4.1.3
text: "If proxy kubeconfig file exists ensure permissions are set to 644 or more restrictive (Manual)"
audit: |
for i in $(oc get pods -n openshift-sdn -l app=sdn -oname)
do
oc exec -n openshift-sdn $i -- stat -Lc "$i %n permissions=%a" /config/kube-proxy-config.yaml
done 2> /dev/null
use_multiple_values: true
tests:
bin_op: or
test_items:
- flag: "permissions"
set: true
compare:
op: bitmask
value: "644"
remediation: |
None needed.
scored: false
- id: 4.1.4
text: "Ensure that the proxy kubeconfig file ownership is set to root:root (Manual)"
audit: |
for i in $(oc get pods -n openshift-sdn -l app=sdn -oname)
do
oc exec -n openshift-sdn $i -- stat -Lc "$i %n %U:%G" /config/kube-proxy-config.yaml
done 2> /dev/null
use_multiple_values: true
tests:
bin_op: or
test_items:
- flag: root:root
remediation: |
None required. The configuration is managed by OpenShift operators.
scored: false
- id: 4.1.5
text: "Ensure that the --kubeconfig kubelet.conf file permissions are set to 644 or more restrictive (Manual)"
audit: |
# Check permissions
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n permissions=%a" /etc/kubernetes/kubelet.conf
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
None required.
scored: false
- id: 4.1.6
text: "Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root (Manual)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n %U:%G" /etc/kubernetes/kubelet.conf
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: root:root
remediation: |
None required.
scored: false
- id: 4.1.7
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n permissions=%a" /etc/kubernetes/kubelet-ca.crt
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
None required.
scored: true
- id: 4.1.8
text: "Ensure that the client certificate authorities file ownership is set to root:root (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n %U:%G" /etc/kubernetes/kubelet-ca.crt
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: root:root
remediation: |
None required.
scored: true
- id: 4.1.9
text: "Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n permissions=%a" /var/lib/kubelet/kubeconfig
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: "permissions"
compare:
op: bitmask
value: "644"
remediation: |
None required.
scored: true
- id: 4.1.10
text: "Ensure that the kubelet configuration file ownership is set to root:root (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host stat -c "$node %n %U:%G" /var/lib/kubelet/kubeconfig
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: root:root
remediation: |
None required.
scored: true
- id: 4.2
text: "Kubelet"
checks:
- id: 4.2.1
text: "Ensure that the --anonymous-auth argument is set to false (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host grep -B4 -A1 anonymous: /etc/kubernetes/kubelet.conf
done
use_multiple_values: true
tests:
test_items:
- flag: "enabled: true"
set: false
remediation: |
Follow the instructions in the documentation to create a Kubelet config CRD
and set the anonymous-auth is set to false.
scored: true
- id: 4.2.2
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
type: manual
# Takes a lot of time for connection to fail and
audit: |
POD=$(oc -n openshift-kube-apiserver get pod -l app=openshift-kube-apiserver -o jsonpath='{.items[0].metadata.name}')
TOKEN=$(oc whoami -t)
for name in $(oc get nodes -ojsonpath='{.items[*].metadata.name}')
do
oc exec -n openshift-kube-apiserver $POD -- curl -sS https://172.25.0.1/api/v1/nodes/$name/proxy/configz -k -H "Authorization:Bearer $TOKEN" | jq -r '.kubeletconfig.authorization.mode'
done
use_multiple_values: true
tests:
test_items:
- flag: "Connection timed out"
remediation: |
None required. Unauthenticated/Unauthorized users have no access to OpenShift nodes.
scored: true
- id: 4.2.3
text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host grep clientCAFile: /etc/kubernetes/kubelet.conf
done 2> /dev/null
use_multiple_values: true
tests:
test_items:
- flag: "clientCAFile"
compare:
op: eq
value: "/etc/kubernetes/kubelet-ca.crt"
remediation: |
None required. Changing the clientCAFile value is unsupported.
scored: true
- id: 4.2.4
text: "Verify that the read only port is not used or is set to 0 (Automated)"
audit: |
echo `oc -n openshift-kube-apiserver get cm kube-apiserver-pod -o yaml | grep --color read-only-port` 2> /dev/null
echo `oc -n openshift-kube-apiserver get cm config -o yaml | grep --color "read-only-port"` 2> /dev/null
tests:
bin_op: or
test_items:
- flag: "read-only-port"
compare:
op: has
value: "[\"0\"]"
- flag: "read-only-port"
set: false
remediation: |
In earlier versions of OpenShift 4, the read-only-port argument is not used.
Follow the instructions in the documentation to create a Kubelet config CRD
and set the --read-only-port is set to 0.
scored: true
- id: 4.2.5
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Automated)"
audit: |
# Should return 1 for each node
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host ps -ef | grep kubelet | grep streaming-connection-idle-timeout
echo exit_code=$?
done 2>/dev/null
# Should return 1 for each node
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host grep streamingConnectionIdleTimeout /etc/kubernetes/kubelet.conf
echo exit_code=$?
done 2>/dev/null
use_multiple_values: true
tests:
bin_op: or
test_items:
- flag: --streaming-connection-idle-timeout
compare:
op: noteq
value: 0
- flag: "exit_code"
compare:
op: eq
value: 1
remediation: |
Follow the instructions in the documentation to create a Kubelet config CRD and set
the --streaming-connection-idle-timeout to the desired value. Do not set the value to 0.
scored: true
- id: 4.2.6
text: "Ensure that the --protect-kernel-defaults argument is not set (Manual)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}');
do
oc debug node/${node} -- chroot /host more /etc/kubernetes/kubelet.conf;
done
tests:
test_items:
- flag: protectKernelDefaults
set: false
remediation: |
None required. The OpenShift 4 kubelet modifies the system tunable;
using the protect-kernel-defaults flag will cause the kubelet to fail on start if the tunables
don't match the kubelet configuration and the OpenShift node will fail to start.
scored: false
- id: 4.2.7
text: "Ensure that the --make-iptables-util-chains argument is set to true (Manual)"
audit: |
/bin/bash
flag=make-iptables-util-chains
opt=makeIPTablesUtilChains
# look at each machineconfigpool
while read -r pool nodeconfig; do
# true by default
value='true'
# first look for the flag
oc get machineconfig $nodeconfig -o json | jq -r '.spec.config.systemd[][] | select(.name=="kubelet.service") | .contents' | sed -n "/^ExecStart=/,/^\$/ { /^\\s*--$flag=false/ q 100 }"
# if the above command exited with 100, the flag was false
[ $? == 100 ] && value='false'
# now look in the yaml KubeletConfig
yamlconfig=$(oc get machineconfig $nodeconfig -o json | jq -r '.spec.config.storage.files[] | select(.path=="/etc/kubernetes/kubelet.conf") | .contents.source ' | sed 's/^data:,//' | while read; do echo -e ${REPLY//%/\\x}; done)
echo "$yamlconfig" | sed -n "/^$opt:\\s*false\\s*$/ q 100"
[ $? == 100 ] && value='false'
echo "Pool $pool has $flag ($opt) set to $value"
done < <(oc get machineconfigpools -o json | jq -r '.items[] | select(.status.machineCount>0) | .metadata.name + " " + .spec.configuration.name')
use_multiple_values: true
tests:
test_items:
- flag: "set to true"
remediation: |
None required. The --make-iptables-util-chains argument is set to true by default.
scored: false
- id: 4.2.8
text: "Ensure that the --hostname-override argument is not set (Manual)"
audit: |
echo `oc get machineconfig 01-worker-kubelet -o yaml | grep hostname-override`
echo `oc get machineconfig 01-master-kubelet -o yaml | grep hostname-override`
tests:
test_items:
- flag: hostname-override
set: false
remediation: |
By default, --hostname-override argument is not set.
scored: false
- id: 4.2.9
text: "Ensure that the kubeAPIQPS [--event-qps] argument is set to 0 or a level which ensures appropriate event capture (Automated)"
audit: |
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}');
do
oc debug node/${node} -- chroot /host more /etc/kubernetes/kubelet.conf;
done
oc get machineconfig 01-worker-kubelet -o yaml | grep --color kubeAPIQPS%3A%2050
oc get machineconfig 01-master-kubelet -o yaml | grep --color kubeAPIQPS%3A%2050
type: "manual"
remediation: |
Follow the documentation to edit kubelet parameters
https://docs.openshift.com/container-platform/4.5/scalability_and_performance/recommended-host-practices.html#create-a-kubeletconfig-crd-to-edit-kubelet-parameters
KubeAPIQPS: <QPS>
scored: true
- id: 4.2.10
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)"
audit: |
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.kubeletClientInfo'
tests:
bin_op: and
test_items:
- flag: "/etc/kubernetes/static-pod-certs/secrets/kubelet-client/tls.crt"
- flag: "/etc/kubernetes/static-pod-certs/secrets/kubelet-client/tls.key"
remediation: |
OpenShift automatically manages TLS authentication for the API server communication with the node/kublet.
This is not configurable.
scored: true
- id: 4.2.11
text: "Ensure that the --rotate-certificates argument is not set to false (Manual)"
audit: |
#Verify the rotateKubeletClientCertificate feature gate is not set to false
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot /host cat /etc/kubernetes/kubelet.conf | grep RotateKubeletClientCertificate
done 2> /dev/null
# Verify the rotateCertificates argument is set to true
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot host grep rotate /etc/kubernetes/kubelet.conf;
done 2> /dev/null
use_multiple_values: true
tests:
bin_op: or
test_items:
- flag: rotateCertificates
compare:
op: eq
value: true
- flag: rotateKubeletClientCertificates
compare:
op: noteq
value: false
- flag: rotateKubeletClientCertificates
set: false
remediation: |
None required.
scored: false
- id: 4.2.12
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Manual)"
audit: |
#Verify the rotateKubeletServerCertificate feature gate is on
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}');
do
oc debug node/${node} -- chroot /host grep RotateKubeletServerCertificate /etc/kubernetes/kubelet.conf;
done 2> /dev/null
# Verify the rotateCertificates argument is set to true
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}')
do
oc debug node/${node} -- chroot host grep rotate /etc/kubernetes/kubelet.conf;
done 2> /dev/null
use_multiple_values: true
tests:
bin_op: or
test_items:
- flag: RotateKubeletServerCertificate
compare:
op: eq
value: true
- flag: rotateCertificates
compare:
op: eq
value: true
remediation: |
By default, kubelet server certificate rotation is disabled.
scored: false
- id: 4.2.13
text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Manual)"
audit: |
# needs verification
# verify cipher suites
oc describe --namespace=openshift-ingress-operator ingresscontroller/default
oc get kubeapiservers.operator.openshift.io cluster -o json |jq .spec.observedConfig.servingInfo
oc get openshiftapiservers.operator.openshift.io cluster -o json |jq .spec.observedConfig.servingInfo
oc get cm -n openshift-authentication v4-0-config-system-cliconfig -o jsonpath='{.data.v4\-0\-config\-system\-cliconfig}' | jq .servingInfo
#check value for tlsSecurityProfile; null is returned if default is used
oc get kubeapiservers.operator.openshift.io cluster -o json |jq .spec.tlsSecurityProfile
type: manual
remediation: |
Follow the directions above and in the OpenShift documentation to configure the tlsSecurityProfile.
Configuring Ingress
scored: false

283
cfg/rh-1.0/policies.yaml Normal file
View File

@@ -0,0 +1,283 @@
---
controls:
version: rh-1.0
id: 5
text: "Kubernetes Policies"
type: "policies"
groups:
- id: 5.1
text: "RBAC and Service Accounts"
checks:
- id: 5.1.1
text: "Ensure that the cluster-admin role is only used where required (Manual)"
type: "manual"
remediation: |
Identify all clusterrolebindings to the cluster-admin role. Check if they are used and
if they need this role or if they could use a role with fewer privileges.
Where possible, first bind users to a lower privileged role and then remove the
clusterrolebinding to the cluster-admin role :
kubectl delete clusterrolebinding [name]
scored: false
- id: 5.1.2
text: "Minimize access to secrets (Manual)"
type: "manual"
remediation: |
Where possible, remove get, list and watch access to secret objects in the cluster.
scored: false
- id: 5.1.3
text: "Minimize wildcard use in Roles and ClusterRoles (Manual)"
type: "manual"
remediation: |
Where possible replace any use of wildcards in clusterroles and roles with specific
objects or actions.
scored: false
- id: 5.1.4
text: "Minimize access to create pods (Manual)"
type: "manual"
remediation: |
Where possible, remove create access to pod objects in the cluster.
scored: false
- id: 5.1.5
text: "Ensure that default service accounts are not actively used. (Manual)"
type: "manual"
remediation: |
None required.
scored: false
- id: 5.1.6
text: "Ensure that Service Account Tokens are only mounted where necessary (Manual)"
type: "manual"
remediation: |
Modify the definition of pods and service accounts which do not need to mount service
account tokens to disable it.
scored: false
- id: 5.2
text: "Pod Security Policies"
checks:
- id: 5.2.1
text: "Minimize the admission of privileged containers (Manual)"
audit: |
# needs verification
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i"; oc describe scc $i | grep "Allow Privileged";
done
tests:
test_items:
- flag: "false"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Allow
Privileged field is set to false.
scored: false
- id: 5.2.2
text: "Minimize the admission of containers wishing to share the host process ID namespace (Manual)"
audit: |
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i"; oc describe scc $i | grep "Allow Host PID";
done
tests:
test_items:
- flag: "false"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Allow Host
PID field is set to false.
scored: false
- id: 5.2.3
text: "Minimize the admission of containers wishing to share the host IPC namespace (Manual)"
audit: |
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i"; oc describe scc $i | grep "Allow Host IPC";
done
tests:
test_items:
- flag: "false"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Allow Host
IPC field is set to false.
scored: false
- id: 5.2.4
text: "Minimize the admission of containers wishing to share the host network namespace (Manual)"
audit: |
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i"; oc describe scc $i | grep "Allow Host Network";
done
tests:
test_items:
- flag: "false"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Allow Host
Network field is omitted or set to false.
scored: false
- id: 5.2.5
text: "Minimize the admission of containers with allowPrivilegeEscalation (Manual)"
audit: |
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i"; oc describe scc $i | grep "Allow Privilege Escalation";
done
tests:
test_items:
- flag: "false"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Allow
Privilege Escalation field is omitted or set to false.
scored: false
- id: 5.2.6
text: "Minimize the admission of root containers (Manual)"
audit: |
# needs verification
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i";
oc describe scc $i | grep "Run As User Strategy";
done
#For SCCs with MustRunAs verify that the range of UIDs does not include 0
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i";
oc describe scc $i | grep "\sUID";
done
tests:
bin_op: or
test_items:
- flag: "MustRunAsNonRoot"
- flag: "MustRunAs"
compare:
op: nothave
value: 0
remediation: |
None required. By default, OpenShift includes the non-root SCC with the the Run As User
Strategy is set to either MustRunAsNonRoot. If additional SCCs are appropriate, follow the
OpenShift documentation to create custom SCCs.
scored: false
- id: 5.2.7
text: "Minimize the admission of containers with the NET_RAW capability (Manual)"
audit: |
# needs verification
for i in `oc get scc --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'`;
do
echo "$i";
oc describe scc $i | grep "Required Drop Capabilities";
done
tests:
bin_op: or
test_items:
- flag: "ALL"
- flag: "NET_RAW"
remediation: |
Create a SCC as described in the OpenShift documentation, ensuring that the Required
Drop Capabilities is set to include either NET_RAW or ALL.
scored: false
- id: 5.2.8
text: "Minimize the admission of containers with added capabilities (Manual)"
type: "manual"
remediation: |
Ensure that Allowed Capabilities is set to an empty array for every SCC in the cluster
except for the privileged SCC.
scored: false
- id: 5.2.9
text: "Minimize the admission of containers with capabilities assigned (Manual)"
type: "manual"
remediation: |
Review the use of capabilites in applications running on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider
adding a SCC which forbids the admission of containers which do not drop all capabilities.
scored: false
- id: 5.3
text: "Network Policies and CNI"
checks:
- id: 5.3.1
text: "Ensure that the CNI in use supports Network Policies (Manual)"
type: "manual"
remediation: |
None required.
scored: false
- id: 5.3.2
text: "Ensure that all Namespaces have Network Policies defined (Manual)"
type: "manual"
remediation: |
Follow the documentation and create NetworkPolicy objects as you need them.
scored: false
- id: 5.4
text: "Secrets Management"
checks:
- id: 5.4.1
text: "Prefer using secrets as files over secrets as environment variables (Manual)"
type: "manual"
remediation: |
If possible, rewrite application code to read secrets from mounted secret files, rather than
from environment variables.
scored: false
- id: 5.4.2
text: "Consider external secret storage (Manual)"
type: "manual"
remediation: |
Refer to the secrets management options offered by your cloud provider or a third-party
secrets management solution.
scored: false
- id: 5.5
text: "Extensible Admission Control"
checks:
- id: 5.5.1
text: "Configure Image Provenance using ImagePolicyWebhook admission controller (Manual)"
type: "manual"
remediation: |
Follow the OpenShift documentation: [Image configuration resources](https://docs.openshift.com/container-platform/4.5/openshift_images/image-configuration.html
scored: false
- id: 5.7
text: "General Policies"
checks:
- id: 5.7.1
text: "Create administrative boundaries between resources using namespaces (Manual)"
type: "manual"
remediation: |
Follow the documentation and create namespaces for objects in your deployment as you need
them.
scored: false
- id: 5.7.2
text: "Ensure that the seccomp profile is set to docker/default in your pod definitions (Manual)"
type: "manual"
remediation: |
To enable the default seccomp profile, use the reserved value /runtime/default that will
make sure that the pod uses the default policy available on the host.
scored: false
- id: 5.7.3
text: "Apply Security Context to Your Pods and Containers (Manual)"
type: "manual"
remediation: |
Follow the Kubernetes documentation and apply security contexts to your pods. For a
suggested list of security contexts, you may refer to the CIS Security Benchmark for Docker
Containers.
scored: false
- id: 5.7.4
text: "The default namespace should not be used (Manual)"
type: "manual"
remediation: |
Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
resources and that all new resources are created in a specific namespace.
scored: false

View File

@@ -107,12 +107,14 @@ func (r *defaultRunner) Run(c *Check) State {
// Run executes the audit commands specified in a check and outputs
// the results.
func (c *Check) run() State {
glog.V(3).Infof("----- Running check %v -----", c.ID)
// Since this is an Scored check
// without tests return a 'WARN' to alert
// the user that this check needs attention
if c.Scored && strings.TrimSpace(c.Type) == "" && c.Tests == nil {
c.Reason = "There are no tests"
c.State = WARN
glog.V(3).Info(c.Reason)
return c.State
}
@@ -120,6 +122,7 @@ func (c *Check) run() State {
if c.Type == SKIP {
c.Reason = "Test marked as skip"
c.State = INFO
glog.V(3).Info(c.Reason)
return c.State
}
@@ -127,6 +130,7 @@ func (c *Check) run() State {
if c.Type == MANUAL {
c.Reason = "Test marked as a manual test"
c.State = WARN
glog.V(3).Info(c.Reason)
return c.State
}
@@ -138,6 +142,7 @@ func (c *Check) run() State {
} else {
c.State = WARN
}
glog.V(3).Info(c.Reason)
return c.State
}
@@ -172,12 +177,13 @@ func (c *Check) run() State {
} else {
c.State = WARN
}
glog.V(3).Info(c.Reason)
}
if finalOutput != nil {
glog.V(3).Infof("Check.ID: %s Command: %q TestResult: %t State: %q \n", c.ID, lastCommand, finalOutput.testResult, c.State)
glog.V(3).Infof("Command: %q TestResult: %t State: %q \n", lastCommand, finalOutput.testResult, c.State)
} else {
glog.V(3).Infof("Check.ID: %s Command: %q TestResult: <<EMPTY>> \n", c.ID, lastCommand)
glog.V(3).Infof("Command: %q TestResult: <<EMPTY>> \n", lastCommand)
}
if c.Reason != "" {
@@ -212,7 +218,7 @@ func (c *Check) execute() (finalOutput *testOutput, err error) {
res := make([]testOutput, len(ts.TestItems))
expectedResultArr := make([]string, len(res))
glog.V(3).Infof("%d tests", len(ts.TestItems))
glog.V(3).Infof("Running %d test_items", len(ts.TestItems))
for i, t := range ts.TestItems {
t.isMultipleOutput = c.IsMultiple
@@ -236,6 +242,7 @@ func (c *Check) execute() (finalOutput *testOutput, err error) {
t.auditUsed = AuditEnv
result = *(t.execute(c.AuditEnvOutput))
}
glog.V(2).Infof("Used %s", t.auditUsed)
res[i] = result
expectedResultArr[i] = res[i].ExpectedResult
}
@@ -289,8 +296,8 @@ func runAudit(audit string) (output string, err error) {
if err != nil {
err = fmt.Errorf("failed to run: %q, output: %q, error: %s", audit, output, err)
} else {
glog.V(3).Infof("Command %q\n - Output:\n %q", audit, output)
glog.V(3).Infof("Command: %q", audit)
glog.V(3).Infof("Output:\n %q", output)
}
return output, err
}

View File

@@ -47,11 +47,12 @@ type OverallControls struct {
// Controls holds all controls to check for master nodes.
type Controls struct {
ID string `yaml:"id" json:"id"`
Version string `json:"version"`
Text string `json:"text"`
Type NodeType `json:"node_type"`
Groups []*Group `json:"tests"`
ID string `yaml:"id" json:"id"`
Version string `json:"version"`
DetectedVersion string `json:"detected_version,omitempty"`
Text string `json:"text"`
Type NodeType `json:"node_type"`
Groups []*Group `json:"tests"`
Summary
}
@@ -79,7 +80,7 @@ type Summary struct {
type Predicate func(group *Group, check *Check) bool
// NewControls instantiates a new master Controls object.
func NewControls(t NodeType, in []byte) (*Controls, error) {
func NewControls(t NodeType, in []byte, detectedVersion string) (*Controls, error) {
c := new(Controls)
err := yaml.Unmarshal(in, c)
@@ -90,7 +91,7 @@ func NewControls(t NodeType, in []byte) (*Controls, error) {
if t != c.Type {
return nil, fmt.Errorf("non-%s controls file specified", t)
}
c.DetectedVersion = detectedVersion
return c, nil
}

View File

@@ -83,7 +83,7 @@ type: # not specified
groups:
`)
// when
_, err := NewControls(MASTER, in)
_, err := NewControls(MASTER, in, "")
// then
assert.EqualError(t, err, "non-master controls file specified")
})
@@ -92,7 +92,7 @@ groups:
// given
in := []byte("BOOM")
// when
_, err := NewControls(MASTER, in)
_, err := NewControls(MASTER, in, "")
// then
assert.EqualError(t, err, "failed to unmarshal YAML: yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `BOOM` into check.Controls")
})
@@ -118,7 +118,7 @@ groups:
- id: G2/C1
- id: G2/C2
`)
controls, err := NewControls(MASTER, in)
controls, err := NewControls(MASTER, in, "")
assert.NoError(t, err)
var allChecks Predicate = func(group *Group, c *Check) bool {
@@ -153,7 +153,7 @@ groups:
checks:
- id: G1/C1
`)
controls, err := NewControls(MASTER, in)
controls, err := NewControls(MASTER, in, "")
assert.NoError(t, err)
var allChecks Predicate = func(group *Group, c *Check) bool {
@@ -196,7 +196,7 @@ groups:
scored: true
`)
// and
controls, err := NewControls(MASTER, in)
controls, err := NewControls(MASTER, in, "")
assert.NoError(t, err)
// and
runner.On("Run", controls.Groups[0].Checks[0]).Return(PASS)

View File

@@ -126,6 +126,9 @@ func (t flagTestItem) findValue(s string) (match bool, value string, err error)
// flag: somevalue
// --flag
// somevalue
// DOESN'T COVER - use pathTestItem implementation of findValue() for this
// flag:
// - wehbook
pttn := `(` + t.Flag + `)(=|: *)*([^\s]*) *`
flagRe := regexp.MustCompile(pttn)
vals := flagRe.FindStringSubmatch(s)
@@ -145,7 +148,7 @@ func (t flagTestItem) findValue(s string) (match bool, value string, err error)
err = fmt.Errorf("invalid flag in testItem definition: %s", s)
}
}
glog.V(3).Infof("In flagTestItem.findValue %s, match %v, s %s, t.Flag %s", value, match, s, t.Flag)
glog.V(3).Infof("In flagTestItem.findValue %s", value)
return match, value, err
}
@@ -183,6 +186,7 @@ func (t envTestItem) findValue(s string) (match bool, value string, err error) {
value = ""
}
}
glog.V(3).Infof("In envTestItem.findValue %s", value)
return match, value, nil
}
@@ -232,10 +236,22 @@ func (t testItem) evaluate(s string) *testOutput {
}
result.flagFound = match
glog.V(3).Info(fmt.Sprintf("found %v", result.flagFound))
return result
var isExist = "exists"
if !result.flagFound{
isExist = "does not exist"
}
switch t.auditUsed {
case "auditCommand":
glog.V(3).Infof("Flag '%s' %s", t.Flag, isExist)
case "auditConfig":
glog.V(3).Infof("Path '%s' %s", t.Path, isExist)
case "auditEnv":
glog.V(3).Infof("Env '%s' %s", t.Env, isExist)
default:
glog.V(3).Infof("Error with identify audit used %s", t.auditUsed)
}
return result
}
func compareOp(tCompareOp string, flagVal string, tCompareValue string, flagName string) (string, bool) {

View File

@@ -38,7 +38,7 @@ func init() {
user := os.Getenv("USER")
s := strings.Replace(string(in), "$user", user, -1)
controls, err = NewControls(MASTER, []byte(s))
controls, err = NewControls(MASTER, []byte(s), "")
// controls, err = NewControls(MASTER, in)
if err != nil {
panic("Failed creating test controls: " + err.Error())

View File

@@ -64,7 +64,7 @@ func NewRunFilter(opts FilterOpts) (check.Predicate, error) {
}, nil
}
func runChecks(nodetype check.NodeType, testYamlFile string) {
func runChecks(nodetype check.NodeType, testYamlFile, detectedVersion string) {
// Verify config file was loaded into Viper during Cobra sub-command initialization.
if configFileError != nil {
colorPrint(check.FAIL, fmt.Sprintf("Failed to read config file: %v\n", configFileError))
@@ -106,7 +106,7 @@ func runChecks(nodetype check.NodeType, testYamlFile string) {
s, _ = makeSubstitutions(s, "kubeconfig", kubeconfmap)
s, _ = makeSubstitutions(s, "cafile", cafilemap)
controls, err := check.NewControls(nodetype, []byte(s))
controls, err := check.NewControls(nodetype, []byte(s), detectedVersion)
if err != nil {
exitWithError(fmt.Errorf("error setting up %s controls: %v", nodetype, err))
}
@@ -123,7 +123,7 @@ func runChecks(nodetype check.NodeType, testYamlFile string) {
controlsCollection = append(controlsCollection, controls)
}
func generateDefaultEnvAudit(controls *check.Controls, binSubs []string){
func generateDefaultEnvAudit(controls *check.Controls, binSubs []string) {
for _, group := range controls.Groups {
for _, checkItem := range group.Checks {
if checkItem.Tests != nil && !checkItem.DisableEnvTesting {
@@ -313,12 +313,16 @@ func loadTargetMapping(v *viper.Viper) (map[string][]string, error) {
return benchmarkVersionToTargetsMap, nil
}
func getBenchmarkVersion(kubeVersion, benchmarkVersion string, v *viper.Viper) (bv string, err error) {
func getBenchmarkVersion(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper) (bv string, err error) {
detecetedKubeVersion = "none"
if !isEmpty(kubeVersion) && !isEmpty(benchmarkVersion) {
return "", fmt.Errorf("It is an error to specify both --version and --benchmark flags")
}
if isEmpty(benchmarkVersion) && isEmpty(kubeVersion) {
benchmarkVersion = getPlatformBenchmarkVersion(getPlatformName())
if isEmpty(benchmarkVersion) && isEmpty(kubeVersion) && !isEmpty(platformName) {
benchmarkVersion = getPlatformBenchmarkVersion(platformName)
if !isEmpty(benchmarkVersion) {
detecetedKubeVersion = benchmarkVersion
}
}
if isEmpty(benchmarkVersion) {
@@ -328,6 +332,7 @@ func getBenchmarkVersion(kubeVersion, benchmarkVersion string, v *viper.Viper) (
return "", fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err)
}
kubeVersion = kv.BaseVersion()
detecetedKubeVersion = kubeVersion
}
kubeToBenchmarkMap, err := loadVersionMapping(v)

View File

@@ -195,17 +195,19 @@ func TestIsMaster(t *testing.T) {
defer restore()
for _, tc := range testCases {
cfgFile = tc.cfgFile
initConfig()
func() {
cfgFile = tc.cfgFile
initConfig()
oldGetBinariesFunc := getBinariesFunc
getBinariesFunc = tc.getBinariesFunc
defer func() {
getBinariesFunc = oldGetBinariesFunc
cfgFile = ""
oldGetBinariesFunc := getBinariesFunc
getBinariesFunc = tc.getBinariesFunc
defer func() {
getBinariesFunc = oldGetBinariesFunc
cfgFile = ""
}()
assert.Equal(t, tc.isMaster, isMaster(), tc.name)
}()
assert.Equal(t, tc.isMaster, isMaster(), tc.name)
}
}
@@ -320,11 +322,11 @@ func TestGetBenchmarkVersion(t *testing.T) {
t.Fatalf("Unable to load config file %v", err)
}
type getBenchmarkVersionFnToTest func(kubeVersion, benchmarkVersion string, v *viper.Viper) (string, error)
type getBenchmarkVersionFnToTest func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper) (string, error)
withFakeKubectl := func(kubeVersion, benchmarkVersion string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
withFakeKubectl := func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
execCode := `#!/bin/sh
echo '{"serverVersion": {"major": "1", "minor": "15", "gitVersion": "v1.15.10"}}'
echo '{"serverVersion": {"major": "1", "minor": "18", "gitVersion": "v1.18.10"}}'
`
restore, err := fakeExecutableInPath("kubectl", execCode)
if err != nil {
@@ -332,39 +334,40 @@ func TestGetBenchmarkVersion(t *testing.T) {
}
defer restore()
return fn(kubeVersion, benchmarkVersion, v)
return fn(kubeVersion, benchmarkVersion, platformName, v)
}
withNoPath := func(kubeVersion, benchmarkVersion string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
withNoPath := func(kubeVersion, benchmarkVersion, platformName string, v *viper.Viper, fn getBenchmarkVersionFnToTest) (string, error) {
restore, err := prunePath()
if err != nil {
t.Fatal("Failed when calling prunePath ", err)
}
defer restore()
return fn(kubeVersion, benchmarkVersion, v)
return fn(kubeVersion, benchmarkVersion, platformName, v)
}
type getBenchmarkVersionFn func(string, string, *viper.Viper, getBenchmarkVersionFnToTest) (string, error)
type getBenchmarkVersionFn func(string, string, string, *viper.Viper, getBenchmarkVersionFnToTest) (string, error)
cases := []struct {
n string
kubeVersion string
benchmarkVersion string
platformName string
v *viper.Viper
callFn getBenchmarkVersionFn
exp string
succeed bool
}{
{n: "both versions", kubeVersion: "1.11", benchmarkVersion: "cis-1.3", exp: "cis-1.3", callFn: withNoPath, v: viper.New(), succeed: false},
{n: "no version-missing-kubectl", kubeVersion: "", benchmarkVersion: "", v: viperWithData, exp: "", callFn: withNoPath, succeed: false},
{n: "no version-fakeKubectl", kubeVersion: "", benchmarkVersion: "", v: viperWithData, exp: "cis-1.5", callFn: withFakeKubectl, succeed: true},
{n: "kubeVersion", kubeVersion: "1.15", benchmarkVersion: "", v: viperWithData, exp: "cis-1.5", callFn: withNoPath, succeed: true},
{n: "ocpVersion310", kubeVersion: "ocp-3.10", benchmarkVersion: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
{n: "ocpVersion311", kubeVersion: "ocp-3.11", benchmarkVersion: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
{n: "gke10", kubeVersion: "gke-1.0", benchmarkVersion: "", v: viperWithData, exp: "gke-1.0", callFn: withNoPath, succeed: true},
{n: "both versions", kubeVersion: "1.11", benchmarkVersion: "cis-1.3", platformName: "", exp: "cis-1.3", callFn: withNoPath, v: viper.New(), succeed: false},
{n: "no version-missing-kubectl", kubeVersion: "", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.6", callFn: withNoPath, succeed: true},
{n: "no version-fakeKubectl", kubeVersion: "", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.6", callFn: withFakeKubectl, succeed: true},
{n: "kubeVersion", kubeVersion: "1.15", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "cis-1.5", callFn: withNoPath, succeed: true},
{n: "ocpVersion310", kubeVersion: "ocp-3.10", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
{n: "ocpVersion311", kubeVersion: "ocp-3.11", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "rh-0.7", callFn: withNoPath, succeed: true},
{n: "gke10", kubeVersion: "gke-1.0", benchmarkVersion: "", platformName: "", v: viperWithData, exp: "gke-1.0", callFn: withNoPath, succeed: true},
}
for _, c := range cases {
rv, err := c.callFn(c.kubeVersion, c.benchmarkVersion, c.v, getBenchmarkVersion)
rv, err := c.callFn(c.kubeVersion, c.benchmarkVersion, c.platformName, c.v, getBenchmarkVersion)
if c.succeed {
if err != nil {
t.Errorf("[%q]-Unexpected error: %v", c.n, err)
@@ -506,17 +509,19 @@ func TestIsEtcd(t *testing.T) {
defer restore()
for _, tc := range testCases {
cfgFile = tc.cfgFile
initConfig()
func() {
cfgFile = tc.cfgFile
initConfig()
oldGetBinariesFunc := getBinariesFunc
getBinariesFunc = tc.getBinariesFunc
defer func() {
getBinariesFunc = oldGetBinariesFunc
cfgFile = ""
oldGetBinariesFunc := getBinariesFunc
getBinariesFunc = tc.getBinariesFunc
defer func() {
getBinariesFunc = oldGetBinariesFunc
cfgFile = ""
}()
assert.Equal(t, tc.isEtcd, isEtcd(), tc.name)
}()
assert.Equal(t, tc.isEtcd, isEtcd(), tc.name)
}
}
@@ -625,7 +630,7 @@ groups:
Edit the config file /this/is/a/file/path and set SomeSampleFlag to true.
scored: true
`)
controls, err := check.NewControls(check.MASTER, input)
controls, err := check.NewControls(check.MASTER, input, "")
assert.NoError(t, err)
binSubs := []string{"TestBinPath"}

View File

@@ -33,24 +33,28 @@ func (k *KubeVersion) BaseVersion() string {
}
func getKubeVersionFromRESTAPI() (*KubeVersion, error) {
glog.V(2).Info("Try to get version from Rest API")
k8sVersionURL := getKubernetesURL()
serviceaccount := "/var/run/secrets/kubernetes.io/serviceaccount"
cacertfile := fmt.Sprintf("%s/ca.crt", serviceaccount)
tokenfile := fmt.Sprintf("%s/token", serviceaccount)
tlsCert, err := loadCertficate(cacertfile)
tlsCert, err := loadCertificate(cacertfile)
if err != nil {
glog.V(2).Infof("Failed loading certificate Error: %s", err)
return nil, err
}
tb, err := ioutil.ReadFile(tokenfile)
if err != nil {
glog.V(2).Infof("Failed reading token file Error: %s", err)
return nil, err
}
token := strings.TrimSpace(string(tb))
data, err := getWebDataWithRetry(k8sVersionURL, token, tlsCert)
if err != nil {
glog.V(2).Infof("Failed to get data Error: %s", err)
return nil, err
}
@@ -143,7 +147,7 @@ func getWebData(srvURL, token string, cacert *tls.Certificate) ([]byte, error) {
return ioutil.ReadAll(resp.Body)
}
func loadCertficate(certFile string) (*tls.Certificate, error) {
func loadCertificate(certFile string) (*tls.Certificate, error) {
cacert, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, err

View File

@@ -11,8 +11,8 @@ import (
"testing"
)
func TestLoadCertficate(t *testing.T) {
tmp, err := ioutil.TempDir("", "TestFakeLoadCertficate")
func TestLoadCertificate(t *testing.T) {
tmp, err := ioutil.TempDir("", "TestFakeLoadCertificate")
if err != nil {
t.Fatalf("unable to create temp directory: %v", err)
}
@@ -58,7 +58,7 @@ FAjB57z2NcIgJuVpQnGRYtr/JcH2Qdsq8bLtXaojUIWOOqoTDRLYozdMOOQ=
for id, c := range cases {
t.Run(strconv.Itoa(id), func(t *testing.T) {
tlsCert, err := loadCertficate(c.file)
tlsCert, err := loadCertificate(c.file)
if !c.fail {
if err != nil {
t.Errorf("unexpected error: %v", err)

View File

@@ -28,15 +28,16 @@ var masterCmd = &cobra.Command{
Short: "Run Kubernetes benchmark checks from the master.yaml file.",
Long: `Run Kubernetes benchmark checks from the master.yaml file in cfg/<version>.`,
Run: func(cmd *cobra.Command, args []string) {
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
if err != nil {
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
}
filename := loadConfig(check.MASTER, bv)
runChecks(check.MASTER, filename)
runChecks(check.MASTER, filename, detecetedKubeVersion)
writeOutput(controlsCollection)
},
Deprecated: "this command will be retired soon. Please use the `run` command with `--targets=master` instead.",
}
func init() {

View File

@@ -28,15 +28,16 @@ var nodeCmd = &cobra.Command{
Short: "Run Kubernetes benchmark checks from the node.yaml file.",
Long: `Run Kubernetes benchmark checks from the node.yaml file in cfg/<version>.`,
Run: func(cmd *cobra.Command, args []string) {
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
if err != nil {
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
}
filename := loadConfig(check.NODE, bv)
runChecks(check.NODE, filename)
runChecks(check.NODE, filename, detecetedKubeVersion)
writeOutput(controlsCollection)
},
Deprecated: "this command will be retired soon. Please use the `run` command with `--targets=node` instead.",
}
func init() {

View File

@@ -33,33 +33,34 @@ type FilterOpts struct {
}
var (
envVarsPrefix = "KUBE_BENCH"
defaultKubeVersion = "1.18"
kubeVersion string
benchmarkVersion string
cfgFile string
cfgDir = "./cfg/"
jsonFmt bool
junitFmt bool
pgSQL bool
aSFF bool
masterFile = "master.yaml"
nodeFile = "node.yaml"
etcdFile = "etcd.yaml"
controlplaneFile = "controlplane.yaml"
policiesFile = "policies.yaml"
managedservicesFile = "managedservices.yaml"
exitCode int
noResults bool
noSummary bool
noRemediations bool
skipIds string
noTotals bool
filterOpts FilterOpts
includeTestOutput bool
outputFile string
configFileError error
controlsCollection []*check.Controls
envVarsPrefix = "KUBE_BENCH"
defaultKubeVersion = "1.18"
kubeVersion string
detecetedKubeVersion string
benchmarkVersion string
cfgFile string
cfgDir = "./cfg/"
jsonFmt bool
junitFmt bool
pgSQL bool
aSFF bool
masterFile = "master.yaml"
nodeFile = "node.yaml"
etcdFile = "etcd.yaml"
controlplaneFile = "controlplane.yaml"
policiesFile = "policies.yaml"
managedservicesFile = "managedservices.yaml"
exitCode int
noResults bool
noSummary bool
noRemediations bool
skipIds string
noTotals bool
filterOpts FilterOpts
includeTestOutput bool
outputFile string
configFileError error
controlsCollection []*check.Controls
)
// RootCmd represents the base command when called without any subcommands
@@ -68,7 +69,7 @@ var RootCmd = &cobra.Command{
Short: "Run CIS Benchmarks checks against a Kubernetes deployment",
Long: `This tool runs the CIS Kubernetes Benchmark (https://www.cisecurity.org/benchmark/kubernetes/)`,
Run: func(cmd *cobra.Command, args []string) {
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
if err != nil {
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
}
@@ -76,7 +77,7 @@ var RootCmd = &cobra.Command{
if isMaster() {
glog.V(1).Info("== Running master checks ==")
runChecks(check.MASTER, loadConfig(check.MASTER, bv))
runChecks(check.MASTER, loadConfig(check.MASTER, bv), detecetedKubeVersion)
// Control Plane is only valid for CIS 1.5 and later,
// this a gatekeeper for previous versions
@@ -86,7 +87,7 @@ var RootCmd = &cobra.Command{
}
if valid {
glog.V(1).Info("== Running control plane checks ==")
runChecks(check.CONTROLPLANE, loadConfig(check.CONTROLPLANE, bv))
runChecks(check.CONTROLPLANE, loadConfig(check.CONTROLPLANE, bv), detecetedKubeVersion)
}
} else {
glog.V(1).Info("== Skipping master checks ==")
@@ -100,13 +101,13 @@ var RootCmd = &cobra.Command{
}
if valid && isEtcd() {
glog.V(1).Info("== Running etcd checks ==")
runChecks(check.ETCD, loadConfig(check.ETCD, bv))
runChecks(check.ETCD, loadConfig(check.ETCD, bv), detecetedKubeVersion)
} else {
glog.V(1).Info("== Skipping etcd checks ==")
}
glog.V(1).Info("== Running node checks ==")
runChecks(check.NODE, loadConfig(check.NODE, bv))
runChecks(check.NODE, loadConfig(check.NODE, bv), detecetedKubeVersion)
// Policies is only valid for CIS 1.5 and later,
// this a gatekeeper for previous versions.
@@ -116,7 +117,7 @@ var RootCmd = &cobra.Command{
}
if valid {
glog.V(1).Info("== Running policies checks ==")
runChecks(check.POLICIES, loadConfig(check.POLICIES, bv))
runChecks(check.POLICIES, loadConfig(check.POLICIES, bv), detecetedKubeVersion)
} else {
glog.V(1).Info("== Skipping policies checks ==")
}
@@ -129,7 +130,7 @@ var RootCmd = &cobra.Command{
}
if valid {
glog.V(1).Info("== Running managed services checks ==")
runChecks(check.MANAGEDSERVICES, loadConfig(check.MANAGEDSERVICES, bv))
runChecks(check.MANAGEDSERVICES, loadConfig(check.MANAGEDSERVICES, bv), detecetedKubeVersion)
} else {
glog.V(1).Info("== Skipping managed services checks ==")
}

View File

@@ -32,7 +32,7 @@ var runCmd = &cobra.Command{
exitWithError(fmt.Errorf("unable to get `targets` from command line :%v", err))
}
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, viper.GetViper())
bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformName(), viper.GetViper())
if err != nil {
exitWithError(fmt.Errorf("unable to get benchmark version. error: %v", err))
}
@@ -52,7 +52,10 @@ var runCmd = &cobra.Command{
// Merge version-specific config if any.
path := filepath.Join(cfgDir, bv)
mergeConfig(path)
err = mergeConfig(path)
if err != nil {
fmt.Printf("Error in mergeConfig: %v\n", err)
}
err = run(targets, bv)
if err != nil {
@@ -72,7 +75,7 @@ func run(targets []string, benchmarkVersion string) (err error) {
for _, yamlFile := range yamlFiles {
_, name := filepath.Split(yamlFile)
testType := check.NodeType(strings.Split(name, ".")[0])
runChecks(testType, yamlFile)
runChecks(testType, yamlFile, detecetedKubeVersion)
}
writeOutput(controlsCollection)

View File

@@ -291,17 +291,22 @@ func getKubeVersion() (*KubeVersion, error) {
_, err := exec.LookPath("kubectl")
if err != nil {
glog.V(3).Infof("Error locating kubectl: %s", err)
_, err = exec.LookPath("kubelet")
if err != nil {
glog.V(3).Infof("Error locating kubelet: %s", err)
// Search for the kubelet binary all over the filesystem and run the first match to get the kubernetes version
cmd := exec.Command("/bin/sh", "-c", "`find / -type f -executable -name kubelet 2>/dev/null | grep -m1 .` --version")
out, err := cmd.CombinedOutput()
if err == nil {
glog.V(3).Infof("Found kubelet and query kubernetes version is: %s", string(out))
return getVersionFromKubeletOutput(string(out)), nil
}
glog.Warning(missingKubectlKubeletMessage)
return nil, fmt.Errorf("unable to find the programs kubectl or kubelet in the PATH")
glog.V(1).Info("unable to find the programs kubectl or kubelet in the PATH")
glog.V(1).Infof("Cant detect version, assuming default %s", defaultKubeVersion)
return &KubeVersion{baseVersion: defaultKubeVersion}, nil
}
return getKubeVersionFromKubelet(), nil
}
@@ -313,6 +318,7 @@ func getKubeVersionFromKubectl() *KubeVersion {
cmd := exec.Command("kubectl", "version", "-o", "json")
out, err := cmd.CombinedOutput()
if err != nil {
glog.V(2).Infof("Failed to query kubectl: %s", err)
glog.V(2).Info(err)
}
@@ -324,6 +330,7 @@ func getKubeVersionFromKubelet() *KubeVersion {
out, err := cmd.CombinedOutput()
if err != nil {
glog.V(2).Infof("Failed to query kubelet: %s", err)
glog.V(2).Info(err)
}
@@ -331,7 +338,7 @@ func getKubeVersionFromKubelet() *KubeVersion {
}
func getVersionFromKubectlOutput(s string) *KubeVersion {
glog.V(2).Info(s)
glog.V(2).Infof("Kubectl output: %s", s)
type versionResult struct {
ServerVersion VersionResponse
}
@@ -354,7 +361,7 @@ func getVersionFromKubectlOutput(s string) *KubeVersion {
}
func getVersionFromKubeletOutput(s string) *KubeVersion {
glog.V(2).Info(s)
glog.V(2).Infof("Kubelet output: %s", s)
serverVersionRe := regexp.MustCompile(`Kubernetes v(\d+.\d+)`)
subs := serverVersionRe.FindStringSubmatch(s)
if len(subs) < 2 {
@@ -421,6 +428,12 @@ These program names are provided in the config.yaml, section '%s.%s.bins'
}
func getPlatformName() string {
openShiftVersion := getOpenShiftVersion()
if openShiftVersion != "" {
return openShiftVersion
}
kv, err := getKubeVersion()
if err != nil {
glog.V(2).Info(err)
@@ -439,11 +452,69 @@ func getPlatformNameFromVersion(s string) string {
}
func getPlatformBenchmarkVersion(platform string) string {
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
switch platform {
case "eks":
return "eks-1.0"
case "gke":
return "gke-1.0"
case "aliyun":
return "ack-1.0"
case "ocp-3.10":
return "rh-0.7"
case "ocp-4.1":
return "rh-1.0"
}
return ""
}
func getOpenShiftVersion() string {
glog.V(1).Info("Checking for oc")
_, err := exec.LookPath("oc")
if err == nil {
cmd := exec.Command("oc", "version")
out, err := cmd.CombinedOutput()
if err == nil {
versionRe := regexp.MustCompile(`oc v(\d+\.\d+)`)
subs := versionRe.FindStringSubmatch(string(out))
if len(subs) < 1 {
versionRe = regexp.MustCompile(`Client Version:\s*(\d+\.\d+)`)
subs = versionRe.FindStringSubmatch(string(out))
}
if len(subs) > 1 {
glog.V(2).Infof("OCP output '%s' \nplatform is %s \nocp %v", string(out), getPlatformNameFromVersion(string(out)), subs[1])
ocpBenchmarkVersion, err := getOcpValidVersion(subs[1])
if err == nil {
return fmt.Sprintf("ocp-%s", ocpBenchmarkVersion)
} else {
glog.V(1).Infof("Can't get getOcpValidVersion: %v", err)
}
} else {
glog.V(1).Infof("Can't parse version output: %v", subs)
}
} else {
glog.V(1).Infof("Can't use oc command: %v", err)
}
} else {
glog.V(1).Infof("Can't find oc command: %v", err)
}
return ""
}
func getOcpValidVersion(ocpVer string) (string, error) {
ocpOriginal := ocpVer
for !isEmpty(ocpVer) {
glog.V(3).Info(fmt.Sprintf("getOcpBenchmarkVersion check for ocp: %q \n", ocpVer))
if ocpVer == "3.10" || ocpVer == "4.1" {
glog.V(1).Info(fmt.Sprintf("getOcpBenchmarkVersion found valid version for ocp: %q \n", ocpVer))
return ocpVer, nil
}
ocpVer = decrementVersion(ocpVer)
}
glog.V(1).Info(fmt.Sprintf("getOcpBenchmarkVersion unable to find a match for: %q", ocpOriginal))
return "", fmt.Errorf("unable to find a matching Benchmark Version match for ocp version: %s", ocpOriginal)
}

View File

@@ -15,14 +15,16 @@
package cmd
import (
"github.com/magiconair/properties/assert"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strconv"
"testing"
"github.com/magiconair/properties/assert"
"github.com/aquasecurity/kube-bench/check"
"github.com/spf13/viper"
)
@@ -389,9 +391,9 @@ func TestGetServiceFiles(t *testing.T) {
func TestMakeSubsitutions(t *testing.T) {
cases := []struct {
input string
subst map[string]string
exp string
input string
subst map[string]string
exp string
expectedSubs []string
}{
{input: "Replace $thisbin", subst: map[string]string{"this": "that"}, exp: "Replace that", expectedSubs: []string{"that"}},
@@ -404,6 +406,7 @@ func TestMakeSubsitutions(t *testing.T) {
if s != c.exp {
t.Fatalf("Got %s expected %s", s, c.exp)
}
sort.Strings(subs)
assert.Equal(t, c.expectedSubs, subs)
})
}
@@ -536,6 +539,11 @@ func Test_getPlatformNameFromKubectlOutput(t *testing.T) {
args: args{s: "v1.17.6-gke.1"},
want: "gke",
},
{
name: "ack",
args: args{s: "v1.18.8-aliyun.1"},
want: "aliyun",
},
{
name: "unknown",
args: args{s: "v1.17.6"},
@@ -579,6 +587,13 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
},
want: "gke-1.0",
},
{
name: "aliyun",
args: args{
platform: "aliyun",
},
want: "ack-1.0",
},
{
name: "unknown",
args: args{
@@ -593,6 +608,20 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
},
want: "",
},
{
name: "openshift3",
args: args{
platform: "ocp-3.10",
},
want: "rh-0.7",
},
{
name: "openshift4",
args: args{
platform: "ocp-4.1",
},
want: "rh-1.0",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -602,3 +631,32 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
})
}
}
func Test_getOcpValidVersion(t *testing.T) {
cases := []struct {
openShiftVersion string
succeed bool
exp string
}{
{openShiftVersion: "3.11", succeed: true, exp: "3.10"},
{openShiftVersion: "3.10", succeed: true, exp: "3.10"},
{openShiftVersion: "2.9", succeed: false, exp: ""},
{openShiftVersion: "4.1", succeed: true, exp: "4.1"},
{openShiftVersion: "4.5", succeed: true, exp: "4.1"},
{openShiftVersion: "4.6", succeed: true, exp: "4.1"},
{openShiftVersion: "invalid", succeed: false, exp: ""},
}
for _, c := range cases {
ocpVer,_ := getOcpValidVersion(c.openShiftVersion)
if c.succeed {
if c.exp != ocpVer {
t.Errorf("getOcpValidVersion(%q) - Got %q expected %s", c.openShiftVersion, ocpVer, c.exp)
}
} else {
if len(ocpVer) > 0 {
t.Errorf("getOcpValidVersion(%q) - Expected empty string but Got %s", c.openShiftVersion, ocpVer)
}
}
}
}

25
docs/architecture.md Normal file
View File

@@ -0,0 +1,25 @@
## Test config YAML representation
The tests (or "controls") are maintained in YAML documents. There are different versions of these test YAML files reflecting different [versions and platforms of the CIS Kubernetes Benchmark](./platforms.md). You will find more information about the test file YAML definitions in our [controls documentation](./controls.md).
## Kube-bench benchmarks
The test files for the various versions of Benchmarks can be found in directories
with same name as the Benchmark versions under the `cfg` directory next to the kube-bench executable,
for example `./cfg/cis-1.5` will contain all test files for [CIS Kubernetes Benchmark v1.5.1](https://workbench.cisecurity.org/benchmarks/4892) which are:
master.yaml, controlplane.yaml, node.yaml, etcd.yaml, policies.yaml and config.yaml
Check the contents of the benchmark directory under `cfg` to see which targets are available for that benchmark. Each file except `config.yaml` represents a target (also known as a `control` in other parts of this documentation).
The following table shows the valid targets based on the CIS Benchmark version.
| CIS Benchmark | Targets |
|---|---|
| cis-1.5| master, controlplane, node, etcd, policies |
| cis-1.6| master, controlplane, node, etcd, policies |
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
| eks-1.0| controlplane, node, policies, managedservices |
| ack-1.0| master, controlplane, node, etcd, policies, managedservices |
| rh-0.7| master,node|
| rh-1.0| master, controlplane, node, etcd, policies |

View File

@@ -15,7 +15,7 @@ You can configure kube-bench with the `--asff` to send findings to AWS Security
## Configure permissions in an IAM Role
* Grant these permissions to the IAM Role that the kube-bench pod will be associated with. There are two potions:
* Grant these permissions to the IAM Role that the kube-bench pod will be associated with. There are two options:
* You can run the kube-bench pod under a specific [service account associated with an IAM role](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) that has these permissions to write Security Hub findings.
* Alternatively the pod can be granted permissions specified by the Role that your [EKS node group uses](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html).
@@ -36,16 +36,14 @@ Here is an example IAM Policy that you can attach to your EKS node group's IAM R
}
```
## Configure and rebuild kube-bench
### Modify the job configuration
You will need to download, build and push the kube-bench container image to your ECR repo as described in Step 3 of the [EKS instructions][eks-instructions], except that before you build the container image, you need to edit `cfg/eks-1.0/config.yaml` to specify the AWS account, AWS region, and the EKS Cluster ARN.
* Modify the kube-bench Configmap in `job-eks-asff.yaml` to specify the AWS account, AWS region, and the EKS Cluster ARN.
* In the same file, modify the image specifed in the Job to use the kube-bench image pushed to your ECR
* [Optional] - If you have created a dedicated IAM role to be used with kube-bench as described above in [Configure permissions in an IAM Role](#configure-permissions-in-an-iam-role), you will need to add the IAM role arn to the kube-bench ServiceAccount in `job-eks-asff.yaml`.
* Make sure that `job-eks-asff.yaml` specifies the container image you just pushed to your ECR registry.
## Modify the job configuration
* Modify `job-eks.yaml` to specify the `--asff` flag, so that kube-bench writes output in ASFF format to Security Hub
* Make sure that `job-eks.yaml` specifies the container image you just pushed to your ECR registry.
You can now run kube-bench as a pod in your cluster: `kubectl apply -f job-eks.yaml`
You can now run kube-bench as a pod in your cluster: `kubectl apply -f job-eks-asff.yaml`
Findings will be generated for any kube-bench test that generates a `[FAIL]` or `[WARN]` output. If all tests pass, no findings will be generated. However, it's recommended that you consult the pod log output to check whether any findings were generated but could not be written to Security Hub.

View File

@@ -41,7 +41,7 @@ groups:
text: "Ensure that the --profiling argument is set to false (Scored)"
audit: "ps -ef | grep kube-scheduler | grep -v grep"
tests:
bin_op: or
bin_op: and
test_items:
- flag: "--profiling"
set: true
@@ -150,11 +150,15 @@ pass a check. This criteria is made up of keywords extracted from the output of
the `audit` command and operations that compare these keywords against
values expected by the CIS Kubernetes Benchmark.
There are three ways to extract keywords from the output of the `audit` command,
`flag`, `path`, `env`.
There are three ways to run and extract keywords from the output of the command used,
| Command | Output var |
|---|---|
| `audit` | `flag` |
| `audit_config` | `path` |
| `audit_env` | `env` |
`flag` is used when the keyword is a command-line flag. The associated `audit`
command is usually a `ps` command and a `grep` for the binary whose flag we are
`flag` is used when the keyword is a command-line flag. The associated `audit` command could
be any binaries available on the system like `ps` command and a `grep` for the binary whose flag we are
checking:
```sh
@@ -173,7 +177,7 @@ tests:
```
`path` is used when the keyword is an option set in a JSON or YAML config file.
The associated `audit` command is usually `cat /path/to/config-yaml-or-json`.
The associated `audit_command` command is usually `cat /path/to/config-yaml-or-json`.
For example:
```yml
@@ -189,7 +193,7 @@ tests:
`env` is used to check if the value is present within a specified environment variable. The presence of `env` is treated as an OR operation, if both `flag` and `env` are supplied it will use either to attempt pass the check.
The command used for checking the environment variables of a process **is generated by default**.
If the command being generated is causing errors, you can override the command used by setting `auditEnv` on the check.
If the command being generated is causing errors, you can override the command used by setting `audit_env` on the check.
Similarly, if you don't want the environment checking command to be generated or run at all, specify `disableEnvTesting` as true on the check.
The example below will check if the flag `--auto-tls` is equal to false *OR* `ETCD_AUTO_TLS` is equal to false
@@ -202,6 +206,7 @@ The example below will check if the flag `--auto-tls` is equal to false *OR* `ET
op: eq
value: false
```
**Note:** flag, path and env will act as OR if more then one present.
`test_item` compares the output of the audit command and keywords using the
`set` and `compare` fields.
@@ -220,6 +225,7 @@ The example below will check if the flag `--auto-tls` is equal to false *OR* `ET
If `set` is true, the check passes only if the keyword is present in the output
of the audit command, or config file. If `set` is false, the check passes only
if the keyword is not present in the output of the audit command, or config file.
`set` is true by default.
`compare` has two fields `op` and `value` to compare keywords with expected
value. `op` specifies which operation is used for the comparison, and `value`
@@ -240,6 +246,22 @@ The `op` (operations) currently supported in `kube-bench` are:
- `regex`: tests if the flag value matches the compared value regular expression.
When defining regular expressions in YAML it is generally easier to wrap them in
single quotes, for example `'^[abc]$'`, to avoid issues with string escaping.
- `bitmask` : tests if keyward is bitmasked with the compared value, common usege is for
comparing file permissions in linux.
## Omitting checks
If you decide that a recommendation is not appropriate for your environment, you can choose to omit it by editing the test YAML file to give it the check type `skip` as in this example:
```yaml
checks:
- id: 2.1.1
text: "Ensure that the --allow-privileged argument is set to false (Scored)"
type: "skip"
scored: true
```
No tests will be run for this check and the output will be marked [INFO].
## Configuration and Variables
@@ -256,7 +278,7 @@ version-specific config overwrite similar values in `cfg/config.yaml`.
For example, the kube-apiserver in Red Hat OCP distribution is run as
`hypershift openshift-kube-apiserver` instead of the default `kube-apiserver`.
This difference can be specified by editing the `master.apiserver.defaultbin`
entry `cfg/ocp-3.10/config.yaml`.
entry `cfg/rh-0.7/config.yaml`.
Below is the structure of `cfg/config.yaml`:
@@ -283,7 +305,7 @@ Every node type has a subsection that specifies the main configuration items.
Each component has the following entries:
- `bins`: A list of candidate binaries for a component. `kube-bench` checks this
list and selects the first binary that is running on the node.
list and selects the **first** binary that is running on the node.
If none of the binaries in `bins` list is running, `kube-bench` checks if the
binary specified by `defaultbin` is running and terminates if none of the
@@ -302,7 +324,7 @@ Every node type has a subsection that specifies the main configuration items.
```
- `confs`: A list of candidate configuration files for a component. `kube-bench`
checks this list and selects the first config file that is found on the node.
checks this list and selects the **first** config file that is found on the node.
If none of the config files exists, `kube-bench` defaults conf to the value
of `defaultconf`.
@@ -319,7 +341,7 @@ Every node type has a subsection that specifies the main configuration items.
```
- `svcs`: A list of candidate unitfiles for a component. `kube-bench` checks this
list and selects the first unitfile that is found on the node. If none of the
list and selects the **first** unitfile that is found on the node. If none of the
unitfiles exists, `kube-bench` defaults unitfile to the value of `defaultsvc`.
The selected unitfile for a component can be referenced in `controls` via a
@@ -341,7 +363,7 @@ Every node type has a subsection that specifies the main configuration items.
```
- `kubeconfig`: A list of candidate kubeconfig files for a component. `kube-bench`
checks this list and selects the first file that is found on the node. If none
checks this list and selects the **first** file that is found on the node. If none
of the files exists, `kube-bench` defaults kubeconfig to the value of
`defaultkubeconfig`.

137
docs/flags-and-commands.md Normal file
View File

@@ -0,0 +1,137 @@
## Commands
Command | Description
--- | ---
help | Prints help about any command
run | List of components to run
version | Print kube-bench version
## Flags
Flag | Description
--- | ---
--alsologtostderr | log to standard error as well as files
--asff | Send findings to AWS Security Hub for any benchmark tests that fail or that generate a warning. See [this page][kube-bench-aws-security-hub] for more information on how to enable the kube-bench integration with AWS Security Hub.
--benchmark | Manually specify CIS benchmark version
-c, --check | A comma-delimited list of checks to run as specified in Benchmark document.
--config | config file (default is ./cfg/config.yaml)
--exit-code | Specify the exit code for when checks fail
--group | Run all the checks under this comma-delimited list of groups.
--include-test-output | Prints the actual result when test fails.
--json | Prints the results as JSON
--junit | Prints the results as JUnit
--log_backtrace_at traceLocation | when logging hits line file:N, emit a stack trace (default :0)
--logtostderr | log to standard error instead of files
--noremediations | Disable printing of remediations section to stdout.
--noresults | Disable printing of results section to stdout.
--nototals | Disable calculating and printing of totals for failed, passed, ... checks across all sections
--outputfile | Writes the JSON results to output file
--pgsql | Save the results to PostgreSQL
--scored | Run the scored CIS checks (default true)
--skip string | List of comma separated values of checks to be skipped
--stderrthreshold severity | logs at or above this threshold go to stderr (default 2)
-v, --v Level | log level for V logs (default 0)
--version string | Manually specify Kubernetes version, automatically detected if unset
--vmodule moduleSpec | comma-separated list of pattern=N settings for file-filtered logging
### Examples
#### Report kube-bench findings to AWS Security Hub
You can configure kube-bench with the `--asff` option to send findings to AWS Security Hub for any benchmark tests that fail or that generate a warning. See [this page](asff.md) for more information on how to enable the kube-bench integration with AWS Security Hub.
#### Specifying the benchmark or Kubernetes version
`kube-bench` uses the Kubernetes API, or access to the `kubectl` or `kubelet` executables to try to determine the Kubernetes version, and hence which benchmark to run. If you wish to override this, or if none of these methods are available, you can specify either the Kubernetes version or CIS Benchmark as a command line parameter.
You can specify a particular version of Kubernetes by setting the `--version` flag or with the `KUBE_BENCH_VERSION` environment variable. The value of `--version` takes precedence over the value of `KUBE_BENCH_VERSION`.
For example, run kube-bench using the tests for Kubernetes version 1.13:
```
kube-bench --version 1.13
```
You can specify `--benchmark` to run a specific CIS Benchmark version:
```
kube-bench --benchmark cis-1.5
```
**Note:** It is an error to specify both `--version` and `--benchmark` flags together
#### Specifying Benchmark sections
If you want to run specific CIS Benchmark sections (i.e master, node, etcd, etc...)
you can use the `run --targets` subcommand.
```
kube-bench run --targets master,node
```
or
```
kube-bench run --targets master,node,etcd,policies
```
If no targets are specified, `kube-bench` will determine the appropriate targets based on the CIS Benchmark version and the components detected on the node. The detection is done by verifying which components are running, as defined in the config files (see [Configuration](controls.md#configuration-and-variables).
#### Run specific check or group
`kube-bench` supports running individual checks by specifying the check's `id`
as a comma-delimited list on the command line with the `--check` | `-c` flag.
`kube-bench --check="1.1.1,1.1.2,1.2.1,1.3.3"`
`kube-bench` supports running all checks under group by specifying the group's `id`
as a comma-delimited list on the command line with the `--group` | `-g` flag.
`kube-bench --check="1.1,2.2"`
Will run all checks 1.1.X and 2.2.X.
#### Skip specific check or group
`kube-bench` supports skipping checks or groups by specifying the `id`
as a comma-delimited list on the command line with the `--skip` flag.
`kube-bench --skip="1.1,1.2.1,1.3.3"`
Will skip 1.1.X group and individual checks 1.2.1, 1.3.3.
Skipped checks returns [INFO] output.
#### Exit code
`kube-bench` supports using uniqe exit code when failing a check or more.
`kube-bench --exit-code 42`
Will return 42 if one check or more failed, and 0 incase none failed.
**Note:** [WARN] is not [FAIL].
#### Output manipulation flags
There are four output states:
- [PASS] indicates that the test was run successfully, and passed.
- [FAIL] indicates that the test was run successfully, and failed. The remediation output describes how to correct the configuration, or includes an error message describing why the test could not be run.
- [WARN] means this test needs further attention, for example it is a test that needs to be run manually. Check the remediation output for further information.
- [INFO] is informational output that needs no further action.
Note:
- If the test is Manual, this always generates WARN (because the user has to run it manually)
- If the test is Scored, and kube-bench was unable to run the test, this generates FAIL (because the test has not been passed, and as a Scored test, if it doesn't pass then it must be considered a failure).
- If the test is Not Scored, and kube-bench was unable to run the test, this generates WARN.
- If the test is Scored, type is empty, and there are no `test_items` present, it generates a WARN. This is to highlight tests that appear to be incompletely defined.
`kube-bench` supports multiple output manipulation flags.
`kube-bench --include-test-output` will print failing checks output in the results section
```
[INFO] 1 Master Node Security Configuration
[INFO] 1.1 Master Node Configuration Files
[FAIL] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)
**permissions=777**
```
**Note:** `--noresults` `--noremediations` and `--include-test-output` **will not** effect the json output but only stdout.
Only `--nototals` will effect the json output and thats because it will not call the function to calculate totals.
#### Troubleshooting
Running `kube-bench` with the `-v 3` parameter will generate debug logs that can be very helpful for debugging problems.
If you are using one of the example `job*.yaml` files, you will need to edit the `command` field, for example `["kube-bench", "-v", "3"]`. Once the job has run, the logs can be retrieved using `kubectl logs` on the job's pod.

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

BIN
docs/images/kube-bench.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
docs/images/kube-bench.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x30_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="135px" viewBox="0 0 500 135" enable-background="new 0 0 500 135" xml:space="preserve">
<polygon fill="#1904DA" points="71.153,8.189 31.4,62.284 71.153,112.569 110.419,62.923 "/>
<path fill="#FF445F" d="M46.731,131.015c0.001,0,0.002,0,0.003,0l48.846-0.011c0.002,0,0.004,0,0.005,0
c1.14,0,2.273-0.246,3.319-0.694l-27.752-17.741l-27.598,17.813C44.561,130.792,45.643,131.015,46.731,131.015z"/>
<path fill="#FFC900" d="M110.419,62.923l-39.266,49.646l27.752,17.741c1.262-0.541,2.397-1.376,3.256-2.442l27.959-34.782
l2.489-3.097c0.513-0.638,0.923-1.354,1.224-2.112c0.143-0.359,0.261-0.728,0.353-1.103L110.419,62.923z"/>
<path fill="#FFC900" d="M8.078,86.64c0.217,0.956,0.599,1.875,1.137,2.697c0.149,0.229,0.309,0.45,0.478,0.664l30.461,37.873
c0.892,1.108,2.08,1.969,3.402,2.508l27.598-17.813L31.4,62.284L8.078,86.64z"/>
<path fill="#00FFE4" d="M20.78,32.099c-0.897,1.028-1.543,2.271-1.856,3.634L8.072,82.937c-0.242,1.052-0.266,2.15-0.089,3.214
c0.027,0.164,0.058,0.327,0.095,0.488L31.4,62.284L20.78,32.099z"/>
<path fill="#00FFE4" d="M134.188,86.774c0.311-1.258,0.34-2.585,0.049-3.848l-10.873-47.232c-0.295-1.279-0.884-2.452-1.7-3.438
l-11.244,30.667L134.188,86.774z"/>
<g>
<path fill="#08B1D5" d="M56.624,27.961L71.153,8.189c-0.004,0-0.008,0-0.013,0c-0.017,0-0.035,0.001-0.052,0.001
C70.964,8.191,70.84,8.194,70.715,8.2c-0.014,0.001-0.028,0.003-0.043,0.004c-1.1,0.06-2.188,0.337-3.182,0.812L23.483,30.043
c-1.046,0.5-1.96,1.204-2.703,2.056L31.4,62.284L56.624,27.95V27.961z"/>
<path fill="#08B1D5" d="M118.832,30.042L74.797,9.016c-1.132-0.542-2.387-0.825-3.643-0.827l39.266,54.733l11.244-30.667
C120.901,31.333,119.94,30.571,118.832,30.042z"/>
</g>
<g>
<path fill="#07242D" d="M179,108.611h-8.361l-16.315-16.496c-0.664,0.083-1.34,0.126-2.027,0.126v16.37h-5.959V62.369h5.959
c0,0-0.011,23.984,0,23.984c2.902,0,5.558-1.198,7.443-3.125l7.132-7.286h8.545l-11.596,11.514
c-1.027,1.028-2.192,1.921-3.462,2.646L179,108.611z"/>
<path fill="#07242D" d="M211.871,75.856v16.505c0,0,0,0.024,0,0.035c0,8.961-7.261,16.215-16.223,16.215
c-8.961,0-16.217-7.276-16.217-16.237c0-0.012,0-16.518,0-16.518h5.778v16.505c0,5.762,4.677,10.457,10.439,10.457
c5.762,0,10.433-4.695,10.433-10.457V75.856H211.871z"/>
<path fill="#07242D" d="M250.26,92.238c0,9.042-7.33,16.373-16.373,16.373c-3.967,0-7.605-1.411-10.438-3.758v3.758h-5.944
c0.004-0.373,0.004-46.242,0.004-46.242h5.944l-0.003,17.254c2.834-2.348,6.471-3.758,10.439-3.758
C242.93,75.864,250.261,83.195,250.26,92.238z M244.333,92.238c0-5.769-4.677-10.445-10.446-10.445
c-5.637,0-10.447,4.578-10.447,10.429c0,5.851,4.81,10.462,10.447,10.462C239.656,102.683,244.333,98.007,244.333,92.238z"/>
<path fill="#07242D" d="M286.212,94.367h-26.414c0.994,4.714,5.176,8.271,10.181,8.271c3.265,0,6.176-1.516,8.081-3.878h6.927
c-2.529,5.792-8.3,9.851-15.007,9.851c-9.033,0-16.379-7.358-16.379-16.402s7.345-16.353,16.379-16.353
C279.783,75.779,287.568,84.659,286.212,94.367z M279.65,88.392c-1.521-3.845-5.277-6.553-9.672-6.553s-8.155,2.71-9.679,6.553
H279.65z"/>
<path fill="#07242D" d="M307.437,86.979v5.459h-16.855v-5.459H307.437z"/>
<path fill="#07242D" d="M345.923,92.238c0,9.042-7.33,16.373-16.373,16.373c-3.967,0-7.605-1.411-10.438-3.758v3.758h-5.944
c0.004-0.373,0.004-46.242,0.004-46.242h5.944l-0.003,17.254c2.834-2.348,6.471-3.758,10.438-3.758
C338.593,75.864,345.924,83.195,345.923,92.238z M339.996,92.238c0-5.769-4.677-10.445-10.446-10.445
c-5.637,0-10.447,4.578-10.447,10.429c0,5.851,4.81,10.462,10.447,10.462C335.318,102.683,339.996,98.007,339.996,92.238z"/>
<path fill="#07242D" d="M381.874,94.367H355.46c0.994,4.714,5.176,8.271,10.181,8.271c3.265,0,6.176-1.516,8.081-3.878h6.927
c-2.529,5.792-8.3,9.851-15.007,9.851c-9.033,0-16.379-7.358-16.379-16.402s7.345-16.353,16.379-16.353
C375.445,75.779,383.23,84.659,381.874,94.367z M375.312,88.392c-1.521-3.845-5.277-6.553-9.672-6.553s-8.155,2.71-9.679,6.553
H375.312z"/>
<path fill="#07242D" d="M419.609,92.201c0,11.479,0,16.41,0,16.41h-5.976c0,0,0-10.761,0-16.41c0-5.855-4.767-10.363-10.389-10.363
c-5.622,0-10.41,4.458-10.41,10.363c0,5.652,0,16.41,0,16.41h-5.975V75.856c0,0,2.56,0,5.975,0v3.69c0,0,3.921-3.69,10.41-3.69
C410.942,75.856,419.609,81.839,419.609,92.201z"/>
<path fill="#07242D" d="M447.468,99.621l4.194,4.194c-2.964,2.964-7.058,4.797-11.581,4.797c-4.522,0-8.616-1.833-11.581-4.797
c-2.964-2.964-4.797-7.058-4.797-11.581s1.833-8.616,4.797-11.581c2.964-2.964,7.058-4.797,11.581-4.797
c4.522,0,8.616,1.833,11.581,4.797l-4.194,4.194c-1.89-1.891-4.502-3.061-7.386-3.061s-5.497,1.17-7.386,3.061
c-1.891,1.89-3.06,4.502-3.06,7.386c0,2.885,1.169,5.497,3.06,7.387c1.89,1.89,4.502,3.059,7.386,3.059
S445.577,101.511,447.468,99.621z"/>
<path fill="#07242D" d="M488.639,92.244c0,11.448,0,16.366,0,16.366h-5.96c0,0,0-10.733,0-16.366
c0-5.838-4.756-10.334-10.361-10.334c-5.607,0-10.382,4.446-10.382,10.334c0,5.637,0,16.366,0,16.366h-5.958v-46.24h5.958v17.255
c0,0,3.909-3.679,10.382-3.679C479.996,75.945,488.639,81.912,488.639,92.244z"/>
</g>
<g>
<path fill="#07242D" d="M180.326,58.699h3.129V39.263c0.01-0.171,0-0.344,0-0.517c0-4.751-3.841-8.602-8.592-8.602
c-4.751,0-8.602,3.851-8.602,8.602s3.851,8.602,8.602,8.602h0.435l3.164-3.15h-3.36h-0.239c-3.011,0-5.451-2.441-5.451-5.451
s2.441-5.451,5.451-5.451c3.011,0,5.463,2.441,5.463,5.451V58.699z"/>
<g>
<path fill="#07242D" d="M200.111,30.144v8.709c0,3.041-2.465,5.518-5.505,5.518c-3.041,0-5.508-2.477-5.508-5.518v-8.709h-3.049
v8.709c0,0,0,0,0,0.007c0,4.729,3.828,8.568,8.557,8.568c4.729,0,8.561-3.827,8.561-8.556c0-0.006,0-0.019,0-0.019v-8.709H200.111
z"/>
</g>
<g>
<path fill="#07242D" d="M163.154,35.833c-3.405-8.994-16.602-6.81-16.802,2.939c0.005,2.094,0.724,3.972,1.979,5.502
c1.472,1.787,3.646,2.973,6.101,3.134c0.189,0.012,0.379,0.019,0.57,0.019h8.665c0,0,0-8.656,0-8.655
C163.666,37.773,163.493,36.772,163.154,35.833z M160.464,44.267c0,0-3.937,0-5.455,0c-3.028,0-5.482-2.468-5.482-5.496
c0-1.517,0.617-2.877,1.613-3.87l0.001,0.001c3.386-3.431,9.345-1.024,9.324,3.869C160.464,40.289,160.464,44.267,160.464,44.267z
"/>
</g>
<g>
<path fill="#07242D" d="M222.563,35.833c-3.405-8.994-16.602-6.81-16.802,2.939c0.005,2.094,0.724,3.972,1.979,5.502
c1.472,1.787,3.646,2.973,6.101,3.134c0.189,0.012,0.379,0.019,0.57,0.019h8.665c0,0,0-8.656,0-8.655
C223.075,37.773,222.902,36.772,222.563,35.833z M219.873,44.267c0,0-3.938,0-5.455,0c-3.028,0-5.482-2.468-5.482-5.496
c0-1.517,0.617-2.877,1.613-3.87l0.001,0.001c3.386-3.431,9.345-1.024,9.324,3.869C219.873,40.289,219.873,44.267,219.873,44.267z
"/>
</g>
</g>
<path fill="#FFFFFF" d="M87.645,83.488h-8.361L62.969,66.992c-0.664,0.083-1.34,0.126-2.027,0.126v16.37h-5.959V37.246h5.959
c0,0-0.011,23.984,0,23.984c2.902,0,5.558-1.198,7.443-3.125l7.132-7.286h8.545L72.467,62.333c-1.027,1.028-2.192,1.921-3.462,2.646
L87.645,83.488z"/>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

35
docs/index.md Normal file
View File

@@ -0,0 +1,35 @@
[download]: https://img.shields.io/github/downloads/aquasecurity/kube-bench/total?logo=github
[release-img]: https://img.shields.io/github/release/aquasecurity/kube-bench.svg?logo=github
[release]: https://github.com/aquasecurity/kube-bench/releases
[docker-pull]: https://img.shields.io/docker/pulls/aquasec/kube-bench?logo=docker&label=docker%20pulls%20%2F%20kube-bench
[cov-img]: https://codecov.io/github/aquasecurity/kube-bench/branch/main/graph/badge.svg
[cov]: https://codecov.io/github/aquasecurity/kube-bench
[report-card-img]: https://goreportcard.com/badge/github.com/aquasecurity/kube-bench
[report-card]: https://goreportcard.com/report/github.com/aquasecurity/kube-bench
![Kube-bench Logo](images/kube-bench.jpg)
[![GitHub Release][release-img]][release]
![Downloads][download]
![Docker Pulls][docker-pull]
[![Go Report Card][report-card-img]][report-card]
[![Build Status](https://github.com/aquasecurity/kube-bench/workflows/Build/badge.svg?branch=main)](https://github.com/aquasecurity/kube-bench/actions)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/aquasecurity/kube-bench/blob/main/LICENSE)
[![Docker image](https://images.microbadger.com/badges/image/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench "Get your own image badge on microbadger.com")
[![Source commit](https://images.microbadger.com/badges/commit/aquasec/kube-bench.svg)](https://microbadger.com/images/aquasec/kube-bench)
[![Coverage Status][cov-img]][cov]
# Kube-bench
kube-bench is a Go application that checks whether Kubernetes is deployed securely by running the checks documented in the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/).
Tests are configured with YAML files, making this tool easy to update as test specifications evolve.
1. kube-bench implements the [CIS Kubernetes Benchmark](https://www.cisecurity.org/benchmark/kubernetes/) as closely as possible. Please raise issues here if kube-bench is not correctly implementing the test as described in the Benchmark. To report issues in the Benchmark itself (for example, tests that you believe are inappropriate), please join the [CIS community](https://cisecurity.org).
1. There is not a one-to-one mapping between releases of Kubernetes and releases of the CIS benchmark. See [CIS Kubernetes Benchmark support](#cis-kubernetes-benchmark-support) to see which releases of Kubernetes are covered by different releases of the benchmark.
1. It is impossible to inspect the master nodes of managed clusters, e.g. GKE, EKS, AKS and ACK, using kube-bench as one does not have access to such nodes, although it is still possible to use kube-bench to check worker node configuration in these environments.
For help and more information go to our [github discussions q&a](https://github.com/aquasecurity/kube-bench/discussions/categories/q-a)

79
docs/installation.md Normal file
View File

@@ -0,0 +1,79 @@
## Installation
You can choose to
* Run kube-bench from inside a container (sharing PID namespace with the host). See [Running inside a container](./running.md#running-inside-a-container) for additional details.
* Run a container that installs kube-bench on the host, and then run kube-bench directly on the host. See [Installing from a container](#installing-from-a-container) for additional details.
* install the latest binaries from the [Releases page](https://github.com/aquasecurity/kube-bench/releases), though please note that you also need to download the config and test files from the `cfg` directory. See [Download and Install binaries](#download-and-install-binaries) for details.
* Compile it from source. See [Installing from sources](#installing-from-sources) for details.
### Download and Install binaries
It is possible to manually install and run kube-bench release binaries. In order to do that, you must have access to your Kubernetes cluster nodes. Note that if you're using one of the managed Kubernetes services (e.g. EKS, AKS, GKE, ACK, OCP), you will not have access to the master nodes of your cluster and you cant perform any tests on the master nodes.
First, log into one of the nodes using SSH.
Install kube-bench binary for your platform using the commands below. Note that there may be newer releases available. See [releases page](https://github.com/aquasecurity/kube-bench/releases).
Ubuntu/Debian:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.2/kube-bench_0.6.2_linux_amd64.deb -o kube-bench_0.6.2_linux_amd64.deb
sudo apt install ./kube-bench_0.6.2_linux_amd64.deb -f
```
RHEL:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.2/kube-bench_0.6.2_linux_amd64.rpm -o kube-bench_0.6.2_linux_amd64.rpm
sudo yum install kube-bench_0.6.2_linux_amd64.rpm -y
```
Alternatively, you can manually download and extract the kube-bench binary:
```
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.6.2/kube-bench_0.6.2_linux_amd64.tar.gz -o kube-bench_0.6.2_linux_amd64.tar.gz
tar -xvf kube-bench_0.6.2_linux_amd64.tar.gz
```
You can then run kube-bench directly:
```
kube-bench
```
If you manually downloaded the kube-bench binary (using curl command above), you have to specify the location of configuration directory and file. For example:
```
./kube-bench --config-dir `pwd`/cfg --config `pwd`/cfg/config.yaml
```
See previous section on [Running kube-bench](./running.md#running-kube-bench) for further details on using the kube-bench binary.
### Installing from sources
If Go is installed on the target machines, you can simply clone this repository and run as follows (assuming your [`GOPATH` is set](https://github.com/golang/go/wiki/GOPATH)):
```shell
go get github.com/aquasecurity/kube-bench
cd $GOPATH/src/github.com/aquasecurity/kube-bench
go build -o kube-bench .
# See all supported options
./kube-bench --help
# Run all checks
./kube-bench
```
### Installing from a container
This command copies the kube-bench binary and configuration files to your host from the Docker container:
**binaries compiled for linux-x86-64 only (so they won't run on macOS or Windows)**
```
docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
```
You can then run `./kube-bench`.

16
docs/platforms.md Normal file
View File

@@ -0,0 +1,16 @@
## CIS Kubernetes Benchmark support
kube-bench supports running tests for Kubernetes.
Most of our supported benchmarks are defined in the [CIS Kubernetes Benchmarks](https://www.cisecurity.org/benchmark/kubernetes/).
Some defined by other hardenening guides.
| Source | Kubernetes Benchmark | kube-bench config | Kubernetes versions |
|---|---|---|---|
| CIS | [1.5.1](https://workbench.cisecurity.org/benchmarks/4892) | cis-1.5 | 1.15- |
| CIS | [1.6.0](https://workbench.cisecurity.org/benchmarks/4834) | cis-1.6 | 1.16- |
| CIS | [GKE 1.0.0](https://workbench.cisecurity.org/benchmarks/4536) | gke-1.0 | GKE |
| CIS | [EKS 1.0.0](https://workbench.cisecurity.org/benchmarks/5190) | eks-1.0 | EKS |
| CIS | [ACK 1.0.0](https://workbench.cisecurity.org/benchmarks/6467) | ack-1.0 | ACK |
| RHEL | RedHat OpenShift hardening guide | rh-0.7 | OCP 3.10-3.11 |
| CIS | [OCP4 1.1.0](https://workbench.cisecurity.org/benchmarks/6778) | rh-1.0 | OCP 4.1- |

145
docs/running.md Normal file
View File

@@ -0,0 +1,145 @@
## Running kube-bench
If you run kube-bench directly from the command line you may need to be root / sudo to have access to all the config files.
By default kube-bench attempts to auto-detect the running version of Kubernetes, and map this to the corresponding CIS Benchmark version. For example, Kubernetes version 1.15 is mapped to CIS Benchmark version `cis-1.15` which is the benchmark version valid for Kubernetes 1.15.
kube-bench also attempts to identify the components running on the node, and uses this to determine which tests to run (for example, only running the master node tests if the node is running an API server).
**Please note**
It is impossible to inspect the master nodes of managed clusters, e.g. GKE, EKS, AKS and ACK, using kube-bench as one does not have access to such nodes, although it is still possible to use kube-bench to check worker node configuration in these environments.
### Running inside a container
You can avoid installing kube-bench on the host by running it inside a container using the host PID namespace and mounting the `/etc` and `/var` directories where the configuration and other files are located on the host so that kube-bench can check their existence and permissions.
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t aquasec/kube-bench:latest --version 1.18
```
> Note: the tests require either the kubelet or kubectl binary in the path in order to auto-detect the Kubernetes version. You can pass `-v $(which kubectl):/usr/local/mount-from-host/bin/kubectl` to resolve this. You will also need to pass in kubeconfig credentials. For example:
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -v $(which kubectl):/usr/local/mount-from-host/bin/kubectl -v ~/.kube:/.kube -e KUBECONFIG=/.kube/config -t aquasec/kube-bench:latest
```
You can use your own configs by mounting them over the default ones in `/opt/kube-bench/cfg/`
```
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro -t -v path/to/my-config.yaml:/opt/kube-bench/cfg/config.yaml -v $(which kubectl):/usr/local/mount-from-host/bin/kubectl -v ~/.kube:/.kube -e KUBECONFIG=/.kube/config aquasec/kube-bench:latest
```
### Running in a Kubernetes cluster
You can run kube-bench inside a pod, but it will need access to the host's PID namespace in order to check the running processes, as well as access to some directories on the host where config files and other files are stored.
The supplied `job.yaml` file can be applied to run the tests as a job. For example:
```bash
$ kubectl apply -f job.yaml
job.batch/kube-bench created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-j76s9 0/1 ContainerCreating 0 3s
# Wait for a few seconds for the job to complete
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-j76s9 0/1 Completed 0 11s
# The results are held in the pod's logs
kubectl logs kube-bench-j76s9
[INFO] 1 Master Node Security Configuration
[INFO] 1.1 API Server
...
```
To run tests on the master node, the pod needs to be scheduled on that node. This involves setting a nodeSelector and tolerations in the pod spec.
The default labels applied to master nodes has changed since Kubernetes 1.11, so if you are using an older version you may need to modify the nodeSelector and tolerations to run the job on the master node.
### Running in an AKS cluster
1. Create an AKS cluster(e.g. 1.13.7) with RBAC enabled, otherwise there would be 4 failures
1. Use the [kubectl-enter plugin](https://github.com/kvaps/kubectl-enter) to shell into a node
`
kubectl-enter {node-name}
`
or ssh to one agent node
could open nsg 22 port and assign a public ip for one agent node (only for testing purpose)
1. Run CIS benchmark to view results:
```
docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
./kube-bench
```
kube-bench cannot be run on AKS master nodes
### Running in an EKS cluster
There is a `job-eks.yaml` file for running the kube-bench node checks on an EKS cluster. The significant difference on EKS is that it's not possible to schedule jobs onto the master node, so master checks can't be performed
1. To create an EKS Cluster refer to [Getting Started with Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html) in the *Amazon EKS User Guide*
- Information on configuring `eksctl`, `kubectl` and the AWS CLI is within
2. Create an [Amazon Elastic Container Registry (ECR)](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) repository to host the kube-bench container image
```
aws ecr create-repository --repository-name k8s/kube-bench --image-tag-mutability MUTABLE
```
3. Download, build and push the kube-bench container image to your ECR repo
```
git clone https://github.com/aquasecurity/kube-bench.git
cd kube-bench
aws ecr get-login-password --region <AWS_REGION> | docker login --username AWS --password-stdin <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com
docker build -t k8s/kube-bench .
docker tag k8s/kube-bench:latest <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
docker push <AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest
```
4. Copy the URI of your pushed image, the URI format is like this: `<AWS_ACCT_NUMBER>.dkr.ecr.<AWS_REGION>.amazonaws.com/k8s/kube-bench:latest`
5. Replace the `image` value in `job-eks.yaml` with the URI from Step 4
6. Run the kube-bench job on a Pod in your Cluster: `kubectl apply -f job-eks.yaml`
7. Find the Pod that was created, it *should* be in the `default` namespace: `kubectl get pods --all-namespaces`
8. Retrieve the value of this Pod and output the report, note the Pod name will vary: `kubectl logs kube-bench-<value>`
- You can save the report for later reference: `kubectl logs kube-bench-<value> > kube-bench-report.txt`
### Running on OpenShift
| OpenShift Hardening Guide | kube-bench config |
|---|---|
| ocp-3.10 +| rh-0.7 |
| ocp-4.1 +| rh-1.0 |
kube-bench includes a set of test files for Red Hat's OpenShift hardening guide for OCP 3.10 and 4.1. To run this you will need to specify `--benchmark rh-07`, or `--version ocp-3.10` or,`--version ocp-4.5` or `--benchmark rh-1.0`
`kube-bench` supports auto-detection, when you run the `kube-bench` command it will autodetect if running in openshift environment.
### Running in a GKE cluster
| CIS Benchmark | Targets |
|---|---|
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
kube-bench includes benchmarks for GKE. To run this you will need to specify `--benchmark gke-1.0` when you run the `kube-bench` command.
To run the benchmark as a job in your GKE cluster apply the included `job-gke.yaml`.
```
kubectl apply -f job-gke.yaml
```
### Running in a ACK cluster
| CIS Benchmark | Targets |
|---|---|
| ack-1.0| master, controlplane, node, etcd, policies, managedservices |
kube-bench includes benchmarks for Alibaba Cloud Container Service For Kubernetes (ACK).
To run this you will need to specify `--benchmark ack-1.0` when you run the `kube-bench` command.
To run the benchmark as a job in your ACK cluster apply the included `job-ack.yaml`.
```
kubectl apply -f job-ack.yaml
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,121 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 831.49597 755.90533"
height="755.90533"
width="831.49597"
xml:space="preserve"
id="svg2"
version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs6"><clipPath
id="clipPath22"
clipPathUnits="userSpaceOnUse"><path
id="path20"
d="M 0,566.929 H 623.622 V 0 H 0 Z" /></clipPath></defs><g
transform="matrix(1.3333333,0,0,-1.3333333,0,755.90533)"
id="g10"><g
transform="translate(314.8111,521.959)"
id="g12"><path
id="path14"
style="fill:#0ab1d5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 -106.784,-145.31 0,-280.384 105.477,-147.025 Z" /></g><g
id="g16"><g
clip-path="url(#clipPath22)"
id="g18"><g
transform="translate(51.8912,72.061)"
id="g24"><path
id="path26"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 71.061 c 0,3.629 2.86,6.6 6.6,6.6 3.74,0 6.6,-2.971 6.6,-6.6 V 32.45 h 2.97 c 1.32,0 2.42,0.551 3.52,1.981 L 33.44,52.69 c 1.43,1.981 3.081,3.3 5.72,3.3 3.63,0 6.271,-2.969 6.271,-6.599 0,-1.87 -0.881,-3.411 -1.981,-4.731 L 29.59,27.5 44.44,3.96 C 45.32,2.641 45.76,1.21 45.76,0 c 0,-3.63 -2.97,-6.6 -6.6,-6.6 -2.309,0 -4.4,1.54 -5.5,3.411 L 19.8,19.25 c -0.88,1.431 -1.98,2.091 -3.52,2.091 H 13.2 L 13.2,0 C 13.2,-3.63 10.34,-6.6 6.6,-6.6 2.86,-6.6 0,-3.63 0,0" /></g><g
transform="translate(104.9547,86.8013)"
id="g28"><path
id="path30"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 34.65 c 0,3.63 2.97,6.6 6.6,6.6 3.629,0 6.6,-2.97 6.6,-6.6 V 2.86 c 0,-8.47 3.409,-11.44 9.57,-11.44 4.73,0 9.24,2.86 11.33,4.95 v 38.28 c 0,3.63 2.97,6.6 6.6,6.6 3.63,0 6.6,-2.97 6.6,-6.6 v -50.16 c 0,-3.3 -2.53,-5.83 -5.72,-5.83 -2.97,0 -5.06,2.09 -5.72,4.95 l -0.55,2.42 C 32.12,-17.16 26.18,-21.34 18.149,-21.34 5.06,-21.34 0,-11.99 0,0" /></g><g
transform="translate(197.5084,90.4312)"
id="g32"><path
id="path34"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 12.65 c 0,8.47 -2.971,12.54 -10.341,12.54 -4.069,0 -8.029,-2.2 -10.559,-4.839 V -7.59 c 2.53,-2.639 6.49,-4.95 10.559,-4.95 C -2.971,-12.54 0,-8.47 0,0 m -34.101,-19.14 v 71.83 c 0,3.63 2.861,6.601 6.6,6.601 3.74,0 6.601,-2.971 6.601,-6.601 V 31.57 c 3.08,3.191 8.359,6.05 14.299,6.05 13.09,0 19.8,-8.8 19.8,-23.54 V -1.319 c 0,-14.741 -6.819,-23.651 -20.13,-23.651 -6.16,0 -11.88,2.97 -14.96,6.491 l -0.66,-2.201 c -0.769,-2.53 -3.08,-4.29 -5.72,-4.29 -3.299,0 -5.83,2.75 -5.83,5.83" /></g><g
transform="translate(251.7047,102.311)"
id="g36"><path
id="path38"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,9.57 -1.87,14.301 -9.9,14.301 -7.92,0 -9.9,-4.181 -9.9,-14.301 z M -33,-15.069 V 2.2 c 0,14.521 7.479,23.54 23.1,23.54 15.95,0 22.77,-8.689 22.77,-23.54 v -7.37 c 0,-2.859 -2.309,-5.17 -5.17,-5.17 h -27.5 v -5.939 c 0,-4.62 2.86,-9.13 10.89,-9.13 5.72,0 8.8,0.88 13.09,2.97 0.66,0.33 1.54,0.66 2.42,0.66 2.97,0 5.39,-2.42 5.39,-5.391 0,-2.309 -1.429,-3.96 -3.52,-5.17 -5.17,-2.97 -10.23,-4.51 -17.93,-4.51 -15.73,0 -23.54,8.25 -23.54,21.781" /></g><g
transform="translate(271.7564,99.4517)"
id="g40"><path
id="path42"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,3.3 2.53,5.83 5.721,5.83 h 19.91 c 3.3,0 5.83,-2.53 5.83,-5.83 0,-3.19 -2.53,-5.72 -5.83,-5.72 H 5.721 C 2.53,-5.72 0,-3.19 0,0" /></g><g
transform="translate(345.776,90.4312)"
id="g44"><path
id="path46"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 12.65 c 0,8.47 -2.971,12.54 -10.341,12.54 -4.069,0 -8.029,-2.2 -10.559,-4.839 V -7.59 c 2.53,-2.639 6.49,-4.95 10.559,-4.95 C -2.971,-12.54 0,-8.47 0,0 m -34.101,-19.14 v 71.83 c 0,3.63 2.861,6.601 6.6,6.601 3.74,0 6.601,-2.971 6.601,-6.601 V 31.57 c 3.08,3.191 8.359,6.05 14.299,6.05 13.09,0 19.8,-8.8 19.8,-23.54 V -1.319 c 0,-14.741 -6.819,-23.651 -20.13,-23.651 -6.16,0 -11.88,2.97 -14.96,6.491 l -0.66,-2.201 c -0.769,-2.53 -3.08,-4.29 -5.72,-4.29 -3.299,0 -5.83,2.75 -5.83,5.83" /></g><g
transform="translate(399.9723,102.311)"
id="g48"><path
id="path50"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0,9.57 -1.87,14.301 -9.9,14.301 -7.92,0 -9.9,-4.181 -9.9,-14.301 z M -33,-15.069 V 2.2 c 0,14.521 7.479,23.54 23.1,23.54 15.95,0 22.77,-8.689 22.77,-23.54 v -7.37 c 0,-2.859 -2.309,-5.17 -5.17,-5.17 h -27.5 v -5.939 c 0,-4.62 2.86,-9.13 10.89,-9.13 5.72,0 8.8,0.88 13.09,2.97 0.66,0.33 1.54,0.66 2.42,0.66 2.97,0 5.39,-2.42 5.39,-5.391 0,-2.309 -1.429,-3.96 -3.52,-5.17 -5.17,-2.97 -10.23,-4.51 -17.93,-4.51 -15.73,0 -23.54,8.25 -23.54,21.781" /></g><g
transform="translate(421.8512,72.061)"
id="g52"><path
id="path54"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 50.16 c 0,3.301 2.53,5.83 5.72,5.83 2.97,0 5.06,-2.09 5.72,-4.949 l 0.55,-2.421 c 3.19,3.191 9.13,7.37 17.16,7.37 13.09,0 18.15,-9.349 18.15,-21.34 V 0 c 0,-3.63 -2.97,-6.6 -6.6,-6.6 -3.63,0 -6.599,2.97 -6.599,6.6 v 31.79 c 0,8.471 -3.411,11.44 -9.571,11.44 -4.73,0 -9.24,-2.86 -11.33,-4.95 L 13.2,0 C 13.2,-3.63 10.23,-6.6 6.6,-6.6 2.97,-6.6 0,-3.63 0,0" /></g><g
transform="translate(478.358,89.1118)"
id="g56"><path
id="path58"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 15.29 c 0,14.52 8.36,23.649 24.31,23.649 8.36,0 14.08,-3.08 18.15,-8.029 1.21,-1.54 1.87,-2.75 1.87,-4.511 0,-3.299 -2.53,-5.83 -5.83,-5.83 -1.76,0 -3.08,0.66 -4.4,1.981 -2.75,2.75 -5.39,4.62 -9.79,4.62 -8.69,0 -11.11,-5.83 -11.11,-12.981 L 13.2,1.1 c 0,-7.151 2.75,-12.981 11.44,-12.981 4.4,0 7.04,1.87 9.79,4.62 1.32,1.321 2.31,1.981 4.29,1.981 3.3,0 5.94,-2.531 5.94,-5.83 0,-1.76 -0.66,-2.97 -1.87,-4.51 C 38.72,-20.57 33,-23.65 24.64,-23.65 8.689,-23.65 0,-14.521 0,0" /></g><g
transform="translate(530.5396,72.061)"
id="g60"><path
id="path62"
style="fill:#464648;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 v 71.061 c 0,3.629 2.86,6.6 6.6,6.6 3.74,0 6.6,-2.971 6.6,-6.6 v -21.34 c 3.41,2.969 9.02,6.269 16.17,6.269 13.09,0 18.26,-9.349 18.26,-21.34 V 0 c 0,-3.63 -2.859,-6.6 -6.6,-6.6 -3.74,0 -6.6,2.97 -6.6,6.6 v 31.79 c 0,8.471 -3.52,11.44 -9.68,11.44 -4.729,0 -9.46,-2.86 -11.55,-4.95 V 0 C 13.2,-3.63 10.34,-6.6 6.6,-6.6 2.86,-6.6 0,-3.63 0,0" /></g><g
transform="translate(249.2096,192.0259)"
id="g64"><path
id="path66"
style="fill:#f1df36;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 h 0.008 l 131.211,0.031 h 0.013 c 3.063,0 6.107,0.66 8.916,1.863 L 65.602,49.549 -8.531,1.7 C -5.83,0.6 -2.923,0 0,0" /></g><g
transform="translate(420.2877,374.9341)"
id="g68"><path
id="path70"
style="fill:#faaf42;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 -105.477,-133.359 74.547,-47.655 c 3.392,1.452 6.439,3.697 8.747,6.559 l 75.104,93.431 6.686,8.317 c 1.38,1.714 2.479,3.637 3.289,5.675 0.384,0.965 0.701,1.954 0.95,2.962 z" /></g><g
transform="translate(145.3785,311.2251)"
id="g72"><path
id="path74"
style="fill:#faaf42;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c 0.583,-2.568 1.609,-5.036 3.054,-7.245 0.401,-0.614 0.83,-1.209 1.285,-1.783 l 81.823,-101.735 c 2.396,-2.975 5.588,-5.289 9.138,-6.736 L 169.433,-69.65 62.648,65.424 Z" /></g><g
transform="translate(179.4977,457.7324)"
id="g76"><path
id="path78"
style="fill:#9ad7ec;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c -2.408,-2.762 -4.144,-6.1 -4.985,-9.762 l -29.149,-126.8 c -0.65,-2.826 -0.715,-5.774 -0.239,-8.633 0.073,-0.44 0.155,-0.878 0.254,-1.312 l 62.648,65.424 z" /></g><g
transform="translate(484.1334,310.8643)"
id="g80"><path
id="path82"
style="fill:#9ad7ec;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 C 0.837,3.378 0.913,6.943 0.131,10.337 L -29.076,137.21 c -0.791,3.437 -2.374,6.586 -4.566,9.236 L -63.846,64.07 Z" /></g><g
transform="translate(317.7506,366.4487)"
id="g84"><path
id="path86"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 0,0 40.622,41.329 H 14.038 L -18.791,6.272 V 77.598 H -39.47 V -56.101 h 20.679 v 40.069 l 3.269,3.181 33.46,-43.25 h 27.03 z" /></g><g
transform="translate(275.7818,468.8486)"
id="g88"><path
id="path90"
style="fill:#1280c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 39.028,53.109 c -0.01,0 -0.022,10e-4 -0.033,10e-4 -0.047,0 -0.094,-0.003 -0.141,-0.003 C 38.521,53.105 38.187,53.099 37.853,53.082 37.814,53.08 37.776,53.072 37.738,53.07 34.783,52.909 31.86,52.166 29.192,50.889 L -89.022,-5.593 c -2.809,-1.342 -5.266,-3.235 -7.262,-5.523 L -67.755,-92.199 0,0.03 Z" /></g><g
transform="translate(442.8853,463.2578)"
id="g92"><path
id="path94"
style="fill:#1280c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 -118.288,56.48 c -3.039,1.455 -6.412,2.215 -9.785,2.22 L -22.598,-88.324 7.606,-5.947 C 5.558,-3.467 2.978,-1.422 0,0" /></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -47,7 +47,7 @@
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
[WARN] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Scored)
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
@@ -140,6 +140,11 @@ on the master node and set the --audit-log-maxsize parameter to an appropriate s
For example, to set it as 100 MB:
--audit-log-maxsize=100
1.2.26 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
and set the below parameter as appropriate and if needed.
For example,
--request-timeout=300s
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
@@ -166,13 +171,13 @@ on the master node and set the below parameter.
== Summary master ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
11 checks WARN
0 checks INFO
== Summary total ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
0 checks INFO
11 checks WARN
0 checks INFO

View File

@@ -47,7 +47,7 @@
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Scored)
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Scored)
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Scored)
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
[WARN] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Scored)
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Scored)
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Scored)
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Scored)
@@ -140,6 +140,11 @@ on the master node and set the --audit-log-maxsize parameter to an appropriate s
For example, to set it as 100 MB:
--audit-log-maxsize=100
1.2.26 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
and set the below parameter as appropriate and if needed.
For example,
--request-timeout=300s
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
@@ -166,9 +171,9 @@ on the master node and set the below parameter.
== Summary master ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
11 checks WARN
0 checks INFO
[INFO] 2 Etcd Node Configuration
@@ -353,7 +358,7 @@ UIDs not including 0.
5.2.8 Ensure that allowedCapabilities is not present in PSPs for the cluster unless
it is set to an empty array.
5.2.9 Review the use of capabilites in applications runnning on your cluster. Where a namespace
5.2.9 Review the use of capabilites in applications running on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
@@ -410,7 +415,7 @@ resources and that all new resources are created in a specific namespace.
0 checks INFO
== Summary total ==
72 checks PASS
71 checks PASS
13 checks FAIL
37 checks WARN
38 checks WARN
0 checks INFO

View File

@@ -47,7 +47,7 @@
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Automated)
[WARN] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Automated)
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Automated)
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Automated)
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)
@@ -140,6 +140,11 @@ on the master node and set the --audit-log-maxsize parameter to an appropriate s
For example, to set it as 100 MB:
--audit-log-maxsize=100
1.2.26 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
and set the below parameter as appropriate and if needed.
For example,
--request-timeout=300s
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
@@ -169,13 +174,13 @@ on the master node and set the below parameter.
== Summary master ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
11 checks WARN
0 checks INFO
== Summary total ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
0 checks INFO
11 checks WARN
0 checks INFO

View File

@@ -47,7 +47,7 @@
[FAIL] 1.2.23 Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)
[FAIL] 1.2.24 Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)
[FAIL] 1.2.25 Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)
[PASS] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Automated)
[WARN] 1.2.26 Ensure that the --request-timeout argument is set as appropriate (Automated)
[PASS] 1.2.27 Ensure that the --service-account-lookup argument is set to true (Automated)
[PASS] 1.2.28 Ensure that the --service-account-key-file argument is set as appropriate (Automated)
[PASS] 1.2.29 Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)
@@ -140,6 +140,11 @@ on the master node and set the --audit-log-maxsize parameter to an appropriate s
For example, to set it as 100 MB:
--audit-log-maxsize=100
1.2.26 Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
and set the below parameter as appropriate and if needed.
For example,
--request-timeout=300s
1.2.33 Follow the Kubernetes documentation and configure a EncryptionConfig file.
Then, edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
on the master node and set the --encryption-provider-config parameter to the path of that file: --encryption-provider-config=</path/to/EncryptionConfig/File>
@@ -169,9 +174,9 @@ on the master node and set the below parameter.
== Summary master ==
45 checks PASS
44 checks PASS
10 checks FAIL
10 checks WARN
11 checks WARN
0 checks INFO
[INFO] 2 Etcd Node Configuration
@@ -356,7 +361,7 @@ UIDs not including 0.
5.2.8 Ensure that allowedCapabilities is not present in PSPs for the cluster unless
it is set to an empty array.
5.2.9 Review the use of capabilites in applications runnning on your cluster. Where a namespace
5.2.9 Review the use of capabilites in applications running on your cluster. Where a namespace
contains applicaions which do not require any Linux capabities to operate consider adding
a PSP which forbids the admission of containers which do not drop all capabilities.
@@ -413,7 +418,7 @@ resources and that all new resources are created in a specific namespace.
0 checks INFO
== Summary total ==
72 checks PASS
71 checks PASS
11 checks FAIL
39 checks WARN
0 checks INFO
40 checks WARN
0 checks INFO

34
job-ack.yaml Normal file
View File

@@ -0,0 +1,34 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench
spec:
template:
spec:
hostPID: true
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
command: ["kube-bench", "--benchmark", "ack-1.0", "run", "--targets", "node,policies,managedservices"]
volumeMounts:
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-kubelet
hostPath:
path: "/var/lib/kubelet"
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"

View File

@@ -18,6 +18,9 @@ spec:
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: etc-default
mountPath: /etc/default
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
@@ -29,6 +32,9 @@ spec:
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: etc-default
hostPath:
path: "/etc/default"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"

67
job-eks-asff.yaml Normal file
View File

@@ -0,0 +1,67 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-bench
# If using a dedicated IAM role for kube-bench, uncomment the annotations
# block below and replace the ROLE_ARN
# annotations:
# eks.amazonaws.com/role-arn: "<ROLE_ARN>"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-bench-eks-config
data:
config.yaml: |
AWS_ACCOUNT: "<AWS_ACCT_NUMBER>"
AWS_REGION: "<AWS_REGION>"
CLUSTER_ARN: "<AWS_CLUSTER_ARN>"
---
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench
spec:
template:
spec:
hostPID: true
containers:
- name: kube-bench
# Push the image to your ECR and then refer to it here
image: <ID.dkr.ecr.region.amazonaws.com/aquasec/kube-bench:ref>
command: ["kube-bench", "node", "--benchmark", "eks-1.0", "--asff"]
volumeMounts:
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
- name: kube-bench-eks-config
mountPath: "/opt/kube-bench/cfg/eks-1.0/config.yaml"
subPath: config.yaml
readOnly: true
restartPolicy: Never
serviceAccountName: kube-bench
volumes:
- name: var-lib-kubelet
hostPath:
path: "/var/lib/kubelet"
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"
- name: kube-bench-eks-config
configMap:
name: kube-bench-eks-config
items:
- key: config.yaml
path: config.yaml

View File

@@ -10,11 +10,9 @@ spec:
containers:
- name: kube-bench
# Push the image to your ECR and then refer to it here
image: <ID.dkr.ecr.region.amazonaws.com/aquasec/kube-bench:ref>
# Use the --asff flag if you would like to send findings to AWS Security Hub
# Note that this requires you to rebuild a version of the kube-bench image
# after editing the cfg/eks-1.0/config.yaml with your account information
# command: ["kube-bench", "node", "--benchmark", "eks-1.0", "--asff"]
# image: <ID.dkr.ecr.region.amazonaws.com/aquasec/kube-bench:ref>
image: aquasec/kube-bench:latest
# To send findings to AWS Security Hub, refer to `job-eks-asff.yaml` instead
command: ["kube-bench", "node", "--benchmark", "eks-1.0"]
volumeMounts:
- name: var-lib-kubelet

View File

@@ -16,11 +16,29 @@ spec:
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
command: ["kube-bench", "master"]
command: ["kube-bench", "run", "--targets=master"]
volumeMounts:
- name: var-lib-etcd
mountPath: /var/lib/etcd
readOnly: true
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: var-lib-kube-scheduler
mountPath: /var/lib/kube-scheduler
readOnly: true
- name: var-lib-kube-controller-manager
mountPath: /var/lib/kube-controller-manager
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: lib-systemd
mountPath: /lib/systemd/
readOnly: true
- name: srv-kubernetes
mountPath: /srv/kubernetes/
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
@@ -29,14 +47,56 @@ spec:
- name: usr-bin
mountPath: /usr/local/mount-from-host/bin
readOnly: true
- name: etc-cni-netd
mountPath: /etc/cni/net.d/
readOnly: true
- name: opt-cni-bin
mountPath: /opt/cni/bin/
readOnly: true
- name: etc-passwd
mountPath: /etc/passwd
readOnly: true
- name: etc-group
mountPath: /etc/group
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-etcd
hostPath:
path: "/var/lib/etcd"
- name: var-lib-kubelet
hostPath:
path: "/var/lib/kubelet"
- name: var-lib-kube-scheduler
hostPath:
path: "/var/lib/kube-scheduler"
- name: var-lib-kube-controller-manager
hostPath:
path: "/var/lib/kube-controller-manager"
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: lib-systemd
hostPath:
path: "/lib/systemd"
- name: srv-kubernetes
hostPath:
path: "/srv/kubernetes"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"
- name: usr-bin
hostPath:
path: "/usr/bin"
- name: etc-cni-netd
hostPath:
path: "/etc/cni/net.d/"
- name: opt-cni-bin
hostPath:
path: "/opt/cni/bin/"
- name: etc-passwd
hostPath:
path: "/etc/passwd"
- name: etc-group
hostPath:
path: "/etc/group"

View File

@@ -10,14 +10,29 @@ spec:
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
command: ["kube-bench", "node"]
command: ["kube-bench", "run", "--targets=node"]
volumeMounts:
- name: var-lib-etcd
mountPath: /var/lib/etcd
readOnly: true
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: var-lib-kube-scheduler
mountPath: /var/lib/kube-scheduler
readOnly: true
- name: var-lib-kube-controller-manager
mountPath: /var/lib/kube-controller-manager
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: lib-systemd
mountPath: /lib/systemd/
readOnly: true
- name: srv-kubernetes
mountPath: /srv/kubernetes/
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
@@ -26,17 +41,44 @@ spec:
- name: usr-bin
mountPath: /usr/local/mount-from-host/bin
readOnly: true
- name: etc-cni-netd
mountPath: /etc/cni/net.d/
readOnly: true
- name: opt-cni-bin
mountPath: /opt/cni/bin/
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-etcd
hostPath:
path: "/var/lib/etcd"
- name: var-lib-kubelet
hostPath:
path: "/var/lib/kubelet"
- name: var-lib-kube-scheduler
hostPath:
path: "/var/lib/kube-scheduler"
- name: var-lib-kube-controller-manager
hostPath:
path: "/var/lib/kube-controller-manager"
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: lib-systemd
hostPath:
path: "/lib/systemd"
- name: srv-kubernetes
hostPath:
path: "/srv/kubernetes"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"
- name: usr-bin
hostPath:
path: "/usr/bin"
- name: etc-cni-netd
hostPath:
path: "/etc/cni/net.d/"
- name: opt-cni-bin
hostPath:
path: "/opt/cni/bin/"

View File

@@ -21,9 +21,21 @@ spec:
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: var-lib-kube-scheduler
mountPath: /var/lib/kube-scheduler
readOnly: true
- name: var-lib-kube-controller-manager
mountPath: /var/lib/kube-controller-manager
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
- name: lib-systemd
mountPath: /lib/systemd/
readOnly: true
- name: srv-kubernetes
mountPath: /srv/kubernetes/
readOnly: true
- name: etc-kubernetes
mountPath: /etc/kubernetes
readOnly: true
@@ -32,6 +44,12 @@ spec:
- name: usr-bin
mountPath: /usr/local/mount-from-host/bin
readOnly: true
- name: etc-cni-netd
mountPath: /etc/cni/net.d/
readOnly: true
- name: opt-cni-bin
mountPath: /opt/cni/bin/
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-etcd
@@ -40,12 +58,30 @@ spec:
- name: var-lib-kubelet
hostPath:
path: "/var/lib/kubelet"
- name: var-lib-kube-scheduler
hostPath:
path: "/var/lib/kube-scheduler"
- name: var-lib-kube-controller-manager
hostPath:
path: "/var/lib/kube-controller-manager"
- name: etc-systemd
hostPath:
path: "/etc/systemd"
- name: lib-systemd
hostPath:
path: "/lib/systemd"
- name: srv-kubernetes
hostPath:
path: "/srv/kubernetes"
- name: etc-kubernetes
hostPath:
path: "/etc/kubernetes"
- name: usr-bin
hostPath:
path: "/usr/bin"
- name: etc-cni-netd
hostPath:
path: "/etc/cni/net.d/"
- name: opt-cni-bin
hostPath:
path: "/opt/cni/bin/"

41
mkdocs.yml Normal file
View File

@@ -0,0 +1,41 @@
---
site_name: Kube-bench
site_url: https://aquasecurity.github.io/kube-bench/
site_description: Checks whether Kubernetes is deployed according to security best practices as defined in the CIS Kubernetes Benchmark
docs_dir: docs/
repo_name: GitHub
repo_url: https://github.com/aquasecurity/kube-bench/
edit_uri: ""
nav:
- Overview: index.md
- Getting Started:
- Installation: installation.md
- Platforms: platforms.md
- How to run: running.md
- ASFF: asff.md
- Flags: flags-and-commands.md
- Configuration Options:
- Understanding the yamls: controls.md
- Architecture: architecture.md
- Contributing: CONTRIBUTING.md
markdown_extensions:
- pymdownx.highlight
- pymdownx.superfences
- admonition
extra:
generator: false
version:
method: mike
provider: mike
theme:
name: material
language: 'en'
logo: images/kube-bench-logo-only.png
plugins:
- search
- macros