This repository holds the Google Kubernetes Engine (GKE) Center for Internet Security (CIS) version 1.1 Benchmark.
This is not an officially supported Google product. This code is intended to help users assess their security posture on the GKE against the CIS Benchmark. This code is not certified by CIS.
The benchmark contains of three Inspec profiles which can be found in the subdirectories inspec-gke-cis-gcp, inspec-gke-cis-k8s and inspec-gke-cis-ssh. The profiles are separated, since each profile needs to run against a different target (-t
) option when running inspec exec
. Targets which are used:
- inspec-gke-cis-gcp uses inspec-gcp
- inspec-gke-cis-k8s uses inspec-k8s
- inspec-gke-cis-ssh uses the SSH protocol for remote access (requires root privileges).
A wrapper script run_profiles.sh
is provided in the root directory of the repository which executes all profiles sequentially and stores reports in a dedicated folder /reports
. Note, that you need to configure access via the Identity-Aware Proxy (IAP) to cluster nodes for this script to run successfully.
- Configure access via the Identity-Aware Proxy (IAP) to cluster nodes for the inspec-gke-cis-ssh profile to run successfully
- Follow the setup steps for inspec-k8s as explained here
Open a Cloud Shell in GCP for the project.
# install inspec (later version might work but not tested)
$ gem install inspec-bin -v 4.41.2 --no-document --quiet
# clone the Git Repo
$ git clone https://github.com/tigera/inspec-gke-cis-benchmark.git
$ cd inspec-gke-cis-benchmark
$ git checkout tigera-tesla
# Check the input file is correct:
$ cat inputs.yml
# Connect to GKE Cluster (getting credentials in ~/.kubeconfig, validate using kubectl)
$ ./get_cluster_creds.sh
# install inspec-k8s and relevant gems (needs to run in directory of Gemfile)
# (refer to the inspec-k8s docs for details and troubleshooting)
$ bundle install
# install InSpec plugin train-kubernetes
$ inspec plugin install train-kubernetes
# (skip this) Add the host you are running from to the master-authorized-networks to allow access to Private K8S Clusters
$ gcloud container clusters update <cluster name> \
--zone <zone> \
--enable-master-authorized-networks \
--master-authorized-networks <your host's IP address>/32
---
# make sure you're authenticated to GCP
$ gcloud auth list
# (skip if authed) acquire credentials to use with Application Default Credentials
$ gcloud auth application-default login
---
# Run
$ ./exec_inspec.sh
# install inspec (later version might work but not tested)
$ gem install inspec-bin -v 4.41.2 --no-document --quiet
# clone the Git Repo
$ git clone https://github.com/tigera/inspec-gke-cis-benchmark.git
$ cd inspec-gke-cis-benchmark
# Write an inputs file, see basic example below
$ cat <<EOF > inputs.yml
gcp_project_id: "<YOUR PROJECT ID>"
gcp_gke_locations:
- 'us-central1-c'
gce_zones:
- 'us-central1'
- 'us-central1-c'
EOF
# Connect to GKE Cluster (getting credentials in ~/.kubeconfig, validate using kubectl)
$ gcloud container clusters get-credentials <cluster name> \
--zone <zone> --project <YOUR PROJECT ID>
# install inspec-k8s and relevant gems (needs to run in directory of Gemfile)
# (refer to the inspec-k8s docs for details and troubleshooting)
$ bundle install
# install InSpec plugin train-kubernetes
$ inspec plugin install train-kubernetes
# Add the host you are running from to the master-authorized-networks to allow access to Private K8S Clusters
$ gcloud container clusters update <cluster name> \
--zone <zone> \
--enable-master-authorized-networks \
--master-authorized-networks <your host's IP address>/32
# make sure you're authenticated to GCP
$ gcloud auth list
# acquire credentials to use with Application Default Credentials
$ gcloud auth application-default login
# Create a file inputs.yml which contains the required and optional inputs to the profiles in the subdirectories
$ ./run_profiles.sh -c <cluster name> -u <ssh user> -k <keyfile path> -z <cluster zone> -i inputs.yml
- gcp_project_id - (Default: "", type: string) - The target GCP Project that must be specified.
- gcp_gke_locations - (Default: "", type: array) - The list of regions and/or zone names where GKE clusters are running. An empty array searches all locations
- gce_zones - (Default: "", type: array) - The list of zone names where GCE instances are running. An empty array searches all locations.
- registry_storage_admin_list - (Default: "", type: array) - The allowed list of Storage Admins on Registry image bucket
- registry_storage_object_admin_list - (Default: "", type: array) - The allowed list of Storage Object Admins on Registry image bucket
- registry_storage_object_creator_list - (Default: "", type: array) - The allowed list of Storage Object Admins on Registry image bucket
- registry_storage_object_creator_list - (Default: "", type: array) - The allowed list of Storage Object Creators on Registry image bucket
- registry_storage_legacy_bucket_owner_list - (Default: "", type: array) - The allowed list of Storage Legacy Bucket Owners on Registry image bucket
- registry_storage_legacy_bucket_writer_list - (Default: "", type: array) - The allowed list of Storage Legacy Bucket Writers on Registry image bucket
- registry_storage_legacy_object_owner_list - (Default: "", type: array) - The allowed list of Storage Legacy Object Owners on Registry image bucket
- client_ca_file_path - (Default: "/etc/srv/kubernetes/pki/ca-certificates.crt", type: string) - Path to the client ca file used in Kubelet config
- event_record_qps - (Default: "0", type: string) - --event-qps flag of Kubelet config (see control 3.2.9)
- tls_cert_file - (Default: "", type: string) - Location of the certificate file to use to identify the Kubelet
- tls_private_key_file - (Default: "", type: string) - Location of the corresponding private key file to use to identify the Kubelet
Use this Cloud Shell walkthrough for a hands-on example.
The following permissions are required to run the CIS benchmark profile on project level:
- compute.regions.list
- compute.zones.list
- container.clusters.get
- container.clusters.list
- serviceusage.services.get
- storage.buckets.get
- storage.buckets.getIamPolicy