diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 069f89c7..0a071131 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,11 @@ #### What is this PR About? Describe the contents of the PR -#### How do we test this? -Have you followed the TESTING.md doc? If not, please provide commands/steps to test this PR. +#### Check list +- [ ] Have you created a test case in `_test/conftest-unittests.sh` +- [ ] Have you created a test case in `_test/opa-profile.sh` +- [ ] Have you created a test case in `_test/gatekeeper-integrationtests.sh` +- [ ] Have you followed the TESTING.md doc? If not, please provide commands/steps to test this PR. +- [ ] Have you re-generated `POLICIES.md` cc: @redhat-cop/rego-policies diff --git a/.github/workflows/conftest.yaml b/.github/workflows/conftest.yaml index eb400d1d..58d579d8 100644 --- a/.github/workflows/conftest.yaml +++ b/.github/workflows/conftest.yaml @@ -1,4 +1,4 @@ -name: Run conftest +name: Run conftest-unittests.sh on: [push, pull_request] diff --git a/.github/workflows/opa-profile.yaml b/.github/workflows/opa-profile.yaml new file mode 100644 index 00000000..27d00b78 --- /dev/null +++ b/.github/workflows/opa-profile.yaml @@ -0,0 +1,22 @@ +name: Run opa-profile.sh + +on: [push, pull_request] + +jobs: + opa: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Opa eval --profile + uses: garethahealy/github-actions/confbatstest@master + with: + tests: _test/opa-profile.sh + policies: '[{"name": "deprek8ion", "url":"github.com/swade1987/deprek8ion.git//policies"}]' + + - name: Upload opa-profile.log + uses: actions/upload-artifact@v2 + with: + name: profile-results + path: opa-profile.log \ No newline at end of file diff --git a/.gitignore b/.gitignore index fcb8dfd8..81e33be0 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ local.properties # BATS _test/test_helper/ +opa-profile.log ## Gatekeeper **/template.yaml diff --git a/README.md b/README.md index a846ffdc..5a0a2d48 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Run conftest](https://github.com/redhat-cop/rego-policies/workflows/Run%20conftest/badge.svg) +![Run conftest-unittests.sh](https://github.com/garethahealy/rego-policies/workflows/Run%20conftest-unittests.sh/badge.svg) # rego-policies [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policies collection. diff --git a/TESTING.md b/TESTING.md index 7e8650ba..fe286af6 100644 --- a/TESTING.md +++ b/TESTING.md @@ -12,11 +12,18 @@ Each policy must have a BATS test executed by its usecase: - unit test files will be executed by [_test/conftest-unittests.sh](_test/conftest-unittests.sh). - integration test files will be executed by [_test/gatekeeper-integrationtests.sh](_test/gatekeeper-integrationtests.sh). +Each policy, if applicable, must have an `opa eval --profile` test executed by [_test/opa-profile.sh](_test/opa-profile.sh). + ## Execute unit tests ```bash bats _test/conftest-unittests.sh ``` +## Execute profile tests +```bash +bats _test/opa-profile.sh +``` + ## Execute integration units ```bash _test/deploy-gatekeeper.sh deploy_gatekeeper @@ -38,5 +45,6 @@ The following tools must be installed locally: - [conftest](https://www.conftest.dev/install) - [konstraint](https://github.com/plexsystems/konstraint#installation) +- [bats-core](https://github.com/bats-core/bats-core) - [jq](https://stedolan.github.io/jq/download) - [yq](https://pypi.org/project/yq) \ No newline at end of file diff --git a/_test/opa-profile.sh b/_test/opa-profile.sh new file mode 100755 index 00000000..65f741ef --- /dev/null +++ b/_test/opa-profile.sh @@ -0,0 +1,442 @@ +#!/usr/bin/env bats + +load bats-support-clone +load test_helper/bats-support/load +load test_helper/redhatcop-bats-library/load + +setup_file() { + rm -rf /tmp/rhcop + rm -f opa-profile.log +} + +#################### +# ocp/bestpractices +#################### + +@test "policy/ocp/bestpractices/common-k8s-labels-notset" { + tmp=$(split_files "policy/ocp/bestpractices/common-k8s-labels-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.common_k8s_labels_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-env-maxmemory-notset" { + tmp=$(split_files "policy/ocp/bestpractices/container-env-maxmemory-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_env_maxmemory_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-image-latest" { + tmp=$(split_files "policy/ocp/bestpractices/container-image-latest/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_image_latest" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-java-xmx-set" { + tmp=$(split_files "policy/ocp/bestpractices/container-java-xmx-set/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_java_xmx_set" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-labelkey-inconsistent" { + tmp=$(split_files "policy/ocp/bestpractices/container-labelkey-inconsistent/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_labelkey_inconsistent" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-liveness-readinessprobe-equal" { + tmp=$(split_files "policy/ocp/bestpractices/container-liveness-readinessprobe-equal/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_liveness_readinessprobe_equal" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-livenessprobe-notset" { + tmp=$(split_files "policy/ocp/bestpractices/container-livenessprobe-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_livenessprobe_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-readinessprobe-notset" { + tmp=$(split_files "policy/ocp/bestpractices/container-readinessprobe-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_readinessprobe_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-limits-cpu-set" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-limits-cpu-set/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_limits_cpu_set" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-limits-memory-greater-than" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-limits-memory-greater-than/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_limits_memory_greater_than" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-limits-memory-notset" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-limits-memory-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_limits_memory_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-memoryunit-incorrect" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-memoryunit-incorrect/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_memoryunit_incorrect" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-requests-cpuunit-incorrect" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-requests-cpuunit-incorrect/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_requests_cpuunit_incorrect" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-resources-requests-memory-greater-than" { + tmp=$(split_files "policy/ocp/bestpractices/container-resources-requests-memory-greater-than/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_resources_requests_memory_greater_than" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-secret-mounted-envs" { + tmp=$(split_files "policy/ocp/bestpractices/container-secret-mounted-envs/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_secret_mounted_envs" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-volumemount-inconsistent-path" { + tmp=$(split_files "policy/ocp/bestpractices/container-volumemount-inconsistent-path/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_volumemount_inconsistent_path" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/container-volumemount-missing" { + tmp=$(split_files "policy/ocp/bestpractices/container-volumemount-missing/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.container_volumemount_missing" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/deploymentconfig-triggers-notset" { + tmp=$(split_files "policy/ocp/bestpractices/deploymentconfig-triggers-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.bestpractices.deploymentconfig_triggers_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/pod-hostnetwork" { + tmp=$(split_files "policy/ocp/bestpractices/pod-hostnetwork/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.pod_hostnetwork" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/pod-replicas-below-one" { + tmp=$(split_files "policy/ocp/bestpractices/pod-replicas-below-one/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.pod_replicas_below_one" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/pod-replicas-not-odd" { + tmp=$(split_files "policy/ocp/bestpractices/pod-replicas-not-odd/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/list.yml --profile --format=pretty data.ocp.bestpractices.pod_replicas_not_odd" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/rolebinding-roleref-apigroup-notset" { + tmp=$(split_files "policy/ocp/bestpractices/rolebinding-roleref-apigroup-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.bestpractices.rolebinding_roleref_apigroup_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/bestpractices/rolebinding-roleref-kind-notset" { + tmp=$(split_files "policy/ocp/bestpractices/rolebinding-roleref-kind-notset/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.bestpractices.rolebinding_roleref_kind_notset" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +#################### +# ocp/deprecated +#################### + +@test "policy/ocp/deprecated/3_11/buildconfig-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/buildconfig-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.buildconfig_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/deploymentconfig-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/deploymentconfig-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.deploymentconfig_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/imagestream-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/imagestream-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.imagestream_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/projectrequest-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/projectrequest-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.projectrequest_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/rolebinding-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/rolebinding-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.rolebinding_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/route-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/route-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.route_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/securitycontextconstraints-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/securitycontextconstraints-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.securitycontextconstraints_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/3_11/template-v1" { + tmp=$(split_files "policy/ocp/deprecated/3_11/template-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp3_11.template_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_1/buildconfig-custom-strategy" { + tmp=$(split_files "policy/ocp/deprecated/4_1/buildconfig-custom-strategy/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_1.buildconfig_custom_strategy" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/authorization-openshift" { + tmp=$(split_files "policy/ocp/deprecated/4_2/authorization-openshift/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.authorization_openshift" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/automationbroker-v1alpha1" { + tmp=$(split_files "policy/ocp/deprecated/4_2/automationbroker-v1alpha1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.automationbroker_v1alpha1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/catalogsourceconfigs-v1" { + tmp=$(split_files "policy/ocp/deprecated/4_2/catalogsourceconfigs-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.catalogsourceconfigs_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/catalogsourceconfigs-v2" { + tmp=$(split_files "policy/ocp/deprecated/4_2/catalogsourceconfigs-v2/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.catalogsourceconfigs_v2" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/operatorsources-v1" { + tmp=$(split_files "policy/ocp/deprecated/4_2/operatorsources-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.operatorsources_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/osb-v1" { + tmp=$(split_files "policy/ocp/deprecated/4_2/osb-v1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.osb_v1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_2/servicecatalog-v1beta1" { + tmp=$(split_files "policy/ocp/deprecated/4_2/servicecatalog-v1beta1/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_2.servicecatalog_v1beta1" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/ocp/deprecated/4_3/buildconfig-jenkinspipeline-strategy" { + tmp=$(split_files "policy/ocp/deprecated/4_3/buildconfig-jenkinspipeline-strategy/test_data/unit") + + cmd="opa eval --bundle policy/ --input ${tmp}/example.yml --profile --format=pretty data.ocp.deprecated.ocp4_3.buildconfig_jenkinspipeline_strategy" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +#################### +# podman +#################### + +@test "policy/podman/history/contains-layer" { + tmp=$(split_files "policy/podman/history/contains-layer/test_data/unit/jenkins-python-mising.json" "true") + + cmd="opa eval --bundle policy/ --input ${tmp}/jenkins-python-mising.json --profile --format=pretty data.podman.history.contains_layer" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} + +@test "policy/podman/images/image-size-not-greater-than" { + tmp=$(split_files "policy/podman/images/image-size-not-greater-than/test_data/unit" "true") + + cmd="opa eval --bundle policy/ --input ${tmp}/jenkins-base.json --profile --format=pretty data.podman.images.image_size_not_greater_than" + run ${cmd} + + echo "${cmd} ${output}" >> opa-profile.log + [ "$status" -eq 0 ] +} \ No newline at end of file diff --git a/policy/ocp/bestpractices/container-image-latest/test_data/unit/list.yml b/policy/ocp/bestpractices/container-image-latest/test_data/unit/list.yml index bca8d87a..cd244e15 100644 --- a/policy/ocp/bestpractices/container-image-latest/test_data/unit/list.yml +++ b/policy/ocp/bestpractices/container-image-latest/test_data/unit/list.yml @@ -7,7 +7,6 @@ items: metadata: name: imageuseslatesttag spec: - replicas: 3 template: spec: containers: @@ -18,7 +17,6 @@ items: metadata: name: imageuseslatesttag spec: - replicas: 3 template: spec: containers: