mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2026-02-19 20:40:17 +00:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c6915c478 | ||
|
|
9363cdf8ef | ||
|
|
b29ed6b6ed | ||
|
|
aa16551811 | ||
|
|
40cdc1bfbb | ||
|
|
e2e353a81a | ||
|
|
a727d73e8a | ||
|
|
76c25b2db2 | ||
|
|
ca8743c1f7 | ||
|
|
84f80b59b8 | ||
|
|
60dde65d72 | ||
|
|
124c57c6f4 | ||
|
|
e41755ba90 | ||
|
|
6de03bbd7d | ||
|
|
c2880848f0 | ||
|
|
968ee5814e | ||
|
|
29c8f16167 | ||
|
|
b0e49c8789 | ||
|
|
e38c829dbc | ||
|
|
8098489433 | ||
|
|
b43f58dcda | ||
|
|
dd6573f3ed | ||
|
|
0ff5dd0b8e | ||
|
|
124a8b3a5a | ||
|
|
c3b6871766 | ||
|
|
96c6b385ef | ||
|
|
9e41099cec | ||
|
|
0decc8a53f | ||
|
|
7aeb6c3977 | ||
|
|
7d0d8ca993 | ||
|
|
823f3e1064 | ||
|
|
fc72a8a620 | ||
|
|
c17b4dd2ba | ||
|
|
edff7f45a9 | ||
|
|
b942ed3f0b | ||
|
|
e1d1053358 | ||
|
|
07cd55da9c | ||
|
|
e6d0056b8e | ||
|
|
9991268c85 | ||
|
|
465c16fe4b | ||
|
|
e08cf54cb0 | ||
|
|
8f654a9fc6 | ||
|
|
4ccffb8fdd | ||
|
|
ec51394eb7 | ||
|
|
e096229a5a | ||
|
|
98742f014e | ||
|
|
f959abe0da | ||
|
|
d5039002af | ||
|
|
ba23ef534a | ||
|
|
bd8dd3adcc | ||
|
|
865817dfda | ||
|
|
3ccafa7be1 | ||
|
|
44eef9289e | ||
|
|
bb3c8e9685 | ||
|
|
55688aa62d | ||
|
|
9660e7842d | ||
|
|
3b8379f081 | ||
|
|
377a05f872 | ||
|
|
150c40b5b1 | ||
|
|
a1e2870e83 | ||
|
|
dd39b19ffc | ||
|
|
df687cbe0d | ||
|
|
818d57d620 | ||
|
|
4d76c77c6a | ||
|
|
07e01cf38c | ||
|
|
a34047c105 | ||
|
|
e05dabe0a9 | ||
|
|
59760891bd | ||
|
|
9e95301f09 | ||
|
|
113ee337ee | ||
|
|
93a167a917 | ||
|
|
7146b65da4 | ||
|
|
c4e904d909 | ||
|
|
1c46d386a8 | ||
|
|
ddae7417ef | ||
|
|
670782c47b | ||
|
|
7b9ec26432 | ||
|
|
eaa84fc34e | ||
|
|
7a68b38763 | ||
|
|
af7e0c0f0b | ||
|
|
3c3cffa5ae | ||
|
|
3321b2d129 | ||
|
|
7078772f6d | ||
|
|
e6b3eddb03 | ||
|
|
907d952fb3 | ||
|
|
ce53cffc70 | ||
|
|
ed5ebc5740 | ||
|
|
ebdfba55cc | ||
|
|
f90e3a41cd | ||
|
|
68cd8c6be5 | ||
|
|
b6bc27db17 | ||
|
|
f423325423 | ||
|
|
3f85968c3c | ||
|
|
e0704da7d0 | ||
|
|
b03069171f | ||
|
|
5685f81676 | ||
|
|
681f8fe0db | ||
|
|
41e3e64472 | ||
|
|
181d621456 | ||
|
|
9c3d2051a5 | ||
|
|
e8654d0281 | ||
|
|
1cd61c2ac5 | ||
|
|
54b797349b | ||
|
|
06b7941e13 | ||
|
|
72a96b1f56 | ||
|
|
aa66470631 | ||
|
|
2696870027 | ||
|
|
ca4c9c6339 | ||
|
|
2496e391f5 | ||
|
|
f4c372fe42 | ||
|
|
149c5268e8 | ||
|
|
d5018f280b | ||
|
|
d190cbcaf6 | ||
|
|
fbc89e1275 | ||
|
|
b8edf791f9 | ||
|
|
3089d6e1b5 | ||
|
|
aea61c93c7 | ||
|
|
02fd0d4be2 | ||
|
|
521136504c | ||
|
|
48b80f8f01 | ||
|
|
3040a1f80e | ||
|
|
f28d9f804e | ||
|
|
1a08ef2dbc | ||
|
|
b6a2ff8c83 | ||
|
|
741ce79883 | ||
|
|
f445e33671 | ||
|
|
436141eac9 | ||
|
|
e0fe5698a0 | ||
|
|
10ab72abfb | ||
|
|
faa1e88d0d | ||
|
|
74d91d2941 | ||
|
|
b3902d2d14 | ||
|
|
70a544e916 | ||
|
|
be157a8a5a | ||
|
|
85020ff474 | ||
|
|
9d01d2a393 | ||
|
|
08e3b371da | ||
|
|
8a2699da44 | ||
|
|
ccded4277a | ||
|
|
55c5b981cf | ||
|
|
021bb13b05 | ||
|
|
f0fb1b6ea2 | ||
|
|
c72c9e9e25 | ||
|
|
c28e7a796e | ||
|
|
9e5d95eb60 | ||
|
|
675515a9b0 | ||
|
|
0d9e05ed86 | ||
|
|
1e592d5f41 | ||
|
|
2595727c38 | ||
|
|
fb10678a88 | ||
|
|
e2599b1e06 | ||
|
|
10f1672bfe | ||
|
|
a9bc826dc1 | ||
|
|
d6c3841018 | ||
|
|
db385c7d09 | ||
|
|
67f8b338d5 | ||
|
|
9f92e81361 | ||
|
|
3b4e87cbc0 | ||
|
|
e73c07d86f | ||
|
|
c0349f0ca8 | ||
|
|
d232ae0fb9 | ||
|
|
9119968940 |
50
.github/workflows/build.yml
vendored
50
.github/workflows/build.yml
vendored
@@ -14,49 +14,54 @@ on:
|
||||
- "LICENSE"
|
||||
- "NOTICE"
|
||||
env:
|
||||
GO_VERSION: "1.16"
|
||||
GO_VERSION: "1.19"
|
||||
KIND_VERSION: "v0.11.1"
|
||||
KIND_IMAGE: "kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: yaml-lint
|
||||
uses: ibiqlik/action-yamllint@v3
|
||||
- name: Setup golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: --verbose
|
||||
unit:
|
||||
name: Unit tests
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Run unit tests
|
||||
run: make tests
|
||||
- name: Upload code coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.txt
|
||||
e2e:
|
||||
name: E2e tests
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Kubernetes cluster (KIND)
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
@@ -78,17 +83,20 @@ jobs:
|
||||
expected_result: PASSED
|
||||
release:
|
||||
name: Release snapshot
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
needs: [e2e, unit]
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Dry-run release snapshot
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
version: v0.169.0
|
||||
fetch-depth: 0
|
||||
- name: Dry-run release snapshot
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: v1.7.0
|
||||
args: release --snapshot --skip-publish --rm-dist
|
||||
|
||||
6
.github/workflows/mkdocs-deploy.yaml
vendored
6
.github/workflows/mkdocs-deploy.yaml
vendored
@@ -13,14 +13,14 @@ on:
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy documentation
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout main
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- run: |
|
||||
|
||||
56
.github/workflows/publish.yml
vendored
56
.github/workflows/publish.yml
vendored
@@ -12,36 +12,36 @@ env:
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check Out Repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildxarch-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildxarch-
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USER }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Login to ECR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
username: ${{ secrets.ECR_ACCESS_KEY_ID }}
|
||||
password: ${{ secrets.ECR_SECRET_ACCESS_KEY }}
|
||||
- name: Get version
|
||||
id: get_version
|
||||
uses: crazy-max/ghaction-docker-meta@v3
|
||||
uses: crazy-max/ghaction-docker-meta@v4
|
||||
with:
|
||||
images: ${{ env.REP }}
|
||||
tag-semver: |
|
||||
@@ -49,10 +49,10 @@ jobs:
|
||||
|
||||
- name: Build and push - Docker/ECR
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
push: true
|
||||
build-args: |
|
||||
@@ -64,5 +64,41 @@ jobs:
|
||||
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
|
||||
|
||||
- name: Build and push ubi image - Docker/ECR
|
||||
id: docker_build_ubi
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
push: true
|
||||
file: Dockerfile.ubi
|
||||
build-args: |
|
||||
KUBEBENCH_VERSION=${{ steps.get_version.outputs.version }}
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}-ubi
|
||||
public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}-ubi
|
||||
cache-from: type=local,src=/tmp/.buildx-cache/release
|
||||
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache/release
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
|
||||
- name: Build and push fips ubi image - Docker/ECR
|
||||
id: docker_build_fips_ubi
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
push: true
|
||||
file: Dockerfile.fips.ubi
|
||||
build-args: |
|
||||
KUBEBENCH_VERSION=${{ steps.get_version.outputs.version }}
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}-ubi-fips
|
||||
public.ecr.aws/${{ env.ALIAS }}/${{ env.REP }}:${{ steps.get_version.outputs.version }}-ubi-fips
|
||||
cache-from: type=local,src=/tmp/.buildx-cache/release
|
||||
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache/release
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
|
||||
17
.github/workflows/release.yml
vendored
17
.github/workflows/release.yml
vendored
@@ -5,21 +5,23 @@ on:
|
||||
tags:
|
||||
- "v*"
|
||||
env:
|
||||
GO_VERSION: "1.16"
|
||||
GO_VERSION: "1.19"
|
||||
KIND_VERSION: "v0.11.1"
|
||||
KIND_IMAGE: "kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.16
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run unit tests
|
||||
run: make tests
|
||||
- name: Setup Kubernetes cluster (KIND)
|
||||
@@ -42,9 +44,10 @@ jobs:
|
||||
second_file_path: integration/testdata/Expected_output.data
|
||||
expected_result: PASSED
|
||||
- name: Release
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
version: v0.169.0
|
||||
distribution: goreleaser
|
||||
version: v1.7.0
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,3 +13,4 @@ coverage.txt
|
||||
thumbs.db
|
||||
/kubeconfig.kube-bench
|
||||
/test.data
|
||||
*.iml
|
||||
12
.golangci.yaml
Normal file
12
.golangci.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- govet
|
||||
- misspell
|
||||
- typecheck
|
||||
- varcheck
|
||||
@@ -8,10 +8,13 @@ builds:
|
||||
binary: kube-bench
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
- ppc64le
|
||||
- s390x
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
|
||||
@@ -77,3 +77,4 @@ Finally, we can use the `make kind-run` target to run the current version of kub
|
||||
|
||||
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` )
|
||||
|
||||
To run the STIG tests locally execute the following: `make build-docker kind-push kind-run-stig`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17.6 AS build
|
||||
FROM golang:1.20.4 AS build
|
||||
WORKDIR /go/src/github.com/aquasecurity/kube-bench/
|
||||
COPY makefile makefile
|
||||
COPY go.mod go.sum ./
|
||||
@@ -9,7 +9,7 @@ COPY internal/ internal/
|
||||
ARG KUBEBENCH_VERSION
|
||||
RUN make build && cp kube-bench /go/bin/kube-bench
|
||||
|
||||
FROM alpine:3.15.0 AS run
|
||||
FROM alpine:3.18 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
|
||||
@@ -26,8 +26,7 @@ RUN apk update && apk upgrade && 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 gcompat
|
||||
RUN apk add jq
|
||||
|
||||
ENV PATH=$PATH:/usr/local/mount-from-host/bin
|
||||
|
||||
49
Dockerfile.fips.ubi
Normal file
49
Dockerfile.fips.ubi
Normal file
@@ -0,0 +1,49 @@
|
||||
FROM golang:1.20.4 AS build
|
||||
WORKDIR /go/src/github.com/aquasecurity/kube-bench/
|
||||
COPY makefile makefile
|
||||
COPY go.mod go.sum ./
|
||||
COPY main.go .
|
||||
COPY check/ check/
|
||||
COPY cmd/ cmd/
|
||||
COPY internal/ internal/
|
||||
ARG KUBEBENCH_VERSION
|
||||
RUN make build-fips && cp kube-bench /go/bin/kube-bench
|
||||
|
||||
|
||||
# ubi8-minimal base image for build with ubi standards
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal as run
|
||||
|
||||
RUN microdnf install -y yum findutils openssl \
|
||||
&& yum -y update-minimal --security --sec-severity=Moderate --sec-severity=Important --sec-severity=Critical \
|
||||
&& yum update -y \
|
||||
&& yum install -y glibc \
|
||||
&& yum update -y glibc \
|
||||
&& yum install -y procps \
|
||||
&& yum update -y procps \
|
||||
&& yum install jq -y \
|
||||
&& yum clean all \
|
||||
&& microdnf remove yum || rpm -e -v yum \
|
||||
&& microdnf clean all
|
||||
|
||||
WORKDIR /opt/kube-bench/
|
||||
|
||||
ENV PATH=$PATH:/usr/local/mount-from-host/bin
|
||||
|
||||
COPY LICENSE /licenses/LICENSE
|
||||
COPY --from=build /go/bin/kube-bench /usr/local/bin/kube-bench
|
||||
COPY entrypoint.sh .
|
||||
COPY cfg/ cfg/
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["install"]
|
||||
|
||||
|
||||
# Build-time metadata as defined at http://label-schema.org
|
||||
ARG BUILD_DATE
|
||||
ARG VCS_REF
|
||||
LABEL org.label-schema.build-date=$BUILD_DATE \
|
||||
org.label-schema.name="kube-bench" \
|
||||
org.label-schema.description="Run the CIS Kubernetes Benchmark tests" \
|
||||
org.label-schema.url="https://github.com/aquasecurity/kube-bench" \
|
||||
org.label-schema.vcs-ref=$VCS_REF \
|
||||
org.label-schema.vcs-url="https://github.com/aquasecurity/kube-bench" \
|
||||
org.label-schema.schema-version="1.0"
|
||||
49
Dockerfile.ubi
Normal file
49
Dockerfile.ubi
Normal file
@@ -0,0 +1,49 @@
|
||||
FROM golang:1.20.4 AS build
|
||||
WORKDIR /go/src/github.com/aquasecurity/kube-bench/
|
||||
COPY makefile makefile
|
||||
COPY go.mod go.sum ./
|
||||
COPY main.go .
|
||||
COPY check/ check/
|
||||
COPY cmd/ cmd/
|
||||
COPY internal/ internal/
|
||||
ARG KUBEBENCH_VERSION
|
||||
RUN make build && cp kube-bench /go/bin/kube-bench
|
||||
|
||||
|
||||
# ubi8-minimal base image for build with ubi standards
|
||||
FROM registry.access.redhat.com/ubi8/ubi-minimal as run
|
||||
|
||||
RUN microdnf install -y yum findutils openssl \
|
||||
&& yum -y update-minimal --security --sec-severity=Moderate --sec-severity=Important --sec-severity=Critical \
|
||||
&& yum update -y \
|
||||
&& yum install -y glibc \
|
||||
&& yum update -y glibc \
|
||||
&& yum install -y procps \
|
||||
&& yum update -y procps \
|
||||
&& yum install jq -y \
|
||||
&& yum clean all \
|
||||
&& microdnf remove yum || rpm -e -v yum \
|
||||
&& microdnf clean all
|
||||
|
||||
WORKDIR /opt/kube-bench/
|
||||
|
||||
ENV PATH=$PATH:/usr/local/mount-from-host/bin
|
||||
|
||||
COPY LICENSE /licenses/LICENSE
|
||||
COPY --from=build /go/bin/kube-bench /usr/local/bin/kube-bench
|
||||
COPY entrypoint.sh .
|
||||
COPY cfg/ cfg/
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
CMD ["install"]
|
||||
|
||||
|
||||
# Build-time metadata as defined at http://label-schema.org
|
||||
ARG BUILD_DATE
|
||||
ARG VCS_REF
|
||||
LABEL org.label-schema.build-date=$BUILD_DATE \
|
||||
org.label-schema.name="kube-bench" \
|
||||
org.label-schema.description="Run the CIS Kubernetes Benchmark tests" \
|
||||
org.label-schema.url="https://github.com/aquasecurity/kube-bench" \
|
||||
org.label-schema.vcs-ref=$VCS_REF \
|
||||
org.label-schema.vcs-url="https://github.com/aquasecurity/kube-bench" \
|
||||
org.label-schema.schema-version="1.0"
|
||||
@@ -1,17 +1,16 @@
|
||||
[![GitHub Release][release-img]][release]
|
||||
![Downloads][download]
|
||||
![Docker Pulls][docker-pull]
|
||||
[![Downloads][download]][release]
|
||||
[![Docker Pulls][docker-pull]][docker]
|
||||
[![Go Report Card][report-card-img]][report-card]
|
||||
[](https://github.com/aquasecurity/kube-bench/actions)
|
||||
[](https://github.com/aquasecurity/kube-bench/blob/main/LICENSE)
|
||||
[](https://microbadger.com/images/aquasec/kube-bench "Get your own image badge on microbadger.com")
|
||||
[](https://microbadger.com/images/aquasec/kube-bench)
|
||||
[![Coverage Status][cov-img]][cov]
|
||||
|
||||
[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
|
||||
[docker]: https://hub.docker.com/r/aquasec/kube-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
|
||||
|
||||
@@ -97,7 +97,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c permissions=%a $CAFILE; fi
|
||||
tests:
|
||||
@@ -114,7 +114,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
|
||||
@@ -37,7 +37,7 @@ groups:
|
||||
- id: 4.1.4
|
||||
text: "Minimize access to create pods (Manual)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
|
||||
@@ -153,7 +153,13 @@ groups:
|
||||
|
||||
- id: 1.1.11
|
||||
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c permissions=%a
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
@@ -170,7 +176,13 @@ groups:
|
||||
|
||||
- id: 1.1.12
|
||||
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G "$DATA_DIR"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "etcd:etcd"
|
||||
|
||||
@@ -98,7 +98,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c permissions=%a $CAFILE; fi
|
||||
tests:
|
||||
@@ -115,7 +115,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
@@ -388,7 +388,7 @@ groups:
|
||||
scored: false
|
||||
|
||||
- id: 4.2.11
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Manual)"
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
@@ -412,7 +412,7 @@ groups:
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
scored: true
|
||||
|
||||
- id: 4.2.12
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
|
||||
2
cfg/cis-1.23/config.yaml
Normal file
2
cfg/cis-1.23/config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
46
cfg/cis-1.23/controlplane.yaml
Normal file
46
cfg/cis-1.23/controlplane.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.23"
|
||||
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)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
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"
|
||||
set: true
|
||||
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: |
|
||||
Review the audit policy provided for the cluster and ensure that it covers
|
||||
at least the following areas,
|
||||
- Access to Secrets managed by the cluster. Care should be taken to only
|
||||
log Metadata for requests to Secrets, ConfigMaps, and TokenReviews, in
|
||||
order to avoid risk of logging sensitive data.
|
||||
- Modification of Pod and Deployment objects.
|
||||
- Use of `pods/exec`, `pods/portforward`, `pods/proxy` and `services/proxy`.
|
||||
For most requests, minimally logging at the Metadata level is recommended
|
||||
(the most basic level of logging).
|
||||
scored: false
|
||||
135
cfg/cis-1.23/etcd.yaml
Normal file
135
cfg/cis-1.23/etcd.yaml
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.23"
|
||||
id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
type: "etcd"
|
||||
groups:
|
||||
- id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
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
|
||||
966
cfg/cis-1.23/master.yaml
Normal file
966
cfg/cis-1.23/master.yaml
Normal file
@@ -0,0 +1,966 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.23"
|
||||
id: 1
|
||||
text: "Control Plane Security Configuration"
|
||||
type: "master"
|
||||
groups:
|
||||
- id: 1.1
|
||||
text: "Control Plane 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
|
||||
control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane node.
|
||||
For example, chown root:root $schedulerconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.7
|
||||
text: "Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Automated)"
|
||||
audit: "/bin/sh -c '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 control plane node.
|
||||
For example,
|
||||
chmod 644 $etcdconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.8
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)"
|
||||
audit: "/bin/sh -c '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 control plane 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: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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 control plane 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: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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 control plane 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
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 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G "$DATA_DIR"
|
||||
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 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 /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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 --anonymous-auth argument is set to false (Manual)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
scored: false
|
||||
|
||||
- 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 control plane node and remove the --token-auth-file=<filename> parameter.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.3
|
||||
text: "Ensure that the --DenyServiceExternalIPs 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: "DenyServiceExternalIPs"
|
||||
- flag: "--enable-admission-plugins"
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and remove the `DenyServiceExternalIPs`
|
||||
from enabled admission plugins.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.4
|
||||
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 control plane node and remove the --kubelet-https parameter.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.5
|
||||
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 control plane 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.6
|
||||
text: "Ensure that the --kubelet-certificate-authority argument is set as appropriate (Automated)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--kubelet-certificate-authority"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and setup the TLS connection between
|
||||
the apiserver and kubelets. Then, edit the API server pod specification file
|
||||
$apiserverconf on the control plane node and set the
|
||||
--kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.7
|
||||
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 control plane 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.8
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes Node.
|
||||
--authorization-mode=Node,RBAC
|
||||
scored: true
|
||||
|
||||
- id: 1.2.9
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes RBAC,
|
||||
for example `--authorization-mode=Node,RBAC`.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.10
|
||||
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.11
|
||||
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 control plane 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.12
|
||||
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 control plane node and set the --enable-admission-plugins parameter to include
|
||||
AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
scored: false
|
||||
|
||||
- id: 1.2.13
|
||||
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 control plane 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.14
|
||||
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 control plane node and ensure that the --disable-admission-plugins parameter is set to a
|
||||
value that does not include ServiceAccount.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.15
|
||||
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 control plane node and set the --disable-admission-plugins parameter to
|
||||
ensure it does not include NamespaceLifecycle.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.16
|
||||
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 control plane node and set the --enable-admission-plugins parameter to a
|
||||
value that includes NodeRestriction.
|
||||
--enable-admission-plugins=...,NodeRestriction,...
|
||||
scored: true
|
||||
|
||||
- id: 1.2.17
|
||||
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 control plane node and either remove the --secure-port parameter or
|
||||
set it to a different (non-zero) desired port.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.18
|
||||
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 control plane node and set the below parameter.
|
||||
--profiling=false
|
||||
scored: true
|
||||
|
||||
- id: 1.2.19
|
||||
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 control plane 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.20
|
||||
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 control plane node and set the --audit-log-maxage parameter to 30
|
||||
or as an appropriate number of days, for example,
|
||||
--audit-log-maxage=30
|
||||
scored: true
|
||||
|
||||
- id: 1.2.21
|
||||
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 control plane node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
|
||||
value. For example,
|
||||
--audit-log-maxbackup=10
|
||||
scored: true
|
||||
|
||||
- id: 1.2.22
|
||||
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 control plane 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.23
|
||||
text: "Ensure that the --request-timeout argument is set as appropriate (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 1.2.24
|
||||
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 control plane 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.25
|
||||
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 control plane node and set the --service-account-key-file parameter
|
||||
to the public key file for service accounts. For example,
|
||||
--service-account-key-file=<filename>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.26
|
||||
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 control plane 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.27
|
||||
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 control plane 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.28
|
||||
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 control plane node and set the client certificate authority file.
|
||||
--client-ca-file=<path/to/client-ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.29
|
||||
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 control plane node and set the etcd certificate authority file parameter.
|
||||
--etcd-cafile=<path/to/ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.30
|
||||
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 control plane node and set the --encryption-provider-config parameter to the path of that file.
|
||||
For example, --encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
scored: false
|
||||
|
||||
- id: 1.2.31
|
||||
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.32
|
||||
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_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384"
|
||||
remediation: |
|
||||
Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the control plane node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane node and ensure the correct value for the --bind-address parameter
|
||||
scored: true
|
||||
462
cfg/cis-1.23/node.yaml
Normal file
462
cfg/cis-1.23/node.yaml
Normal file
@@ -0,0 +1,462 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.23"
|
||||
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"
|
||||
set: true
|
||||
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 (Automated)"
|
||||
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: true
|
||||
|
||||
- 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}' | uniq)
|
||||
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}' | uniq)
|
||||
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 (Automated)"
|
||||
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` to `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: true
|
||||
|
||||
- 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` to `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 --hostname-override argument is not set (Manual)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override 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: false
|
||||
|
||||
- id: 4.2.9
|
||||
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.10
|
||||
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.11
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line `rotateCertificates` to `true` or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example,
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 4.2.12
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
compare:
|
||||
op: nothave
|
||||
value: false
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 4.2.13
|
||||
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
|
||||
269
cfg/cis-1.23/policies.yaml
Normal file
269
cfg/cis-1.23/policies.yaml
Normal file
@@ -0,0 +1,269 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.23"
|
||||
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.1.7
|
||||
text: "Avoid use of system:masters group (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Remove the system:masters group from all users in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.8
|
||||
text: "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove the impersonate, bind and escalate rights from subjects.
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Pod Security Standards"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Ensure that the cluster has at least one active policy control mechanism in place (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that either Pod Security Admission or an external policy control system is in place
|
||||
for every namespace which contains user workloads.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.2
|
||||
text: "Minimize the admission of privileged containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of privileged containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostPID` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostIPC` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.5
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostNetwork` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.6
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `.spec.allowPrivilegeEscalation` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.7
|
||||
text: "Minimize the admission of root containers (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a policy for each namespace in the cluster, ensuring that either `MustRunAsNonRoot`
|
||||
or `MustRunAs` with the range of UIDs not including 0, is set.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.8
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with the `NET_RAW` capability.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with added capabilities (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that `allowedCapabilities` is not present in policies for the cluster unless
|
||||
it is set to an empty array.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.10
|
||||
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 PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.11
|
||||
text: "Minimize the admission of Windows HostProcess containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers that have `.securityContext.windowsOptions.hostProcess` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.12
|
||||
text: "Minimize the admission of HostPath volumes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `hostPath` volumes.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.13
|
||||
text: "Minimize the admission of containers which use HostPorts (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers which use `hostPort` sections.
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "Network Policies and CNI"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure that the CNI in use supports NetworkPolicies (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 NetworkPolicies 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.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: |
|
||||
Use `securityContext` to enable the docker/default seccomp profile in your pod definitions.
|
||||
An example is as below:
|
||||
securityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
scored: false
|
||||
|
||||
- id: 5.7.3
|
||||
text: "Apply SecurityContext to your Pods and Containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and apply SecurityContexts to your Pods. For a
|
||||
suggested list of SecurityContexts, 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
|
||||
2
cfg/cis-1.24/config.yaml
Normal file
2
cfg/cis-1.24/config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
46
cfg/cis-1.24/controlplane.yaml
Normal file
46
cfg/cis-1.24/controlplane.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.24"
|
||||
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)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
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"
|
||||
set: true
|
||||
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: |
|
||||
Review the audit policy provided for the cluster and ensure that it covers
|
||||
at least the following areas,
|
||||
- Access to Secrets managed by the cluster. Care should be taken to only
|
||||
log Metadata for requests to Secrets, ConfigMaps, and TokenReviews, in
|
||||
order to avoid risk of logging sensitive data.
|
||||
- Modification of Pod and Deployment objects.
|
||||
- Use of `pods/exec`, `pods/portforward`, `pods/proxy` and `services/proxy`.
|
||||
For most requests, minimally logging at the Metadata level is recommended
|
||||
(the most basic level of logging).
|
||||
scored: false
|
||||
135
cfg/cis-1.24/etcd.yaml
Normal file
135
cfg/cis-1.24/etcd.yaml
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.24"
|
||||
id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
type: "etcd"
|
||||
groups:
|
||||
- id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
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
|
||||
949
cfg/cis-1.24/master.yaml
Normal file
949
cfg/cis-1.24/master.yaml
Normal file
@@ -0,0 +1,949 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.24"
|
||||
id: 1
|
||||
text: "Control Plane Security Configuration"
|
||||
type: "master"
|
||||
groups:
|
||||
- id: 1.1
|
||||
text: "Control Plane Node Configuration Files"
|
||||
checks:
|
||||
- id: 1.1.1
|
||||
text: "Ensure that the API server pod specification file permissions are set to 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the
|
||||
control plane node.
|
||||
For example, chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 $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 control plane node.
|
||||
For example, chown root:root $schedulerconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.7
|
||||
text: "Ensure that the etcd pod specification file permissions are set to 600 or more restrictive (Automated)"
|
||||
audit: "/bin/sh -c '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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $etcdconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.8
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)"
|
||||
audit: "/bin/sh -c '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 control plane 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 600 or more restrictive (Manual)"
|
||||
audit: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 <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: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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 control plane 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
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 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G "$DATA_DIR"
|
||||
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 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 /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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $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 control plane 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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod -R 600 /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 control plane 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 --anonymous-auth argument is set to false (Manual)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
scored: false
|
||||
|
||||
- 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 control plane node and remove the --token-auth-file=<filename> parameter.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.3
|
||||
text: "Ensure that the --DenyServiceExternalIPs 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: "DenyServiceExternalIPs"
|
||||
- flag: "--enable-admission-plugins"
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and remove the `DenyServiceExternalIPs`
|
||||
from enabled admission plugins.
|
||||
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 control plane 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 --kubelet-certificate-authority argument is set as appropriate (Automated)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--kubelet-certificate-authority"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and setup the TLS connection between
|
||||
the apiserver and kubelets. Then, edit the API server pod specification file
|
||||
$apiserverconf on the control plane node and set the
|
||||
--kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.6
|
||||
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 control plane 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.7
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes Node.
|
||||
--authorization-mode=Node,RBAC
|
||||
scored: true
|
||||
|
||||
- id: 1.2.8
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes RBAC,
|
||||
for example `--authorization-mode=Node,RBAC`.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.9
|
||||
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.10
|
||||
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 control plane 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.11
|
||||
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 control plane node and set the --enable-admission-plugins parameter to include
|
||||
AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
scored: false
|
||||
|
||||
- id: 1.2.12
|
||||
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 control plane 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.13
|
||||
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 control plane node and ensure that the --disable-admission-plugins parameter is set to a
|
||||
value that does not include ServiceAccount.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.14
|
||||
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 control plane node and set the --disable-admission-plugins parameter to
|
||||
ensure it does not include NamespaceLifecycle.
|
||||
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 control plane 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 --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 control plane node and either remove the --secure-port parameter or
|
||||
set it to a different (non-zero) desired port.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.17
|
||||
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 control plane node and set the below parameter.
|
||||
--profiling=false
|
||||
scored: true
|
||||
|
||||
- id: 1.2.18
|
||||
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 control plane 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.19
|
||||
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 control plane node and set the --audit-log-maxage parameter to 30
|
||||
or as an appropriate number of days, for example,
|
||||
--audit-log-maxage=30
|
||||
scored: true
|
||||
|
||||
- id: 1.2.20
|
||||
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 control plane node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
|
||||
value. For example,
|
||||
--audit-log-maxbackup=10
|
||||
scored: true
|
||||
|
||||
- id: 1.2.21
|
||||
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 control plane 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.22
|
||||
text: "Ensure that the --request-timeout argument is set as appropriate (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 1.2.23
|
||||
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 control plane 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.24
|
||||
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 control plane node and set the --service-account-key-file parameter
|
||||
to the public key file for service accounts. For example,
|
||||
--service-account-key-file=<filename>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.25
|
||||
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 control plane 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.26
|
||||
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 control plane 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.27
|
||||
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 control plane node and set the client certificate authority file.
|
||||
--client-ca-file=<path/to/client-ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.28
|
||||
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 control plane node and set the etcd certificate authority file parameter.
|
||||
--etcd-cafile=<path/to/ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.29
|
||||
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 control plane node and set the --encryption-provider-config parameter to the path of that file.
|
||||
For example, --encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
scored: false
|
||||
|
||||
- id: 1.2.30
|
||||
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.31
|
||||
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_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384"
|
||||
remediation: |
|
||||
Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the control plane node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane node and ensure the correct value for the --bind-address parameter
|
||||
scored: true
|
||||
466
cfg/cis-1.24/node.yaml
Normal file
466
cfg/cis-1.24/node.yaml
Normal file
@@ -0,0 +1,466 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.24"
|
||||
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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example, chmod 600 $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 600 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"
|
||||
set: true
|
||||
compare:
|
||||
op: bitmask
|
||||
value: "600"
|
||||
- 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 600 $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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example,
|
||||
chmod 600 $kubeletkubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 4.1.6
|
||||
text: "Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root (Automated)"
|
||||
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: true
|
||||
|
||||
- id: 4.1.7
|
||||
text: "Ensure that the certificate authorities file permissions are set to 600 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}' | uniq)
|
||||
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: "600"
|
||||
remediation: |
|
||||
Run the following command to modify the file permissions of the
|
||||
--client-ca-file chmod 600 <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}' | uniq)
|
||||
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: "If the kubelet config.yaml configuration file is being used validate permissions set to 600 or more restrictive (Manual)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c permissions=%a $kubeletconf; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
compare:
|
||||
op: bitmask
|
||||
value: "600"
|
||||
remediation: |
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 600 $kubeletconf
|
||||
scored: false
|
||||
|
||||
- id: 4.1.10
|
||||
text: "If the kubelet config.yaml configuration file is being used validate file ownership is set to root:root (Manual)"
|
||||
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: false
|
||||
|
||||
- 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: "Verify 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 (Automated)"
|
||||
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` to `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: true
|
||||
|
||||
- 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` to `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 --hostname-override argument is not set (Manual)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override 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: false
|
||||
|
||||
- id: 4.2.9
|
||||
text: "Ensure that the eventRecordQPS argument is set to 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: gte
|
||||
value: 0
|
||||
- flag: --event-qps
|
||||
path: '{.eventRecordQPS}'
|
||||
set: false
|
||||
bin_op: or
|
||||
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.10
|
||||
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.11
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line `rotateCertificates` to `true` or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example,
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 4.2.12
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
compare:
|
||||
op: nothave
|
||||
value: false
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 4.2.13
|
||||
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
|
||||
269
cfg/cis-1.24/policies.yaml
Normal file
269
cfg/cis-1.24/policies.yaml
Normal file
@@ -0,0 +1,269 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.24"
|
||||
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.1.7
|
||||
text: "Avoid use of system:masters group (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Remove the system:masters group from all users in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.8
|
||||
text: "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove the impersonate, bind and escalate rights from subjects.
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Pod Security Standards"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Ensure that the cluster has at least one active policy control mechanism in place (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that either Pod Security Admission or an external policy control system is in place
|
||||
for every namespace which contains user workloads.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.2
|
||||
text: "Minimize the admission of privileged containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of privileged containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostPID` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostIPC` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.5
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostNetwork` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.6
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `.spec.allowPrivilegeEscalation` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.7
|
||||
text: "Minimize the admission of root containers (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a policy for each namespace in the cluster, ensuring that either `MustRunAsNonRoot`
|
||||
or `MustRunAs` with the range of UIDs not including 0, is set.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.8
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with the `NET_RAW` capability.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with added capabilities (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that `allowedCapabilities` is not present in policies for the cluster unless
|
||||
it is set to an empty array.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.10
|
||||
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 PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.11
|
||||
text: "Minimize the admission of Windows HostProcess containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers that have `.securityContext.windowsOptions.hostProcess` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.12
|
||||
text: "Minimize the admission of HostPath volumes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `hostPath` volumes.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.13
|
||||
text: "Minimize the admission of containers which use HostPorts (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers which use `hostPort` sections.
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "Network Policies and CNI"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure that the CNI in use supports NetworkPolicies (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 NetworkPolicies 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.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: |
|
||||
Use `securityContext` to enable the docker/default seccomp profile in your pod definitions.
|
||||
An example is as below:
|
||||
securityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
scored: false
|
||||
|
||||
- id: 5.7.3
|
||||
text: "Apply SecurityContext to your Pods and Containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and apply SecurityContexts to your Pods. For a
|
||||
suggested list of SecurityContexts, 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
|
||||
@@ -158,7 +158,13 @@ groups:
|
||||
|
||||
- id: 1.1.11
|
||||
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Scored)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c permissions=%a
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
@@ -176,7 +182,13 @@ groups:
|
||||
|
||||
- id: 1.1.12
|
||||
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Scored)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G $DATA_DIR
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "etcd:etcd"
|
||||
|
||||
@@ -106,7 +106,7 @@ groups:
|
||||
- id: 4.1.7
|
||||
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Scored)"
|
||||
audit: |
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c permissions=%a $CAFILE; fi
|
||||
tests:
|
||||
@@ -124,7 +124,7 @@ groups:
|
||||
- id: 4.1.8
|
||||
text: "Ensure that the client certificate authorities file ownership is set to root:root (Scored)"
|
||||
audit: |
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
|
||||
42
cfg/cis-1.6-k3s/config.yaml
Normal file
42
cfg/cis-1.6-k3s/config.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
|
||||
master:
|
||||
components:
|
||||
- scheduler
|
||||
- controllermanager
|
||||
- node
|
||||
|
||||
scheduler:
|
||||
kubeconfig:
|
||||
- /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig
|
||||
defaultkubeconfig: /var/lib/rancher/k3s/server/cred/scheduler.kubeconfig
|
||||
|
||||
controllermanager:
|
||||
kubeconfig:
|
||||
- /var/lib/rancher/k3s/server/cred/cloud-controller.kubeconfig
|
||||
defaultkubeconfig: /var/lib/rancher/k3s/server/cred/cloud-controller.kubeconfig
|
||||
|
||||
etcd:
|
||||
components:
|
||||
- etcd
|
||||
etcd:
|
||||
confs:
|
||||
- /var/lib/rancher/k3s/server/db/etcd/config
|
||||
defaultconf: /var/lib/rancher/k3s/server/db/etcd/config
|
||||
|
||||
node:
|
||||
components:
|
||||
- proxy
|
||||
- kubelet
|
||||
proxy:
|
||||
kubeconfig:
|
||||
- "/var/lib/rancher/k3s/agent/kubeproxy.kubeconfig"
|
||||
defaultkubeconfig: "/var/lib/rancher/k3s/agent/kubeproxy.kubeconfig"
|
||||
kubelet:
|
||||
kubeconfig:
|
||||
- "/var/lib/rancher/k3s/agent/kubelet.kubeconfig"
|
||||
defaultkubeconfig: "/var/lib/rancher/k3s/agent/kubelet.kubeconfig"
|
||||
cafile:
|
||||
- "/var/lib/rancher/k3s/server/tls/server-ca.crt"
|
||||
defaultcafile: "/var/lib/rancher/k3s/server/tls/server-ca.crt"
|
||||
40
cfg/cis-1.6-k3s/controlplane.yaml
Normal file
40
cfg/cis-1.6-k3s/controlplane.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.6-k3s"
|
||||
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)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
scored: false
|
||||
|
||||
- id: 3.2
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 3.2.1
|
||||
text: "Ensure that a minimal audit policy is created (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "audit-policy-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-policy-file"
|
||||
set: true
|
||||
remediation: |
|
||||
Create an audit policy file for your cluster and pass it to k3s.
|
||||
e.g. --kube-apiserver-arg='audit-log-path=/var/lib/rancher/k3s/server/logs/audit-log'
|
||||
scored: true
|
||||
|
||||
- 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
|
||||
119
cfg/cis-1.6-k3s/etcd.yaml
Normal file
119
cfg/cis-1.6-k3s/etcd.yaml
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.6-k3s"
|
||||
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 if use etcd as database (Automated)"
|
||||
audit: grep -A 4 'client-transport-security' $etcdconf | grep -E 'cert-file|key-file'
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "cert-file"
|
||||
- flag: "key-file"
|
||||
remediation: |
|
||||
By default, K3s uses a config file for etcd that can be found at $etcdconf.
|
||||
The config file contains client-transport-security: which has fields that have the peer cert and peer key files. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 2.2
|
||||
text: "Ensure that the --client-cert-auth argument is set to true (Automated)"
|
||||
audit: grep 'client-cert-auth' $etcdconf
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "client-cert-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
By default, K3s uses a config file for etcd that can be found at $etcdconf.
|
||||
client-cert-auth is set to true. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 2.3
|
||||
text: "Ensure that the --auto-tls argument is not set to true (Automated)"
|
||||
audit: grep 'auto-tls' $etcdconf | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "auto-tls"
|
||||
set: false
|
||||
- flag: "auto-tls"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s starts Etcd without this flag. It is set to false by default.
|
||||
scored: true
|
||||
|
||||
- id: 2.4
|
||||
text: "Ensure that the --peer-cert-file and --peer-key-file arguments are
|
||||
set as appropriate (Automated)"
|
||||
audit: grep -A 4 'peer-transport-security' $etcdconf | grep -E 'cert-file|key-file'
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "cert-file"
|
||||
- flag: "key-file"
|
||||
remediation: |
|
||||
By default, K3s starts Etcd with a config file found here, $etcdconf.
|
||||
The config file contains peer-transport-security: which has fields that have the peer cert and peer key files.
|
||||
scored: true
|
||||
|
||||
- id: 2.5
|
||||
text: "Ensure that the --peer-client-cert-auth argument is set to true (Automated)"
|
||||
audit: grep -A 4 'peer-transport-security' $etcdconf | grep 'client-cert-auth'
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "client-cert-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
By default, K3s uses a config file for etcd that can be found at $etcdconf.
|
||||
The config file contains peer-transport-security: which has client-cert-auth set to true. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 2.6
|
||||
text: "Ensure that the --peer-auto-tls argument is not set to true (Automated)"
|
||||
audit: grep 'peer-auto-tls' $etcdconf | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "peer-auto-tls"
|
||||
set: false
|
||||
- flag: "peer-auto-tls"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s uses a config file for etcd that can be found at $etcdconf.
|
||||
Within the file, it does not contain the peer-auto-tls field. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 2.7
|
||||
text: "Ensure that a unique Certificate Authority is used for etcd (Manual)"
|
||||
audit: |
|
||||
if [ -f "$etcdconf" ];then
|
||||
etcd_ca=$(grep 'trusted-ca-file' $etcdconf | awk -F ":|: *" '{print $NF}');
|
||||
apiserver_ca=$(journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "trusted-ca-file" | awk -F "=" '{print $NF}')
|
||||
if [ "$etcd_ca" == "$apiserver_ca" ]; then
|
||||
echo 'etcd_and_apiserver_have_same_ca';
|
||||
else
|
||||
echo 'etcd_and_apiserver_ca_not_same1' ;
|
||||
fi
|
||||
else
|
||||
echo 'etcd_and_apiserver_ca_not_same'; return ;
|
||||
fi
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "etcd_and_apiserver_ca_not_same"
|
||||
remediation: |
|
||||
By default, K3s uses a config file for etcd that can be found at $etcdconf
|
||||
and the trusted-ca-file parameters in it are set to unique values specific to etcd. No manual remediation needed.
|
||||
scored: false
|
||||
786
cfg/cis-1.6-k3s/master.yaml
Normal file
786
cfg/cis-1.6-k3s/master.yaml
Normal file
@@ -0,0 +1,786 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.6-k3s"
|
||||
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 (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.2
|
||||
text: "Ensure that the API server pod specification file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.3
|
||||
text: "Ensure that the controller manager pod specification file permissions are set to 644 or more restrictive (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.4
|
||||
text: "Ensure that the controller manager pod specification file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.5
|
||||
text: "Ensure that the scheduler pod specification file permissions are set to 644 or more restrictive (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.6
|
||||
text: "Ensure that the scheduler pod specification file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.7
|
||||
text: "Ensure that the etcd pod specification file permissions are set to 644 or more restrictive (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.8
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.9
|
||||
text: "Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.10
|
||||
text: "Ensure that the Container Network Interface file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.11
|
||||
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive if etcd is used (Automated)"
|
||||
audit: stat -c permissions=%a /var/lib/rancher/k3s/server/db/etcd
|
||||
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:
|
||||
journalctl -u k3s | grep 'Managed etcd' | grep -v grep
|
||||
Run the below command (based on the etcd data directory found above). For example,
|
||||
chmod 700 /var/lib/rancher/k3s/server/db/etcd
|
||||
scored: true
|
||||
|
||||
- id: 1.1.12
|
||||
text: "Ensure that the etcd data directory ownership is set to etcd:etcd if etcd is used (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 1.1.13
|
||||
text: "Ensure that the admin.kubeconfig file permissions are set to 644 or more restrictive (Automated)"
|
||||
audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/admin.kubeconfig; then stat -c permissions=%a /var/lib/rancher/k3s/server/cred/admin.kubeconfig; 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 k3s node.
|
||||
For example,
|
||||
chmod 644 /var/lib/rancher/k3s/server/cred/admin.kubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 1.1.14
|
||||
text: "Ensure that the admin.kubeconfig file ownership is set to root:root (Automated)"
|
||||
audit: "/bin/sh -c 'if test -e /var/lib/rancher/k3s/server/cred/admin.kubeconfig; then stat -c %U:%G /var/lib/rancher/k3s/server/cred/admin.kubeconfig; fi'"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "root:root"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the k3s node.
|
||||
For example,
|
||||
chown root:root /var/lib/rancher/k3s/server/cred/admin.kubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 1.1.15
|
||||
text: "Ensure that the scheduler.kubeconfig 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 k3s node.
|
||||
For example,
|
||||
chmod 644 $schedulerkubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 1.1.16
|
||||
text: "Ensure that the scheduler.kubeconfig 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 k3s node.
|
||||
For example,
|
||||
chown root:root $schedulerkubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 1.1.17
|
||||
text: "Ensure that the cloud-controller.kubeconfig 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 $controllermanagerkubeconfig 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: "stat -c %U:%G /var/lib/rancher/k3s/server/tls"
|
||||
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 k3s node.
|
||||
For example,
|
||||
chown -R root:root /var/lib/rancher/k3s/server/tls
|
||||
scored: true
|
||||
|
||||
- id: 1.1.20
|
||||
text: "Ensure that the Kubernetes PKI certificate file permissions are set to 644 or more restrictive (Automated)"
|
||||
audit: "find /var/lib/rancher/k3s/server/tls/ -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 /var/lib/rancher/k3s/server/tls/*.crt
|
||||
scored: true
|
||||
|
||||
- id: 1.1.21
|
||||
text: "Ensure that the Kubernetes PKI key file permissions are set to 600 (Automated)"
|
||||
audit: "find /var/lib/rancher/k3s/server/tls/ -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: true
|
||||
|
||||
- id: 1.2
|
||||
text: "API Server"
|
||||
checks:
|
||||
- id: 1.2.1
|
||||
text: "Ensure that the --anonymous-auth argument is set to false (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "anonymous-auth"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s kube-apiserver is configured to run with --anonymous-auth=false flag and value.
|
||||
scored: false
|
||||
|
||||
- id: 1.2.2
|
||||
text: "Ensure that the --basic-auth-file argument is not set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "basic-auth-file" | cat
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--basic-auth-file"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s does not run with basic authentication enabled. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.3
|
||||
text: "Ensure that the --token-auth-file parameter is not set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "token-auth-file" | cat
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--token-auth-file"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s does not run with basic authentication enabled. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.4
|
||||
text: "Ensure that the --kubelet-https argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "kubelet-https" | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--kubelet-https"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: "--kubelet-https"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s kube-apiserver doesn't run with the --kubelet-https parameter as it runs with TLS. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.5
|
||||
text: "Ensure that the --kubelet-client-certificate and --kubelet-client-key arguments are set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep -E 'kubelet-client-certificate|kubelet-client-key'
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "--kubelet-client-certificate"
|
||||
- flag: "--kubelet-client-key"
|
||||
remediation: |
|
||||
By default, K3s kube-apiserver is ran with these arguments for secure communication with kubelet. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.6
|
||||
text: "Ensure that the --kubelet-certificate-authority argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "kubelet-certificate-authority"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--kubelet-certificate-authority"
|
||||
remediation: |
|
||||
By default, K3s kube-apiserver is ran with this argument for secure communication with kubelet. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.7
|
||||
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "authorization-mode"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--authorization-mode"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "AlwaysAllow"
|
||||
remediation: |
|
||||
By default, K3s sets Node,RBAC as the parameter to the --authorization-mode argument. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.8
|
||||
text: "Ensure that the --authorization-mode argument includes Node (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "authorization-mode"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--authorization-mode"
|
||||
compare:
|
||||
op: has
|
||||
value: "Node"
|
||||
remediation: |
|
||||
By default, K3s sets Node,RBAC as the parameter to the --authorization-mode argument. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.9
|
||||
text: "Ensure that the --authorization-mode argument includes RBAC (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "authorization-mode"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--authorization-mode"
|
||||
compare:
|
||||
op: has
|
||||
value: "RBAC"
|
||||
remediation: |
|
||||
By default, K3s sets Node,RBAC as the parameter to the --authorization-mode argument. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.10
|
||||
text: "Ensure that the admission control plugin EventRateLimit is set (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: has
|
||||
value: "EventRateLimit"
|
||||
remediation: |
|
||||
By default, K3s only sets NodeRestriction,PodSecurityPolicy as the parameter to the --enable-admission-plugins argument.
|
||||
To configure this, follow the Kubernetes documentation and set the desired limits in a configuration file.
|
||||
Then refer to K3s's documentation to see how to supply additional api server configuration via the kube-apiserver-arg parameter.
|
||||
scored: false
|
||||
|
||||
- id: 1.2.11
|
||||
text: "Ensure that the admission control plugin AlwaysAdmit is not set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: nothave
|
||||
value: AlwaysAdmit
|
||||
- flag: "--enable-admission-plugins"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s only sets NodeRestriction,PodSecurityPolicy as the parameter to the --enable-admission-plugins argument.
|
||||
No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.12
|
||||
text: "Ensure that the admission control plugin AlwaysPullImages is set (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: has
|
||||
value: "AlwaysPullImages"
|
||||
remediation: |
|
||||
By default, K3s only sets NodeRestriction,PodSecurityPolicy as the parameter to the --enable-admission-plugins argument.
|
||||
To configure this, follow the Kubernetes documentation and set the desired limits in a configuration file.
|
||||
Then refer to K3s's documentation to see how to supply additional api server configuration via the kube-apiserver-arg parameter.
|
||||
scored: false
|
||||
|
||||
- id: 1.2.13
|
||||
text: "Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
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: |
|
||||
K3s would need to have the SecurityContextDeny admission plugin enabled by passing it as an argument to K3s.
|
||||
--kube-apiserver-arg='enable-admission-plugins=SecurityContextDeny
|
||||
scored: false
|
||||
|
||||
- id: 1.2.14
|
||||
text: "Ensure that the admission control plugin ServiceAccount is set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "ServiceAccount"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--disable-admission-plugins"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "ServiceAccount"
|
||||
- flag: "--disable-admission-plugins"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s does not use this argument.
|
||||
If there's a desire to use this argument, follow the documentation and create ServiceAccount objects as per your environment.
|
||||
Then refer to K3s's documentation to see how to supply additional api server configuration via the kube-apiserver-arg parameter.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.15
|
||||
text: "Ensure that the admission control plugin NamespaceLifecycle is set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "disable-admission-plugins" | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--disable-admission-plugins"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "NamespaceLifecycle"
|
||||
- flag: "--disable-admission-plugins"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s does not use this argument. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.16
|
||||
text: "Ensure that the admission control plugin PodSecurityPolicy is set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: has
|
||||
value: "PodSecurityPolicy"
|
||||
remediation: |
|
||||
K3s would need to have the PodSecurityPolicy admission plugin enabled by passing it as an argument to K3s.
|
||||
--kube-apiserver-arg='enable-admission-plugins=PodSecurityPolicy.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.17
|
||||
text: "Ensure that the admission control plugin NodeRestriction is set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: has
|
||||
value: "NodeRestriction"
|
||||
remediation: |
|
||||
K3s would need to have the NodeRestriction admission plugin enabled by passing it as an argument to K3s.
|
||||
--kube-apiserver-arg='enable-admission-plugins=NodeRestriction.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.18
|
||||
text: "Ensure that the --insecure-bind-address argument is not set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "enable-admission-plugins"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--insecure-bind-address"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s explicitly excludes the use of the --insecure-bind-address parameter. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.19
|
||||
text: "Ensure that the --insecure-port argument is set to 0 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "insecure-port"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--insecure-port"
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
remediation: |
|
||||
By default, K3s starts the kube-apiserver process with this argument's parameter set to 0. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.20
|
||||
text: "Ensure that the --secure-port argument is not set to 0 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "secure-port"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--secure-port"
|
||||
compare:
|
||||
op: gt
|
||||
value: 0
|
||||
- flag: "--secure-port"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s sets the parameter of 6444 for the --secure-port argument. No manual remediation is needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.21
|
||||
text: "Ensure that the --profiling argument is set to false (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "profiling"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--profiling"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s sets the --profiling flag parameter to false. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.22
|
||||
text: "Ensure that the --audit-log-path argument is set (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "audit-log-path"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-log-path"
|
||||
remediation: |
|
||||
K3s server needs to be run with the following argument, --kube-apiserver-arg='audit-log-path=/path/to/log/file'
|
||||
scored: true
|
||||
|
||||
- id: 1.2.23
|
||||
text: "Ensure that the --audit-log-maxage argument is set to 30 or as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "audit-log-maxage"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-log-maxage"
|
||||
compare:
|
||||
op: gte
|
||||
value: 30
|
||||
remediation: |
|
||||
K3s server needs to be run with the following argument, --kube-apiserver-arg='audit-log-maxage=30'
|
||||
scored: true
|
||||
|
||||
- id: 1.2.24
|
||||
text: "Ensure that the --audit-log-maxbackup argument is set to 10 or as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "audit-log-maxbackup"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-log-maxbackup"
|
||||
compare:
|
||||
op: gte
|
||||
value: 10
|
||||
remediation: |
|
||||
K3s server needs to be run with the following argument, --kube-apiserver-arg='audit-log-maxbackup=10'
|
||||
scored: true
|
||||
|
||||
- id: 1.2.25
|
||||
text: "Ensure that the --audit-log-maxsize argument is set to 100 or as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "audit-log-maxsize"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-log-maxsize"
|
||||
compare:
|
||||
op: gte
|
||||
value: 100
|
||||
remediation: |
|
||||
K3s server needs to be run with the following argument, --kube-apiserver-arg='audit-log-maxsize=100'
|
||||
scored: true
|
||||
|
||||
- id: 1.2.26
|
||||
text: "Ensure that the --request-timeout argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "request-timeout" | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--request-timeout"
|
||||
set: false
|
||||
- flag: "--request-timeout"
|
||||
compare:
|
||||
op: lte
|
||||
value: 60
|
||||
remediation: |
|
||||
By default, K3s does not set the --request-timeout argument. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.27
|
||||
text: "Ensure that the --service-account-lookup argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "service-account-lookup"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--service-account-lookup"
|
||||
set: false
|
||||
- flag: "--service-account-lookup"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
K3s server needs to be run with the following argument, --kube-apiserver-arg='service-account-lookup=true'
|
||||
scored: true
|
||||
|
||||
- id: 1.2.28
|
||||
text: "Ensure that the --service-account-key-file argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "service-account-key-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--service-account-key-file"
|
||||
remediation: |
|
||||
By default, K3s sets the --service-account-key-file explicitly. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.29
|
||||
text: "Ensure that the --etcd-certfile and --etcd-keyfile arguments are set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep -E 'etcd-certfile|etcd-keyfile'
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "--etcd-certfile"
|
||||
- flag: "--etcd-keyfile"
|
||||
remediation: |
|
||||
By default, K3s sets the --etcd-certfile and --etcd-keyfile arguments explicitly. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.30
|
||||
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep -E 'tls-cert-file|tls-private-key-file'
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "--tls-cert-file"
|
||||
- flag: "--tls-private-key-file"
|
||||
remediation: |
|
||||
By default, K3s sets the --tls-cert-file and --tls-private-key-file arguments explicitly. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.31
|
||||
text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "client-ca-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--client-ca-file"
|
||||
remediation: |
|
||||
By default, K3s sets the --client-ca-file argument explicitly. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.32
|
||||
text: "Ensure that the --etcd-cafile argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep -E 'etcd-cafile'
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--etcd-cafile"
|
||||
remediation: |
|
||||
By default, K3s sets the --etcd-cafile argument explicitly. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.33
|
||||
text: "Ensure that the --encryption-provider-config argument is set as appropriate (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep -E "encryption-provider-config"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--encryption-provider-config"
|
||||
remediation: |
|
||||
K3s server needs to be ran with the follow, --kube-apiserver-arg='encryption-provider-config=/path/to/encryption_config'.
|
||||
This can be done by running k3s with the --secrets-encryptiuon argument which will configure the encryption provider.
|
||||
scored: false
|
||||
|
||||
- id: 1.2.34
|
||||
text: "Ensure that encryption providers are appropriately configured (Manual)"
|
||||
type: manual
|
||||
remediation: |
|
||||
K3s server needs to be run with the following, --secrets-encryption=true, and verify that one of the allowed encryption providers is present.
|
||||
Run the below command on the master node.
|
||||
grep aescbc /path/to/encryption-config.json
|
||||
Verify that aescbc/kms/secretbox is set as the encryption provider for all the desired resources.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.35
|
||||
text: "Ensure that the API Server only makes use of Strong Cryptographic Ciphers (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "tls-cipher-suites"
|
||||
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: |
|
||||
By default, K3s explicitly doesn't set this flag. No manual remediation needed.
|
||||
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: |
|
||||
journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "terminated-pod-gc-threshold"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--terminated-pod-gc-threshold"
|
||||
remediation: |
|
||||
K3s server needs to be run with the following, --kube-controller-manager-arg='terminated-pod-gc-threshold=10.
|
||||
scored: false
|
||||
|
||||
- id: 1.3.2
|
||||
text: "Ensure that the --profiling argument is set to false (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "profiling"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--profiling"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s sets the --profiling flag parameter to false. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.3.3
|
||||
text: "Ensure that the --use-service-account-credentials argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "use-service-account-credentials"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--use-service-account-credentials"
|
||||
compare:
|
||||
op: noteq
|
||||
value: false
|
||||
remediation: |
|
||||
K3s server needs to be run with the following, --kube-controller-manager-arg='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: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "service-account-private-key-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--service-account-private-key-file"
|
||||
remediation: |
|
||||
By default, K3s sets the --service-account-private-key-file argument with the service account key file. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.3.5
|
||||
text: "Ensure that the --root-ca-file argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "root-ca-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--root-ca-file"
|
||||
remediation: |
|
||||
By default, K3s sets the --root-ca-file argument with the root ca file. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.3.6
|
||||
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "RotateKubeletServerCertificate" | cat
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--feature-gates"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "RotateKubeletServerCertificate=false"
|
||||
set: true
|
||||
- flag: "--feature-gates"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s implements its own logic for certificate generation and rotation.
|
||||
scored: true
|
||||
|
||||
- id: 1.3.7
|
||||
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "bind-address"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--bind-address"
|
||||
compare:
|
||||
op: eq
|
||||
value: "127.0.0.1"
|
||||
- flag: "--bind-address"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s sets the --bind-address argument to 127.0.0.1. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.4
|
||||
text: "Scheduler"
|
||||
checks:
|
||||
- id: 1.4.1
|
||||
text: "Ensure that the --profiling argument is set to false (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-scheduler" | tail -n1 | grep "profiling"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--profiling"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s sets the --profiling flag parameter to false. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 1.4.2
|
||||
text: "Ensure that the --bind-address argument is set to 127.0.0.1 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-controller-manager" | tail -n1 | grep "bind-address"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--bind-address"
|
||||
compare:
|
||||
op: eq
|
||||
value: "127.0.0.1"
|
||||
- flag: "--bind-address"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s sets the --bind-address argument to 127.0.0.1. No manual remediation needed.
|
||||
scored: true
|
||||
253
cfg/cis-1.6-k3s/node.yaml
Normal file
253
cfg/cis-1.6-k3s/node.yaml
Normal file
@@ -0,0 +1,253 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.6-k3s"
|
||||
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 (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.1.2
|
||||
text: "Ensure that the kubelet service file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.1.3
|
||||
text: "If proxy kubeproxy.kubeconfig file exists ensure permissions are set to 644 or more restrictive (Automated)"
|
||||
audit: stat -c %a $proxykubeconfig
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
set: true
|
||||
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: true
|
||||
|
||||
- id: 4.1.4
|
||||
text: "Ensure that the proxy kubeconfig file ownership is set to root:root (Automated)"
|
||||
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: true
|
||||
|
||||
- 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: |
|
||||
By default, K3s creates $kubeletkubeconfig with 644 permissions. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 4.1.6
|
||||
text: "Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root (Automated)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletkubeconfig; then stat -c %U:%G $kubeletkubeconfig; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
remediation: |
|
||||
By default, K3s creates $kubeletkubeconfig with root:root ownership. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 4.1.7
|
||||
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Automated)"
|
||||
audit: stat -c permissions=%a $kubeletcafile
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
compare:
|
||||
op: bitmask
|
||||
value: "644"
|
||||
remediation: |
|
||||
By default, K3s creates $kubeletcafile with 644 permissions.
|
||||
scored: true
|
||||
|
||||
- id: 4.1.8
|
||||
text: "Ensure that the client certificate authorities file ownership is set to root:root (Automated)"
|
||||
audit: stat -c %U:%G $kubeletcafile
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
compare:
|
||||
op: eq
|
||||
value: root:root
|
||||
remediation: |
|
||||
By default, K3s creates $kubeletcafile with root:root ownership.
|
||||
scored: true
|
||||
|
||||
- id: 4.1.9
|
||||
text: "Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.1.10
|
||||
text: "Ensure that the kubelet --config configuration file ownership is set to root:root (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.2
|
||||
text: "Kubelet"
|
||||
checks:
|
||||
- id: 4.2.1
|
||||
text: "Ensure that the anonymous-auth argument is set to false (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "anonymous-auth"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
By default, K3s starts kubelet with --anonymous-auth set to false. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.2
|
||||
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "authorization-mode"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --authorization-mode
|
||||
compare:
|
||||
op: nothave
|
||||
value: AlwaysAllow
|
||||
remediation: |
|
||||
K3s starts kubelet with Webhook as the value for the --authorization-mode argument. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.3
|
||||
text: "Ensure that the --client-ca-file argument is set as appropriate (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kube-apiserver" | tail -n1 | grep "client-ca-file"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --client-ca-file
|
||||
remediation: |
|
||||
By default, K3s starts the kubelet process with the --client-ca-file. No manual remediation needed.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.4
|
||||
text: "Ensure that the --read-only-port argument is set to 0 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kubelet" | tail -n1 | grep "read-only-port"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--read-only-port"
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
- flag: "--read-only-port"
|
||||
set: false
|
||||
remediation: |
|
||||
By default, K3s starts the kubelet process with the --read-only-port argument set to 0.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.5
|
||||
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kubelet" | tail -n1 | grep "streaming-connection-idle-timeout"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --streaming-connection-idle-timeout
|
||||
compare:
|
||||
op: noteq
|
||||
value: 0
|
||||
- flag: --streaming-connection-idle-timeout
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
By default, K3s does not set --streaming-connection-idle-timeout when starting kubelet.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.6
|
||||
text: "Ensure that the --protect-kernel-defaults argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kubelet" | tail -n1 | grep "protect-kernel-defaults"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --protect-kernel-defaults
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
K3s server needs to be started with the following, --protect-kernel-defaults=true.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.7
|
||||
text: "Ensure that the --make-iptables-util-chains argument is set to true (Automated)"
|
||||
audit: journalctl -u k3s | grep "Running kubelet" | tail -n1 | grep "make-iptables-util-chains"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --make-iptables-util-chains
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --make-iptables-util-chains
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
K3s server needs to be run with the following, --kube-apiserver-arg='make-iptables-util-chains=true'.
|
||||
scored: true
|
||||
|
||||
- id: 4.2.8
|
||||
text: "Ensure that the --hostname-override argument is not set (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.2.9
|
||||
text: "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture (Manual)"
|
||||
audit: /bin/ps -fC containerd
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --event-qps
|
||||
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.10
|
||||
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Manual)"
|
||||
audit: journalctl -u k3s | grep "Running kubelet" | tail -n1 | grep -E 'tls-cert-file|tls-private-key-file'
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --tls-cert-file
|
||||
- flag: --tls-private-key-file
|
||||
remediation: |
|
||||
By default, K3s sets the --tls-cert-file and --tls-private-key-file arguments when executing the kubelet process.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.11
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.2.12
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Not Applicable)"
|
||||
scored: false
|
||||
|
||||
- id: 4.2.13
|
||||
text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers (Not Applicable)"
|
||||
scored: false
|
||||
260
cfg/cis-1.6-k3s/policies.yaml
Normal file
260
cfg/cis-1.6-k3s/policies.yaml
Normal file
@@ -0,0 +1,260 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.6-k3s"
|
||||
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.
|
||||
kubectl get roles --all-namespaces -o yaml
|
||||
kubectl get clusterroles -o yaml
|
||||
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: |
|
||||
kubectl describe psp <psp_name> | grep MustRunAsNonRoot
|
||||
An operator should apply a PodSecurityPolicy that sets the Rule value to MustRunAsNonRoot. An example of this can be found in the Hardening Guide
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.2
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp -o json | jq .items[] | jq -r 'select((.spec.hostPID == null) or (.spec.hostPID == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}'
|
||||
An operator should apply a PodSecurityPolicy that sets the hostPID value to false explicitly for the PSP it creates. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp -o json | jq .items[] | jq -r 'select((.spec.hostIPC == null) or (.spec.hostIPC == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}'
|
||||
An operator should apply a PodSecurityPolicy that sets the HostIPC value to false explicitly for the PSP it creates. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp -o json | jq .items[] | jq -r 'select((.spec.hostNetwork == null) or (.spec.hostNetwork == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}'
|
||||
An operator should apply a PodSecurityPolicy that sets the HostNetwork value to false explicitly for the PSP it creates. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.5
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp -o json | jq .items[] | jq -r 'select((.spec.allowPrivilegeEscalation == null) or (.spec.allowPrivilegeEscalation == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}'
|
||||
An operator should apply a PodSecurityPolicy that sets the allowPrivilegeEscalation value to false explicitly for the PSP it creates. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.6
|
||||
text: "Minimize the admission of root containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp -o json | jq .items[] | jq -r 'select((.spec.allowPrivilegeEscalation == null) or (.spec.allowPrivilegeEscalation == false))' | jq .metadata.name | wc -l | xargs -I {} echo '--count={}'
|
||||
An operator should apply a PodSecurityPolicy that sets the runAsUser.Rule value to MustRunAsNonRoot. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.7
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp <psp_name> -o json | jq .spec.requiredDropCapabilities[]
|
||||
An operator should apply a PodSecurityPolicy that sets .spec.requiredDropCapabilities[] to a value of All. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.8
|
||||
text: "Minimize the admission of containers with added capabilities (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp
|
||||
An operator should apply a PodSecurityPolicy that sets allowedCapabilities to anything other than an empty array. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with capabilities assigned (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
kubectl get psp
|
||||
An operator should apply a PodSecurityPolicy that sets requiredDropCapabilities to ALL. An example of this can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
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: |
|
||||
By default, K3s use Canal (Calico and Flannel) and fully supports network policies.
|
||||
scored: false
|
||||
|
||||
- id: 5.3.2
|
||||
text: "Ensure that all Namespaces have Network Policies defined (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Run the below command on the master node.
|
||||
for i in kube-system kube-public default; do
|
||||
kubectl get networkpolicies -n $i;
|
||||
done
|
||||
Verify that there are network policies applied to each of the namespaces.
|
||||
An operator should apply NetworkPolcyies that prevent unneeded traffic from traversing networks unnecessarily. An example of applying a NetworkPolcy can be found in the Hardening Guide.
|
||||
https://docs.rancher.cn/docs/k3s/security/hardening-guide/_index
|
||||
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: |
|
||||
Run the following command to find references to objects which use environment variables defined from secrets.
|
||||
kubectl get all -o jsonpath='{range .items[?(@..secretKeyRef)]} {.kind} {.metadata.name} {"\n"}{end}' -A
|
||||
|
||||
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.7
|
||||
text: "General Policies"
|
||||
checks:
|
||||
- id: 5.7.1
|
||||
text: "Create administrative boundaries between resources using namespaces (Manual)"
|
||||
audit: kubectl get namespaces
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that these namespaces are the ones you need and are adequately administered as per your requirements.
|
||||
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: |
|
||||
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.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: |
|
||||
Run the below command on the master node.
|
||||
kubectl get all -n default
|
||||
The only entries there should be system-managed resources such as the kubernetes service.
|
||||
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
|
||||
@@ -153,7 +153,13 @@ groups:
|
||||
|
||||
- id: 1.1.11
|
||||
text: "Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c permissions=%a
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
@@ -170,7 +176,13 @@ groups:
|
||||
|
||||
- id: 1.1.12
|
||||
text: "Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)"
|
||||
audit: ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%' | xargs stat -c %U:%G
|
||||
audit: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G $DATA_DIR
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "etcd:etcd"
|
||||
|
||||
@@ -98,7 +98,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c permissions=%a $CAFILE; fi
|
||||
tests:
|
||||
@@ -115,7 +115,7 @@ groups:
|
||||
- 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}')
|
||||
CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
|
||||
if test -z $CAFILE; then CAFILE=$kubeletcafile; fi
|
||||
if test -e $CAFILE; then stat -c %U:%G $CAFILE; fi
|
||||
tests:
|
||||
|
||||
2
cfg/cis-1.7/config.yaml
Normal file
2
cfg/cis-1.7/config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
60
cfg/cis-1.7/controlplane.yaml
Normal file
60
cfg/cis-1.7/controlplane.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.7"
|
||||
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)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
scored: false
|
||||
- id: 3.1.2
|
||||
text: "Service account token authentication should not be used for users (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be implemented
|
||||
in place of service account tokens.
|
||||
scored: false
|
||||
- id: 3.1.3
|
||||
text: "Bootstrap token authentication should not be used for users (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be implemented
|
||||
in place of bootstrap tokens.
|
||||
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"
|
||||
set: true
|
||||
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: |
|
||||
Review the audit policy provided for the cluster and ensure that it covers
|
||||
at least the following areas,
|
||||
- Access to Secrets managed by the cluster. Care should be taken to only
|
||||
log Metadata for requests to Secrets, ConfigMaps, and TokenReviews, in
|
||||
order to avoid risk of logging sensitive data.
|
||||
- Modification of Pod and Deployment objects.
|
||||
- Use of `pods/exec`, `pods/portforward`, `pods/proxy` and `services/proxy`.
|
||||
For most requests, minimally logging at the Metadata level is recommended
|
||||
(the most basic level of logging).
|
||||
scored: false
|
||||
135
cfg/cis-1.7/etcd.yaml
Normal file
135
cfg/cis-1.7/etcd.yaml
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.7"
|
||||
id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
type: "etcd"
|
||||
groups:
|
||||
- id: 2
|
||||
text: "Etcd Node Configuration"
|
||||
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
|
||||
947
cfg/cis-1.7/master.yaml
Normal file
947
cfg/cis-1.7/master.yaml
Normal file
@@ -0,0 +1,947 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.7"
|
||||
id: 1
|
||||
text: "Control Plane Security Configuration"
|
||||
type: "master"
|
||||
groups:
|
||||
- id: 1.1
|
||||
text: "Control Plane Node Configuration Files"
|
||||
checks:
|
||||
- id: 1.1.1
|
||||
text: "Ensure that the API server pod specification file permissions are set to 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the
|
||||
control plane node.
|
||||
For example, chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 $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 control plane node.
|
||||
For example, chown root:root $schedulerconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.7
|
||||
text: "Ensure that the etcd pod specification file permissions are set to 600 or more restrictive (Automated)"
|
||||
audit: "/bin/sh -c '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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $etcdconf
|
||||
scored: true
|
||||
|
||||
- id: 1.1.8
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)"
|
||||
audit: "/bin/sh -c '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 control plane 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 600 or more restrictive (Manual)"
|
||||
audit: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 <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: |
|
||||
ps -ef | grep $kubeletbin | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty 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 control plane 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c permissions=%a "$DATA_DIR"
|
||||
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 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: |
|
||||
DATA_DIR=''
|
||||
for d in $(ps -ef | grep $etcdbin | grep -- --data-dir | sed 's%.*data-dir[= ]\([^ ]*\).*%\1%'); do
|
||||
if test -d "$d"; then DATA_DIR="$d"; fi
|
||||
done
|
||||
if ! test -d "$DATA_DIR"; then DATA_DIR=$etcddatadir; fi
|
||||
stat -c %U:%G "$DATA_DIR"
|
||||
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 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example, chmod 600 /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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod 600 $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 control plane 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 control plane 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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the control plane node.
|
||||
For example,
|
||||
chmod -R 600 /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 control plane 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 --anonymous-auth argument is set to false (Manual)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and set the below parameter.
|
||||
--anonymous-auth=false
|
||||
scored: false
|
||||
|
||||
- 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 control plane node and remove the --token-auth-file=<filename> parameter.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.3
|
||||
text: "Ensure that the --DenyServiceExternalIPs is set (Manual)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--enable-admission-plugins"
|
||||
compare:
|
||||
op: have
|
||||
value: "DenyServiceExternalIPs"
|
||||
remediation: |
|
||||
Edit the API server pod specification file $apiserverconf
|
||||
on the control plane node and remove the `DenyServiceExternalIPs`
|
||||
from enabled admission plugins.
|
||||
scored: false
|
||||
|
||||
- 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 control plane 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 --kubelet-certificate-authority argument is set as appropriate (Automated)"
|
||||
audit: "/bin/ps -ef | grep $apiserverbin | grep -v grep"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--kubelet-certificate-authority"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and setup the TLS connection between
|
||||
the apiserver and kubelets. Then, edit the API server pod specification file
|
||||
$apiserverconf on the control plane node and set the
|
||||
--kubelet-certificate-authority parameter to the path to the cert file for the certificate authority.
|
||||
--kubelet-certificate-authority=<ca-string>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.6
|
||||
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 control plane 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.7
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes Node.
|
||||
--authorization-mode=Node,RBAC
|
||||
scored: true
|
||||
|
||||
- id: 1.2.8
|
||||
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 control plane node and set the --authorization-mode parameter to a value that includes RBAC,
|
||||
for example `--authorization-mode=Node,RBAC`.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.9
|
||||
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.10
|
||||
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 control plane 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.11
|
||||
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 control plane node and set the --enable-admission-plugins parameter to include
|
||||
AlwaysPullImages.
|
||||
--enable-admission-plugins=...,AlwaysPullImages,...
|
||||
scored: false
|
||||
|
||||
- id: 1.2.12
|
||||
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 control plane 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.13
|
||||
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 control plane node and ensure that the --disable-admission-plugins parameter is set to a
|
||||
value that does not include ServiceAccount.
|
||||
scored: true
|
||||
|
||||
- id: 1.2.14
|
||||
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 control plane node and set the --disable-admission-plugins parameter to
|
||||
ensure it does not include NamespaceLifecycle.
|
||||
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 control plane 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 --secure-port argument is not set to 0 - NoteThis recommendation is obsolete and will be deleted per the consensus process (Manual)"
|
||||
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 control plane node and either remove the --secure-port parameter or
|
||||
set it to a different (non-zero) desired port.
|
||||
scored: false
|
||||
|
||||
- id: 1.2.17
|
||||
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 control plane node and set the below parameter.
|
||||
--profiling=false
|
||||
scored: true
|
||||
|
||||
- id: 1.2.18
|
||||
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 control plane 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.19
|
||||
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 control plane node and set the --audit-log-maxage parameter to 30
|
||||
or as an appropriate number of days, for example,
|
||||
--audit-log-maxage=30
|
||||
scored: true
|
||||
|
||||
- id: 1.2.20
|
||||
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 control plane node and set the --audit-log-maxbackup parameter to 10 or to an appropriate
|
||||
value. For example,
|
||||
--audit-log-maxbackup=10
|
||||
scored: true
|
||||
|
||||
- id: 1.2.21
|
||||
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 control plane 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.22
|
||||
text: "Ensure that the --request-timeout argument is set as appropriate (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 1.2.23
|
||||
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 control plane 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.24
|
||||
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 control plane node and set the --service-account-key-file parameter
|
||||
to the public key file for service accounts. For example,
|
||||
--service-account-key-file=<filename>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.25
|
||||
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 control plane 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.26
|
||||
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 control plane 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.27
|
||||
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 control plane node and set the client certificate authority file.
|
||||
--client-ca-file=<path/to/client-ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.28
|
||||
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 control plane node and set the etcd certificate authority file parameter.
|
||||
--etcd-cafile=<path/to/ca-file>
|
||||
scored: true
|
||||
|
||||
- id: 1.2.29
|
||||
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 control plane node and set the --encryption-provider-config parameter to the path of that file.
|
||||
For example, --encryption-provider-config=</path/to/EncryptionConfig/File>
|
||||
scored: false
|
||||
|
||||
- id: 1.2.30
|
||||
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.31
|
||||
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_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384"
|
||||
remediation: |
|
||||
Edit the API server pod specification file /etc/kubernetes/manifests/kube-apiserver.yaml
|
||||
on the control plane node and set the below parameter.
|
||||
--tls-cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane 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 control plane node and ensure the correct value for the --bind-address parameter
|
||||
scored: true
|
||||
457
cfg/cis-1.7/node.yaml
Normal file
457
cfg/cis-1.7/node.yaml
Normal file
@@ -0,0 +1,457 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.7"
|
||||
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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example, chmod 600 $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 600 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"
|
||||
set: true
|
||||
compare:
|
||||
op: bitmask
|
||||
value: "600"
|
||||
- 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 600 $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 600 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: "600"
|
||||
remediation: |
|
||||
Run the below command (based on the file location on your system) on the each worker node.
|
||||
For example,
|
||||
chmod 600 $kubeletkubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 4.1.6
|
||||
text: "Ensure that the --kubeconfig kubelet.conf file ownership is set to root:root (Automated)"
|
||||
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: true
|
||||
|
||||
- id: 4.1.7
|
||||
text: "Ensure that the certificate authorities file permissions are set to 600 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}' | uniq)
|
||||
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: "600"
|
||||
remediation: |
|
||||
Run the following command to modify the file permissions of the
|
||||
--client-ca-file chmod 600 <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}' | uniq)
|
||||
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: "If the kubelet config.yaml configuration file is being used validate permissions set to 600 or more restrictive (Manual)"
|
||||
audit: '/bin/sh -c ''if test -e $kubeletconf; then stat -c permissions=%a $kubeletconf; fi'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "permissions"
|
||||
compare:
|
||||
op: bitmask
|
||||
value: "600"
|
||||
remediation: |
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chmod 600 $kubeletconf
|
||||
scored: false
|
||||
|
||||
- id: 4.1.10
|
||||
text: "If the kubelet config.yaml configuration file is being used validate file ownership is set to root:root (Manual)"
|
||||
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: false
|
||||
|
||||
- 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: "Verify 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 --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` to `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.7
|
||||
text: "Ensure that the --hostname-override argument is not set (Manual)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override 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: false
|
||||
|
||||
- id: 4.2.8
|
||||
text: "Ensure that the eventRecordQPS argument is set to 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: gte
|
||||
value: 0
|
||||
- flag: --event-qps
|
||||
path: '{.eventRecordQPS}'
|
||||
set: false
|
||||
bin_op: or
|
||||
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 --rotate-certificates argument is not set to false (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line `rotateCertificates` to `true` or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example,
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
|
||||
- id: 4.2.11
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
compare:
|
||||
op: nothave
|
||||
value: false
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 4.2.12
|
||||
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
|
||||
|
||||
- id: 4.2.13
|
||||
text: "Ensure that a limit is set on pod PIDs (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --pod-max-pids
|
||||
path: '{.podPidsLimit}'
|
||||
remediation: |
|
||||
Decide on an appropriate level for this parameter and set it,
|
||||
either via the --pod-max-pids command line parameter or the PodPidsLimit configuration file setting.
|
||||
scored: false
|
||||
304
cfg/cis-1.7/policies.yaml
Normal file
304
cfg/cis-1.7/policies.yaml
Normal file
@@ -0,0 +1,304 @@
|
||||
---
|
||||
controls:
|
||||
version: "cis-1.7"
|
||||
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.1.7
|
||||
text: "Avoid use of system:masters group (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Remove the system:masters group from all users in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.8
|
||||
text: "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove the impersonate, bind and escalate rights from subjects.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.9
|
||||
text: "Minimize access to create persistent volumes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove create access to PersistentVolume objects in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.10
|
||||
text: "Minimize access to the proxy sub-resource of nodes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove access to the proxy sub-resource of node objects.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.11
|
||||
text: "Minimize access to the approval sub-resource of certificatesigningrequests objects (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove access to the approval sub-resource of certificatesigningrequest objects.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.12
|
||||
text: "Minimize access to webhook configuration objects (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove access to the validatingwebhookconfigurations or mutatingwebhookconfigurations objects
|
||||
scored: false
|
||||
|
||||
- id: 5.1.13
|
||||
text: "Minimize access to the service account token creation (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove access to the token sub-resource of serviceaccount objects.
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Pod Security Standards"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Ensure that the cluster has at least one active policy control mechanism in place (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that either Pod Security Admission or an external policy control system is in place
|
||||
for every namespace which contains user workloads.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.2
|
||||
text: "Minimize the admission of privileged containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of privileged containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostPID` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostIPC` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.5
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of `hostNetwork` containers.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.6
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `.spec.allowPrivilegeEscalation` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.7
|
||||
text: "Minimize the admission of root containers (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a policy for each namespace in the cluster, ensuring that either `MustRunAsNonRoot`
|
||||
or `MustRunAs` with the range of UIDs not including 0, is set.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.8
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with the `NET_RAW` capability.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with added capabilities (Automated)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that `allowedCapabilities` is not present in policies for the cluster unless
|
||||
it is set to an empty array.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.10
|
||||
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 PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.11
|
||||
text: "Minimize the admission of Windows HostProcess containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers that have `.securityContext.windowsOptions.hostProcess` set to `true`.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.12
|
||||
text: "Minimize the admission of HostPath volumes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers with `hostPath` volumes.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.13
|
||||
text: "Minimize the admission of containers which use HostPorts (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Add policies to each namespace in the cluster which has user workloads to restrict the
|
||||
admission of containers which use `hostPort` sections.
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "Network Policies and CNI"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure that the CNI in use supports NetworkPolicies (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 NetworkPolicies 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.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: |
|
||||
Use `securityContext` to enable the docker/default seccomp profile in your pod definitions.
|
||||
An example is as below:
|
||||
securityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
scored: false
|
||||
|
||||
- id: 5.7.3
|
||||
text: "Apply SecurityContext to your Pods and Containers (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and apply SecurityContexts to your Pods. For a
|
||||
suggested list of SecurityContexts, 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
|
||||
@@ -89,6 +89,9 @@ master:
|
||||
bins:
|
||||
- "etcd"
|
||||
- "openshift start etcd"
|
||||
datadirs:
|
||||
- /var/lib/etcd/default.etcd
|
||||
- /var/lib/etcd/data.etcd
|
||||
confs:
|
||||
- /etc/kubernetes/manifests/etcd.yaml
|
||||
- /etc/kubernetes/manifests/etcd.yml
|
||||
@@ -99,6 +102,7 @@ master:
|
||||
- /var/snap/microk8s/current/args/etcd
|
||||
- /usr/lib/systemd/system/etcd.service
|
||||
defaultconf: /etc/kubernetes/manifests/etcd.yaml
|
||||
defaultdatadir: /var/lib/etcd/default.etcd
|
||||
|
||||
flanneld:
|
||||
optional: true
|
||||
@@ -211,6 +215,9 @@ etcd:
|
||||
etcd:
|
||||
bins:
|
||||
- "etcd"
|
||||
datadirs:
|
||||
- /var/lib/etcd/default.etcd
|
||||
- /var/lib/etcd/data.etcd
|
||||
confs:
|
||||
- /etc/kubernetes/manifests/etcd.yaml
|
||||
- /etc/kubernetes/manifests/etcd.yml
|
||||
@@ -221,6 +228,7 @@ etcd:
|
||||
- /var/snap/microk8s/current/args/etcd
|
||||
- /usr/lib/systemd/system/etcd.service
|
||||
defaultconf: /etc/kubernetes/manifests/etcd.yaml
|
||||
defaultdatadir: /var/lib/etcd/default.etcd
|
||||
|
||||
controlplane:
|
||||
components:
|
||||
@@ -246,7 +254,14 @@ version_mapping:
|
||||
"1.18": "cis-1.6"
|
||||
"1.19": "cis-1.20"
|
||||
"1.20": "cis-1.20"
|
||||
"1.21": "cis-1.20"
|
||||
"1.22": "cis-1.23"
|
||||
"1.23": "cis-1.23"
|
||||
"1.24": "cis-1.24"
|
||||
"1.25": "cis-1.7"
|
||||
"eks-1.0.1": "eks-1.0.1"
|
||||
"eks-1.1.0": "eks-1.1.0"
|
||||
"eks-1.2.0": "eks-1.2.0"
|
||||
"gke-1.0": "gke-1.0"
|
||||
"gke-1.2.0": "gke-1.2.0"
|
||||
"ocp-3.10": "rh-0.7"
|
||||
@@ -254,6 +269,8 @@ version_mapping:
|
||||
"ocp-4.0": "rh-1.0"
|
||||
"aks-1.0": "aks-1.0"
|
||||
"ack-1.0": "ack-1.0"
|
||||
"cis-1.6-k3s": "cis-1.6-k3s"
|
||||
"tkgi-1.2.53": "tkgi-1.2.53"
|
||||
|
||||
target_mapping:
|
||||
"cis-1.5":
|
||||
@@ -268,12 +285,36 @@ target_mapping:
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"cis-1.6-k3s":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"cis-1.20":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"cis-1.23":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"cis-1.24":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"cis-1.7":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "etcd"
|
||||
- "policies"
|
||||
"gke-1.0":
|
||||
- "master"
|
||||
- "node"
|
||||
@@ -293,6 +334,18 @@ target_mapping:
|
||||
- "controlplane"
|
||||
- "policies"
|
||||
- "managedservices"
|
||||
"eks-1.1.0":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "policies"
|
||||
- "managedservices"
|
||||
"eks-1.2.0":
|
||||
- "master"
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "policies"
|
||||
- "managedservices"
|
||||
"rh-0.7":
|
||||
- "master"
|
||||
- "node"
|
||||
@@ -315,3 +368,14 @@ target_mapping:
|
||||
- "controlplane"
|
||||
- "policies"
|
||||
- "etcd"
|
||||
"eks-stig-kubernetes-v1r6":
|
||||
- "node"
|
||||
- "controlplane"
|
||||
- "policies"
|
||||
- "managedservices"
|
||||
"tkgi-1.2.53":
|
||||
- "master"
|
||||
- "etcd"
|
||||
- "controlplane"
|
||||
- "node"
|
||||
- "policies"
|
||||
|
||||
@@ -37,7 +37,7 @@ groups:
|
||||
- id: 4.1.4
|
||||
text: "Minimize access to create pods (Manual)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
|
||||
9
cfg/eks-1.1.0/config.yaml
Normal file
9
cfg/eks-1.1.0/config.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
## These settings are required if you are using the --asff option to report findings to AWS Security Hub
|
||||
## AWS account number is required.
|
||||
AWS_ACCOUNT: "<AWS_ACCT_NUMBER>"
|
||||
## AWS region is required.
|
||||
AWS_REGION: "<AWS_REGION>"
|
||||
## EKS Cluster ARN is required.
|
||||
CLUSTER_ARN: "<AWS_CLUSTER_ARN>"
|
||||
14
cfg/eks-1.1.0/controlplane.yaml
Normal file
14
cfg/eks-1.1.0/controlplane.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.1.0"
|
||||
id: 2
|
||||
text: "Control Plane Configuration"
|
||||
type: "controlplane"
|
||||
groups:
|
||||
- id: 2.1
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 2.1.1
|
||||
text: "Enable audit logs (Manual)"
|
||||
remediation: "Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler."
|
||||
scored: false
|
||||
154
cfg/eks-1.1.0/managedservices.yaml
Normal file
154
cfg/eks-1.1.0/managedservices.yaml
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.1.0"
|
||||
id: 5
|
||||
text: "Managed Services"
|
||||
type: "managedservices"
|
||||
groups:
|
||||
- id: 5.1
|
||||
text: "Image Registry and Image Scanning"
|
||||
checks:
|
||||
- id: 5.1.1
|
||||
text: "Ensure Image Vulnerability Scanning using Amazon ECR image scanning or a third-party provider (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
To utilize AWS ECR for Image scanning please follow the steps below:
|
||||
|
||||
To create a repository configured for scan on push (AWS CLI):
|
||||
aws ecr create-repository --repository-name $REPO_NAME --image-scanning-configuration scanOnPush=true --region $REGION_CODE
|
||||
|
||||
To edit the settings of an existing repository (AWS CLI):
|
||||
aws ecr put-image-scanning-configuration --repository-name $REPO_NAME --image-scanning-configuration scanOnPush=true --region $REGION_CODE
|
||||
|
||||
Use the following steps to start a manual image scan using the AWS Management Console.
|
||||
Open the Amazon ECR console at https://console.aws.amazon.com/ecr/repositories.
|
||||
From the navigation bar, choose the Region to create your repository in.
|
||||
In the navigation pane, choose Repositories.
|
||||
On the Repositories page, choose the repository that contains the image to scan.
|
||||
On the Images page, select the image to scan and then choose Scan.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.2
|
||||
text: "Minimize user access to Amazon ECR (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Before you use IAM to manage access to Amazon ECR, you should understand what IAM features
|
||||
are available to use with Amazon ECR. To get a high-level view of how Amazon ECR and other
|
||||
AWS services work with IAM, see AWS Services That Work with IAM in the IAM User Guide.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.3
|
||||
text: "Minimize cluster access to read-only for Amazon ECR (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
You can use your Amazon ECR images with Amazon EKS, but you need to satisfy the following prerequisites.
|
||||
|
||||
The Amazon EKS worker node IAM role (NodeInstanceRole) that you use with your worker nodes must possess
|
||||
the following IAM policy permissions for Amazon ECR.
|
||||
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:GetAuthorizationToken"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
scored: false
|
||||
|
||||
- id: 5.1.4
|
||||
text: "Minimize Container Registries to only those approved (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Identity and Access Management (IAM)"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Prefer using dedicated Amazon EKS Service Accounts (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "AWS Key Management Service (KMS)"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure Kubernetes Secrets are encrypted using Customer Master Keys (CMKs) managed in AWS KMS (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
This process can only be performed during Cluster Creation.
|
||||
|
||||
Enable 'Secrets Encryption' during Amazon EKS cluster creation as described
|
||||
in the links within the 'References' section.
|
||||
scored: false
|
||||
|
||||
- id: 5.4
|
||||
text: "Cluster Networking"
|
||||
checks:
|
||||
- id: 5.4.1
|
||||
text: "Restrict Access to the Control Plane Endpoint (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.2
|
||||
text: "Ensure clusters are created with Private Endpoint Enabled and Public Access Disabled (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.3
|
||||
text: "Ensure clusters are created with Private Nodes (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.4
|
||||
text: "Ensure Network Policy is Enabled and set as appropriate (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.5
|
||||
text: "Encrypt traffic to HTTPS load balancers with TLS certificates (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.5
|
||||
text: "Authentication and Authorization"
|
||||
checks:
|
||||
- id: 5.5.1
|
||||
text: "Manage Kubernetes RBAC users with AWS IAM Authenticator for Kubernetes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Refer to the 'Managing users or IAM roles for your cluster' in Amazon EKS documentation.
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.6
|
||||
text: "Other Cluster Configurations"
|
||||
checks:
|
||||
- id: 5.6.1
|
||||
text: "Consider Fargate for running untrusted workloads (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a Fargate profile for your cluster Before you can schedule pods running on Fargate
|
||||
in your cluster, you must define a Fargate profile that specifies which pods should use
|
||||
Fargate when they are launched. For more information, see AWS Fargate profile.
|
||||
|
||||
Note: If you created your cluster with eksctl using the --fargate option, then a Fargate profile has
|
||||
already been created for your cluster with selectors for all pods in the kube-system
|
||||
and default namespaces. Use the following procedure to create Fargate profiles for
|
||||
any other namespaces you would like to use with Fargate.
|
||||
scored: false
|
||||
6
cfg/eks-1.1.0/master.yaml
Normal file
6
cfg/eks-1.1.0/master.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.1.0"
|
||||
id: 1
|
||||
text: "Control Plane Components"
|
||||
type: "master"
|
||||
330
cfg/eks-1.1.0/node.yaml
Normal file
330
cfg/eks-1.1.0/node.yaml
Normal file
@@ -0,0 +1,330 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.1.0"
|
||||
id: 3
|
||||
text: "Worker Node Security Configuration"
|
||||
type: "node"
|
||||
groups:
|
||||
- id: 3.1
|
||||
text: "Worker Node Configuration Files"
|
||||
checks:
|
||||
- id: 3.1.1
|
||||
text: "Ensure that the kubeconfig file permissions are set to 644 or more restrictive (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.1.2
|
||||
text: "Ensure that the kubelet kubeconfig 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: 3.1.3
|
||||
text: "Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.1.4
|
||||
text: "Ensure that the kubelet configuration file ownership is set to root:root (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.2
|
||||
text: "Kubelet"
|
||||
checks:
|
||||
- id: 3.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}'
|
||||
set: true
|
||||
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: 3.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}'
|
||||
set: true
|
||||
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: 3.2.3
|
||||
text: "Ensure that the --client-ca-file argument is set as appropriate (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --client-ca-file
|
||||
path: '{.authentication.x509.clientCAFile}'
|
||||
set: true
|
||||
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: false
|
||||
|
||||
- id: 3.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:
|
||||
test_items:
|
||||
- flag: "--read-only-port"
|
||||
path: '{.readOnlyPort}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
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: 3.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}'
|
||||
set: true
|
||||
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: 3.2.6
|
||||
text: "Ensure that the --protect-kernel-defaults argument is set to true (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --protect-kernel-defaults
|
||||
path: '{.protectKernelDefaults}'
|
||||
set: true
|
||||
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: true
|
||||
|
||||
- id: 3.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}'
|
||||
set: true
|
||||
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: 3.2.8
|
||||
text: "Ensure that the --hostname-override argument is not set (Manual)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override 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: false
|
||||
|
||||
- id: 3.2.9
|
||||
text: "Ensure that the --eventRecordQPS argument is set to 0 or a level which ensures appropriate event capture (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --event-qps
|
||||
path: '{.eventRecordQPS}'
|
||||
set: true
|
||||
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: 3.2.10
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line rotateCertificates: true or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 3.2.11
|
||||
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
- id: 3.3
|
||||
text: "Container Optimized OS"
|
||||
checks:
|
||||
- id: 3.3.1
|
||||
text: "Prefer using Container-Optimized OS when possible (Manual)"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
205
cfg/eks-1.1.0/policies.yaml
Normal file
205
cfg/eks-1.1.0/policies.yaml
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.1.0"
|
||||
id: 4
|
||||
text: "Policies"
|
||||
type: "policies"
|
||||
groups:
|
||||
- id: 4.1
|
||||
text: "RBAC and Service Accounts"
|
||||
checks:
|
||||
- id: 4.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: 4.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: 4.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: 4.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: 4.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: 4.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: 4.2
|
||||
text: "Pod Security Policies"
|
||||
checks:
|
||||
- id: 4.2.1
|
||||
text: "Minimize the admission of privileged containers (Automated)"
|
||||
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: 4.2.2
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Automated)"
|
||||
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: 4.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Automated)"
|
||||
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: 4.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Automated)"
|
||||
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: 4.2.5
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Automated)"
|
||||
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: 4.2.6
|
||||
text: "Minimize the admission of root containers (Automated)"
|
||||
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: 4.2.7
|
||||
text: "Minimize the admission of containers with the NET_RAW capability (Automated)"
|
||||
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: 4.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: 4.2.9
|
||||
text: "Minimize the admission of containers with capabilities assigned (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the use of capabilities 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: false
|
||||
|
||||
- id: 4.3
|
||||
text: "CNI Plugin"
|
||||
checks:
|
||||
- id: 4.3.1
|
||||
text: "Ensure that the latest CNI version is used (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the documentation of AWS CNI plugin, and ensure latest CNI version is used.
|
||||
scored: false
|
||||
|
||||
- id: 4.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: 4.4
|
||||
text: "Secrets Management"
|
||||
checks:
|
||||
- id: 4.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: 4.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: 4.5
|
||||
text: "Extensible Admission Control"
|
||||
checks: []
|
||||
|
||||
- id: 4.6
|
||||
text: "General Policies"
|
||||
checks:
|
||||
- id: 4.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: 4.6.2
|
||||
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: 4.6.3
|
||||
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
|
||||
9
cfg/eks-1.2.0/config.yaml
Normal file
9
cfg/eks-1.2.0/config.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
## These settings are required if you are using the --asff option to report findings to AWS Security Hub
|
||||
## AWS account number is required.
|
||||
AWS_ACCOUNT: "<AWS_ACCT_NUMBER>"
|
||||
## AWS region is required.
|
||||
AWS_REGION: "<AWS_REGION>"
|
||||
## EKS Cluster ARN is required.
|
||||
CLUSTER_ARN: "<AWS_CLUSTER_ARN>"
|
||||
14
cfg/eks-1.2.0/controlplane.yaml
Normal file
14
cfg/eks-1.2.0/controlplane.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.2.0"
|
||||
id: 2
|
||||
text: "Control Plane Configuration"
|
||||
type: "controlplane"
|
||||
groups:
|
||||
- id: 2.1
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 2.1.1
|
||||
text: "Enable audit logs (Manual)"
|
||||
remediation: "Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler."
|
||||
scored: false
|
||||
154
cfg/eks-1.2.0/managedservices.yaml
Normal file
154
cfg/eks-1.2.0/managedservices.yaml
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.2.0"
|
||||
id: 5
|
||||
text: "Managed Services"
|
||||
type: "managedservices"
|
||||
groups:
|
||||
- id: 5.1
|
||||
text: "Image Registry and Image Scanning"
|
||||
checks:
|
||||
- id: 5.1.1
|
||||
text: "Ensure Image Vulnerability Scanning using Amazon ECR image scanning or a third-party provider (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
To utilize AWS ECR for Image scanning please follow the steps below:
|
||||
|
||||
To create a repository configured for scan on push (AWS CLI):
|
||||
aws ecr create-repository --repository-name $REPO_NAME --image-scanning-configuration scanOnPush=true --region $REGION_CODE
|
||||
|
||||
To edit the settings of an existing repository (AWS CLI):
|
||||
aws ecr put-image-scanning-configuration --repository-name $REPO_NAME --image-scanning-configuration scanOnPush=true --region $REGION_CODE
|
||||
|
||||
Use the following steps to start a manual image scan using the AWS Management Console.
|
||||
Open the Amazon ECR console at https://console.aws.amazon.com/ecr/repositories.
|
||||
From the navigation bar, choose the Region to create your repository in.
|
||||
In the navigation pane, choose Repositories.
|
||||
On the Repositories page, choose the repository that contains the image to scan.
|
||||
On the Images page, select the image to scan and then choose Scan.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.2
|
||||
text: "Minimize user access to Amazon ECR (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Before you use IAM to manage access to Amazon ECR, you should understand what IAM features
|
||||
are available to use with Amazon ECR. To get a high-level view of how Amazon ECR and other
|
||||
AWS services work with IAM, see AWS Services That Work with IAM in the IAM User Guide.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.3
|
||||
text: "Minimize cluster access to read-only for Amazon ECR (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
You can use your Amazon ECR images with Amazon EKS, but you need to satisfy the following prerequisites.
|
||||
|
||||
The Amazon EKS worker node IAM role (NodeInstanceRole) that you use with your worker nodes must possess
|
||||
the following IAM policy permissions for Amazon ECR.
|
||||
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:GetAuthorizationToken"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
scored: false
|
||||
|
||||
- id: 5.1.4
|
||||
text: "Minimize Container Registries to only those approved (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Identity and Access Management (IAM)"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Prefer using dedicated Amazon EKS Service Accounts (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.3
|
||||
text: "AWS Key Management Service (KMS)"
|
||||
checks:
|
||||
- id: 5.3.1
|
||||
text: "Ensure Kubernetes Secrets are encrypted using Customer Master Keys (CMKs) managed in AWS KMS (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
This process can only be performed during Cluster Creation.
|
||||
|
||||
Enable 'Secrets Encryption' during Amazon EKS cluster creation as described
|
||||
in the links within the 'References' section.
|
||||
scored: false
|
||||
|
||||
- id: 5.4
|
||||
text: "Cluster Networking"
|
||||
checks:
|
||||
- id: 5.4.1
|
||||
text: "Restrict Access to the Control Plane Endpoint (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.2
|
||||
text: "Ensure clusters are created with Private Endpoint Enabled and Public Access Disabled (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.3
|
||||
text: "Ensure clusters are created with Private Nodes (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.4
|
||||
text: "Ensure Network Policy is Enabled and set as appropriate (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
- id: 5.4.5
|
||||
text: "Encrypt traffic to HTTPS load balancers with TLS certificates (Manual)"
|
||||
type: "manual"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.5
|
||||
text: "Authentication and Authorization"
|
||||
checks:
|
||||
- id: 5.5.1
|
||||
text: "Manage Kubernetes RBAC users with AWS IAM Authenticator for Kubernetes (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Refer to the 'Managing users or IAM roles for your cluster' in Amazon EKS documentation.
|
||||
scored: false
|
||||
|
||||
|
||||
- id: 5.6
|
||||
text: "Other Cluster Configurations"
|
||||
checks:
|
||||
- id: 5.6.1
|
||||
text: "Consider Fargate for running untrusted workloads (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a Fargate profile for your cluster Before you can schedule pods running on Fargate
|
||||
in your cluster, you must define a Fargate profile that specifies which pods should use
|
||||
Fargate when they are launched. For more information, see AWS Fargate profile.
|
||||
|
||||
Note: If you created your cluster with eksctl using the --fargate option, then a Fargate profile has
|
||||
already been created for your cluster with selectors for all pods in the kube-system
|
||||
and default namespaces. Use the following procedure to create Fargate profiles for
|
||||
any other namespaces you would like to use with Fargate.
|
||||
scored: false
|
||||
6
cfg/eks-1.2.0/master.yaml
Normal file
6
cfg/eks-1.2.0/master.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.2.0"
|
||||
id: 1
|
||||
text: "Control Plane Components"
|
||||
type: "master"
|
||||
330
cfg/eks-1.2.0/node.yaml
Normal file
330
cfg/eks-1.2.0/node.yaml
Normal file
@@ -0,0 +1,330 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.2.0"
|
||||
id: 3
|
||||
text: "Worker Node Security Configuration"
|
||||
type: "node"
|
||||
groups:
|
||||
- id: 3.1
|
||||
text: "Worker Node Configuration Files"
|
||||
checks:
|
||||
- id: 3.1.1
|
||||
text: "Ensure that the kubeconfig file permissions are set to 644 or more restrictive (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.1.2
|
||||
text: "Ensure that the kubelet kubeconfig 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: 3.1.3
|
||||
text: "Ensure that the kubelet configuration file has permissions set to 644 or more restrictive (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.1.4
|
||||
text: "Ensure that the kubelet configuration file ownership is set to root:root (Manual)"
|
||||
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: false
|
||||
|
||||
- id: 3.2
|
||||
text: "Kubelet"
|
||||
checks:
|
||||
- id: 3.2.1
|
||||
text: "Ensure that the Anonymous Auth is Not Enabled (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
path: '{.authentication.anonymous.enabled}'
|
||||
set: true
|
||||
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: 3.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}'
|
||||
set: true
|
||||
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: 3.2.3
|
||||
text: "Ensure that a Client CA File is Configured (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --client-ca-file
|
||||
path: '{.authentication.x509.clientCAFile}'
|
||||
set: true
|
||||
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: false
|
||||
|
||||
- id: 3.2.4
|
||||
text: "Ensure that the --read-only-port is disabled (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--read-only-port"
|
||||
path: '{.readOnlyPort}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
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: 3.2.5
|
||||
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0 (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --streaming-connection-idle-timeout
|
||||
path: '{.streamingConnectionIdleTimeout}'
|
||||
set: true
|
||||
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: true
|
||||
|
||||
- id: 3.2.6
|
||||
text: "Ensure that the --protect-kernel-defaults argument is set to true (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --protect-kernel-defaults
|
||||
path: '{.protectKernelDefaults}'
|
||||
set: true
|
||||
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: true
|
||||
|
||||
- id: 3.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}'
|
||||
set: true
|
||||
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: 3.2.8
|
||||
text: "Ensure that the --hostname-override argument is not set (Manual)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and remove the --hostname-override 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: false
|
||||
|
||||
- id: 3.2.9
|
||||
text: "Ensure that the --eventRecordQPS argument is set to 0 or a level which ensures appropriate event capture (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --event-qps
|
||||
path: '{.eventRecordQPS}'
|
||||
set: true
|
||||
compare:
|
||||
op: gte
|
||||
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: 3.2.10
|
||||
text: "Ensure that the --rotate-certificates argument is not present or is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
- flag: --rotate-certificates
|
||||
path: '{.rotateCertificates}'
|
||||
set: false
|
||||
bin_op: or
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line rotateCertificates: true or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
$kubeletsvc on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
|
||||
- id: 3.2.11
|
||||
text: "Ensure that the RotateKubeletServerCertificate argument is set to true (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: RotateKubeletServerCertificate
|
||||
path: '{.featureGates.RotateKubeletServerCertificate}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletsvc
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: false
|
||||
- id: 3.3
|
||||
text: "Container Optimized OS"
|
||||
checks:
|
||||
- id: 3.3.1
|
||||
text: "Prefer using a container-optimized OS when possible (Manual)"
|
||||
remediation: "No remediation"
|
||||
scored: false
|
||||
213
cfg/eks-1.2.0/policies.yaml
Normal file
213
cfg/eks-1.2.0/policies.yaml
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-1.2.0"
|
||||
id: 4
|
||||
text: "Policies"
|
||||
type: "policies"
|
||||
groups:
|
||||
- id: 4.1
|
||||
text: "RBAC and Service Accounts"
|
||||
checks:
|
||||
- id: 4.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: 4.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: 4.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: 4.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: 4.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: 4.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: 4.1.7
|
||||
text: "Avoid use of system:masters group (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Remove the system:masters group from all users in the cluster.
|
||||
scored: false
|
||||
|
||||
- id: 4.1.8
|
||||
text: "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove the impersonate, bind and escalate rights from subjects.
|
||||
scored: false
|
||||
|
||||
- id: 4.2
|
||||
text: "Pod Security Policies"
|
||||
checks:
|
||||
- id: 4.2.1
|
||||
text: "Minimize the admission of privileged containers (Automated)"
|
||||
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: 4.2.2
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace (Automated)"
|
||||
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: 4.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace (Automated)"
|
||||
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: 4.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace (Automated)"
|
||||
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: 4.2.5
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation (Automated)"
|
||||
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: 4.2.6
|
||||
text: "Minimize the admission of root containers (Automated)"
|
||||
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: 4.2.7
|
||||
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: 4.2.8
|
||||
text: "Minimize the admission of containers with capabilities assigned (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Review the use of capabilities 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: false
|
||||
|
||||
- id: 4.3
|
||||
text: "CNI Plugin"
|
||||
checks:
|
||||
- id: 4.3.1
|
||||
text: "Ensure CNI plugin supports network policies (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
As with RBAC policies, network policies should adhere to the policy of least privileged
|
||||
access. Start by creating a deny all policy that restricts all inbound and outbound traffic
|
||||
from a namespace or create a global policy using Calico.
|
||||
scored: false
|
||||
|
||||
- id: 4.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: 4.4
|
||||
text: "Secrets Management"
|
||||
checks:
|
||||
- id: 4.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: 4.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: 4.5
|
||||
text: "Extensible Admission Control"
|
||||
checks: []
|
||||
|
||||
- id: 4.6
|
||||
text: "General Policies"
|
||||
checks:
|
||||
- id: 4.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: 4.6.2
|
||||
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: 4.6.3
|
||||
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
|
||||
9
cfg/eks-stig-kubernetes-v1r6/config.yaml
Normal file
9
cfg/eks-stig-kubernetes-v1r6/config.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
## These settings are required if you are using the --asff option to report findings to AWS Security Hub
|
||||
## AWS account number is required.
|
||||
AWS_ACCOUNT: "<AWS_ACCT_NUMBER>"
|
||||
## AWS region is required.
|
||||
AWS_REGION: "<AWS_REGION>"
|
||||
## EKS Cluster ARN is required.
|
||||
CLUSTER_ARN: "<AWS_CLUSTER_ARN>"
|
||||
124
cfg/eks-stig-kubernetes-v1r6/controlplane.yaml
Normal file
124
cfg/eks-stig-kubernetes-v1r6/controlplane.yaml
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-stig-kubernetes-v1r6"
|
||||
id: 2
|
||||
text: "Control Plane Configuration"
|
||||
type: "controlplane"
|
||||
groups:
|
||||
- id: 2.1
|
||||
text: "DISA Category Code I"
|
||||
checks:
|
||||
- id: V-242390
|
||||
text: "The Kubernetes API server must have anonymous authentication disabled (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
path: '{.authentication.anonymous.enabled}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: V-242400
|
||||
text: "The Kubernetes API server must have Alpha APIs disabled (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--feature-gates"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "AllAlpha=true"
|
||||
set: true
|
||||
- flag: "--feature-gates"
|
||||
set: false
|
||||
remediation: |
|
||||
Edit any manifest files or $kubeletconf that contain the feature-gates
|
||||
setting with AllAlpha set to "true".
|
||||
Set the flag to "false" or remove the "AllAlpha" setting
|
||||
completely. Restart the kubelet service if the kubelet config file
|
||||
if the kubelet config file is changed.
|
||||
scored: true
|
||||
- id: 2.2
|
||||
text: "DISA Category Code II"
|
||||
checks:
|
||||
- id: V-242381
|
||||
text: "The Kubernetes Controller Manager must create unique service accounts for each work payload. (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: V-242402
|
||||
text: "The Kubernetes API Server must have an audit log path set (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242403
|
||||
text: "Kubernetes API Server must generate audit records (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242461
|
||||
text: "Kubernetes API Server audit logs must be enabled. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242462
|
||||
text: "The Kubernetes API Server must be set to audit log max size. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242463
|
||||
text: "The Kubernetes API Server must be set to audit log maximum backup. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242464
|
||||
text: "The Kubernetes API Server audit log retention must be set. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: V-242465
|
||||
text: "The Kubernetes API Server audit log path must be set. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Enable control plane logging for API Server, Audit, Authenticator, Controller Manager, and Scheduler.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
|
||||
scored: false
|
||||
- id: 2.2
|
||||
text: "DISA Category Code II"
|
||||
checks:
|
||||
- id: V-242443
|
||||
text: " Kubernetes must contain the latest updates as authorized by IAVMs, CTOs, DTMs, and STIGs. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Upgrade Kubernetes to a supported version.
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html
|
||||
268
cfg/eks-stig-kubernetes-v1r6/managedservices.yaml
Normal file
268
cfg/eks-stig-kubernetes-v1r6/managedservices.yaml
Normal file
@@ -0,0 +1,268 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-stig-kubernetes-v1r6"
|
||||
id: 5
|
||||
text: "Managed Services"
|
||||
type: "managedservices"
|
||||
groups:
|
||||
- id: 5.1
|
||||
text: "DISA Category Code I"
|
||||
checks:
|
||||
- id: V-242386
|
||||
text: "The Kubernetes API server must have the insecure port flag disabled | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242388
|
||||
text: "The Kubernetes API server must have the insecure bind address not set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242436
|
||||
text: "The Kubernetes API server must have the ValidatingAdmissionWebhook enabled (manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Amazon EKS version 1.18 and later automatically enable ValidatingAdmissionWebhook
|
||||
Ref: https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html
|
||||
scored: false
|
||||
|
||||
- id: V-245542
|
||||
text: "Kubernetes API Server must disable basic authentication to protect information in transit | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: 5.2
|
||||
text: "DISA Category Code II"
|
||||
checks:
|
||||
- id: V-242376
|
||||
text: "The Kubernetes Controller Manager must use TLS 1.2, at a minimum | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242377
|
||||
text: "The Kubernetes Scheduler must use TLS 1.2, at a minimum | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242378
|
||||
text: "The Kubernetes API Server must use TLS 1.2, at a minimum | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242379
|
||||
text: "The Kubernetes etcd must use TLS to protect the confidentiality of sensitive data during electronic dissemination | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242380
|
||||
text: "The Kubernetes etcd must use TLS to protect the confidentiality of sensitive data during electronic dissemination | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242382
|
||||
text: "The Kubernetes API Server must enable Node,RBAC as the authorization mode | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242384
|
||||
text: "The Kubernetes Scheduler must have secure binding | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242385
|
||||
text: "The Kubernetes Controller Manager must have secure binding | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242389
|
||||
text: "The Kubernetes API server must have the secure port set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242401
|
||||
text: "The Kubernetes API Server must have an audit policy set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242402
|
||||
text: "The Kubernetes API Server must have an audit log path set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242403
|
||||
text: "Kubernetes API Server must generate audit records | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242405
|
||||
text: "The Kubernetes manifests must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242408
|
||||
text: "The Kubernetes manifests must have least privileges | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242409
|
||||
text: "Kubernetes Controller Manager must disable profiling | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242410
|
||||
text: "The Kubernetes API Server must enforce PPS that adhere to PPSM CAL | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242411
|
||||
text: "The Kubernetes Scheduler must enforce PPS that adhere to PPSM CAL | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242412
|
||||
text: "The Kubernetes Controllers must enforce PPS that adhere to PPSM CAL | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242413
|
||||
text: "The Kubernetes etcd must enforce PPS that adhere to PPSM CAL | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242418
|
||||
text: "The Kubernetes API server must use approved cipher suites | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242419
|
||||
text: "Kubernetes API Server must have the SSL Certificate Authority set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242420
|
||||
text: "Kubernetes Kubelet must have the SSL Certificate Authority set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242421
|
||||
text: "Kubernetes Controller Manager must have the SSL Certificate Authority set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242422
|
||||
text: "Kubernetes API Server must have a certificate for communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242423
|
||||
text: "Kubernetes etcd must enable client authentication to secure service | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242424
|
||||
text: "Kubernetes etcd must enable client authentication to secure service | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242425
|
||||
text: "Kubernetes Kubelet must enable tls-cert-file for client authentication to secure service | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242426
|
||||
text: "Kubernetes etcd must enable client authentication to secure service | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242427
|
||||
text: "Kubernetes etcd must have a key file for secure communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242428
|
||||
text: "Kubernetes etcd must have a certificate for communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242429
|
||||
text: "Kubernetes etcd must have the SSL Certificate Authority set | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242430
|
||||
text: "Kubernetes etcd must have a certificate for communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242431
|
||||
text: "Kubernetes etcd must have a key file for secure communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242432
|
||||
text: "Kubernetes etcd must have peer-cert-file set for secure communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242433
|
||||
text: "Kubernetes etcd must have a peer-key-file set for secure communication | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242438
|
||||
text: "Kubernetes API Server must configure timeouts to limit attack surface | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242444
|
||||
text: "The Kubernetes component manifests must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242445
|
||||
text: "The Kubernetes component etcd must be owned by etcd | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242446
|
||||
text: "The Kubernetes conf files must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242447
|
||||
text: "The Kubernetes Kube Proxy must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242448
|
||||
text: "The Kubernetes Kube Proxy must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242449
|
||||
text: "The Kubernetes Kubelet certificate authority file must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242450
|
||||
text: "The Kubernetes Kubelet certificate authority must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242451
|
||||
text: "The Kubernetes component PKI must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242452
|
||||
text: "The Kubernetes kubelet config must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242453
|
||||
text: "The Kubernetes kubelet config must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242454
|
||||
text: "The Kubernetes kubeadm.conf must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242455
|
||||
text: "The Kubernetes kubeadm.conf must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242456
|
||||
text: "The Kubernetes kubelet config must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242457
|
||||
text: "The Kubernetes kubelet config must be owned by root | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242458
|
||||
text: "The Kubernetes API Server must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242459
|
||||
text: "The Kubernetes etcd must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242460
|
||||
text: "The Kubernetes admin.conf must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242466
|
||||
text: "The Kubernetes PKI CRT must have file permissions set to 644 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242467
|
||||
text: "The Kubernetes PKI keys must have file permissions set to 600 or more restrictive | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-242468
|
||||
text: "The Kubernetes API Server must prohibit communication using TLS version 1.0 and 1.1, and SSL 2.0 and 3.0 | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-245541
|
||||
text: "Kubernetes Kubelet must not disable timeouts | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-245543
|
||||
text: "Kubernetes API Server must disable token authentication to protect information in transit | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
|
||||
- id: V-245544
|
||||
text: "Kubernetes endpoints must use approved organizational certificate and key pair to protect information in transit | Component of EKS Control Plane"
|
||||
type: "skip"
|
||||
6
cfg/eks-stig-kubernetes-v1r6/master.yaml
Normal file
6
cfg/eks-stig-kubernetes-v1r6/master.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-stig-kubernetes-v1r6"
|
||||
id: 1
|
||||
text: "Control Plane Components"
|
||||
type: "master"
|
||||
287
cfg/eks-stig-kubernetes-v1r6/node.yaml
Normal file
287
cfg/eks-stig-kubernetes-v1r6/node.yaml
Normal file
@@ -0,0 +1,287 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-stig-kubernetes-v1r6"
|
||||
id: 3
|
||||
text: "Worker Node Security Configuration"
|
||||
type: "node"
|
||||
groups:
|
||||
- id: 3.1
|
||||
text: "DISA Category Code I"
|
||||
checks:
|
||||
- id: V-242387 # CIS 3.2.4
|
||||
text: "The Kubernetes Kubelet must have the read-only port flag disabled (Manual)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--read-only-port"
|
||||
path: '{.readOnlyPort}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: 0
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: V-242391 # CIS 3.2.1
|
||||
text: "The Kubernetes Kubelet must have anonymous authentication disabled (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--anonymous-auth"
|
||||
path: '{.authentication.anonymous.enabled}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: false
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: V-242392 # CIS 3.2.2
|
||||
text: "The Kubernetes kubelet must enable explicit authorization (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --authorization-mode
|
||||
path: '{.authorization.mode}'
|
||||
set: true
|
||||
compare:
|
||||
op: nothave
|
||||
value: AlwaysAllow
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: V-242397
|
||||
text: "The Kubernetes kubelet static PodPath must not enable static pods (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- path: '{.staticPodPath}'
|
||||
set: false
|
||||
remediation: |
|
||||
Edit $kubeletconf on each node to to remove the staticPodPath
|
||||
Based on your system, restart the kubelet service. For example,
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
scored: true
|
||||
- id: V-242415
|
||||
text: "Secrets in Kubernetes must not be stored as environment variables.(Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Run the following command:
|
||||
kubectl get all -o jsonpath='{range .items[?(@..secretKeyRef)]} {.kind} {.metadata.name} {"\n"}{end}' -A
|
||||
If any of the values returned reference environment variables
|
||||
rewrite application code to read secrets from mounted secret files, rather than
|
||||
from environment variables.
|
||||
scored: false
|
||||
- id: V-242434 # CIS 3.2.6
|
||||
text: "Kubernetes Kubelet must enable kernel protection (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --protect-kernel-defaults
|
||||
path: '{.protectKernelDefaults}'
|
||||
set: true
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: true
|
||||
- id: V-242435
|
||||
text: "Kubernetes must prevent non-privileged users from executing privileged functions (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --authorization-mode
|
||||
path: '{.authorization.mode}'
|
||||
set: true
|
||||
compare:
|
||||
op: nothave
|
||||
value: AlwaysAllow
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit $kubeletconf 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: V-242393
|
||||
text: "Kubernetes Worker Nodes must not have sshd service running. (Automated)"
|
||||
audit: '/bin/sh -c ''systemctl show -p ActiveState sshd'' '
|
||||
tests:
|
||||
test_items:
|
||||
- flag: ActiveState
|
||||
compare:
|
||||
op: eq
|
||||
value: inactive
|
||||
remediation: |
|
||||
To stop the sshd service, run the command: systemctl stop sshd
|
||||
scored: true
|
||||
- id: V-242394
|
||||
text: "Kubernetes Worker Nodes must not have the sshd service enabled. (Automated)"
|
||||
audit: "/bin/sh -c 'systemctl is-enabled sshd.service'"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "disabled"
|
||||
remediation: |
|
||||
To disable the sshd service, run the command:
|
||||
chkconfig sshd off
|
||||
scored: true
|
||||
- id: V-242395
|
||||
text: "Kubernetes dashboard must not be enabled. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Run the command: kubectl get pods --all-namespaces -l k8s-app=kubernetes-dashboard
|
||||
If any resources are returned, this is a finding.
|
||||
Fix Text: Delete the Kubernetes dashboard deployment with the following command:
|
||||
kubectl delete deployment kubernetes-dashboard --namespace=kube-system
|
||||
scored: false
|
||||
- id: V-242398
|
||||
text: "Kubernetes DynamicAuditing must not be enabled. (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--feature-gates"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "DynamicAuditing=true"
|
||||
set: true
|
||||
- flag: "--feature-gates"
|
||||
set: false
|
||||
remediation: |
|
||||
Edit any manifest files or kubelet config files that contain the feature-gates
|
||||
setting with DynamicAuditing set to "true".
|
||||
Set the flag to "false" or remove the "DynamicAuditing" setting
|
||||
completely. Restart the kubelet service if the kubelet config file
|
||||
if the kubelet config file is changed.
|
||||
scored: true
|
||||
- id: V-242399
|
||||
text: "Kubernetes DynamicKubeletConfig must not be enabled. (Automated)"
|
||||
audit: "/bin/ps -fC $kubeletbin"
|
||||
audit_config: "/bin/cat $kubeletconf"
|
||||
tests:
|
||||
bin_op: or
|
||||
test_items:
|
||||
- flag: "--feature-gates"
|
||||
compare:
|
||||
op: nothave
|
||||
value: "DynamicKubeletConfig=true"
|
||||
set: true
|
||||
- flag: "--feature-gates"
|
||||
set: false
|
||||
remediation: |
|
||||
Edit any manifest files or $kubeletconf that contain the feature-gates
|
||||
setting with DynamicKubeletConfig set to "true".
|
||||
Set the flag to "false" or remove the "DynamicKubeletConfig" setting
|
||||
completely. Restart the kubelet service if the kubelet config file
|
||||
if the kubelet config file is changed.
|
||||
scored: true
|
||||
- id: V-242404 # CIS 3.2.8
|
||||
text: "Kubernetes Kubelet must deny hostname override (Automated)"
|
||||
# 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:
|
||||
- flag: --hostname-override
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the kubelet service file $kubeletbin
|
||||
on each worker node and remove the --hostname-override 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: V-242406
|
||||
text: "The Kubernetes kubelet configuration file must be owned by root (Automated)"
|
||||
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: true
|
||||
- id: V-242407
|
||||
text: "The Kubernetes kubelet configuration files must have file 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: V-242414
|
||||
text: "The Kubernetes cluster must use non-privileged host ports for user pods. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
For any of the pods that are using ports below 1024,
|
||||
reconfigure the pod to use a service to map a host non-privileged
|
||||
port to the pod port or reconfigure the image to use non-privileged ports.
|
||||
scored: false
|
||||
- id: V-242442
|
||||
text: "Kubernetes must remove old components after updated versions have been installed. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
To view all pods and the images used to create the pods, from the Master node, run the following command:
|
||||
kubectl get pods --all-namespaces -o jsonpath="{..image}" | \
|
||||
tr -s '[[:space:]]' '\n' | \
|
||||
sort | \
|
||||
uniq -c
|
||||
Review the images used for pods running within Kubernetes.
|
||||
Remove any old pods that are using older images.
|
||||
scored: false
|
||||
- id: V-242396
|
||||
text: "Kubernetes Kubectl cp command must give expected access and results. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
If any Worker nodes are not using kubectl version 1.12.9 or newer, this is a finding.
|
||||
Upgrade the Master and Worker nodes to the latest version of kubectl.
|
||||
scored: false
|
||||
33
cfg/eks-stig-kubernetes-v1r6/policies.yaml
Normal file
33
cfg/eks-stig-kubernetes-v1r6/policies.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
controls:
|
||||
version: "eks-stig-kubernetes-v1r6"
|
||||
id: 4
|
||||
text: "Policies"
|
||||
type: "policies"
|
||||
groups:
|
||||
- id: 4.1
|
||||
text: "Policies - DISA Category Code I"
|
||||
checks:
|
||||
- id: V-242381
|
||||
text: "The Kubernetes Controller Manager must create unique service accounts for each work payload. (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: V-242383
|
||||
text: "User-managed resources must be created in dedicated namespaces. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Move any user-managed resources from the default, kube-public and kube-node-lease namespaces, to user namespaces.
|
||||
scored: false
|
||||
|
||||
- id: V-242417
|
||||
text: "Kubernetes must separate user functionality. (Manual)"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Move any user pods that are present in the Kubernetes system namespaces to user specific namespaces.
|
||||
scored: false
|
||||
@@ -37,7 +37,7 @@ groups:
|
||||
- id: 5.1.4
|
||||
text: "Minimize access to create pods (Not Scored)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ groups:
|
||||
- id: 4.1.4
|
||||
text: "Minimize access to create pods (Manual)"
|
||||
type: "manual"
|
||||
Remediation: |
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
scored: false
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@ groups:
|
||||
#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[]'
|
||||
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[]'
|
||||
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig[]?'
|
||||
type: manual
|
||||
remediation: |
|
||||
No remediation required.
|
||||
@@ -52,9 +52,9 @@ groups:
|
||||
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[]'
|
||||
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[]'
|
||||
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,
|
||||
|
||||
@@ -57,7 +57,7 @@ groups:
|
||||
# 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=$?
|
||||
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | grep -- --auto-tls=true 2>/dev/null ; echo exit_code=$?
|
||||
done 2>/dev/null
|
||||
use_multiple_values: true
|
||||
tests:
|
||||
@@ -118,7 +118,7 @@ groups:
|
||||
# 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=$?
|
||||
oc exec -n openshift-etcd -c etcd $i -- ps -o command= -C etcd | grep -- --peer-auto-tls=true 2>/dev/null ; echo exit_code=$?
|
||||
done 2>/dev/null
|
||||
use_multiple_values: true
|
||||
tests:
|
||||
|
||||
@@ -129,7 +129,7 @@ groups:
|
||||
scored: false
|
||||
|
||||
- id: 1.1.8
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Automated)"
|
||||
text: "Ensure that the etcd pod specification file ownership is set to root:root (Manual)"
|
||||
audit: |
|
||||
for i in $( oc get pods -n openshift-etcd -l app=etcd -o name | grep etcd )
|
||||
do
|
||||
@@ -141,7 +141,7 @@ groups:
|
||||
- flag: "root:root"
|
||||
remediation: |
|
||||
No remediation required; file permissions are managed by the operator.
|
||||
scored: true
|
||||
scored: false
|
||||
|
||||
- id: 1.1.9
|
||||
text: "Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Manual)"
|
||||
@@ -316,7 +316,7 @@ groups:
|
||||
scored: false
|
||||
|
||||
- id: 1.1.19
|
||||
text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Automated)"
|
||||
text: "Ensure that the Kubernetes PKI directory and file ownership is set to root:root (Manual)"
|
||||
audit: |
|
||||
# Should return root:root for all files and directories
|
||||
for i in $(oc -n openshift-kube-apiserver get pod -l app=openshift-kube-apiserver -o jsonpath='{.items[*].metadata.name}')
|
||||
@@ -334,7 +334,7 @@ groups:
|
||||
- flag: "root:root"
|
||||
remediation: |
|
||||
No remediation required; file permissions are managed by the operator.
|
||||
scored: true
|
||||
scored: false
|
||||
|
||||
- id: 1.1.20
|
||||
text: "Ensure that the OpenShift PKI certificate file permissions are set to 644 or more restrictive (Manual)"
|
||||
@@ -381,9 +381,9 @@ groups:
|
||||
text: "Ensure that anonymous requests are authorized (Manual)"
|
||||
audit: |
|
||||
# To verify that userGroups include system:unauthenticated
|
||||
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]'
|
||||
oc get configmap config -n openshift-kube-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]?'
|
||||
# To verify that userGroups include system:unauthenticated
|
||||
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[].userGroups'
|
||||
oc get configmap config -n openshift-apiserver -ojson | jq -r '.data["config.yaml"]' | jq '.auditConfig.policyConfiguration.rules[]?.userGroups'
|
||||
# To verify RBAC is enabled
|
||||
oc get clusterrolebinding
|
||||
oc get clusterrole
|
||||
|
||||
@@ -186,7 +186,7 @@ groups:
|
||||
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
|
||||
oc debug node/${node} -- chroot /host grep -B4 -A1 anonymous /etc/kubernetes/kubelet.conf
|
||||
done
|
||||
use_multiple_values: true
|
||||
tests:
|
||||
@@ -199,7 +199,7 @@ groups:
|
||||
scored: true
|
||||
|
||||
- id: 4.2.2
|
||||
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Automated)"
|
||||
text: "Ensure that the --authorization-mode argument is not set to AlwaysAllow (Manual)"
|
||||
type: manual
|
||||
# Takes a lot of time for connection to fail and
|
||||
audit: |
|
||||
@@ -215,14 +215,14 @@ groups:
|
||||
- flag: "Connection timed out"
|
||||
remediation: |
|
||||
None required. Unauthenticated/Unauthorized users have no access to OpenShift nodes.
|
||||
scored: true
|
||||
scored: false
|
||||
|
||||
- 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
|
||||
oc debug node/${node} -- chroot /host grep clientCAFile /etc/kubernetes/kubelet.conf
|
||||
done 2> /dev/null
|
||||
use_multiple_values: true
|
||||
tests:
|
||||
@@ -346,7 +346,7 @@ groups:
|
||||
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)"
|
||||
text: "Ensure that the kubeAPIQPS [--event-qps] argument is set to 0 or a level which ensures appropriate event capture (Manual)"
|
||||
audit: |
|
||||
for node in $(oc get nodes -o jsonpath='{.items[*].metadata.name}');
|
||||
do
|
||||
@@ -359,7 +359,7 @@ groups:
|
||||
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
|
||||
scored: false
|
||||
|
||||
- id: 4.2.10
|
||||
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate (Automated)"
|
||||
|
||||
2
cfg/tkgi-1.2.53/config.yaml
Normal file
2
cfg/tkgi-1.2.53/config.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
## Version-specific settings that override the values in cfg/config.yaml
|
||||
67
cfg/tkgi-1.2.53/controlplane.yaml
Normal file
67
cfg/tkgi-1.2.53/controlplane.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
controls:
|
||||
version: "tkgi-1.2.53"
|
||||
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"
|
||||
audit: ps -ef | grep kube-apiserver | grep -- "--oidc-issuer-url="
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Alternative mechanisms provided by Kubernetes such as the use of OIDC should be
|
||||
implemented in place of client certificates.
|
||||
Exception
|
||||
This setting is site-specific. It can be set in the "Configure created clusters to use UAA as the OIDC provider."
|
||||
section of the "UAA"
|
||||
scored: false
|
||||
|
||||
- id: 3.2
|
||||
text: "Logging"
|
||||
checks:
|
||||
- id: 3.2.1
|
||||
text: "Ensure that a minimal audit policy is created"
|
||||
audit: ps -ef | grep kube-apiserver | grep -v tini | grep -- "--audit-policy-file="
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--audit-policy-file"
|
||||
remediation: |
|
||||
Create an audit policy file for your cluster.
|
||||
scored: true
|
||||
|
||||
- id: 3.2.2
|
||||
text: "Ensure that the audit policy covers key security concerns"
|
||||
audit: |
|
||||
diff /var/vcap/jobs/kube-apiserver/config/audit_policy.yml \ <(echo "--- apiVersion: audit.k8s.io/v1beta1 kind:
|
||||
Policy rules: - level: None resources: - group: '' resources: - endpoints - services - services/status users: -
|
||||
system:kube-proxy verbs: - watch - level: None resources: - group: '' resources: - nodes - nodes/status users: -
|
||||
kubelet verbs: - get - level: None resources: - group: '' resources: - nodes - nodes/status userGroups: -
|
||||
system:nodes verbs: - get - level: None namespaces: - kube-system resources: - group: '' resources: -
|
||||
endpoints users: - system:kube-controller-manager - system:kube-scheduler - system:serviceaccount:kube-
|
||||
system:endpoint-controller verbs: - get - update - level: None resources: - group: '' resources: - namespaces -
|
||||
namespaces/status - namespaces/finalize users: - system:apiserver verbs: - get - level: None resources: -
|
||||
group: metrics.k8s.io users: - system:kube-controller-manager verbs: - get - list - level: None
|
||||
nonResourceURLs: - \"/healthz*\" - \"/version\" - \"/swagger*\" - level: None resources: - group: '' resources: -
|
||||
events - level: Request omitStages: - RequestReceived resources: - group: '' resources: - nodes/status -
|
||||
pods/status userGroups: - system:nodes verbs: - update - patch - level: Request omitStages: -
|
||||
RequestReceived users: - system:serviceaccount:kube-system:namespace-controller verbs: - deletecollection -
|
||||
level: Metadata omitStages: - RequestReceived resources: - group: '' resources: - secrets - configmaps - group:
|
||||
authentication.k8s.io resources: - tokenreviews - level: Request omitStages: - RequestReceived resources: -
|
||||
group: '' - group: admissionregistration.k8s.io - group: apiextensions.k8s.io - group: apiregistration.k8s.io -
|
||||
group: apps - group: authentication.k8s.io - group: authorization.k8s.io - group: autoscaling - group: batch -
|
||||
group: certificates.k8s.io - group: extensions - group: metrics.k8s.io - group: networking.k8s.io - group: policy -
|
||||
group: rbac.authorization.k8s.io - group: settings.k8s.io - group: storage.k8s.io verbs: - get - list - watch - level:
|
||||
RequestResponse omitStages: - RequestReceived resources: - group: '' - group: admissionregistration.k8s.io -
|
||||
group: apiextensions.k8s.io - group: apiregistration.k8s.io - group: apps - group: authentication.k8s.io - group:
|
||||
authorization.k8s.io - group: autoscaling - group: batch - group: certificates.k8s.io - group: extensions - group:
|
||||
metrics.k8s.io - group: networking.k8s.io - group: policy - group: rbac.authorization.k8s.io - group:
|
||||
settings.k8s.io - group: storage.k8s.io - level: Metadata omitStages: - RequestReceived ")
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Consider modification of the audit policy in use on the cluster to include these items, at a
|
||||
minimum.
|
||||
scored: false
|
||||
121
cfg/tkgi-1.2.53/etcd.yaml
Normal file
121
cfg/tkgi-1.2.53/etcd.yaml
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
controls:
|
||||
version: "tkgi-1.2.53"
|
||||
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"
|
||||
audit: ps -ef | grep etcd | grep -- "--cert-file=/var/vcap/jobs/etcd/config/etcd.crt" | grep -- "--key-file=/var/vcap/jobs/etcd/config/etcd.key"
|
||||
type: manual
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "--cert-file"
|
||||
- flag: "--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: false
|
||||
|
||||
- id: 2.2
|
||||
text: "Ensure that the --client-cert-auth argument is set to true"
|
||||
audit: ps -ef | grep etcd | grep -- "--client\-cert\-auth"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--client-cert-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
Edit the etcd pod specification file etcd config 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"
|
||||
audit: ps -ef | grep etcd | grep -v -- "--auto-tls"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--auto-tls"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the etcd pod specification file etcd config 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"
|
||||
audit: ps -ef | grep etcd | grep -- "--peer-cert-file=/var/vcap/jobs/etcd/config/peer.crt" | grep -- "--peer-key-file=/var/vcap/jobs/etcd/config/peer.key"
|
||||
type: manual
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "--peer-cert-file"
|
||||
- flag: "--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 etcd config 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: false
|
||||
|
||||
- id: 2.5
|
||||
text: "Ensure that the --peer-client-cert-auth argument is set to true"
|
||||
audit: ps -ef | grep etcd | grep -- "--peer\-client\-cert\-auth"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--peer-client-cert-auth"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
remediation: |
|
||||
Edit the etcd pod specification file etcd config 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"
|
||||
audit: ps -ef | grep etcd | grep -v -- "--peer-auto-tls"
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--peer-auto-tls"
|
||||
compare:
|
||||
op: eq
|
||||
value: true
|
||||
set: false
|
||||
remediation: |
|
||||
Edit the etcd pod specification file etcd config 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"
|
||||
audit: diff /var/vcap/jobs/kube-apiserver/config/kubernetes-ca.pem /var/vcap/jobs/etcd/config/etcd-ca.crt | grep -c"^>" | grep -v "^0$"
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--trusted-ca-file"
|
||||
remediation: |
|
||||
Follow the etcd documentation and create a dedicated certificate authority setup for the
|
||||
etcd service.
|
||||
Then, edit the etcd pod specification file etcd config on the
|
||||
master node and set the below parameter.
|
||||
--trusted-ca-file=</path/to/ca-file>
|
||||
scored: false
|
||||
1098
cfg/tkgi-1.2.53/master.yaml
Normal file
1098
cfg/tkgi-1.2.53/master.yaml
Normal file
File diff suppressed because it is too large
Load Diff
418
cfg/tkgi-1.2.53/node.yaml
Normal file
418
cfg/tkgi-1.2.53/node.yaml
Normal file
@@ -0,0 +1,418 @@
|
||||
---
|
||||
controls:
|
||||
version: "tkgi-1.2.53"
|
||||
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"
|
||||
audit: stat -c permissions=%a /var/vcap/jobs/kubelet/monit
|
||||
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 /var/vcap/jobs/kubelet/monit
|
||||
scored: true
|
||||
|
||||
- id: 4.1.2
|
||||
text: "Ensure that the kubelet service file ownership is set to root:root"
|
||||
audit: stat -c %U:%G /var/vcap/jobs/kubelet/monit
|
||||
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 /var/vcap/jobs/kubelet/monit
|
||||
Exception
|
||||
File is group owned by vcap
|
||||
scored: true
|
||||
|
||||
- id: 4.1.3
|
||||
text: "Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive"
|
||||
audit: stat -c permissions=%a /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
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 /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
scored: true
|
||||
|
||||
- id: 4.1.4
|
||||
text: "Ensure that the proxy kubeconfig file ownership is set to root:root"
|
||||
audit: stat -c %U:%G /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
type: manual
|
||||
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 /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
Exception
|
||||
File is group owned by vcap
|
||||
scored: false
|
||||
|
||||
- id: 4.1.5
|
||||
text: "Ensure that the kubelet.conf file permissions are set to 644 or more restrictive"
|
||||
audit: stat -c permissions=%a /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
type: manual
|
||||
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 /var/vcap/jobs/kube-proxy/config/kubeconfig
|
||||
Exception
|
||||
kubeadm is not used to provision/bootstrap the cluster. kubeadm and associated config files do not exist on worker
|
||||
scored: false
|
||||
|
||||
- id: 4.1.6
|
||||
text: "Ensure that the kubelet.conf file ownership is set to root:root"
|
||||
audit: stat -c %U:%G /etc/kubernetes/kubelet.conf
|
||||
type: manual
|
||||
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 /etc/kubernetes/kubelet.conf
|
||||
Exception
|
||||
file ownership is vcap:vcap
|
||||
scored: false
|
||||
|
||||
- id: 4.1.7
|
||||
text: "Ensure that the certificate authorities file permissions are set to 644 or more restrictive"
|
||||
audit: stat -c permissions=%a /var/vcap/jobs/kubelet/config/kubelet-client-ca.pem
|
||||
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: true
|
||||
|
||||
- id: 4.1.8
|
||||
text: "Ensure that the client certificate authorities file ownership is set to root:root"
|
||||
audit: stat -c %U:%G /var/vcap/jobs/kubelet/config/kubelet-client-ca.pem
|
||||
type: manual
|
||||
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>
|
||||
Exception
|
||||
File is group owned by vcap
|
||||
scored: false
|
||||
|
||||
- id: 4.1.9
|
||||
text: "Ensure that the kubelet --config configuration file has permissions set to 644 or more restrictive"
|
||||
audit: stat -c permissions=%a /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
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 /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
scored: true
|
||||
|
||||
- id: 4.1.10
|
||||
text: "Ensure that the kubelet --config configuration file ownership is set to root:root"
|
||||
audit: stat -c %U:%G /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: root:root
|
||||
remediation: |
|
||||
Run the following command (using the config file location identified in the Audit step)
|
||||
chown root:root /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
Exception
|
||||
File is group owned by vcap
|
||||
scored: false
|
||||
|
||||
- id: 4.2
|
||||
text: "Kubelet"
|
||||
checks:
|
||||
- id: 4.2.1
|
||||
text: "Ensure that the anonymous-auth argument is set to false"
|
||||
audit: grep "^authentication:\n\s{2}anonymous:\n\s{4}enabled:\sfalse$" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "enabled: 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
|
||||
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"
|
||||
audit: |
|
||||
grep "^authorization:\n\s{2}mode: AlwaysAllow$" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "AlwaysAllow"
|
||||
set: false
|
||||
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
|
||||
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"
|
||||
audit: |
|
||||
grep ^authentication:\n\s{2}anonymous:\n\s{4}enabled:\sfalse\n(\s{2}webhook:\n\s{4}cacheTTL:\s\d+s\n\s{4}enabled:.*\n)?
|
||||
\s{2}x509:\n\s{4}clientCAFile:\s"\/var\/vcap\/jobs\/kubelet\/config\/kubelet-client-ca\.pem" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "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
|
||||
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"
|
||||
audit: |
|
||||
grep "readOnlyPort: 0" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "readOnlyPort: 0"
|
||||
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
|
||||
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: true
|
||||
|
||||
- id: 4.2.5
|
||||
text: "Ensure that the --streaming-connection-idle-timeout argument is not set to 0"
|
||||
audit: |
|
||||
grep -- "streamingConnectionIdleTimeout: 0" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "streamingConnectionIdleTimeout: 0"
|
||||
set: false
|
||||
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
|
||||
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: true
|
||||
|
||||
- id: 4.2.6
|
||||
text: "Ensure that the --protect-kernel-defaults argument is set to true"
|
||||
audit: |
|
||||
grep -- "protectKernelDefaults: true" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "protectKernelDefaults: 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
|
||||
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: true
|
||||
|
||||
- id: 4.2.7
|
||||
text: "Ensure that the --make-iptables-util-chains argument is set to true"
|
||||
audit: |
|
||||
grep -- "makeIPTablesUtilChains: true" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "makeIPTablesUtilChains: true"
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to set makeIPTablesUtilChains: true.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
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 --hostname-override argument is not set"
|
||||
audit: |
|
||||
ps -ef | grep [k]ubelet | grep -- --[c]onfig=/var/vcap/jobs/kubelet/config/kubeletconfig.yml | grep -v -- --hostname-override
|
||||
type: manual
|
||||
remediation: |
|
||||
Edit the kubelet service file
|
||||
on each worker node and remove the --hostname-override 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
|
||||
Exception
|
||||
On GCE, the hostname needs to be set to the instance name so the gce cloud provider can manage the instance.
|
||||
In other cases its set to the IP address of the VM.
|
||||
scored: false
|
||||
|
||||
- id: 4.2.9
|
||||
text: "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture"
|
||||
audit: grep -- "--event-qps" /var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--event-qps"
|
||||
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
|
||||
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.10
|
||||
text: "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate"
|
||||
audit: |
|
||||
grep ^tlsCertFile:\s\"\/var\/vcap\/jobs\/kubelet\/config\/kubelet\.pem\"\ntlsPrivateKeyFile:\s\"\/var\/vcap\/jobs\/kubelet\/config\/kubelet-key\.pem\"$
|
||||
/var/vcap/jobs/kubelet/config/kubeletconfig.yml
|
||||
tests:
|
||||
bin_op: and
|
||||
test_items:
|
||||
- flag: "tlsCertFile"
|
||||
- flag: "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
|
||||
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: true
|
||||
|
||||
- id: 4.2.11
|
||||
text: "Ensure that the --rotate-certificates argument is not set to false"
|
||||
audit: ps -ef | grep kubele[t] | grep -- "--rotate-certificates=false"
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "--rotate-certificates=false"
|
||||
set: false
|
||||
remediation: |
|
||||
If using a Kubelet config file, edit the file to add the line rotateCertificates: true or
|
||||
remove it altogether to use the default value.
|
||||
If using command line arguments, edit the kubelet service file
|
||||
on each worker node and
|
||||
remove --rotate-certificates=false argument from the KUBELET_CERTIFICATE_ARGS
|
||||
variable.
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
Exception
|
||||
Certificate rotation is handled by Credhub
|
||||
scored: false
|
||||
|
||||
- id: 4.2.12
|
||||
text: "Verify that the RotateKubeletServerCertificate argument is set to true"
|
||||
audit: ps -ef | grep kubele[t] | grep -- "--feature-gates=\(\w\+\|,\)*RotateKubeletServerCertificate=true\(\w\+\|,\)*"
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: "RotateKubeletServerCertificate=true"
|
||||
remediation: |
|
||||
Edit the kubelet service file
|
||||
on each worker node and set the below parameter in KUBELET_CERTIFICATE_ARGS variable.
|
||||
--feature-gates=RotateKubeletServerCertificate=true
|
||||
Based on your system, restart the kubelet service. For example:
|
||||
systemctl daemon-reload
|
||||
systemctl restart kubelet.service
|
||||
Exception
|
||||
Certificate rotation is handled by Credhub
|
||||
scored: false
|
||||
|
||||
- id: 4.2.13
|
||||
text: "Ensure that the Kubelet only makes use of Strong Cryptographic Ciphers"
|
||||
audit: ps -ef | grep kubele[t] | grep -- "--tls-cipher-
|
||||
suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
|
||||
type: manual
|
||||
tests:
|
||||
test_items:
|
||||
- flag: --tls-cipher-suites
|
||||
compare:
|
||||
op: regex
|
||||
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
|
||||
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
|
||||
287
cfg/tkgi-1.2.53/policies.yaml
Normal file
287
cfg/tkgi-1.2.53/policies.yaml
Normal file
@@ -0,0 +1,287 @@
|
||||
---
|
||||
controls:
|
||||
version: "tkgi-1.2.53"
|
||||
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"
|
||||
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]
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.2
|
||||
text: "Minimize access to secrets"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove get, list and watch access to secret objects in the cluster.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.3
|
||||
text: "Minimize wildcard use in Roles and ClusterRoles"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible replace any use of wildcards in clusterroles and roles with specific
|
||||
objects or actions.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.4
|
||||
text: "Minimize access to create pods"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Where possible, remove create access to pod objects in the cluster.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.5
|
||||
text: "Ensure that default service accounts are not actively used."
|
||||
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
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.1.6
|
||||
text: "Ensure that Service Account Tokens are only mounted where necessary"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Modify the definition of pods and service accounts which do not need to mount service
|
||||
account tokens to disable it.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2
|
||||
text: "Pod Security Policies"
|
||||
checks:
|
||||
- id: 5.2.1
|
||||
text: "Minimize the admission of privileged containers"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that
|
||||
the .spec.privileged field is omitted or set to false.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.2
|
||||
text: "Minimize the admission of containers wishing to share the host process ID namespace"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostPID field is omitted or set to false.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.3
|
||||
text: "Minimize the admission of containers wishing to share the host IPC namespace"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostIPC field is omitted or set to false.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.4
|
||||
text: "Minimize the admission of containers wishing to share the host network namespace"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.hostNetwork field is omitted or set to false.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.5
|
||||
text: "Minimize the admission of containers with allowPrivilegeEscalation"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Create a PSP as described in the Kubernetes documentation, ensuring that the
|
||||
.spec.allowPrivilegeEscalation field is omitted or set to false.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.6
|
||||
text: "Minimize the admission of root containers"
|
||||
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.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.7
|
||||
text: "Minimize the admission of containers with the NET_RAW capability"
|
||||
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.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.8
|
||||
text: "Minimize the admission of containers with added capabilities"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Ensure that allowedCapabilities is not present in PSPs for the cluster unless
|
||||
it is set to an empty array.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.2.9
|
||||
text: "Minimize the admission of containers with capabilities assigned"
|
||||
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 PSP which forbids the admission of containers which do not drop all capabilities.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
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"
|
||||
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.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.3.2
|
||||
text: "Ensure that all Namespaces have Network Policies defined"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the documentation and create NetworkPolicy objects as you need them.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.4
|
||||
text: "Secrets Management"
|
||||
checks:
|
||||
- id: 5.4.1
|
||||
text: "Prefer using secrets as files over secrets as environment variables"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
if possible, rewrite application code to read secrets from mounted secret files, rather than
|
||||
from environment variables.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.4.2
|
||||
text: "Consider external secret storage"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Refer to the secrets management options offered by your cloud provider or a third-party
|
||||
secrets management solution.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.5
|
||||
text: "Extensible Admission Control"
|
||||
checks:
|
||||
- id: 5.5.1
|
||||
text: "Configure Image Provenance using ImagePolicyWebhook admission controller"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the Kubernetes documentation and setup image provenance.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.7
|
||||
text: "General Policies"
|
||||
checks:
|
||||
- id: 5.7.1
|
||||
text: "Create administrative boundaries between resources using namespaces"
|
||||
type: "manual"
|
||||
remediation: |
|
||||
Follow the documentation and create namespaces for objects in your deployment as you need
|
||||
them.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.7.2
|
||||
text: "Ensure that the seccomp profile is set to docker/default in your pod definitions"
|
||||
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
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.7.3
|
||||
text: "Apply Security Context to Your Pods and Containers "
|
||||
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.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
|
||||
- id: 5.7.4
|
||||
text: "The default namespace should not be used"
|
||||
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.
|
||||
Exception
|
||||
This is site-specific setting.
|
||||
scored: false
|
||||
@@ -208,6 +208,16 @@ func (c *Check) runAuditCommands() (lastCommand string, err error) {
|
||||
}
|
||||
|
||||
c.AuditConfigOutput, err = runAudit(c.AuditConfig)
|
||||
// when file not found then error comes as exit status 127
|
||||
// in some env same error comes as exit status 1
|
||||
if err != nil && (strings.Contains(err.Error(), "exit status 127") ||
|
||||
strings.Contains(err.Error(), "No such file or directory")) &&
|
||||
(c.AuditEnvOutput != "" || c.AuditOutput != "") {
|
||||
// suppress file not found error when there is Audit OR auditEnv output present
|
||||
glog.V(3).Info(err)
|
||||
err = nil
|
||||
c.AuditConfigOutput = ""
|
||||
}
|
||||
return c.AuditConfig, err
|
||||
}
|
||||
|
||||
@@ -227,9 +237,9 @@ func (c *Check) execute() (finalOutput *testOutput, err error) {
|
||||
t.auditUsed = AuditCommand
|
||||
result := *(t.execute(c.AuditOutput))
|
||||
|
||||
// Check for AuditConfigOutput only if AuditConfig is set
|
||||
if !result.flagFound && c.AuditConfig != "" {
|
||||
//t.isConfigSetting = true
|
||||
// Check for AuditConfigOutput only if AuditConfig is set and auditConfigOutput is not empty
|
||||
if !result.flagFound && c.AuditConfig != "" && c.AuditConfigOutput != "" {
|
||||
// t.isConfigSetting = true
|
||||
t.auditUsed = AuditConfig
|
||||
result = *(t.execute(c.AuditConfigOutput))
|
||||
if !result.flagFound && t.Env != "" {
|
||||
|
||||
@@ -69,6 +69,31 @@ func TestCheck_Run(t *testing.T) {
|
||||
},
|
||||
Expected: PASS,
|
||||
},
|
||||
{
|
||||
name: "Scored checks that pass should PASS when config file is not present",
|
||||
check: Check{
|
||||
Scored: true,
|
||||
Audit: "echo hello",
|
||||
AuditConfig: "/test/config.yaml",
|
||||
Tests: &tests{TestItems: []*testItem{{
|
||||
Flag: "hello",
|
||||
Set: true,
|
||||
}}},
|
||||
},
|
||||
Expected: PASS,
|
||||
},
|
||||
{
|
||||
name: "Scored checks that pass should FAIL when config file is not present",
|
||||
check: Check{
|
||||
Scored: true,
|
||||
AuditConfig: "/test/config.yaml",
|
||||
Tests: &tests{TestItems: []*testItem{{
|
||||
Flag: "hello",
|
||||
Set: true,
|
||||
}}},
|
||||
},
|
||||
Expected: FAIL,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
@@ -115,7 +140,6 @@ func TestCheckAuditEnv(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCheckAuditConfig(t *testing.T) {
|
||||
|
||||
passingCases := []*Check{
|
||||
controls.Groups[1].Checks[0],
|
||||
controls.Groups[1].Checks[3],
|
||||
|
||||
@@ -21,8 +21,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/securityhub"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/securityhub/types"
|
||||
"github.com/golang/glog"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/spf13/viper"
|
||||
@@ -206,13 +206,13 @@ func (controls *Controls) JUnit() ([]byte, error) {
|
||||
}
|
||||
|
||||
// ASFF encodes the results of last run to AWS Security Finding Format(ASFF).
|
||||
func (controls *Controls) ASFF() ([]*securityhub.AwsSecurityFinding, error) {
|
||||
fs := []*securityhub.AwsSecurityFinding{}
|
||||
a, err := getConfig("AWS_ACCOUNT")
|
||||
func (controls *Controls) ASFF() ([]types.AwsSecurityFinding, error) {
|
||||
fs := []types.AwsSecurityFinding{}
|
||||
account, err := getConfig("AWS_ACCOUNT")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := getConfig("CLUSTER_ARN")
|
||||
cluster, err := getConfig("CLUSTER_ARN")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -220,6 +220,7 @@ func (controls *Controls) ASFF() ([]*securityhub.AwsSecurityFinding, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodeName, _ := getConfig("NODE_NAME")
|
||||
arn := fmt.Sprintf(ARN, region)
|
||||
|
||||
ti := time.Now()
|
||||
@@ -244,47 +245,52 @@ func (controls *Controls) ASFF() ([]*securityhub.AwsSecurityFinding, error) {
|
||||
if len(check.Reason) > 1024 {
|
||||
reason = check.Reason[0:1023]
|
||||
}
|
||||
id := aws.String(fmt.Sprintf("%s%sEKSnodeID+%s+%s", arn, account, check.ID, cluster))
|
||||
if nodeName != "" {
|
||||
id = aws.String(fmt.Sprintf("%s%sEKSnodeID+%s+%s+%s", arn, account, check.ID, cluster, nodeName))
|
||||
}
|
||||
|
||||
f := securityhub.AwsSecurityFinding{
|
||||
AwsAccountId: aws.String(a),
|
||||
Confidence: aws.Int64(100),
|
||||
f := types.AwsSecurityFinding{
|
||||
AwsAccountId: aws.String(account),
|
||||
Confidence: *aws.Int32(100),
|
||||
GeneratorId: aws.String(fmt.Sprintf("%s/cis-kubernetes-benchmark/%s/%s", arn, controls.Version, check.ID)),
|
||||
Id: aws.String(fmt.Sprintf("%s%sEKSnodeID+%s%s", arn, a, check.ID, tf)),
|
||||
Id: id,
|
||||
CreatedAt: aws.String(tf),
|
||||
Description: aws.String(check.Text),
|
||||
ProductArn: aws.String(arn),
|
||||
SchemaVersion: aws.String(SCHEMA),
|
||||
Title: aws.String(fmt.Sprintf("%s %s", check.ID, check.Text)),
|
||||
UpdatedAt: aws.String(tf),
|
||||
Types: []*string{aws.String(TYPE)},
|
||||
Severity: &securityhub.Severity{
|
||||
Label: aws.String(securityhub.SeverityLabelHigh),
|
||||
Types: []string{*aws.String(TYPE)},
|
||||
Severity: &types.Severity{
|
||||
Label: types.SeverityLabelHigh,
|
||||
},
|
||||
Remediation: &securityhub.Remediation{
|
||||
Recommendation: &securityhub.Recommendation{
|
||||
Remediation: &types.Remediation{
|
||||
Recommendation: &types.Recommendation{
|
||||
Text: aws.String(remediation),
|
||||
},
|
||||
},
|
||||
ProductFields: map[string]*string{
|
||||
"Reason": aws.String(reason),
|
||||
"Actual result": aws.String(actualValue),
|
||||
"Expected result": aws.String(check.ExpectedResult),
|
||||
"Section": aws.String(fmt.Sprintf("%s %s", controls.ID, controls.Text)),
|
||||
"Subsection": aws.String(fmt.Sprintf("%s %s", g.ID, g.Text)),
|
||||
ProductFields: map[string]string{
|
||||
"Reason": reason,
|
||||
"Actual result": actualValue,
|
||||
"Expected result": check.ExpectedResult,
|
||||
"Section": fmt.Sprintf("%s %s", controls.ID, controls.Text),
|
||||
"Subsection": fmt.Sprintf("%s %s", g.ID, g.Text),
|
||||
},
|
||||
Resources: []*securityhub.Resource{
|
||||
Resources: []types.Resource{
|
||||
{
|
||||
Id: aws.String(c),
|
||||
Id: aws.String(cluster),
|
||||
Type: aws.String(TYPE),
|
||||
},
|
||||
},
|
||||
}
|
||||
fs = append(fs, &f)
|
||||
fs = append(fs, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func getConfig(name string) (string, error) {
|
||||
r := viper.GetString(name)
|
||||
if len(r) == 0 {
|
||||
@@ -292,6 +298,7 @@ func getConfig(name string) (string, error) {
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func summarize(controls *Controls, state State) {
|
||||
switch state {
|
||||
case PASS:
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/securityhub"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/securityhub/types"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -374,7 +374,7 @@ func TestControls_ASFF(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want []*securityhub.AwsSecurityFinding
|
||||
want []types.AwsSecurityFinding
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -405,32 +405,32 @@ func TestControls_ASFF(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: []*securityhub.AwsSecurityFinding{
|
||||
want: []types.AwsSecurityFinding{
|
||||
{
|
||||
AwsAccountId: aws.String("foo account"),
|
||||
Confidence: aws.Int64(100),
|
||||
Confidence: *aws.Int32(100),
|
||||
GeneratorId: aws.String(fmt.Sprintf("%s/cis-kubernetes-benchmark/%s/%s", fmt.Sprintf(ARN, "somewhere"), "1", "check1id")),
|
||||
Description: aws.String("check1text"),
|
||||
ProductArn: aws.String(fmt.Sprintf(ARN, "somewhere")),
|
||||
SchemaVersion: aws.String(SCHEMA),
|
||||
Title: aws.String(fmt.Sprintf("%s %s", "check1id", "check1text")),
|
||||
Types: []*string{aws.String(TYPE)},
|
||||
Severity: &securityhub.Severity{
|
||||
Label: aws.String(securityhub.SeverityLabelHigh),
|
||||
Types: []string{*aws.String(TYPE)},
|
||||
Severity: &types.Severity{
|
||||
Label: types.SeverityLabelHigh,
|
||||
},
|
||||
Remediation: &securityhub.Remediation{
|
||||
Recommendation: &securityhub.Recommendation{
|
||||
Remediation: &types.Remediation{
|
||||
Recommendation: &types.Recommendation{
|
||||
Text: aws.String("fix me"),
|
||||
},
|
||||
},
|
||||
ProductFields: map[string]*string{
|
||||
"Reason": aws.String("failed"),
|
||||
"Actual result": aws.String("failed"),
|
||||
"Expected result": aws.String("failed"),
|
||||
"Section": aws.String(fmt.Sprintf("%s %s", "test1", "test runnner")),
|
||||
"Subsection": aws.String(fmt.Sprintf("%s %s", "g1", "Group text")),
|
||||
ProductFields: map[string]string{
|
||||
"Reason": "failed",
|
||||
"Actual result": "failed",
|
||||
"Expected result": "failed",
|
||||
"Section": fmt.Sprintf("%s %s", "test1", "test runnner"),
|
||||
"Subsection": fmt.Sprintf("%s %s", "g1", "Group text"),
|
||||
},
|
||||
Resources: []*securityhub.Resource{
|
||||
Resources: []types.Resource{
|
||||
{
|
||||
Id: aws.String("foo Cluster"),
|
||||
Type: aws.String(TYPE),
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
"k8s.io/client-go/util/jsonpath"
|
||||
)
|
||||
|
||||
@@ -68,9 +68,11 @@ type testItem struct {
|
||||
auditUsed AuditUsed
|
||||
}
|
||||
|
||||
type envTestItem testItem
|
||||
type pathTestItem testItem
|
||||
type flagTestItem testItem
|
||||
type (
|
||||
envTestItem testItem
|
||||
pathTestItem testItem
|
||||
flagTestItem testItem
|
||||
)
|
||||
|
||||
type compare struct {
|
||||
Op string
|
||||
@@ -236,16 +238,16 @@ func (t testItem) evaluate(s string) *testOutput {
|
||||
}
|
||||
|
||||
result.flagFound = match
|
||||
var isExist = "exists"
|
||||
isExist := "exists"
|
||||
if !result.flagFound {
|
||||
isExist = "does not exist"
|
||||
}
|
||||
switch t.auditUsed {
|
||||
case "auditCommand":
|
||||
case AuditCommand:
|
||||
glog.V(3).Infof("Flag '%s' %s", t.Flag, isExist)
|
||||
case "auditConfig":
|
||||
case AuditConfig:
|
||||
glog.V(3).Infof("Path '%s' %s", t.Path, isExist)
|
||||
case "auditEnv":
|
||||
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)
|
||||
@@ -255,7 +257,6 @@ func (t testItem) evaluate(s string) *testOutput {
|
||||
}
|
||||
|
||||
func compareOp(tCompareOp string, flagVal string, tCompareValue string, flagName string) (string, bool) {
|
||||
|
||||
expectedResultPattern := ""
|
||||
testResult := false
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ func init() {
|
||||
}
|
||||
|
||||
func TestTestExecute(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
check *Check
|
||||
str string
|
||||
@@ -305,7 +304,6 @@ func TestTestExecute(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTestExecuteExceptions(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
*Check
|
||||
str string
|
||||
@@ -366,7 +364,8 @@ func TestTestUnmarshal(t *testing.T) {
|
||||
`,
|
||||
kubeletConfig{},
|
||||
false,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
`
|
||||
kind: KubeletConfiguration
|
||||
address: 0.0.0.0
|
||||
@@ -490,34 +489,42 @@ func TestAllElementsValid(t *testing.T) {
|
||||
},
|
||||
{
|
||||
source: []string{},
|
||||
target: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
target: []string{
|
||||
"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"},
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
},
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
source: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
|
||||
target: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
target: []string{
|
||||
"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"},
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
},
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
source: []string{"blah"},
|
||||
target: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
target: []string{
|
||||
"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"},
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
},
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
source: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "blah"},
|
||||
target: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
target: []string{
|
||||
"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"},
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
},
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
@@ -594,494 +601,628 @@ func TestCompareOp(t *testing.T) {
|
||||
// Test Op "eq"
|
||||
{label: "op=eq, both empty", op: "eq", flagVal: "", compareValue: "", expectedResultPattern: "'' is equal to ''", testResult: true, flagName: ""},
|
||||
|
||||
{label: "op=eq, true==true", op: "eq", flagVal: "true",
|
||||
{
|
||||
label: "op=eq, true==true", op: "eq", flagVal: "true",
|
||||
compareValue: "true",
|
||||
expectedResultPattern: "'parameterTrue' is equal to 'true'",
|
||||
testResult: true,
|
||||
flagName: "parameterTrue"},
|
||||
flagName: "parameterTrue",
|
||||
},
|
||||
|
||||
{label: "op=eq, false==false", op: "eq", flagVal: "false",
|
||||
{
|
||||
label: "op=eq, false==false", op: "eq", flagVal: "false",
|
||||
compareValue: "false",
|
||||
expectedResultPattern: "'parameterFalse' is equal to 'false'",
|
||||
testResult: true,
|
||||
flagName: "parameterFalse"},
|
||||
flagName: "parameterFalse",
|
||||
},
|
||||
|
||||
{label: "op=eq, false==true", op: "eq", flagVal: "false",
|
||||
{
|
||||
label: "op=eq, false==true", op: "eq", flagVal: "false",
|
||||
compareValue: "true",
|
||||
expectedResultPattern: "'parameterFalse' is equal to 'true'",
|
||||
testResult: false,
|
||||
flagName: "parameterFalse"},
|
||||
flagName: "parameterFalse",
|
||||
},
|
||||
|
||||
{label: "op=eq, strings match", op: "eq", flagVal: "KubeletConfiguration",
|
||||
{
|
||||
label: "op=eq, strings match", op: "eq", flagVal: "KubeletConfiguration",
|
||||
compareValue: "KubeletConfiguration",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is equal to 'KubeletConfiguration'",
|
||||
testResult: true,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
{label: "op=eq, flagVal=empty", op: "eq", flagVal: "",
|
||||
{
|
||||
label: "op=eq, flagVal=empty", op: "eq", flagVal: "",
|
||||
compareValue: "KubeletConfiguration",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is equal to 'KubeletConfiguration'",
|
||||
testResult: false,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
{label: "op=eq, compareValue=empty",
|
||||
{
|
||||
label: "op=eq, compareValue=empty",
|
||||
op: "eq",
|
||||
flagVal: "KubeletConfiguration",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is equal to ''",
|
||||
testResult: false,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
// Test Op "noteq"
|
||||
{label: "op=noteq, both empty",
|
||||
{
|
||||
label: "op=noteq, both empty",
|
||||
op: "noteq",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'parameter' is not equal to ''",
|
||||
testResult: false,
|
||||
flagName: "parameter"},
|
||||
flagName: "parameter",
|
||||
},
|
||||
|
||||
{label: "op=noteq, true!=true",
|
||||
{
|
||||
label: "op=noteq, true!=true",
|
||||
op: "noteq",
|
||||
flagVal: "true",
|
||||
compareValue: "true",
|
||||
expectedResultPattern: "'parameterTrue' is not equal to 'true'",
|
||||
testResult: false,
|
||||
flagName: "parameterTrue"},
|
||||
flagName: "parameterTrue",
|
||||
},
|
||||
|
||||
{label: "op=noteq, false!=false",
|
||||
{
|
||||
label: "op=noteq, false!=false",
|
||||
op: "noteq",
|
||||
flagVal: "false",
|
||||
compareValue: "false",
|
||||
expectedResultPattern: "'parameterFalse' is not equal to 'false'",
|
||||
testResult: false,
|
||||
flagName: "parameterFalse"},
|
||||
flagName: "parameterFalse",
|
||||
},
|
||||
|
||||
{label: "op=noteq, false!=true",
|
||||
{
|
||||
label: "op=noteq, false!=true",
|
||||
op: "noteq",
|
||||
flagVal: "false",
|
||||
compareValue: "true",
|
||||
expectedResultPattern: "'parameterFalse' is not equal to 'true'",
|
||||
testResult: true,
|
||||
flagName: "parameterFalse"},
|
||||
flagName: "parameterFalse",
|
||||
},
|
||||
|
||||
{label: "op=noteq, strings match",
|
||||
{
|
||||
label: "op=noteq, strings match",
|
||||
op: "noteq",
|
||||
flagVal: "KubeletConfiguration",
|
||||
compareValue: "KubeletConfiguration",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is not equal to 'KubeletConfiguration'",
|
||||
testResult: false,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
{label: "op=noteq, flagVal=empty",
|
||||
{
|
||||
label: "op=noteq, flagVal=empty",
|
||||
op: "noteq",
|
||||
flagVal: "",
|
||||
compareValue: "KubeletConfiguration",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is not equal to 'KubeletConfiguration'",
|
||||
testResult: true,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
{label: "op=noteq, compareValue=empty",
|
||||
{
|
||||
label: "op=noteq, compareValue=empty",
|
||||
op: "noteq",
|
||||
flagVal: "KubeletConfiguration",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'--FlagNameKubeletConf' is not equal to ''",
|
||||
testResult: true,
|
||||
flagName: "--FlagNameKubeletConf"},
|
||||
flagName: "--FlagNameKubeletConf",
|
||||
},
|
||||
|
||||
// Test Op "gt"
|
||||
{label: "op=gt, both empty",
|
||||
{
|
||||
label: "op=gt, both empty",
|
||||
op: "gt",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, 0 > 0",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, 0 > 0",
|
||||
op: "gt",
|
||||
flagVal: "0",
|
||||
compareValue: "0", expectedResultPattern: "'flagName' is greater than 0",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, 4 > 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, 4 > 5",
|
||||
op: "gt",
|
||||
flagVal: "4",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is greater than 5",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, 5 > 4",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, 5 > 4",
|
||||
op: "gt",
|
||||
flagVal: "5",
|
||||
compareValue: "4",
|
||||
expectedResultPattern: "'flagName' is greater than 4",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, 5 > 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, 5 > 5",
|
||||
op: "gt",
|
||||
flagVal: "5",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is greater than 5",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, Pikachu > 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, Pikachu > 5",
|
||||
op: "gt",
|
||||
flagVal: "Pikachu",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: 'Pikachu' '5'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gt, 5 > Bulbasaur",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gt, 5 > Bulbasaur",
|
||||
op: "gt",
|
||||
flagVal: "5",
|
||||
compareValue: "Bulbasaur",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Bulbasaur'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
flagName: "flagName",
|
||||
},
|
||||
// Test Op "lt"
|
||||
{label: "op=lt, both empty",
|
||||
{
|
||||
label: "op=lt, both empty",
|
||||
op: "lt",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, 0 < 0",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, 0 < 0",
|
||||
op: "lt",
|
||||
flagVal: "0",
|
||||
compareValue: "0",
|
||||
expectedResultPattern: "'flagName' is lower than 0",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, 4 < 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, 4 < 5",
|
||||
op: "lt",
|
||||
flagVal: "4",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is lower than 5",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, 5 < 4",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, 5 < 4",
|
||||
op: "lt",
|
||||
flagVal: "5",
|
||||
compareValue: "4",
|
||||
expectedResultPattern: "'flagName' is lower than 4",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, 5 < 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, 5 < 5",
|
||||
op: "lt",
|
||||
flagVal: "5",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is lower than 5",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, Charmander < 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, Charmander < 5",
|
||||
op: "lt",
|
||||
flagVal: "Charmander",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: 'Charmander' '5'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lt, 5 < Charmeleon",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lt, 5 < Charmeleon",
|
||||
op: "lt",
|
||||
flagVal: "5",
|
||||
compareValue: "Charmeleon",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Charmeleon'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
flagName: "flagName",
|
||||
},
|
||||
// Test Op "gte"
|
||||
{label: "op=gte, both empty",
|
||||
{
|
||||
label: "op=gte, both empty",
|
||||
op: "gte",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, 0 >= 0",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, 0 >= 0",
|
||||
op: "gte",
|
||||
flagVal: "0",
|
||||
compareValue: "0",
|
||||
expectedResultPattern: "'flagName' is greater or equal to 0",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, 4 >= 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, 4 >= 5",
|
||||
op: "gte",
|
||||
flagVal: "4",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is greater or equal to 5",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, 5 >= 4",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, 5 >= 4",
|
||||
op: "gte",
|
||||
flagVal: "5",
|
||||
compareValue: "4",
|
||||
expectedResultPattern: "'flagName' is greater or equal to 4",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, 5 >= 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, 5 >= 5",
|
||||
op: "gte",
|
||||
flagVal: "5",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is greater or equal to 5",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, Ekans >= 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, Ekans >= 5",
|
||||
op: "gte",
|
||||
flagVal: "Ekans",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: 'Ekans' '5'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=gte, 4 >= Zubat",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=gte, 4 >= Zubat",
|
||||
op: "gte",
|
||||
flagVal: "4",
|
||||
compareValue: "Zubat",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '4' 'Zubat'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
flagName: "flagName",
|
||||
},
|
||||
// Test Op "lte"
|
||||
{label: "op=lte, both empty",
|
||||
{
|
||||
label: "op=lte, both empty",
|
||||
op: "lte",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '' ''",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, 0 <= 0",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, 0 <= 0",
|
||||
op: "lte",
|
||||
flagVal: "0",
|
||||
compareValue: "0",
|
||||
expectedResultPattern: "'flagName' is lower or equal to 0",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, 4 <= 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, 4 <= 5",
|
||||
op: "lte",
|
||||
flagVal: "4",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is lower or equal to 5",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, 5 <= 4",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, 5 <= 4",
|
||||
op: "lte",
|
||||
flagVal: "5",
|
||||
compareValue: "4",
|
||||
expectedResultPattern: "'flagName' is lower or equal to 4",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, 5 <= 5",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, 5 <= 5",
|
||||
op: "lte",
|
||||
flagVal: "5",
|
||||
compareValue: "5",
|
||||
expectedResultPattern: "'flagName' is lower or equal to 5",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, Venomoth <= 4",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, Venomoth <= 4",
|
||||
op: "lte",
|
||||
flagVal: "Venomoth",
|
||||
compareValue: "4",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: 'Venomoth' '4'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=lte, 5 <= Meowth",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=lte, 5 <= Meowth",
|
||||
op: "lte",
|
||||
flagVal: "5",
|
||||
compareValue: "Meowth",
|
||||
expectedResultPattern: "Invalid Number(s) used for comparison: '5' 'Meowth'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
flagName: "flagName",
|
||||
},
|
||||
|
||||
// Test Op "has"
|
||||
{label: "op=has, both empty",
|
||||
{
|
||||
label: "op=has, both empty",
|
||||
op: "has",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagName' has ''",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=has, flagVal=empty",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=has, flagVal=empty",
|
||||
op: "has",
|
||||
flagVal: "",
|
||||
compareValue: "blah",
|
||||
expectedResultPattern: "'flagName' has 'blah'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=has, compareValue=empty",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=has, compareValue=empty",
|
||||
op: "has",
|
||||
flagVal: "blah",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagName-blah' has ''",
|
||||
testResult: true,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=has, 'blah' has 'la'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=has, 'blah' has 'la'",
|
||||
op: "has",
|
||||
flagVal: "blah",
|
||||
compareValue: "la",
|
||||
expectedResultPattern: "'flagName-blah' has 'la'",
|
||||
testResult: true,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=has, 'blah' has 'LA'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=has, 'blah' has 'LA'",
|
||||
op: "has",
|
||||
flagVal: "blah",
|
||||
compareValue: "LA",
|
||||
expectedResultPattern: "'flagName-blah' has 'LA'",
|
||||
testResult: false,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=has, 'blah' has 'lo'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=has, 'blah' has 'lo'",
|
||||
op: "has",
|
||||
flagVal: "blah",
|
||||
compareValue: "lo",
|
||||
expectedResultPattern: "'flagName-blah' has 'lo'",
|
||||
testResult: false,
|
||||
flagName: "flagName-blah"},
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
|
||||
// Test Op "nothave"
|
||||
{label: "op=nothave, both empty",
|
||||
{
|
||||
label: "op=nothave, both empty",
|
||||
op: "nothave",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagName' does not have ''",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
{label: "op=nothave, flagVal=empty",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=nothave, flagVal=empty",
|
||||
op: "nothave",
|
||||
flagVal: "",
|
||||
compareValue: "blah",
|
||||
expectedResultPattern: "'flagName' does not have 'blah'",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=nothave, compareValue=empty",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=nothave, compareValue=empty",
|
||||
op: "nothave",
|
||||
flagVal: "blah",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagName-blah' does not have ''",
|
||||
testResult: false,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=nothave, 'blah' not have 'la'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=nothave, 'blah' not have 'la'",
|
||||
op: "nothave",
|
||||
flagVal: "blah",
|
||||
compareValue: "la",
|
||||
expectedResultPattern: "'flagName-blah' does not have 'la'",
|
||||
testResult: false,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=nothave, 'blah' not have 'LA'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=nothave, 'blah' not have 'LA'",
|
||||
op: "nothave",
|
||||
flagVal: "blah",
|
||||
compareValue: "LA",
|
||||
expectedResultPattern: "'flagName-blah' does not have 'LA'",
|
||||
testResult: true,
|
||||
flagName: "flagName-blah"},
|
||||
{label: "op=nothave, 'blah' not have 'lo'",
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
{
|
||||
label: "op=nothave, 'blah' not have 'lo'",
|
||||
op: "nothave",
|
||||
flagVal: "blah",
|
||||
compareValue: "lo",
|
||||
expectedResultPattern: "'flagName-blah' does not have 'lo'",
|
||||
testResult: true,
|
||||
flagName: "flagName-blah"},
|
||||
flagName: "flagName-blah",
|
||||
},
|
||||
|
||||
// Test Op "regex"
|
||||
{label: "op=regex, both empty",
|
||||
{
|
||||
label: "op=regex, both empty",
|
||||
op: "regex",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagName' matched by regex expression ''",
|
||||
testResult: true,
|
||||
flagName: "flagName"},
|
||||
{label: "op=regex, flagVal=empty",
|
||||
flagName: "flagName",
|
||||
},
|
||||
{
|
||||
label: "op=regex, flagVal=empty",
|
||||
op: "regex",
|
||||
flagVal: "",
|
||||
compareValue: "blah",
|
||||
expectedResultPattern: "'flagName' matched by regex expression 'blah'",
|
||||
testResult: false,
|
||||
flagName: "flagName"},
|
||||
flagName: "flagName",
|
||||
},
|
||||
|
||||
// Test Op "valid_elements"
|
||||
{label: "op=valid_elements, valid_elements both empty",
|
||||
{
|
||||
label: "op=valid_elements, valid_elements both empty",
|
||||
op: "valid_elements",
|
||||
flagVal: "",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from ''",
|
||||
testResult: true,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
|
||||
{label: "op=valid_elements, valid_elements flagVal empty",
|
||||
{
|
||||
label: "op=valid_elements, valid_elements flagVal empty",
|
||||
op: "valid_elements",
|
||||
flagVal: "",
|
||||
compareValue: "a,b",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b'",
|
||||
testResult: false,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
|
||||
{label: "op=valid_elements, valid_elements compareValue empty",
|
||||
{
|
||||
label: "op=valid_elements, valid_elements compareValue empty",
|
||||
op: "valid_elements",
|
||||
flagVal: "a,b",
|
||||
compareValue: "",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from ''",
|
||||
testResult: false,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
{label: "op=valid_elements, valid_elements two list equals",
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
{
|
||||
label: "op=valid_elements, valid_elements two list equals",
|
||||
op: "valid_elements",
|
||||
flagVal: "a,b,c",
|
||||
compareValue: "a,b,c",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b,c'",
|
||||
testResult: true,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
{label: "op=valid_elements, valid_elements partial flagVal valid",
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
{
|
||||
label: "op=valid_elements, valid_elements partial flagVal valid",
|
||||
op: "valid_elements",
|
||||
flagVal: "a,c",
|
||||
compareValue: "a,b,c",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,b,c'",
|
||||
testResult: true,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
{label: "op=valid_elements, valid_elements partial compareValue valid",
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
{
|
||||
label: "op=valid_elements, valid_elements partial compareValue valid",
|
||||
op: "valid_elements",
|
||||
flagVal: "a,b,c",
|
||||
compareValue: "a,c",
|
||||
expectedResultPattern: "'flagWithMultipleElements' contains valid elements from 'a,c'",
|
||||
testResult: false,
|
||||
flagName: "flagWithMultipleElements"},
|
||||
flagName: "flagWithMultipleElements",
|
||||
},
|
||||
|
||||
// Test Op "bitmask"
|
||||
{label: "op=bitmask, 644 AND 640",
|
||||
{
|
||||
label: "op=bitmask, 644 AND 640",
|
||||
op: "bitmask",
|
||||
flagVal: "640",
|
||||
compareValue: "644",
|
||||
expectedResultPattern: "etc/fileExamplePermission640 has permissions 640, expected 644 or more restrictive",
|
||||
testResult: true,
|
||||
flagName: "etc/fileExamplePermission640"},
|
||||
{label: "op=bitmask, 644 AND 777",
|
||||
flagName: "etc/fileExamplePermission640",
|
||||
},
|
||||
{
|
||||
label: "op=bitmask, 644 AND 777",
|
||||
op: "bitmask",
|
||||
flagVal: "777",
|
||||
compareValue: "644",
|
||||
expectedResultPattern: "etc/fileExamplePermission777 has permissions 777, expected 644 or more restrictive",
|
||||
testResult: false,
|
||||
flagName: "etc/fileExamplePermission777"},
|
||||
{label: "op=bitmask, 644 AND 444",
|
||||
flagName: "etc/fileExamplePermission777",
|
||||
},
|
||||
{
|
||||
label: "op=bitmask, 644 AND 444",
|
||||
op: "bitmask",
|
||||
flagVal: "444",
|
||||
compareValue: "644",
|
||||
expectedResultPattern: "etc/fileExamplePermission444 has permissions 444, expected 644 or more restrictive",
|
||||
testResult: true,
|
||||
flagName: "etc/fileExamplePermission444"},
|
||||
{label: "op=bitmask, 644 AND 211",
|
||||
flagName: "etc/fileExamplePermission444",
|
||||
},
|
||||
{
|
||||
label: "op=bitmask, 644 AND 211",
|
||||
op: "bitmask",
|
||||
flagVal: "211",
|
||||
compareValue: "644",
|
||||
expectedResultPattern: "etc/fileExamplePermission211 has permissions 211, expected 644 or more restrictive",
|
||||
testResult: false,
|
||||
flagName: "etc/fileExamplePermission211"},
|
||||
{label: "op=bitmask, Harry AND 211",
|
||||
flagName: "etc/fileExamplePermission211",
|
||||
},
|
||||
{
|
||||
label: "op=bitmask, Harry AND 211",
|
||||
op: "bitmask",
|
||||
flagVal: "Harry",
|
||||
compareValue: "644",
|
||||
expectedResultPattern: "Not numeric value - flag: Harry",
|
||||
testResult: false,
|
||||
flagName: "etc/fileExample"},
|
||||
{label: "op=bitmask, 644 AND Potter",
|
||||
flagName: "etc/fileExample",
|
||||
},
|
||||
{
|
||||
label: "op=bitmask, 644 AND Potter",
|
||||
op: "bitmask",
|
||||
flagVal: "211",
|
||||
compareValue: "Potter",
|
||||
expectedResultPattern: "Not numeric value - flag: Potter",
|
||||
testResult: false,
|
||||
flagName: "etc/fileExample"},
|
||||
flagName: "etc/fileExample",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -1136,37 +1277,36 @@ func TestToNumeric(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
|
||||
type Resources struct {
|
||||
Resources []string `json:"resources"`
|
||||
Providers []map[string]interface{} `json:"providers"`
|
||||
Resources []string `json:"resources"`
|
||||
Providers []map[string]interface{} `json:"providers"`
|
||||
}
|
||||
|
||||
type EncryptionConfig struct {
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Resources []Resources `json:"resources"`
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Resources []Resources `json:"resources"`
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
Secret string `json:"secret"`
|
||||
Name string `json:"name"`
|
||||
Secret string `json:"secret"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Aescbc struct {
|
||||
Keys []Key `json:"keys"`
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
type SecretBox struct {
|
||||
Keys []Key `json:"keys"`
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
type Aesgcm struct {
|
||||
Keys []Key `json:"keys"`
|
||||
type Aesgcm struct {
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
// identity disable encryption when set as the first parameter
|
||||
type Identity struct {}
|
||||
type Identity struct{}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
@@ -1179,11 +1319,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results match",
|
||||
"{.resources[*].providers[*].aescbc.keys[*].secret}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"aescbc": Aescbc{Keys: []Key{Key{Secret: "secret1", Name: "name1"}}}},
|
||||
}}}},
|
||||
{"aescbc": Aescbc{Keys: []Key{{Secret: "secret1", Name: "name1"}}}},
|
||||
}}},
|
||||
},
|
||||
"secret1",
|
||||
false,
|
||||
},
|
||||
@@ -1191,11 +1332,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results match",
|
||||
"{.resources[*].providers[*].aescbc.keys[*].name}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"aescbc": Aescbc{Keys: []Key{Key{Secret: "secret1", Name: "name1"}}}},
|
||||
}}}},
|
||||
{"aescbc": Aescbc{Keys: []Key{{Secret: "secret1", Name: "name1"}}}},
|
||||
}}},
|
||||
},
|
||||
"name1",
|
||||
false,
|
||||
},
|
||||
@@ -1203,11 +1345,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results don't match",
|
||||
"{.resources[*].providers[*].aescbc.keys[*].secret}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"aesgcm": Aesgcm{Keys: []Key{Key{Secret: "secret1", Name: "name1"}}}},
|
||||
}}}},
|
||||
{"aesgcm": Aesgcm{Keys: []Key{{Secret: "secret1", Name: "name1"}}}},
|
||||
}}},
|
||||
},
|
||||
"secret1",
|
||||
true,
|
||||
},
|
||||
@@ -1215,11 +1358,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results match",
|
||||
"{.resources[*].providers[*].aesgcm.keys[*].secret}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"aesgcm": Aesgcm{Keys: []Key{Key{Secret: "secret1", Name: "name1"}}}},
|
||||
}}}},
|
||||
{"aesgcm": Aesgcm{Keys: []Key{{Secret: "secret1", Name: "name1"}}}},
|
||||
}}},
|
||||
},
|
||||
"secret1",
|
||||
false,
|
||||
},
|
||||
@@ -1227,11 +1371,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results match",
|
||||
"{.resources[*].providers[*].secretbox.keys[*].secret}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"secretbox": SecretBox{Keys: []Key{Key{Secret: "secret1", Name: "name1"}}}},
|
||||
}}}},
|
||||
{"secretbox": SecretBox{Keys: []Key{{Secret: "secret1", Name: "name1"}}}},
|
||||
}}},
|
||||
},
|
||||
"secret1",
|
||||
false,
|
||||
},
|
||||
@@ -1239,11 +1384,12 @@ func TestExecuteJSONPathOnEncryptionConfig(t *testing.T) {
|
||||
"JSONPath parse works, results match",
|
||||
"{.resources[*].providers[*].aescbc.keys[*].secret}",
|
||||
EncryptionConfig{
|
||||
Kind: "EncryptionConfig",
|
||||
Kind: "EncryptionConfig",
|
||||
ApiVersion: "v1",
|
||||
Resources: []Resources{{Resources: []string{"secrets"}, Providers: []map[string]interface{}{
|
||||
{"aescbc": Aescbc{Keys: []Key{Key{Secret: "secret1", Name: "name1"}, Key{Secret: "secret2", Name: "name2"}}}},
|
||||
}}}},
|
||||
{"aescbc": Aescbc{Keys: []Key{{Secret: "secret1", Name: "name1"}, {Secret: "secret2", Name: "name2"}}}},
|
||||
}}},
|
||||
},
|
||||
"secret1 secret2",
|
||||
false,
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ func NewRunFilter(opts FilterOpts) (check.Predicate, error) {
|
||||
}
|
||||
|
||||
return func(g *check.Group, c *check.Check) bool {
|
||||
var test = true
|
||||
test := true
|
||||
if len(groupIDs) > 0 {
|
||||
_, ok := groupIDs[g.ID]
|
||||
test = test && ok
|
||||
@@ -87,7 +87,6 @@ func runChecks(nodetype check.NodeType, testYamlFile, detectedVersion string) {
|
||||
|
||||
// Get the set of executables we need for this section of the tests
|
||||
binmap, err := getBinaries(typeConf, nodetype)
|
||||
|
||||
// Checks that the executables we need for the section are running.
|
||||
if err != nil {
|
||||
glog.V(1).Info(fmt.Sprintf("failed to get a set of executables needed for tests: %v", err))
|
||||
@@ -97,6 +96,7 @@ func runChecks(nodetype check.NodeType, testYamlFile, detectedVersion string) {
|
||||
svcmap := getFiles(typeConf, "service")
|
||||
kubeconfmap := getFiles(typeConf, "kubeconfig")
|
||||
cafilemap := getFiles(typeConf, "ca")
|
||||
datadirmap := getFiles(typeConf, "datadir")
|
||||
|
||||
// Variable substitutions. Replace all occurrences of variables in controls files.
|
||||
s := string(in)
|
||||
@@ -105,6 +105,7 @@ func runChecks(nodetype check.NodeType, testYamlFile, detectedVersion string) {
|
||||
s, _ = makeSubstitutions(s, "svc", svcmap)
|
||||
s, _ = makeSubstitutions(s, "kubeconfig", kubeconfmap)
|
||||
s, _ = makeSubstitutions(s, "cafile", cafilemap)
|
||||
s, _ = makeSubstitutions(s, "datadir", datadirmap)
|
||||
|
||||
controls, err := check.NewControls(nodetype, []byte(s), detectedVersion)
|
||||
if err != nil {
|
||||
@@ -134,7 +135,7 @@ func generateDefaultEnvAudit(controls *check.Controls, binSubs []string) {
|
||||
if len(binSubs) == 1 {
|
||||
binPath = binSubs[0]
|
||||
} else {
|
||||
fmt.Printf("AuditEnv not explicit for check (%s), where bin path cannot be determined\n", checkItem.ID)
|
||||
glog.V(1).Infof("AuditEnv not explicit for check (%s), where bin path cannot be determined", checkItem.ID)
|
||||
}
|
||||
|
||||
if test.Env != "" && checkItem.AuditEnv == "" {
|
||||
@@ -148,7 +149,7 @@ func generateDefaultEnvAudit(controls *check.Controls, binSubs []string) {
|
||||
}
|
||||
|
||||
func parseSkipIds(skipIds string) map[string]bool {
|
||||
var skipIdMap = make(map[string]bool, 0)
|
||||
skipIdMap := make(map[string]bool, 0)
|
||||
if skipIds != "" {
|
||||
for _, id := range strings.Split(skipIds, ",") {
|
||||
skipIdMap[strings.Trim(id, " ")] = true
|
||||
|
||||
@@ -52,7 +52,6 @@ func TestParseSkipIds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewRunFilter(t *testing.T) {
|
||||
|
||||
type TestCase struct {
|
||||
Name string
|
||||
FilterOpts FilterOpts
|
||||
@@ -139,7 +138,6 @@ func TestNewRunFilter(t *testing.T) {
|
||||
// then
|
||||
assert.EqualError(t, err, "group option and check option can't be used together")
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestIsMaster(t *testing.T) {
|
||||
@@ -212,7 +210,6 @@ func TestIsMaster(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMapToCISVersion(t *testing.T) {
|
||||
|
||||
viperWithData, err := loadConfigForTest()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to load config file %v", err)
|
||||
@@ -240,6 +237,10 @@ func TestMapToCISVersion(t *testing.T) {
|
||||
{kubeVersion: "1.19", succeed: true, exp: "cis-1.20"},
|
||||
{kubeVersion: "1.20", succeed: true, exp: "cis-1.20"},
|
||||
{kubeVersion: "1.21", succeed: true, exp: "cis-1.20"},
|
||||
{kubeVersion: "1.22", succeed: true, exp: "cis-1.23"},
|
||||
{kubeVersion: "1.23", succeed: true, exp: "cis-1.23"},
|
||||
{kubeVersion: "1.24", succeed: true, exp: "cis-1.24"},
|
||||
{kubeVersion: "1.25", succeed: true, exp: "cis-1.7"},
|
||||
{kubeVersion: "gke-1.2.0", succeed: true, exp: "gke-1.2.0"},
|
||||
{kubeVersion: "ocp-3.10", succeed: true, exp: "rh-0.7"},
|
||||
{kubeVersion: "ocp-3.11", succeed: true, exp: "rh-0.7"},
|
||||
@@ -443,6 +444,18 @@ func TestValidTargets(t *testing.T) {
|
||||
targets: []string{"node", "policies", "controlplane", "managedservices"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "eks-1.1.0 valid",
|
||||
benchmark: "eks-1.1.0",
|
||||
targets: []string{"node", "policies", "controlplane", "managedservices"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "eks-1.2.0 valid",
|
||||
benchmark: "eks-1.2.0",
|
||||
targets: []string{"node", "policies", "controlplane", "managedservices"},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
||||
@@ -38,7 +38,7 @@ func getPsqlConnInfo() (PsqlConnInfo, error) {
|
||||
if value := viper.GetString("PGSQL_DBNAME"); value != "" {
|
||||
dbName = value
|
||||
} else {
|
||||
return PsqlConnInfo{}, fmt.Errorf("%s_PGSQL_USER env var is required", envVarsPrefix)
|
||||
return PsqlConnInfo{}, fmt.Errorf("%s_PGSQL_DBNAME env var is required", envVarsPrefix)
|
||||
}
|
||||
|
||||
var sslMode string
|
||||
|
||||
@@ -128,7 +128,6 @@ func getWebData(srvURL, token string, cacert *tls.Certificate) ([]byte, error) {
|
||||
}
|
||||
|
||||
authToken := fmt.Sprintf("Bearer %s", token)
|
||||
glog.V(2).Info(fmt.Sprintf("getWebData AUTH TOKEN --[%q]--\n", authToken))
|
||||
req.Header.Set("Authorization", authToken)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
@@ -72,7 +72,6 @@ FAjB57z2NcIgJuVpQnGRYtr/JcH2Qdsq8bLtXaojUIWOOqoTDRLYozdMOOQ=
|
||||
t.Errorf("Expected error")
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -124,8 +123,8 @@ func TestGetWebData(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetWebDataWithRetry(t *testing.T) {
|
||||
okfn := func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = fmt.Fprintln(w, `{
|
||||
@@ -173,8 +172,8 @@ func TestGetWebDataWithRetry(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestExtractVersion(t *testing.T) {
|
||||
okJSON := []byte(`{
|
||||
"major": "1",
|
||||
@@ -231,7 +230,6 @@ func TestExtractVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetKubernetesURL(t *testing.T) {
|
||||
|
||||
resetEnvs := func() {
|
||||
os.Unsetenv("KUBE_BENCH_K8S_ENV")
|
||||
os.Unsetenv("KUBERNETES_SERVICE_HOST")
|
||||
@@ -266,16 +264,9 @@ func TestGetKubernetesURL(t *testing.T) {
|
||||
}
|
||||
k8sURL := getKubernetesURL()
|
||||
|
||||
if !c.useDefault {
|
||||
if k8sURL != c.expected {
|
||||
t.Errorf("Expected %q but Got %q", k8sURL, c.expected)
|
||||
}
|
||||
} else {
|
||||
if k8sURL != c.expected {
|
||||
t.Errorf("Expected %q but Got %q", k8sURL, c.expected)
|
||||
}
|
||||
if k8sURL != c.expected {
|
||||
t.Errorf("Expected %q but Got %q", k8sURL, c.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright © 2017-2019 Aqua Security Software Ltd. <info@aquasec.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aquasecurity/kube-bench/check"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// masterCmd represents the master command
|
||||
var masterCmd = &cobra.Command{
|
||||
Use: "master",
|
||||
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, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
|
||||
}
|
||||
|
||||
filename := loadConfig(check.MASTER, bv)
|
||||
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() {
|
||||
masterCmd.PersistentFlags().StringVarP(&masterFile,
|
||||
"file",
|
||||
"f",
|
||||
"/master.yaml",
|
||||
"Alternative YAML file for master checks",
|
||||
)
|
||||
|
||||
RootCmd.AddCommand(masterCmd)
|
||||
}
|
||||
52
cmd/node.go
52
cmd/node.go
@@ -1,52 +0,0 @@
|
||||
// Copyright © 2017-2019 Aqua Security Software Ltd. <info@aquasec.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aquasecurity/kube-bench/check"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// nodeCmd represents the node command
|
||||
var nodeCmd = &cobra.Command{
|
||||
Use: "node",
|
||||
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, getPlatformInfo(), viper.GetViper())
|
||||
if err != nil {
|
||||
exitWithError(fmt.Errorf("unable to determine benchmark version: %v", err))
|
||||
}
|
||||
|
||||
filename := loadConfig(check.NODE, bv)
|
||||
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() {
|
||||
nodeCmd.PersistentFlags().StringVarP(&nodeFile,
|
||||
"file",
|
||||
"f",
|
||||
"/node.yaml",
|
||||
"Alternative YAML file for node checks",
|
||||
)
|
||||
|
||||
RootCmd.AddCommand(nodeCmd)
|
||||
}
|
||||
@@ -136,8 +136,7 @@ var RootCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
writeOutput(controlsCollection)
|
||||
exitCode := exitCodeSelection(controlsCollection)
|
||||
os.Exit(exitCode)
|
||||
os.Exit(exitCodeSelection(controlsCollection))
|
||||
},
|
||||
}
|
||||
|
||||
@@ -173,7 +172,7 @@ func init() {
|
||||
RootCmd.PersistentFlags().BoolVar(&filterOpts.Unscored, "unscored", true, "Run the unscored CIS checks")
|
||||
RootCmd.PersistentFlags().StringVar(&skipIds, "skip", "", "List of comma separated values of checks to be skipped")
|
||||
RootCmd.PersistentFlags().BoolVar(&includeTestOutput, "include-test-output", false, "Prints the actual result when test fails")
|
||||
RootCmd.PersistentFlags().StringVar(&outputFile, "outputfile", "", "Writes the JSON results to output file")
|
||||
RootCmd.PersistentFlags().StringVar(&outputFile, "outputfile", "", "Writes the results to output file when run with --json or --junit")
|
||||
|
||||
RootCmd.PersistentFlags().StringVarP(
|
||||
&filterOpts.CheckList,
|
||||
@@ -201,7 +200,6 @@ func init() {
|
||||
goflag.CommandLine.VisitAll(func(goflag *goflag.Flag) {
|
||||
RootCmd.PersistentFlags().AddGoFlag(goflag)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
|
||||
@@ -54,13 +54,15 @@ var runCmd = &cobra.Command{
|
||||
path := filepath.Join(cfgDir, bv)
|
||||
err = mergeConfig(path)
|
||||
if err != nil {
|
||||
fmt.Printf("Error in mergeConfig: %v\n", err)
|
||||
exitWithError(fmt.Errorf("Error in mergeConfig: %v\n", err))
|
||||
}
|
||||
|
||||
err = run(targets, bv)
|
||||
if err != nil {
|
||||
fmt.Printf("Error in run: %v\n", err)
|
||||
exitWithError(fmt.Errorf("Error in run: %v\n", err))
|
||||
}
|
||||
|
||||
os.Exit(exitCodeSelection(controlsCollection))
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aquasecurity/kube-bench/internal/findings"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/securityhub"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/service/securityhub"
|
||||
"github.com/aws/aws-sdk-go-v2/service/securityhub/types"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
//REGION ...
|
||||
// REGION ...
|
||||
const REGION = "AWS_REGION"
|
||||
|
||||
func writeFinding(in []*securityhub.AwsSecurityFinding) error {
|
||||
func writeFinding(in []types.AwsSecurityFinding) error {
|
||||
r := viper.GetString(REGION)
|
||||
if len(r) == 0 {
|
||||
return fmt.Errorf("%s not set", REGION)
|
||||
}
|
||||
sess, err := session.NewSession(&aws.Config{
|
||||
Region: aws.String(r)},
|
||||
)
|
||||
cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(r))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
svc := securityhub.New(sess)
|
||||
p := findings.New(svc)
|
||||
|
||||
svc := securityhub.NewFromConfig(cfg)
|
||||
p := findings.New(*svc)
|
||||
out, perr := p.PublishFinding(in)
|
||||
print(out)
|
||||
return perr
|
||||
|
||||
49
cmd/util.go
49
cmd/util.go
@@ -16,26 +16,27 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Print colors
|
||||
var colors = map[check.State]*color.Color{
|
||||
check.PASS: color.New(color.FgGreen),
|
||||
check.FAIL: color.New(color.FgRed),
|
||||
check.WARN: color.New(color.FgYellow),
|
||||
check.INFO: color.New(color.FgBlue),
|
||||
}
|
||||
|
||||
var (
|
||||
// Print colors
|
||||
colors = map[check.State]*color.Color{
|
||||
check.PASS: color.New(color.FgGreen),
|
||||
check.FAIL: color.New(color.FgRed),
|
||||
check.WARN: color.New(color.FgYellow),
|
||||
check.INFO: color.New(color.FgBlue),
|
||||
psFunc func(string) string
|
||||
statFunc func(string) (os.FileInfo, error)
|
||||
getBinariesFunc func(*viper.Viper, check.NodeType) (map[string]string, error)
|
||||
TypeMap = map[string][]string{
|
||||
"ca": {"cafile", "defaultcafile"},
|
||||
"kubeconfig": {"kubeconfig", "defaultkubeconfig"},
|
||||
"service": {"svc", "defaultsvc"},
|
||||
"config": {"confs", "defaultconf"},
|
||||
"datadir": {"datadirs", "defaultdatadir"},
|
||||
}
|
||||
)
|
||||
|
||||
var psFunc func(string) string
|
||||
var statFunc func(string) (os.FileInfo, error)
|
||||
var getBinariesFunc func(*viper.Viper, check.NodeType) (map[string]string, error)
|
||||
var TypeMap = map[string][]string{
|
||||
"ca": {"cafile", "defaultcafile"},
|
||||
"kubeconfig": {"kubeconfig", "defaultkubeconfig"},
|
||||
"service": {"svc", "defaultsvc"},
|
||||
"config": {"confs", "defaultconf"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
psFunc = ps
|
||||
statFunc = os.Stat
|
||||
@@ -126,7 +127,7 @@ func getConfigFilePath(benchmarkVersion string, filename string) (path string, e
|
||||
glog.V(2).Info(fmt.Sprintf("Looking for config specific CIS version %q", benchmarkVersion))
|
||||
|
||||
path = filepath.Join(cfgDir, benchmarkVersion)
|
||||
file := filepath.Join(path, string(filename))
|
||||
file := filepath.Join(path, filename)
|
||||
glog.V(2).Info(fmt.Sprintf("Looking for file: %s", file))
|
||||
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
@@ -208,7 +209,6 @@ func getFiles(v *viper.Viper, fileType string) map[string]string {
|
||||
|
||||
// verifyBin checks that the binary specified is running
|
||||
func verifyBin(bin string) bool {
|
||||
|
||||
// Strip any quotes
|
||||
bin = strings.Trim(bin, "'\"")
|
||||
|
||||
@@ -241,7 +241,7 @@ func findConfigFile(candidates []string) string {
|
||||
if err == nil {
|
||||
return c
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
if !os.IsNotExist(err) && !strings.HasSuffix(err.Error(), "not a directory") {
|
||||
exitWithError(fmt.Errorf("error looking for file %s: %v", c, err))
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,6 @@ Alternatively, you can specify the version with --version
|
||||
`
|
||||
|
||||
func getKubeVersion() (*KubeVersion, error) {
|
||||
|
||||
if k8sVer, err := getKubeVersionFromRESTAPI(); err == nil {
|
||||
glog.V(2).Info(fmt.Sprintf("Kubernetes REST API Reported version: %s", k8sVer))
|
||||
return k8sVer, nil
|
||||
@@ -298,7 +297,6 @@ func getKubeVersion() (*KubeVersion, error) {
|
||||
|
||||
// These executables might not be on the user's path.
|
||||
_, err := exec.LookPath("kubectl")
|
||||
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Error locating kubectl: %s", err)
|
||||
_, err = exec.LookPath("kubelet")
|
||||
@@ -337,7 +335,6 @@ func getKubeVersionFromKubectl() *KubeVersion {
|
||||
func getKubeVersionFromKubelet() *KubeVersion {
|
||||
cmd := exec.Command("kubelet", "--version")
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
glog.V(2).Infof("Failed to query kubelet: %s", err)
|
||||
glog.V(2).Info(err)
|
||||
@@ -401,11 +398,9 @@ func makeSubstitutions(s string, ext string, m map[string]string) (string, []str
|
||||
|
||||
func isEmpty(str string) bool {
|
||||
return strings.TrimSpace(str) == ""
|
||||
|
||||
}
|
||||
|
||||
func buildComponentMissingErrorMessage(nodetype check.NodeType, component string, bins []string) string {
|
||||
|
||||
errMessageTemplate := `
|
||||
Unable to detect running programs for component %q
|
||||
The following %q programs have been searched, but none of them have been found:
|
||||
@@ -452,7 +447,7 @@ func getPlatformInfo() Platform {
|
||||
}
|
||||
|
||||
func getPlatformInfoFromVersion(s string) Platform {
|
||||
versionRe := regexp.MustCompile(`v(\d+\.\d+)\.\d+-(\w+)(?:[.\-])\w+`)
|
||||
versionRe := regexp.MustCompile(`v(\d+\.\d+)\.\d+[-+](\w+)(?:[.\-])\w+`)
|
||||
subs := versionRe.FindStringSubmatch(s)
|
||||
if len(subs) < 3 {
|
||||
return Platform{}
|
||||
@@ -467,7 +462,7 @@ func getPlatformBenchmarkVersion(platform Platform) string {
|
||||
glog.V(3).Infof("getPlatformBenchmarkVersion platform: %s", platform)
|
||||
switch platform.Name {
|
||||
case "eks":
|
||||
return "eks-1.0.1"
|
||||
return "eks-1.2.0"
|
||||
case "gke":
|
||||
switch platform.Version {
|
||||
case "1.15", "1.16", "1.17", "1.18", "1.19":
|
||||
@@ -484,6 +479,8 @@ func getPlatformBenchmarkVersion(platform Platform) string {
|
||||
case "4.1":
|
||||
return "rh-1.0"
|
||||
}
|
||||
case "vmware":
|
||||
return "tkgi-1.2.53"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -29,9 +30,11 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var g string
|
||||
var e []error
|
||||
var eIndex int
|
||||
var (
|
||||
g string
|
||||
e []error
|
||||
eIndex int
|
||||
)
|
||||
|
||||
func fakeps(proc string) string {
|
||||
return g
|
||||
@@ -132,7 +135,7 @@ func TestGetBinaries(t *testing.T) {
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
// "anotherthing" in list of components but doesn't have a defintion
|
||||
// "anotherthing" in list of components but doesn't have a definition
|
||||
config: map[string]interface{}{"components": []string{"apiserver", "anotherthing"}, "apiserver": map[string]interface{}{"bins": []string{"apiserver", "kube-apiserver"}}, "thing": map[string]interface{}{"bins": []string{"something else", "thing"}}},
|
||||
psOut: "kube-apiserver thing",
|
||||
exp: map[string]string{"apiserver": "kube-apiserver"},
|
||||
@@ -231,6 +234,7 @@ func TestFindConfigFile(t *testing.T) {
|
||||
{input: []string{"myfile"}, statResults: []error{nil}, exp: "myfile"},
|
||||
{input: []string{"thisfile", "thatfile"}, statResults: []error{os.ErrNotExist, nil}, exp: "thatfile"},
|
||||
{input: []string{"thisfile", "thatfile"}, statResults: []error{os.ErrNotExist, os.ErrNotExist}, exp: ""},
|
||||
{input: []string{"thisfile", "/etc/dummy/thatfile"}, statResults: []error{os.ErrNotExist, errors.New("stat /etc/dummy/thatfile: not a directory")}, exp: ""},
|
||||
}
|
||||
|
||||
statFunc = fakestat
|
||||
@@ -262,7 +266,8 @@ func TestGetConfigFiles(t *testing.T) {
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"apiserver"},
|
||||
"apiserver": map[string]interface{}{"confs": []string{"apiserver", "kube-apiserver"}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}},
|
||||
},
|
||||
statResults: []error{os.ErrNotExist, nil},
|
||||
exp: map[string]string{"apiserver": "kube-apiserver"},
|
||||
},
|
||||
@@ -271,7 +276,8 @@ func TestGetConfigFiles(t *testing.T) {
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"apiserver", "thing"},
|
||||
"apiserver": map[string]interface{}{"confs": []string{"apiserver", "kube-apiserver"}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}},
|
||||
},
|
||||
statResults: []error{os.ErrNotExist, nil, nil},
|
||||
exp: map[string]string{"apiserver": "kube-apiserver", "thing": "/my/file/thing"},
|
||||
},
|
||||
@@ -280,7 +286,8 @@ func TestGetConfigFiles(t *testing.T) {
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"apiserver", "thing"},
|
||||
"apiserver": map[string]interface{}{"confs": []string{"apiserver", "kube-apiserver"}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}, "defaultconf": "another/thing"}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}, "defaultconf": "another/thing"},
|
||||
},
|
||||
statResults: []error{os.ErrNotExist, nil, os.ErrNotExist},
|
||||
exp: map[string]string{"apiserver": "kube-apiserver", "thing": "another/thing"},
|
||||
},
|
||||
@@ -289,7 +296,8 @@ func TestGetConfigFiles(t *testing.T) {
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"apiserver", "thing"},
|
||||
"apiserver": map[string]interface{}{"confs": []string{"apiserver", "kube-apiserver"}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}}},
|
||||
"thing": map[string]interface{}{"confs": []string{"/my/file/thing"}},
|
||||
},
|
||||
statResults: []error{os.ErrNotExist, nil, os.ErrNotExist},
|
||||
exp: map[string]string{"apiserver": "kube-apiserver", "thing": "thing"},
|
||||
},
|
||||
@@ -389,6 +397,58 @@ func TestGetServiceFiles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDatadirFiles(t *testing.T) {
|
||||
var err error
|
||||
datadir, err := ioutil.TempDir("", "kube-bench-test-etcd-data-dir")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory")
|
||||
}
|
||||
defer os.RemoveAll(datadir)
|
||||
|
||||
cases := []struct {
|
||||
config map[string]interface{}
|
||||
exp map[string]string
|
||||
statResults []error
|
||||
}{
|
||||
{
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"etcd"},
|
||||
"etcd": map[string]interface{}{"datadirs": []string{datadir},
|
||||
"defaultdatadir": "/var/lib/etcd/default.etcd"},
|
||||
},
|
||||
statResults: []error{nil},
|
||||
exp: map[string]string{"etcd": datadir},
|
||||
},
|
||||
// fallback to defaultdatadir
|
||||
{
|
||||
config: map[string]interface{}{
|
||||
"components": []string{"etcd"},
|
||||
"etcd": map[string]interface{}{"datadirs": []string{"/path/to/etcd/data.etcd"},
|
||||
"defaultdatadir": "/var/lib/etcd/default.etcd"},
|
||||
},
|
||||
statResults: []error{os.ErrNotExist},
|
||||
exp: map[string]string{"etcd": "/var/lib/etcd/default.etcd"},
|
||||
},
|
||||
}
|
||||
|
||||
v := viper.New()
|
||||
statFunc = fakestat
|
||||
|
||||
for id, c := range cases {
|
||||
t.Run(strconv.Itoa(id), func(t *testing.T) {
|
||||
for k, val := range c.config {
|
||||
v.Set(k, val)
|
||||
}
|
||||
e = c.statResults
|
||||
eIndex = 0
|
||||
m := getFiles(v, "datadir")
|
||||
if !reflect.DeepEqual(m, c.exp) {
|
||||
t.Fatalf("Got %v\nExpected %v", m, c.exp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeSubsitutions(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
@@ -459,7 +519,6 @@ func TestGetConfigFilePath(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecrementVersion(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
kubeVersion string
|
||||
succeed bool
|
||||
@@ -577,7 +636,7 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
|
||||
args: args{
|
||||
platform: Platform{Name: "eks"},
|
||||
},
|
||||
want: "eks-1.0.1",
|
||||
want: "eks-1.2.0",
|
||||
},
|
||||
{
|
||||
name: "gke 1.19",
|
||||
@@ -646,7 +705,6 @@ func Test_getPlatformBenchmarkVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_getOcpValidVersion(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
openShiftVersion string
|
||||
succeed bool
|
||||
|
||||
@@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -14,16 +14,28 @@ Check the contents of the benchmark directory under `cfg` to see which targets a
|
||||
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 |
|
||||
|cis-1.20| master, controlplane, node, etcd, policies |
|
||||
| gke-1.0| master, controlplane, node, etcd, policies, managedservices |
|
||||
| gke-1.2.0| controlplane, node, policies, managedservices |
|
||||
| eks-1.0.1| controlplane, node, policies, managedservices |
|
||||
| ack-1.0| master, controlplane, node, etcd, policies, managedservices |
|
||||
| aks-1.0| controlplane, node, policies, managedservices |
|
||||
| rh-0.7| master,node|
|
||||
| rh-1.0| master, controlplane, node, etcd, policies |
|
||||
|---------------|---------|
|
||||
| cis-1.5 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.6 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.20 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.23 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.24 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.7 | master, controlplane, node, etcd, policies |
|
||||
| gke-1.0 | master, controlplane, node, etcd, policies, managedservices |
|
||||
| gke-1.2.0 | controlplane, node, policies, managedservices |
|
||||
| eks-1.0.1 | controlplane, node, policies, managedservices |
|
||||
| eks-1.1.0 | controlplane, node, policies, managedservices |
|
||||
| eks-1.2.0 | controlplane, node, policies, managedservices |
|
||||
| ack-1.0 | master, controlplane, node, etcd, policies, managedservices |
|
||||
| aks-1.0 | controlplane, node, policies, managedservices |
|
||||
| rh-0.7 | master,node|
|
||||
| rh-1.0 | master, controlplane, node, etcd, policies |
|
||||
| cis-1.6-k3s | master, controlplane, node, etcd, policies |
|
||||
|
||||
The following table shows the valid DISA STIG versions
|
||||
|
||||
| STIG | Targets |
|
||||
|----------------------------|---------|
|
||||
| eks-stig-kubernetes-v1r6 | master, controlplane, node, policies, managedservices |
|
||||
|
||||
|
||||
|
||||
@@ -23,12 +23,13 @@ Flag | Description
|
||||
--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
|
||||
--outputfile | Writes the results to output file when run with --json or --junit
|
||||
--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)
|
||||
--unscored | Run the unscored CIS checks (default true)
|
||||
--version string | Manually specify Kubernetes version, automatically detected if unset
|
||||
--vmodule moduleSpec | comma-separated list of pattern=N settings for file-filtered logging
|
||||
|
||||
@@ -112,7 +113,8 @@ There are four output states:
|
||||
- [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)
|
||||
- Some tests with `Automated` in their description must still be run manually
|
||||
- If the user has to run a test manually, this always generates WARN
|
||||
- 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.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[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
|
||||
[docker]: https://hub.docker.com/r/aquasec/kube-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
|
||||
@@ -9,13 +10,11 @@
|
||||
|
||||

|
||||
[![GitHub Release][release-img]][release]
|
||||
![Downloads][download]
|
||||
![Docker Pulls][docker-pull]
|
||||
[![Downloads][download]][release]
|
||||
[![Docker Pulls][docker-pull]][docker]
|
||||
[![Go Report Card][report-card-img]][report-card]
|
||||
[](https://github.com/aquasecurity/kube-bench/actions)
|
||||
[](https://github.com/aquasecurity/kube-bench/blob/main/LICENSE)
|
||||
[](https://microbadger.com/images/aquasec/kube-bench "Get your own image badge on microbadger.com")
|
||||
[](https://microbadger.com/images/aquasec/kube-bench)
|
||||
[![Coverage Status][cov-img]][cov]
|
||||
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ go build -o kube-bench .
|
||||
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
|
||||
docker run --rm -v `pwd`:/host docker.io/aquasec/kube-bench:latest install
|
||||
```
|
||||
|
||||
You can then run `./kube-bench`.
|
||||
|
||||
@@ -2,18 +2,29 @@
|
||||
## 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/).
|
||||
Most of our supported benchmarks are defined in one of the following:
|
||||
[CIS Kubernetes Benchmarks](https://www.cisecurity.org/benchmark/kubernetes/)
|
||||
[STIG Document Library](https://public.cyber.mil/stigs/downloads)
|
||||
|
||||
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-1.18 |
|
||||
| CIS | [1.20](https://workbench.cisecurity.org/benchmarks/6246) | cis-1.20 | 1.19-1.20 |
|
||||
| CIS | [GKE 1.0.0](https://workbench.cisecurity.org/benchmarks/4536) | gke-1.0 | GKE |
|
||||
| CIS | [GKE 1.2.0](https://workbench.cisecurity.org/benchmarks/7534) | gke-1.2.0 | GKE |
|
||||
| CIS | [EKS 1.0.1](https://workbench.cisecurity.org/benchmarks/6041) | eks-1.0.1 | EKS |
|
||||
| CIS | [ACK 1.0.0](https://workbench.cisecurity.org/benchmarks/6467) | ack-1.0 | ACK |
|
||||
| CIS | [AKS 1.0.0](https://workbench.cisecurity.org/benchmarks/6347) | aks-1.0 | AKS |
|
||||
| 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- |
|
||||
| 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-1.18 |
|
||||
| CIS | [1.20](https://workbench.cisecurity.org/benchmarks/6246) | cis-1.20 | 1.19-1.21 |
|
||||
| CIS | [1.23](https://workbench.cisecurity.org/benchmarks/7532) | cis-1.23 | 1.22-1.23 |
|
||||
| CIS | [1.24](https://workbench.cisecurity.org/benchmarks/10873) | cis-1.24 | 1.24 |
|
||||
| CIS | [1.7](https://workbench.cisecurity.org/benchmarks/11107) | cis-1.7 | 1.25 |
|
||||
| CIS | [GKE 1.0.0](https://workbench.cisecurity.org/benchmarks/4536) | gke-1.0 | GKE |
|
||||
| CIS | [GKE 1.2.0](https://workbench.cisecurity.org/benchmarks/7534) | gke-1.2.0 | GKE |
|
||||
| CIS | [EKS 1.0.1](https://workbench.cisecurity.org/benchmarks/6041) | eks-1.0.1 | EKS |
|
||||
| CIS | [EKS 1.1.0](https://workbench.cisecurity.org/benchmarks/6248) | eks-1.1.0 | EKS |
|
||||
| CIS | [EKS 1.2.0](https://workbench.cisecurity.org/benchmarks/9681) | eks-1.2.0 | EKS |
|
||||
| CIS | [ACK 1.0.0](https://workbench.cisecurity.org/benchmarks/6467) | ack-1.0 | ACK |
|
||||
| CIS | [AKS 1.0.0](https://workbench.cisecurity.org/benchmarks/6347) | aks-1.0 | AKS |
|
||||
| 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- |
|
||||
| CIS | [1.6.0-k3s](https://docs.rancher.cn/docs/k3s/security/self-assessment/_index) | cis-1.6-k3s | k3s v1.16-v1.24 |
|
||||
| DISA | [Kubernetes Ver 1, Rel 6](https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_Kubernetes_V1R6_STIG.zip) | eks-stig-kubernetes-v1r6 | EKS |
|
||||
| CIS | [TKGI 1.2.53](https://network.pivotal.io/products/p-compliance-scanner#/releases/1248397) | tkgi-1.2.53 | vmware |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user