From 7e36892e26873c14633ae39a72b950a2146cb441 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Wed, 23 Oct 2019 17:10:21 +0300 Subject: [PATCH] Add GitHub workflow for manifests validation - validate kustomize build with kubeval strict mode - deny containers with latest image tag - deny deployments and services without app label selector - warn if deployments have no prometheus pod annotations --- .github/policy/kubernetes.rego | 51 ++++++++++++++++++++++++++++++++++ .github/policy/rules.rego | 43 ++++++++++++++++++++++++++++ .github/workflows/test.yml | 17 ++++++++++++ README.md | 2 ++ 4 files changed, 113 insertions(+) create mode 100644 .github/policy/kubernetes.rego create mode 100644 .github/policy/rules.rego create mode 100644 .github/workflows/test.yml diff --git a/.github/policy/kubernetes.rego b/.github/policy/kubernetes.rego new file mode 100644 index 0000000..efdae6f --- /dev/null +++ b/.github/policy/kubernetes.rego @@ -0,0 +1,51 @@ +package kubernetes + +name = input.metadata.name + +kind = input.kind + +is_service { + input.kind = "Service" +} + +is_deployment { + input.kind = "Deployment" +} + +is_pod { + input.kind = "Pod" +} + +split_image(image) = [image, "latest"] { + not contains(image, ":") +} + +split_image(image) = [image_name, tag] { + [image_name, tag] = split(image, ":") +} + +pod_containers(pod) = all_containers { + keys = {"containers", "initContainers"} + all_containers = [c | keys[k]; c = pod.spec[k][_]] +} + +containers[container] { + pods[pod] + all_containers = pod_containers(pod) + container = all_containers[_] +} + +containers[container] { + all_containers = pod_containers(input) + container = all_containers[_] +} + +pods[pod] { + is_deployment + pod = input.spec.template +} + +pods[pod] { + is_pod + pod = input +} diff --git a/.github/policy/rules.rego b/.github/policy/rules.rego new file mode 100644 index 0000000..84d578a --- /dev/null +++ b/.github/policy/rules.rego @@ -0,0 +1,43 @@ +package main + +import data.kubernetes + +name = input.metadata.name + +# Deny containers with latest image tag +deny[msg] { + kubernetes.containers[container] + [image_name, "latest"] = kubernetes.split_image(container.image) + msg = sprintf("%s in the %s %s has an image %s, using the latest tag", [container.name, kubernetes.kind, kubernetes.name, image_name]) +} + +# Deny services without app label selector +service_labels { + input.spec.selector["app"] +} +deny[msg] { + kubernetes.is_service + not service_labels + msg = sprintf("Service %s should set app label selector", [name]) +} + +# Deny deployments without app label selector +match_labels { + input.spec.selector.matchLabels["app"] +} +deny[msg] { + kubernetes.is_deployment + not match_labels + msg = sprintf("Service %s should set app label selector", [name]) +} + +# Warn if deployments have no prometheus pod annotations +annotations { + input.spec.template.metadata.annotations["prometheus.io/scrape"] + input.spec.template.metadata.annotations["prometheus.io/port"] +} +warn[msg] { + kubernetes.is_deployment + not annotations + msg = sprintf("Deployment %s should set prometheus.io/scrape and prometheus.io/port pod annotations", [name]) +} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..1de0635 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,17 @@ +on: [push, pull_request] +name: kustomize +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: kubeval + uses: stefanprodan/kube-tools@v1 + with: + command: | + kustomize build ./kustomize | kubeval --strict + - name: conftest + uses: stefanprodan/kube-tools@v1 + with: + command: | + kustomize build ./kustomize | conftest test -p .github/policy - diff --git a/README.md b/README.md index cd19883..9c72adf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # podinfo [![CircleCI](https://circleci.com/gh/stefanprodan/podinfo.svg?style=svg)](https://circleci.com/gh/stefanprodan/podinfo) +[![conftest](https://github.com/stefanprodan/podinfo/workflows/test/badge.svg)](https://github.com/stefanprodan/podinfo/blob/master/.github/workflows/test.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/stefanprodan/podinfo)](https://goreportcard.com/report/github.com/stefanprodan/podinfo) [![Docker Pulls](https://img.shields.io/docker/pulls/stefanprodan/podinfo)](https://hub.docker.com/r/stefanprodan/podinfo) @@ -20,6 +21,7 @@ Specifications: * Swagger docs * Helm and Kustomize installers * End-to-End testing with Kubernetes Kind and Helm +* Kustomize testing with GitHub Actions and Open Policy Agent Web API: