From ece0a6906e1c483da31a8ce273fa7c7542b101da Mon Sep 17 00:00:00 2001 From: santoshkal Date: Mon, 27 Nov 2023 17:17:36 +0530 Subject: [PATCH] Add default policies for k8s, tf and update README Signed-off-by: santoshkal --- CONTRIBUTION.md | 1 + README.md | 46 +++++++++++++++--- templates/defaultpolicies/rego/k8s.rego | 47 +++++++++++++++++++ templates/defaultpolicies/rego/terraform.rego | 11 +++++ 4 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 templates/defaultpolicies/rego/k8s.rego create mode 100644 templates/defaultpolicies/rego/terraform.rego diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 65a8f2b..c8293aa 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -118,6 +118,7 @@ import "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" apiVersion: string | *"tekton.dev/v1beta1" kind: string | *"Pipeline" ... +} ``` diff --git a/README.md b/README.md index 1e31a87..33a0003 100644 --- a/README.md +++ b/README.md @@ -143,21 +143,22 @@ To build genval from source: The generated binary, genval, will be available in the current working directory. You can move it to your PATH or use it from the current directory. -Genval offers two modes: +Genval offers four modes: -- `container` for Dockerfile validation and generation - +- `container` for Dockerfile validation with rego policies and generation of validated Dockerfile - `cue` for Kubernetes and CRD validation and generation +- `k8s` for validating Kubernetes manifests with Rego policies +- `tf` for validating Terraform resource files with Rego policies -> Both modes accept inputs that include local files and files obtained from a remote URL, such as those from a Git repository. +> All the modes accept inputs that include local files and files obtained from a remote URL, such as those from a Git repository. ### Dockerfile Validation and Generation: -Run Genval with the --mode container flag, providing the path to your input JSON or YAML file using the `--reqinput` flag and specifying the desired output path for the generated Dockerfile along with `--inputpolicy` and `--outputpolicy` for validating the input JSON and the generated Dockerfile respectively. Genval will take care of the rest. +Run Genval with the `--mode container` flag, providing the path to your input JSON or YAML file using the `--reqinput` flag and specifying the desired output path for the generated Dockerfile along with `--inputpolicy` and `--outputpolicy` for validating the input JSON and the generated Dockerfile respectively. Genval will take care of the rest. Example: @@ -178,7 +179,6 @@ $ genval --mode container --reqinput ./templates/inputs/dockerfile_input/golang_ ### Validation and Generation of Kubernetes configurations - The validation and generation of Kubernetes and CRD manifests are facilitated through the use of [cuelang](https://cuelang.org/docs/). When using Genval for validating and generating Kubernetes and related manifests, make use of the Genval tool in `cue` mode. This mode necessitates JSON input provided via the `--reqinput` flag. Furthermore, you should specify a `resource` flag, indicating the Kubernetes or CRD `Kind` that requires validation. Additionally, attach the `.cue schema definitions` to the `--policy` flag. These policy files can be provided from the users local file system or from a remote URL, like a Git repository. @@ -204,6 +204,40 @@ The above command will validate a Deployment manifests using the provided `.cue` For a detailed workflow illustrating the capabilities of Cue and Genval for validating and generating Kubernetes configurations, you can refer to [this document](./cmd/cueval/example.md). The workflow for adding a Cue schema for Kubernetes CRDs is failry easy, and demostrated in the [CONTRIBUTION.md document](./CONTRIBUTION.md/#contributing-by-adding-a-cue-schema-to-the-project). +### Validation of Kubernetes resources with Repgo policies + +To validate Kubernetes manifests with Rego policies, users can use `--mode k8s` with `--reqinput` for providing the required input in JSON or YAML format, and `--policy` flag to pass in the Rego policies. + +Example: + +```shell +genval --mode k8s --reqinput \ + --policy +``` + +### Validate Terraform resource files with Rego policies + +To validate the Terraform resource file in `.tf` format. Use `--mode tf` with two flags as above `--reqinput` and `--policy`. The Genval tool internally will transform the input `.tf` file in JSON and validate the resource file with Rego policies. + +To write custom policies, users might require to know the `JSON` representation of the input `.tf` file. In order to get the `JSON` representation of the `.tf` users can use `--json` flag after passing the `--reqinput` and `--policy` flags. This will print the JSON doc for the input. Now, users can pipe it to tools lie [jq](https://jqlang.github.io/jq/) to get a prettified JSOn representation that could help user write rego policies. + +Example: + +```shell +genval --mode tf --reqinput ../templates/inputs/terraform/sec-group.tf \ + --policy ./templates/defaultpolicies/rego/terraform.rego \ + --json true jq . +{ + "resource": [ + { + "aws_security_group": { + "allow_tls": { + "description": "Allow TLS inbound traffic", + "egress": [ + { + ... +``` + ### Templates The `./templates` folder holds some sample files to be used in Genval. the `./templates/inputs` holds JSON input templates for both generating Dockerfiles in `container` mode and Kubernetes manifests in `cue` mode. Similarly, all the default policies for both the modes are stored in `./templates/defaultpolices` directory. User can use these template files to start with and as they go along they can customize these files to suite their specific use cases. \ No newline at end of file diff --git a/templates/defaultpolicies/rego/k8s.rego b/templates/defaultpolicies/rego/k8s.rego new file mode 100644 index 0000000..dacfa9e --- /dev/null +++ b/templates/defaultpolicies/rego/k8s.rego @@ -0,0 +1,47 @@ +package validate_k8s + +import future.keywords + +default deny_latest = false +default deny_secret = false +default deny_priviliged_pod = false + +deny_latest{ +input.kind == "Deployment" +c:= input.spec.template.spec.containers[i].image +not endswith(c, "latest") +} + +deny_secret{ + input.kind == "Deployment" + container := input.spec.template.spec.containers[_] + not container.envFrom +} + +deny_secret{ + input.kind == "Deployment" + container := input.spec.template.spec.containers[_] + env := container.envFrom[_] + + not env.secretRef + } + +deny_secret{ + input.kind == "Deployment" + container := input.spec.template.spec.containers[_] + + env := container.env[_] + env.valueFrom != [] +} + +deny_priviliged_pod{ + input.kind == "Deployment" + not input.spec.template.spec.securityContext +} + +deny_priviliged_pod{ + input.kind == "Deployment" + podSpec := input.spec.template.spec.securityContext + + not podSpec.priviliged +} diff --git a/templates/defaultpolicies/rego/terraform.rego b/templates/defaultpolicies/rego/terraform.rego new file mode 100644 index 0000000..98cdc7b --- /dev/null +++ b/templates/defaultpolicies/rego/terraform.rego @@ -0,0 +1,11 @@ +package validate_input_tf + +default deny_global_ingress = false + +deny_global_ingress { + input.resource[_].aws_security_group + ing := input.resource[_].aws_security_group.allow_tls.ingress[_] + denied_cidr := "0.0.0.0/0" + global := ing.cidr_blocks[_] + not contains(global, denied_cidr) +}