├── COMPONENT_VERSION ├── RELEASE_MAIN_BRANCH ├── COMPONENT_NAME ├── CHANGELOG ├── CHANGELOG-v0.5.0.md ├── CHANGELOG-v0.8.0.md ├── CHANGELOG-v0.7.0.md └── CHANGELOG-v0.9.0.md ├── test ├── dryrun │ ├── no_ns │ │ ├── ns_role │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ └── enforce_ns │ │ │ ├── input_ns.yaml │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ ├── ns_selector │ │ ├── ns_default │ │ │ ├── desired_status.yaml │ │ │ ├── input.yaml │ │ │ └── output.txt │ │ └── ns_selector_test.go │ ├── kind_field │ │ ├── pod_annotation_match │ │ │ ├── input_ns.yaml │ │ │ ├── output.txt │ │ │ └── input_1.yaml │ │ ├── pod_label_invalid │ │ │ ├── input_ns.yaml │ │ │ ├── input_1.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ ├── pod_annotation_invalid │ │ │ ├── input_ns.yaml │ │ │ ├── input_1.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ └── pod_annotation_mismatch │ │ │ ├── input_ns.yaml │ │ │ ├── output.txt │ │ │ ├── input_1.yaml │ │ │ └── policy.yaml │ ├── context_vars │ │ ├── object_pod_default_func │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ ├── output_from_cluster.txt │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ ├── object_pod_nsselector │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ ├── error.txt │ │ │ └── policy.yaml │ │ ├── object_namespaced │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ ├── output_from_cluster.txt │ │ │ └── output.txt │ │ ├── object_templated_ns │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ ├── error.txt │ │ │ └── policy.yaml │ │ ├── object_unnamed_objdef │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ ├── error.txt │ │ │ └── policy.yaml │ │ ├── object_cluster_scoped │ │ │ ├── input_ns.yaml │ │ │ ├── output.txt │ │ │ ├── output_from_cluster.txt │ │ │ └── policy.yaml │ │ ├── objectns_cluster_scoped │ │ │ ├── input_ns.yaml │ │ │ ├── error.txt │ │ │ └── policy.yaml │ │ ├── objectns_templated_empty │ │ │ ├── output.txt │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ └── policy.yaml │ │ ├── objectns_templated_no_nsselector │ │ │ ├── input_ns.yaml │ │ │ ├── output.txt │ │ │ ├── input.yaml │ │ │ └── policy.yaml │ │ ├── objectname_nsselector │ │ │ ├── input_ns.yaml │ │ │ ├── input.yaml │ │ │ └── policy.yaml │ │ └── object_pod │ │ │ ├── input.yaml │ │ │ ├── output_from_cluster.txt │ │ │ ├── output.txt │ │ │ └── policy.yaml │ ├── no_name │ │ ├── with_object_selector │ │ │ ├── musthave_mixed_noncompliant │ │ │ │ ├── input_ns.yaml │ │ │ │ ├── input_good.yaml │ │ │ │ └── policy.yaml │ │ │ ├── mustnothave_mixed_noncompliant │ │ │ │ ├── input_ns.yaml │ │ │ │ ├── input_good.yaml │ │ │ │ ├── output.txt │ │ │ │ └── policy.yaml │ │ │ └── mustnothave_unmatched │ │ │ │ ├── input.yaml │ │ │ │ ├── output.txt │ │ │ │ ├── desired_status.yaml │ │ │ │ └── policy.yaml │ │ ├── noncompliant_related_obj │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ ├── compliant_related_obj │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ ├── input_good.yaml │ │ │ └── policy.yaml │ │ ├── mustnothave_compliant_related_obj │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ ├── mustnothave_compliant_related_obj_1 │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ ├── input.yaml │ │ │ └── policy.yaml │ │ └── mustnothave_noncompliant_related_obj_1 │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ ├── input_good.yaml │ │ │ └── policy.yaml │ ├── no_name_clusterscope │ │ ├── noncompliant_related_obj │ │ │ ├── input_bad.yaml │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ └── compliant_related_obj │ │ │ ├── desired_status.yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ ├── diff │ │ ├── secret_obj_temp │ │ │ ├── input.yaml │ │ │ ├── desired_status.yaml │ │ │ ├── policy.yaml │ │ │ └── output.txt │ │ ├── from_secret_obj_temp │ │ │ ├── input.yaml │ │ │ ├── policy.yaml │ │ │ ├── desired_status.yaml │ │ │ └── output.txt │ │ └── from_secret_obj_temp_raw │ │ │ ├── input.yaml │ │ │ ├── policy.yaml │ │ │ ├── desired_status.yaml │ │ │ └── output.txt │ ├── obj_tmpl_raw │ │ ├── invalid_yaml │ │ │ ├── output.txt │ │ │ └── policy.yaml │ │ └── range │ │ │ ├── output.txt │ │ │ └── input.yaml │ ├── missing │ │ ├── missing_name │ │ │ ├── output.txt │ │ │ └── input_ns_1.yaml │ │ ├── missing_kind │ │ │ ├── output.txt │ │ │ ├── input_ns_1.yaml │ │ │ ├── input_1.yaml │ │ │ ├── input_2.yaml │ │ │ └── input_3.yaml │ │ └── missing_kind_name │ │ │ ├── output.txt │ │ │ ├── input_ns_1.yaml │ │ │ └── input_1.yaml │ └── multiple │ │ ├── multiple_obj_combo │ │ ├── input_1.yaml │ │ ├── input_2.yaml │ │ └── output.txt │ │ ├── multiple_obj_template │ │ ├── input_ns.yaml │ │ └── output.txt │ │ ├── multiple_namespace_enforce │ │ ├── input_ns_1.yaml │ │ └── output.txt │ │ ├── multiple_namespace_inform │ │ ├── input_ns_1.yaml │ │ └── output.txt │ │ └── multiple_mustnothave │ │ ├── output.txt │ │ └── policy.yaml ├── scripts │ └── README.md └── resources │ ├── case13_templatization │ ├── case13_configmap.yaml │ ├── case13_secret.yaml │ ├── case13_clusterclaim.yaml │ ├── case13_prune_template_error.yaml │ ├── case13_copysecret.yaml │ ├── case13_verifysecret.yaml │ ├── case13_copy_referenced_configmap.yaml │ ├── case13_unterminated.yaml │ ├── case13_lookup_secret.yaml │ ├── case13_pod_name_verify.yaml │ ├── case13_fromsecret.yaml │ ├── case13_update_referenced_object.yaml │ ├── case13_pod_name_verify_configmap.yaml │ └── case13_pod_nameFromClusterClaim.yaml │ ├── case42_resource_selector │ ├── case42_behavior_nomatch.yaml │ ├── case42_behavior_extraobj.yaml │ ├── case42_eval_prereq.yaml │ ├── case42_behavior_prereq.yaml │ ├── case42_results_policy.yaml │ ├── case42_behavior_policy.yaml │ ├── case42_mnh_policy.yaml │ └── case42_eval_policy.yaml │ ├── case16_policy_template_decryption │ ├── secret-invalid.yaml │ ├── secret.yaml │ ├── secret-diff-key.yaml │ ├── policy.yaml │ ├── policy-invalid-iv.yaml │ ├── policy-diff-key.yaml │ └── policy-invalid-key.yaml │ ├── case43_standalone_hub_templates │ ├── hub-configmap.yaml │ ├── hub-configmap-modified.yaml │ ├── hub-secret.yaml │ ├── config-policy-modified.yaml │ └── operator-policy.yaml │ ├── case33_empty_label_handling │ ├── configmap.yaml │ └── empty-labels-config.yaml │ ├── case47_ratelimit │ ├── case47-configmap-to-watch.yaml │ └── case47-cfgpolicy.yaml │ ├── case38_operator_install │ ├── extra-operator-group.yaml │ ├── template-configmap.yaml │ ├── scoped-operator-group.yaml │ ├── parent-policy.yaml │ ├── incorrect-operator-group.yaml │ ├── subscription.yaml │ └── operator-policy-all-defaults.yaml │ ├── case41_custom_message │ └── case41-parent.yaml │ ├── e2e_controller_secret.yaml │ ├── case20_delete_objects │ ├── case20_pod.yaml │ ├── case20_inform_pod.yaml │ ├── case20_change_config_policy_not_prune.yaml │ ├── case20_create_pod.yaml │ ├── case20_change_enforce.yaml │ ├── case20_change_inform.yaml │ ├── case20_musthave_pod_deleteall.yaml │ ├── case20_enforce_noncreated_pod.yaml │ └── case20_change_config_policy.yaml │ ├── managed1-cluster.yaml │ ├── case40_recreate_option │ ├── configmap-with-finalizer.yaml │ ├── policy-always-recreate-option.yaml │ └── deployment.yaml │ ├── case45_set_empty_field │ ├── sriov_config.yaml │ └── policy.yaml │ ├── case14_namespaces │ ├── case14_limitrange.yaml │ └── case14_configmaps_policy.yaml │ ├── case15_event_format │ ├── case15_becomesnoncompliant_pod.yaml │ └── case15_mh_pod_nevercompliant.yaml │ ├── case19_ns_selector │ ├── case19_behavior_prereq.yaml │ ├── case19_results_policy.yaml │ └── case19_behavior_policy.yaml │ ├── case30_multiline_templatization │ ├── case30_configmaps.yaml │ ├── case30_policy_notemplate.yaml │ ├── case30_policy.yaml │ ├── case30_no_object.yaml │ └── case30_unterminated.yaml │ ├── case18_discovery_refresh │ ├── bad-apiservice.yaml │ └── policy-template.yaml │ ├── case6_no_ns │ └── case6_create_ns.yaml │ ├── case28_metric │ ├── case28_operatorpolicy.yaml │ └── case28_policy.yaml │ ├── case23_invalid_field │ ├── policy.yaml │ └── policy-ignore-status-field.yaml │ ├── case17_evaluation_interval │ ├── policy-never-reevaluate.yaml │ └── policy.yaml │ ├── case3_imgvuln │ ├── case3_vuln.yaml │ └── case3_vuln_object.yaml │ ├── case9_md_check │ ├── case9_mustonlyhave_nolabels.yaml │ ├── case9_checkns-md-mh.yaml │ ├── case9_checkns-md-moh.yaml │ ├── case9_multianno_ns_create.yaml │ ├── case9_no_annos.yaml │ ├── case9_pod_create.yaml │ ├── case9_annos.yaml │ ├── case9_label_check.yaml │ ├── case9_label_patch.yaml │ └── case9_ns_create.yaml │ ├── case8_status_check │ ├── case8_service.yaml │ ├── case8_status_check.yaml │ ├── case8_status_check_fail.yaml │ ├── case8_status_enforce_fail.yaml │ ├── case8_pod.yaml │ └── case8_pod_fail.yaml │ ├── case26_user_error_metric │ └── case26-missing-crd.yaml │ ├── case29_trigger_uninstall │ ├── policy.yaml │ └── policy2.yaml │ ├── case44_template_vars │ ├── case44_objectns_var_invalid_ns.yaml │ ├── case44_objectname_var_noselector_ns.yaml │ ├── case44_objectns_var_prereqs.yaml │ ├── case44_objectns_var.yaml │ └── case44_objectname_var_invalid_name.yaml │ ├── case36_empty_map │ ├── deployment.yaml │ └── policy-should-not-add-empty-map.yaml │ ├── case39_diff_generation │ ├── case39-create-cfgmap-policy.yaml │ ├── case39-update-cfgmap-policy.yaml │ └── case39-status-cfgmap-policy.yaml │ ├── case1_pod_handling │ ├── case1_pod_check-mh.yaml │ ├── case1_pod_check-mnh-incomplete.yaml │ ├── case1_pod_check-moh.yaml │ ├── ns_deleting.yaml │ ├── ns_nonexist.yaml │ ├── case1_pod_create_empty_list.yaml │ ├── case1_pod_check-mnh.yaml │ ├── case1_pod_create_enforce.yaml │ ├── case1_pod_create_inform.yaml │ ├── case1_pod_check_multiple_mh.yaml │ └── case1_pod_check_empty_list.yaml │ ├── case27_showupdateinstatus │ ├── case27-create-cfgmap-policy.yaml │ └── case27-update-cfgmap-policy.yaml │ ├── case34_enforce_w_status │ ├── config-policy-updated.yaml │ └── config-policy.yaml │ ├── case4_clusterversion │ ├── case4_clusterversion_inform.yaml │ ├── case4_clusterversion_create.yaml │ └── case4_clusterversion_patch.yaml │ ├── case21_alternative_kubeconfig │ ├── policy.yaml │ └── parent-policy.yaml │ ├── case22_pod_update_image │ └── policy.yaml │ ├── case2_role_handling │ ├── case2_rolebinding_create_patch.yaml │ ├── case2_role_check-moh.yaml │ ├── case2_role_check-mnh.yaml │ └── case2_role_create_inform.yaml │ ├── case12_list_compare │ ├── case12_role_create.yaml │ └── case12_pod_inform.yaml │ ├── case5_multi │ └── case5_single_mh.yaml │ └── grc-operators │ └── catalog.yaml ├── pkg └── dryrun │ ├── utils_testdata │ ├── test_no_color │ │ ├── input.yaml │ │ ├── output.txt │ │ └── actual.yaml │ ├── test_simple │ │ ├── input.yaml │ │ ├── output.txt │ │ └── actual.yaml │ ├── test_array_user_input_error │ │ ├── input.yaml │ │ ├── output.txt │ │ └── actual.yaml │ ├── test_string_array_match │ │ ├── output.txt │ │ └── input.yaml │ ├── test_string_array_not_match │ │ ├── input.yaml │ │ └── output.txt │ ├── test_one_match │ │ ├── output.txt │ │ └── input.yaml │ ├── test_multiple_relobj_compliant │ │ ├── input.yaml │ │ └── output.txt │ ├── test_array_match │ │ ├── input.yaml │ │ ├── output.txt │ │ └── actual.yaml │ ├── test_multiple_array_input │ │ ├── input.yaml │ │ └── output.txt │ └── test_array_no_match │ │ ├── input.yaml │ │ ├── output.txt │ │ └── actual.yaml │ └── testdata │ ├── test_unwatchable_mappings │ ├── input_resource.yaml │ ├── output.txt │ ├── mappings.yaml │ └── policy.yaml │ ├── test_basic_compliant │ ├── output.txt │ ├── input_1.yaml │ └── policy.yaml │ ├── test_mappings │ ├── output.txt │ ├── input_resource.yaml │ ├── mappings.yaml │ └── policy.yaml │ ├── test_bad_fields_creation │ ├── output.txt │ └── input_pod.yaml │ ├── test_stdin │ ├── input_stdin.yaml │ ├── output.txt │ └── policy.yaml │ ├── test_multiple_resources │ ├── input_3.yaml │ ├── input_4.yaml │ ├── input_stdin.yaml │ └── output.txt │ ├── test_wrapped_in_policy │ ├── input_1.yaml │ └── output.txt │ ├── test_basic_noncompliant │ ├── input_1.yaml │ ├── output.txt │ └── policy.yaml │ ├── test_directory_input │ ├── input_directory │ │ ├── input_3.yaml │ │ ├── input_4.yaml │ │ ├── deep │ │ │ └── nonexist.yaml │ │ └── input_1-2.yaml │ └── output.txt │ ├── test_desired_status │ ├── desired_status.yaml │ ├── output.txt │ └── policy.yaml │ ├── README.md │ ├── test_embed_policy │ └── output.txt │ └── test_multiple_object_templates │ ├── input_pods.yaml │ ├── output.txt │ └── policy.yaml ├── deploy ├── manager │ ├── kustomization.yaml │ └── service-account.yaml ├── rbac │ ├── kustomization.yaml │ ├── auth_cluster_role.yaml │ ├── auth_cluster_role_binding.yaml │ └── metrics_reader.yaml └── crds │ ├── kustomize_operatorpolicy │ ├── template-label.json │ ├── remove-diff.json │ └── remove-matches-after-dry-run.json │ └── kustomize_configurationpolicy │ ├── template-label.json │ ├── obj-template-validation.json │ └── kustomization.yaml ├── Makefile.prow ├── hack └── boilerplate.go.txt ├── SECURITY.md ├── .dockerignore ├── CODE_OF_CONDUCT.md ├── version └── version.go ├── images └── config-policy-controller-architecture-diagram.png ├── OWNERS ├── CONTRIBUTING.md ├── tools.go ├── cmd └── dryrun │ └── main.go ├── .github └── workflows │ ├── framework-kind.yml │ ├── fossa.yml │ └── go-postsubmit.yml ├── config └── crd │ ├── patches │ ├── cainjection_in_operatorpolicies.yaml │ └── webhook_in_operatorpolicies.yaml │ └── kustomizeconfig.yaml ├── sonar-project.properties └── PROJECT /COMPONENT_VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 -------------------------------------------------------------------------------- /RELEASE_MAIN_BRANCH: -------------------------------------------------------------------------------- 1 | main -------------------------------------------------------------------------------- /COMPONENT_NAME: -------------------------------------------------------------------------------- 1 | config-policy-controller -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-v0.5.0.md: -------------------------------------------------------------------------------- 1 | # Initial release 2 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/ns_role/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_no_color/input.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_simple/input.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | -------------------------------------------------------------------------------- /test/dryrun/ns_selector/ns_default/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: Compliant 2 | -------------------------------------------------------------------------------- /deploy/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ./manager.yaml 3 | - ./service-account.yaml 4 | - ../rbac/ 5 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/enforce_ns/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: e2etest 5 | spec: {} 6 | -------------------------------------------------------------------------------- /Makefile.prow: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Open Cluster Management project 2 | 3 | -include /opt/build-harness/Makefile.prow 4 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Red Hat, Inc. 2 | // Copyright Contributors to the Open Cluster Management project 3 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | Refer to our [Community Security Response](https://github.com/open-cluster-management-io/community/blob/main/SECURITY.md). 2 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_match/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: managed 5 | spec: {} 6 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_label_invalid/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: managed 5 | spec: {} 6 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_default_func/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: dangler 6 | 7 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_nsselector/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: dangler 6 | 7 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_invalid/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: managed 5 | spec: {} 6 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_mismatch/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: managed 5 | spec: {} 6 | -------------------------------------------------------------------------------- /test/scripts/README.md: -------------------------------------------------------------------------------- 1 | [comment]: # ( Copyright Contributors to the Open Cluster Management project ) 2 | 3 | # Copyright (c) 2020 Red Hat, Inc. -------------------------------------------------------------------------------- /deploy/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - metrics_reader.yaml 4 | - auth_cluster_role.yaml 5 | - auth_cluster_role_binding.yaml 6 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: e2e13config 5 | data: 6 | name: c13-pod -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | .go/ 6 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/musthave_mixed_noncompliant/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: default 5 | spec: {} 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Refer to our [Open Cluster Management Community Code of Conduct](https://github.com/open-cluster-management/community/blob/main/CODE_OF_CONDUCT.md) 2 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_mixed_noncompliant/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: default 5 | spec: {} 6 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_behavior_nomatch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: config-policy-controller.io/v1 2 | kind: FakeAPI 3 | metadata: 4 | name: case42-4-e2e 5 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_namespaced/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | labels: 7 | box: big 8 | 9 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_templated_ns/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | labels: 7 | box: big 8 | 9 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_user_input_error/input.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | notMatch: 3 | name: mymatch 4 | lastEvaluatedGeneration: 5 | - name: typeNotMatch 6 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_unnamed_objdef/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | labels: 7 | box: big 8 | 9 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Red Hat, Inc. 2 | // Copyright Contributors to the Open Cluster Management project 3 | 4 | package version 5 | 6 | var Version = "0.0.1" 7 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_unwatchable_mappings/input_resource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: template.openshift.io/v1 2 | kind: Template 3 | metadata: 4 | name: something 5 | spec: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_no_color/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does not match 'Compliant' 3 | Expected status does not match the actual status 4 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/secret-invalid.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: policy-encryption-key 5 | data: 6 | key: UmFsZWlnaAo= 7 | -------------------------------------------------------------------------------- /test/resources/case43_standalone_hub_templates/hub-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | namespace: default 5 | name: case43-input 6 | data: 7 | info: hello 8 | -------------------------------------------------------------------------------- /images/config-policy-controller-architecture-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open-cluster-management-io/config-policy-controller/HEAD/images/config-policy-controller-architecture-diagram.png -------------------------------------------------------------------------------- /test/resources/case33_empty_label_handling/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: case33-configmap 5 | namespace: managed 6 | labels: 7 | test: "test-label" -------------------------------------------------------------------------------- /test/resources/case47_ratelimit/case47-configmap-to-watch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: case47-configmap-to-watch 5 | namespace: default 6 | data: 7 | foo: "0" 8 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_simple/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does not match 'Compliant' 3 |  Expected status does not match the actual status 4 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_mismatch/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod managed/-: 3 | 4 | # Compliance messages: 5 | NonCompliant; violation - pods found but not as specified in namespace managed 6 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: e2esecret 5 | type: Opaque 6 | data: 7 | USER_NAME: YWRtaW4= 8 | PASSWORD: MWYyZDFlMmU2N2Rm -------------------------------------------------------------------------------- /test/resources/case43_standalone_hub_templates/hub-configmap-modified.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | namespace: default 5 | name: case43-input 6 | data: 7 | info: changed 8 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/extra-operator-group.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1 2 | kind: OperatorGroup 3 | metadata: 4 | name: extra-operator-group 5 | spec: 6 | targetNamespaces: [] 7 | -------------------------------------------------------------------------------- /test/dryrun/no_name/noncompliant_related_obj/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Ingress 4 | metadata: 5 | name: '-' 6 | reason: Resource found but does not match 7 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/noncompliant_related_obj/input_bad.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: IngressClass 3 | metadata: 4 | name: ingress-class 5 | spec: 6 | controller: alien.giant/web 7 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_behavior_extraobj.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: config-policy-controller.io/v1 2 | kind: FakeAPI 3 | metadata: 4 | labels: 5 | case42: case42-3-e2e 6 | name: case42-3-e2e 7 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - dhaiducek 3 | - gparvin 4 | - JustinKuli 5 | - yiraeChristineKim 6 | - jan-law 7 | reviewers: 8 | - dhaiducek 9 | - gparvin 10 | - JustinKuli 11 | - yiraeChristineKim 12 | - jan-law 13 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_compliant/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | 4 | # Compliance messages: 5 | Compliant; notification - pods [nginx-pod-e2e] found as specified in namespace default 6 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_string_array_match/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .relatedObjects[0] matches 3 | .relatedObjects matches 4 |  Expected status matches the actual status 5 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_cluster_scoped/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | labels: 7 | box: big 8 | annotations: 9 | city: durham 10 | -------------------------------------------------------------------------------- /test/dryrun/diff/secret_obj_temp/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: case39-secret 5 | namespace: default 6 | type: Opaque 7 | data: 8 | message: VGhlcmUncyBhIHNuYWtlIGluIG15IGJvb3Qh 9 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_cluster_scoped/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | labels: 7 | box: big 8 | annotations: 9 | city: durham 10 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: case39-secret 5 | namespace: default 6 | type: Opaque 7 | data: 8 | message: VGhlcmUncyBhIHNuYWtlIGluIG15IGJvb3Qh 9 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/enforce_ns/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Namespace 4 | metadata: 5 | name: e2etest 6 | reason: Resource found as expected 7 | compliant: Compliant 8 | -------------------------------------------------------------------------------- /test/dryrun/obj_tmpl_raw/invalid_yaml/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | # Compliance messages: 3 | NonCompliant; violation - Error parsing object-templates-raw YAML: error converting YAML to JSON: yaml: unknown anchor 'odd' referenced 4 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_mappings/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 LimitRange default/mem-limit-range: 3 | 4 | # Compliance messages: 5 | Compliant; notification - limitranges [mem-limit-range] found as specified in namespace default 6 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp_raw/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: case39-secret 5 | namespace: default 6 | type: Opaque 7 | data: 8 | message: VGhlcmUncyBhIHNuYWtlIGluIG15IGJvb3Qh 9 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_name/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod n1/-: 3 | 4 | v1 Pod n2/-: 5 | 6 | v1 Pod n3/-: 7 | 8 | # Compliance messages: 9 | NonCompliant; violation - pods not found in namespaces: n1, n2, n3 10 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_clusterclaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cluster.open-cluster-management.io/v1alpha1 2 | kind: ClusterClaim 3 | metadata: 4 | name: testclaim.open-cluster-management.io 5 | spec: 6 | value: c13-pod -------------------------------------------------------------------------------- /deploy/crds/kustomize_operatorpolicy/template-label.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op":"add", 4 | "path":"/metadata/labels", 5 | "value": {"policy.open-cluster-management.io/policy-type": "template"} 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_string_array_match/input.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - compliant: Compliant 3 | object: 4 | apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: test1 8 | data: ["one","two"] 9 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_namespaced/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: inventory 6 | namespace: mega-mart 7 | data: 8 | inventory.yaml: |- 9 | appliance: toaster 10 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_templated_ns/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: inventory 6 | namespace: mega-mart 7 | data: 8 | inventory.yaml: |- 9 | appliance: toaster 10 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/template-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: op-config 5 | data: 6 | channel: "fakechannel" 7 | namespaces: '["foo", "bar", "operator-policy-testns"]' 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | Please see the Policy SIG 4 | [Contributing guide](https://github.com/open-cluster-management-io/community/blob/main/sig-policy/contribution-guidelines.md) 5 | to learn how to get involved. 6 | -------------------------------------------------------------------------------- /deploy/crds/kustomize_configurationpolicy/template-label.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op":"add", 4 | "path":"/metadata/labels", 5 | "value": {"policy.open-cluster-management.io/policy-type": "template"} 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_bad_fields_creation/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/useless-metadata-pod: 3 | 4 | # Compliance messages: 5 | Compliant; notification - pods [useless-metadata-pod] found as specified in namespace default 6 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_unnamed_objdef/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: inventory 6 | namespace: mega-mart 7 | data: 8 | inventory.yaml: |- 9 | appliance: toaster 10 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_empty/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | # Compliance messages: 3 | NonCompliant; violation - namespaced object templated-ns-configmap of kind ConfigMap has no namespace specified after template resolution 4 | -------------------------------------------------------------------------------- /test/dryrun/no_name/compliant_related_obj/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Ingress 4 | metadata: 5 | name: good-ingress 6 | reason: Resource found as expected 7 | compliant: Compliant 8 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | # Compliance messages: 3 | NonCompliant; violation - The kind and apiVersion fields are required on the object template at index 0 in policy policy-multi-namespace-enforce-kind-missing 4 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Ingress 4 | metadata: 5 | name: '-' 6 | reason: Resource not found as expected 7 | compliant: Compliant 8 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/scoped-operator-group.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1 2 | kind: OperatorGroup 3 | metadata: 4 | name: scoped-operator-group 5 | spec: 6 | targetNamespaces: 7 | - "operator-policy-testns" 8 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_unwatchable_mappings/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | template.openshift.io/v1 Template default/something: 3 | 4 | # Compliance messages: 5 | Compliant; notification - templates [something] found as specified in namespace default 6 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_string_array_not_match/input.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - compliant: Compliant 3 | object: 4 | apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: test1 8 | data: ["one","two","not match"] 9 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind_name/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | # Compliance messages: 3 | NonCompliant; violation - The kind and apiVersion fields are required on the object template at index 0 in policy policy-multi-namespace-enforce-both-missing 4 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj_1/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Ingress 4 | metadata: 5 | name: '-' 6 | reason: Resource not found as expected 7 | compliant: Compliant 8 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/compliant_related_obj/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: IngressClass 4 | metadata: 5 | name: '-' 6 | reason: Resource not found as expected 7 | compliant: Compliant 8 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_empty/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: my-namespace 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: my-other-namespace 11 | 12 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_unmatched/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | namespace: default 5 | name: good-configmap 6 | labels: 7 | isLower: 'true' 8 | privileged: 'no' 9 | 10 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/parent-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: Policy 3 | metadata: 4 | name: parent-policy 5 | spec: 6 | remediationAction: inform 7 | disabled: false 8 | policy-templates: [] 9 | -------------------------------------------------------------------------------- /test/resources/case41_custom_message/case41-parent.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: Policy 3 | metadata: 4 | name: case41-parent 5 | spec: 6 | remediationAction: inform 7 | disabled: false 8 | policy-templates: [] 9 | -------------------------------------------------------------------------------- /deploy/crds/kustomize_operatorpolicy/remove-diff.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "remove", 4 | "path": "/spec/versions/0/schema/openAPIV3Schema/properties/status/properties/relatedObjects/items/properties/properties/properties/diff" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/noncompliant_related_obj/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: IngressClass 4 | metadata: 5 | name: '-' 6 | reason: Resource found but does not match 7 | compliant: NonCompliant 8 | -------------------------------------------------------------------------------- /test/dryrun/ns_selector/ns_default/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: sample-nginx-pod 5 | spec: 6 | containers: 7 | - image: nginx:1.18.0 8 | name: nginx 9 | ports: 10 | - containerPort: 80 11 | -------------------------------------------------------------------------------- /test/resources/e2e_controller_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | type: kubernetes.io/service-account-token 4 | metadata: 5 | name: config-policy-controller 6 | annotations: 7 | kubernetes.io/service-account.name: config-policy-controller 8 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_no_nsselector/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: my-namespace 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: my-other-namespace 11 | 12 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e20 5 | spec: 6 | containers: 7 | - image: nginx:1.7.9 8 | name: nginx 9 | ports: 10 | - containerPort: 80 11 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_noncompliant_related_obj_1/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - object: 3 | kind: Ingress 4 | metadata: 5 | name: good-ingress 6 | reason: Resource found but should not exist 7 | compliant: NonCompliant 8 | -------------------------------------------------------------------------------- /test/resources/managed1-cluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterregistry.k8s.io/v1alpha1 2 | kind: Cluster 3 | metadata: 4 | labels: 5 | cloud: auto-detect 6 | name: managed1 7 | vendor: auto-detect 8 | name: managed1 9 | namespace: managed1 10 | spec: {} -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_one_match/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 |  Expected status matches the actual status 6 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_string_array_not_match/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .relatedObjects[0] does not match any elements 3 | .relatedObjects does not match the elements 4 |  Expected status does not match the actual status 5 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_no_nsselector/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 ConfigMap my-namespace/templated-ns-configmap: 3 | 4 | # Compliance messages: 5 | Compliant; notification - configmaps [templated-ns-configmap] found as specified in namespace my-namespace 6 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: policy-encryption-key 5 | data: 6 | key: KoDiOoIjFile8dPqAyd+XbDAwqGpMQ8YhYukZJnOtt4= 7 | previousKey: QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE= 8 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/secret-diff-key.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: policy-encryption-key 5 | data: 6 | key: QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI= 7 | previousKey: KoDiOoIjFile8dPqAyd+XbDAwqGpMQ8YhYukZJnOtt4= 8 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/incorrect-operator-group.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1 2 | kind: OperatorGroup 3 | metadata: 4 | name: incorrect-operator-group 5 | spec: 6 | targetNamespaces: 7 | - "the-limit-does-not-exist" 8 | - "bad-namespace" 9 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_obj_combo/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: default 5 | name: nginx-pod-1 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_obj_combo/input_2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: default 5 | name: nginx-pod-2 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_compliant/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_stdin/input_stdin.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: engine-x 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_multiple_relobj_compliant/input.yaml: -------------------------------------------------------------------------------- 1 | compliant: Compliant 2 | relatedObjects: 3 | - compliant: Compliant 4 | object: 5 | apiVersion: v1 6 | kind: Namespace 7 | - compliant: Compliant 8 | object: 9 | apiVersion: v1 10 | kind: Pod 11 | -------------------------------------------------------------------------------- /test/resources/case40_recreate_option/configmap-with-finalizer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: case40 5 | namespace: default 6 | finalizers: 7 | - policy.open-cluster-management.io/case40 8 | data: 9 | city: Durham 10 | state: NC 11 | -------------------------------------------------------------------------------- /deploy/crds/kustomize_operatorpolicy/remove-matches-after-dry-run.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op": "remove", 4 | "path": "/spec/versions/0/schema/openAPIV3Schema/properties/status/properties/relatedObjects/items/properties/properties/properties/matchesAfterDryRun" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_resources/input_3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-3 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_resources/input_4.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-4 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_wrapped_in_policy/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: engine-x 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_match/input.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | conditions: 4 | - message: namespaces [test1] found as specified 5 | reason: K8s `must have` object already exists 6 | compliant: Compliant 7 | lastEvaluatedGeneration: 1 8 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_multiple_array_input/input.yaml: -------------------------------------------------------------------------------- 1 | compliant: Compliant 2 | relatedObjects: 3 | - compliant: Compliant 4 | object: 5 | apiVersion: v1 6 | kind: ConfigMap 7 | - compliant: Compliant 8 | object: 9 | apiVersion: v1 10 | kind: Namespace 11 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_noncompliant/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: engine-x 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_default_func/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: nginx-pod 6 | namespace: default 7 | spec: 8 | containers: 9 | - image: nginx:1.7.9 10 | name: nginx 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_nsselector/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: nginx-pod 6 | namespace: default 7 | spec: 8 | containers: 9 | - image: nginx:1.7.9 10 | name: nginx 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_mappings/input_resource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: LimitRange # limit memory usage 3 | metadata: 4 | name: mem-limit-range 5 | spec: 6 | limits: 7 | - default: 8 | memory: 512Mi 9 | defaultRequest: 10 | memory: 256Mi 11 | type: Container 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_mappings/mappings.yaml: -------------------------------------------------------------------------------- 1 | - Group: "" 2 | Kind: LimitRange 3 | Plural: limitranges 4 | Scope: namespace 5 | Singular: limitrange 6 | Version: v1 7 | - Group: "" 8 | Kind: Fake 9 | Plural: fakes 10 | Scope: root 11 | Singular: fake 12 | Version: beta1 13 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_eval_prereq.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: case42-e2e-3 5 | --- 6 | apiVersion: config-policy-controller.io/v1 7 | kind: FakeAPI 8 | metadata: 9 | labels: 10 | case42: case42-1-e2e 11 | name: case42-1-e2e 12 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Red Hat, Inc. 2 | // Copyright Contributors to the Open Cluster Management project 3 | //go:build tools 4 | // +build tools 5 | 6 | // Place any runtime dependencies as imports in this file. 7 | // Go modules will be forced to download and install them. 8 | package tools 9 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_directory_input/input_directory/input_3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default-3 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_directory_input/input_directory/input_4.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default-4 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /test/resources/case45_set_empty_field/sriov_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: sriovnetwork.openshift.io/v1 2 | kind: SriovOperatorConfig 3 | metadata: 4 | name: default 5 | namespace: default 6 | spec: 7 | configDaemonNodeSelector: 8 | node-role.kubernetes.io/master: "" 9 | disableDrain: true 10 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_directory_input/input_directory/deep/nonexist.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: nonexist 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_match/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Namespace default: 3 | 4 | v1 Pod managed/nginx-pod-e2e-10: 5 | 6 | # Compliance messages: 7 | Compliant; notification - namespaces [default] found as specified; notification - pods [nginx-pod-e2e-10] found as specified in namespace managed 8 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_obj_combo/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-1: 3 | 4 | v1 Pod default/nginx-pod-2: 5 | 6 | # Compliance messages: 7 | NonCompliant; violation - pods [nginx-pod-1] found in namespace default; notification - pods [nginx-pod-2] found as specified in namespace default 8 | -------------------------------------------------------------------------------- /test/resources/case14_namespaces/case14_limitrange.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: LimitRange 3 | metadata: 4 | name: container-mem-limit-range 5 | spec: 6 | limits: 7 | - default: 8 | ephemeral-storage: '0' 9 | defaultRequest: 10 | ephemeral-storage: '0' 11 | type: Container -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_desired_status/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: Compliant 2 | compliancyDetails: 3 | - Compliant: Compliant 4 | Validity: {} 5 | conditions: 6 | - message: hello not match 7 | relatedObjects: 8 | - compliant: NonCompliant 9 | object: 10 | apiVersion: v1 11 | kind: Pod 12 | -------------------------------------------------------------------------------- /test/dryrun/obj_tmpl_raw/range/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-1: 3 | 4 | v1 Pod default/nginx-pod-2: 5 | 6 | # Compliance messages: 7 | Compliant; notification - pods [nginx-pod-1] found as specified in namespace default; notification - pods [nginx-pod-2] found as specified in namespace default 8 | -------------------------------------------------------------------------------- /test/resources/case15_event_format/case15_becomesnoncompliant_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: case15-becomesnoncompliant 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_one_match/input.yaml: -------------------------------------------------------------------------------- 1 | compliant: Compliant 2 | relatedObjects: 3 | - compliant: Compliant 4 | object: 5 | apiVersion: v1 6 | kind: Pod 7 | metadata: 8 | name: test1 9 | spec: 10 | containers: 11 | - name: nginx 12 | image: nginx:1.14.2 13 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind/input_ns_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_name/input_ns_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_multiple_array_input/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] does not match any elements 4 | .relatedObjects does not match the elements 5 |  Expected status does not match the actual status 6 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_multiple_relobj_compliant/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects[1] matches 5 | .relatedObjects matches 6 |  Expected status matches the actual status 7 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind_name/input_ns_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_obj_template/input_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /test/resources/case19_ns_selector/case19_behavior_prereq.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | case19b: case19b-1-e2e 6 | name: case19b-1-e2e 7 | --- 8 | apiVersion: v1 9 | kind: Namespace 10 | metadata: 11 | labels: 12 | case19b: case19b-2-e2e 13 | name: case19b-2-e2e 14 | -------------------------------------------------------------------------------- /cmd/dryrun/main.go: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Open Cluster Management project 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | 8 | "open-cluster-management.io/config-policy-controller/pkg/dryrun" 9 | ) 10 | 11 | func main() { 12 | err := dryrun.Execute() 13 | if err != nil { 14 | os.Exit(1) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectname_nsselector/input_ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mega-mart 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: mega-mart-2 11 | --- 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: mega-mart-3 16 | 17 | -------------------------------------------------------------------------------- /.github/workflows/framework-kind.yml: -------------------------------------------------------------------------------- 1 | name: Framework 2 | 3 | on: 4 | push: 5 | tags: 6 | - v[0-9]+.[0-9]+.[0-9]+ 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | fw-kind-tests: 13 | name: KinD 14 | uses: stolostron/governance-policy-framework/.github/workflows/kind.yml@main 15 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_match/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] matches 3 | .compliancyDetails matches 4 | .compliant: 'Compliant' does match 'Compliant' 5 | .lastEvaluatedGeneration: '1' does match '1' 6 |  Expected status matches the actual status 7 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_namespace_enforce/input_ns_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_namespace_inform/input_ns_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: n1 5 | spec: {} 6 | --- 7 | apiVersion: v1 8 | kind: Namespace 9 | metadata: 10 | name: n2 11 | spec: {} 12 | --- 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | name: n3 17 | spec: {} 18 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_user_input_error/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | The input status field '.compliancyDetails' is not the right type - expected '[]interface {}' 3 | skip lastEvaluatedGeneration, .lastEvaluatedGeneration is not array, 4 |  Expected status does not match the actual status 5 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: n1 5 | name: case5-multi-namespace-enforce-kind-missing-pod 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | imagePullPolicy: Never 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind/input_2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: n2 5 | name: case5-multi-namespace-enforce-kind-missing-pod 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | imagePullPolicy: Never 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind/input_3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: n3 5 | name: case5-multi-namespace-enforce-kind-missing-pod 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | imagePullPolicy: Never 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /test/dryrun/missing/missing_kind_name/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: n1 5 | name: case5-multi-namespace-enforce-kind-missing-pod 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | imagePullPolicy: Never 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/README.md: -------------------------------------------------------------------------------- 1 | # About these tests 2 | 3 | The test cases in `pkg/dryrun/testdata/` are meant to exercise the dryrun tool, 4 | and verify it behaves correctly with different kinds of inputs and that the 5 | output format is correct. These tests are not necessarily meant to check that 6 | ConfigruationPolicies are working as intended. 7 | -------------------------------------------------------------------------------- /test/dryrun/ns_selector/ns_default/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | Expected status matches the actual status 4 | 5 | # Diffs: 6 | v1 Pod default/sample-nginx-pod: 7 | 8 | # Compliance messages: 9 | Compliant; notification - pods [sample-nginx-pod] found as specified in namespace default 10 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_no_match/input.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - message: not match 6 | relatedObjects: 7 | - compliant: Compliant 8 | object: 9 | apiVersion: v1 10 | kind: Namespace 11 | metadata: 12 | name: test1 13 | properties: not match 14 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_label_invalid/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-10 5 | namespace: managed 6 | annotations: 7 | test: e2e10 8 | labels: 9 | test: e2e10 10 | spec: 11 | containers: 12 | - image: nginx:1.7.9 13 | name: nginx 14 | ports: 15 | - containerPort: 80 16 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_namespace_inform/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod n1/case5-multi-namespace-inform-pod: 3 | 4 | v1 Pod n2/case5-multi-namespace-inform-pod: 5 | 6 | v1 Pod n3/case5-multi-namespace-inform-pod: 7 | 8 | # Compliance messages: 9 | NonCompliant; violation - pods [case5-multi-namespace-inform-pod] not found in namespaces: n1, n2, n3 10 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_invalid/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-10 5 | namespace: managed 6 | annotations: 7 | test: e2e10 8 | labels: 9 | test: e2e10 10 | spec: 11 | containers: 12 | - image: nginx:1.7.9 13 | name: nginx 14 | ports: 15 | - containerPort: 80 16 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_match/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-10 5 | namespace: managed 6 | annotations: 7 | test: e2e10 8 | labels: 9 | test: e2e10 10 | spec: 11 | containers: 12 | - image: nginx:1.7.9 13 | name: nginx 14 | ports: 15 | - containerPort: 80 16 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_mismatch/input_1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e-10 5 | namespace: managed 6 | annotations: 7 | test: e2e10 8 | labels: 9 | test: e2e10 10 | spec: 11 | containers: 12 | - image: nginx:1.7.9 13 | name: nginx 14 | ports: 15 | - containerPort: 80 16 | -------------------------------------------------------------------------------- /test/dryrun/no_name/noncompliant_related_obj/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .relatedObjects[0] matches 3 | .relatedObjects matches 4 | Expected status matches the actual status 5 | 6 | # Diffs: 7 | networking.k8s.io/v1 Ingress default/-: 8 | 9 | # Compliance messages: 10 | NonCompliant; violation - ingresses found but not as specified in namespace default 11 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/enforce_ns/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | v1 Namespace e2etest: 9 | 10 | # Compliance messages: 11 | Compliant; notification - namespaces [e2etest] found as specified 12 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/ns_role/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | Expected status matches the actual status 4 | 5 | # Diffs: 6 | # Compliance messages: 7 | NonCompliant; violation - namespaced object case6-role-policy-e2e of kind Role has no namespace specified from the policy namespaceSelector nor the object metadata 8 | -------------------------------------------------------------------------------- /deploy/crds/kustomize_configurationpolicy/obj-template-validation.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "op":"add", 4 | "path":"/spec/versions/0/schema/openAPIV3Schema/properties/spec/oneOf", 5 | "value": [{ 6 | "required": ["object-templates"] 7 | },{ 8 | "required": ["object-templates-raw"] 9 | }] 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /test/resources/case30_multiline_templatization/case30_configmaps.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: 30config1 5 | labels: 6 | testcase: "30" 7 | data: 8 | name: testvalue1 9 | --- 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: 30config2 14 | labels: 15 | testcase: "30" 16 | data: 17 | name: testvalue2 -------------------------------------------------------------------------------- /test/resources/case38_operator_install/subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: project-quay 5 | spec: 6 | channel: stable-3.10 7 | name: project-quay 8 | installPlanApproval: Automatic 9 | source: operatorhubio-catalog 10 | sourceNamespace: olm 11 | startingCSV: quay-operator.v3.10.0 12 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_label_invalid/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod managed/nginx-pod-e2e-10: 3 | 4 | # Compliance messages: 5 | NonCompliant; violation - pods [nginx-pod-e2e-10] found but not as specified in namespace managed 6 | NonCompliant; violation - invalid label, error: contains non-string value in the map under key "problem": true is of the type bool, expected string 7 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_namespace_enforce/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod n1/case5-multi-namespace-enforce-pod: 3 | 4 | v1 Pod n2/case5-multi-namespace-enforce-pod: 5 | 6 | v1 Pod n3/case5-multi-namespace-enforce-pod: 7 | 8 | # Compliance messages: 9 | Compliant; notification - pods [case5-multi-namespace-enforce-pod] found as specified in namespaces: n1, n2, n3 10 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_no_match/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] does not match any elements 3 | .compliancyDetails does not match the elements 4 | .relatedObjects[0] does not match any elements 5 | .relatedObjects does not match the elements 6 |  Expected status does not match the actual status 7 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_invalid/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod managed/nginx-pod-e2e-10: 3 | 4 | # Compliance messages: 5 | NonCompliant; violation - pods [nginx-pod-e2e-10] found but not as specified in namespace managed 6 | NonCompliant; violation - invalid annotation, error: contains non-string value in the map under key "case": 10 is of the type int64, expected string 7 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_operatorpolicies.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: operatorpolicies.policy.open-cluster-management.io 8 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_unwatchable_mappings/mappings.yaml: -------------------------------------------------------------------------------- 1 | - group: template.openshift.io 2 | kind: Template 3 | plural: processedtemplates 4 | scope: namespace 5 | singular: processedtemplate 6 | verbs: 7 | - create 8 | version: v1 9 | - group: template.openshift.io 10 | kind: Template 11 | plural: templates 12 | scope: namespace 13 | singular: template 14 | version: v1 15 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/compliant_related_obj/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 IngressClass -: 9 | 10 | # Compliance messages: 11 | Compliant; notification - ingressclasses missing as expected 12 | -------------------------------------------------------------------------------- /test/resources/case18_discovery_refresh/bad-apiservice.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiregistration.k8s.io/v1 2 | kind: APIService 3 | metadata: 4 | name: v1beta1.pizza.example.com 5 | spec: 6 | group: pizza.example.com 7 | groupPriorityMinimum: 100 8 | insecureSkipTLSVerify: true 9 | service: 10 | name: pizza-server 11 | namespace: kube-system 12 | version: v1beta1 13 | versionPriority: 100 14 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_nsselector/error.txt: -------------------------------------------------------------------------------- 1 | Error: 2 | unable to complete the dryrun reconcile: 3 | failed to resolve the template {"apiVersion":"v1","kind":"Pod","metadata":{"labels":{"image":"{{ index .Object.spec.containers 0 \"image\" }}"},"name":"nginx-pod"}}: 4 | template: 5 | tmpl:5:15: 6 | executing "tmpl" at : 7 | error calling index: 8 | index of untyped nil -------------------------------------------------------------------------------- /deploy/rbac/auth_cluster_role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: config-policy-controller-auth 6 | rules: 7 | - apiGroups: 8 | - authentication.k8s.io 9 | resources: 10 | - tokenreviews 11 | verbs: 12 | - create 13 | - apiGroups: 14 | - authorization.k8s.io 15 | resources: 16 | - subjectaccessreviews 17 | verbs: 18 | - create 19 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_embed_policy/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | policy.open-cluster-management.io/v1 ConfigurationPolicy default/hello: 3 | 4 | policy.open-cluster-management.io/v1 Policy default/test-policy-embed: 5 | 6 | # Compliance messages: 7 | NonCompliant; notification - policies [test-policy-embed] found as specified in namespace default; violation - configurationpolicies [hello] not found in namespace default 8 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_cluster_scoped/error.txt: -------------------------------------------------------------------------------- 1 | Error: 2 | unable to complete the dryrun reconcile: 3 | failed to resolve the template {"apiVersion":"v1","kind":"Namespace","metadata":{"labels":{"new-label":"{{ .ObjectNamespace }}"}}}: 4 | template: 5 | tmpl:5:19: 6 | executing "tmpl" at <.ObjectNamespace>: 7 | can't evaluate field ObjectNamespace in type struct { Object map[string]interface {}; ObjectName string } -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/noncompliant_related_obj/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 IngressClass -: 9 | 10 | # Compliance messages: 11 | NonCompliant; violation - ingressclasses found but not as specified 12 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_unnamed_objdef/error.txt: -------------------------------------------------------------------------------- 1 | Error: 2 | unable to complete the dryrun reconcile: 3 | failed to resolve the template {"apiVersion":"v1","kind":"ConfigMap","metadata":{"labels":{"new-label":"{{ (fromYAML (index .Object.data \"inventory.yaml\")).appliance }}"}}}: 4 | template: 5 | tmpl:5:43: 6 | executing "tmpl" at <.Object.data>: 7 | can't evaluate field Object in type struct { ObjectNamespace string } -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 Ingress default/-: 9 | 10 | # Compliance messages: 11 | Compliant; notification - ingresses missing as expected in namespace default 12 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj_1/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 Ingress default/-: 9 | 10 | # Compliance messages: 11 | Compliant; notification - ingresses missing as expected in namespace default 12 | -------------------------------------------------------------------------------- /test/dryrun/no_name/compliant_related_obj/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'Compliant' does match 'Compliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 Ingress default/good-ingress: 9 | 10 | # Compliance messages: 11 | Compliant; notification - ingresses [good-ingress] found as specified in namespace default 12 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/enforce_ns/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-ns 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | kind: Namespace # must have namespace 'e2etest' 11 | apiVersion: v1 12 | metadata: 13 | name: e2etest 14 | -------------------------------------------------------------------------------- /deploy/rbac/auth_cluster_role_binding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: config-policy-controller-auth 6 | subjects: 7 | - kind: ServiceAccount 8 | name: config-policy-controller 9 | namespace: open-cluster-management-agent-addon 10 | roleRef: 11 | kind: ClusterRole 12 | name: config-policy-controller-auth 13 | apiGroup: rbac.authorization.k8s.io 14 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_noncompliant_related_obj_1/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | networking.k8s.io/v1 Ingress default/good-ingress: 9 | 10 | # Compliance messages: 11 | NonCompliant; violation - ingresses [good-ingress] found in namespace default 12 | -------------------------------------------------------------------------------- /test/resources/case6_no_ns/case6_create_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case6-policy-ns 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | kind: Namespace # must have namespace 'e2etest' 11 | apiVersion: v1 12 | metadata: 13 | name: case6-e2etest -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | status: 13 | conditions: 14 | - lastProbeTime: null 15 | lastTransitionTime: "2025-06-27T18:07:17Z" 16 | status: "True" 17 | type: PodReadyToStartContainers 18 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_cluster_scoped/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Namespace mega-mart: 3 | --- mega-mart : existing 4 | +++ mega-mart : updated 5 | @@ -3,7 +3,9 @@ 6 | metadata: 7 | annotations: 8 | city: durham 9 | labels: 10 | box: big 11 | + name: mega-mart 12 | + new-label: durham 13 | name: mega-mart 14 | 15 | # Compliance messages: 16 | NonCompliant; violation - namespaces [mega-mart] found but not as specified 17 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_cluster_scoped/output_from_cluster.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Namespace mega-mart: 3 | --- mega-mart : existing 4 | +++ mega-mart : updated 5 | @@ -5,10 +5,12 @@ 6 | city: durham 7 | labels: 8 | box: big 9 | + name: mega-mart 10 | + new-label: durham 11 | name: mega-mart 12 | spec: 13 | finalizers: 14 | # Compliance messages: 15 | NonCompliant; violation - namespaces [mega-mart] found but not as specified 16 | -------------------------------------------------------------------------------- /test/resources/case28_metric/case28_operatorpolicy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1beta1 2 | kind: OperatorPolicy 3 | metadata: 4 | name: case28-operatorpolicy 5 | spec: 6 | remediationAction: inform 7 | complianceType: musthave 8 | subscription: 9 | channel: stable 10 | name: example-operator 11 | namespace: default 12 | source: grc-mock-source 13 | sourceNamespace: olm 14 | upgradeApproval: Automatic 15 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_bad_fields_creation/input_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: useless-metadata-pod 5 | namespace: default 6 | generateName: coredns-5d78c9869d- 7 | creationTimestamp: "2025-02-18T17:47:28Z" 8 | resourceVersion: "441" 9 | uid: b519206b-8d46-4236-928b-5a8f7f2c0209 10 | spec: 11 | containers: 12 | - image: nginx:1.7.9 13 | name: engine-x 14 | ports: 15 | - containerPort: 8080 16 | -------------------------------------------------------------------------------- /test/dryrun/no_name/compliant_related_obj/input_good.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: default 5 | name: good-ingress 6 | spec: 7 | ingressClassName: test 8 | rules: 9 | - http: 10 | paths: 11 | - path: /testpath 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: test 16 | port: 17 | number: 80 18 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_behavior_prereq.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: case42-e2e-2 5 | --- 6 | apiVersion: config-policy-controller.io/v1 7 | kind: FakeAPI 8 | metadata: 9 | labels: 10 | case42: case42-1-e2e 11 | name: case42-1-e2e 12 | --- 13 | apiVersion: config-policy-controller.io/v1 14 | kind: FakeAPI 15 | metadata: 16 | labels: 17 | case42: case42-2-e2e 18 | name: case42-2-e2e 19 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod/output_from_cluster.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod: 3 | --- default/nginx-pod : existing 4 | +++ default/nginx-pod : updated 5 | @@ -1,9 +1,11 @@ 6 | apiVersion: v1 7 | kind: Pod 8 | metadata: 9 | + labels: 10 | + image: nginx:1.7.9 11 | name: nginx-pod 12 | namespace: default 13 | spec: 14 | # Compliance messages: 15 | NonCompliant; violation - pods [nginx-pod] found but not as specified in namespace default 16 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/compliant_related_obj/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-clusterscope 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: IngressClass 12 | spec: 13 | controller: ingress.k8s.aws/alb 14 | -------------------------------------------------------------------------------- /test/dryrun/no_name_clusterscope/noncompliant_related_obj/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-clusterscope 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: IngressClass 12 | spec: 13 | controller: ingress.k8s.aws/alb 14 | -------------------------------------------------------------------------------- /test/resources/case23_invalid_field/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case23-invalid-field 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: case23 14 | namespace: default 15 | invalid: field 16 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_templated_ns/error.txt: -------------------------------------------------------------------------------- 1 | Error: 2 | unable to complete the dryrun reconcile: 3 | failed to resolve the template {"apiVersion":"v1","kind":"ConfigMap","metadata":{"labels":{"new-label":"{{ (fromYAML (index .Object.data \"inventory.yaml\")).appliance }}"},"name":"inventory","namespace":"{{ .ObjectNamespace }}-extra"}}: 4 | template: 5 | tmpl:5:30: 6 | executing "tmpl" at : 7 | error calling index: 8 | index of untyped nil -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj_1/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: default 5 | name: wrong-1-ingress 6 | spec: 7 | ingressClassName: wrong-name 8 | rules: 9 | - http: 10 | paths: 11 | - path: /testpath 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: test 16 | port: 17 | number: 80 18 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_noncompliant_related_obj_1/input_good.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: default 5 | name: good-ingress 6 | spec: 7 | ingressClassName: test 8 | rules: 9 | - http: 10 | paths: 11 | - path: /testpath 12 | pathType: Prefix 13 | backend: 14 | service: 15 | name: test 16 | port: 17 | number: 80 18 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_results_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case42-selector-results-e2e 5 | spec: 6 | namespaceSelector: 7 | include: 8 | - case42-e2e-1 9 | remediationAction: inform 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: config-policy-controller.io/v1 14 | kind: FakeAPI 15 | -------------------------------------------------------------------------------- /test/dryrun/no_name/compliant_related_obj/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-1 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | -------------------------------------------------------------------------------- /.github/workflows/fossa.yml: -------------------------------------------------------------------------------- 1 | name: FOSSA 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | schedule: 8 | - cron: '0 0 * * 1' 9 | 10 | jobs: 11 | fossa-scan: 12 | name: License and Security Scan 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v6 17 | 18 | - name: Run FOSSA Scan 19 | uses: fossas/fossa-action@v1 20 | with: 21 | api-key: ${{ secrets.FOSSA_API_KEY }} 22 | -------------------------------------------------------------------------------- /test/dryrun/no_name/noncompliant_related_obj/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-1 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod: 3 | --- default/nginx-pod : existing 4 | +++ default/nginx-pod : updated 5 | @@ -1,8 +1,10 @@ 6 | apiVersion: v1 7 | kind: Pod 8 | metadata: 9 | + labels: 10 | + image: nginx:1.7.9 11 | name: nginx-pod 12 | namespace: default 13 | spec: 14 | containers: 15 | - image: nginx:1.7.9 16 | # Compliance messages: 17 | NonCompliant; violation - pods [nginx-pod] found but not as specified in namespace default 18 | -------------------------------------------------------------------------------- /test/dryrun/ns_selector/ns_selector_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Red Hat, Inc. 2 | // Copyright Contributors to the Open Cluster Management project 3 | 4 | package dryruntest 5 | 6 | import ( 7 | "embed" 8 | "testing" 9 | 10 | "open-cluster-management.io/config-policy-controller/test/dryrun" 11 | ) 12 | 13 | //go:embed ns_default/* 14 | var nsDefault embed.FS 15 | 16 | func TestNsDefault(t *testing.T) { 17 | t.Run("Test compliant with namespaceSelector", 18 | dryrun.Run(nsDefault)) 19 | } 20 | -------------------------------------------------------------------------------- /test/dryrun/obj_tmpl_raw/range/input.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | namespace: default 5 | name: nginx-pod-1 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | --- 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | namespace: default 17 | name: nginx-pod-2 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case19_ns_selector/case19_results_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: selector-results-e2e 5 | spec: 6 | namespaceSelector: 7 | include: 8 | - case19a-1-e2e 9 | remediationAction: inform 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: configmap-selector-e2e 17 | -------------------------------------------------------------------------------- /deploy/manager/service-account.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: config-policy-controller 6 | subjects: 7 | - kind: ServiceAccount 8 | name: config-policy-controller 9 | namespace: open-cluster-management-agent-addon 10 | roleRef: 11 | kind: ClusterRole 12 | name: config-policy-controller 13 | apiGroup: rbac.authorization.k8s.io 14 | --- 15 | apiVersion: v1 16 | kind: ServiceAccount 17 | metadata: 18 | name: config-policy-controller 19 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case37-test-policy-mustnothave 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_compliant_related_obj_1/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case37-test-policy-mustnothave 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_empty/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: templated-ns-configmap 6 | namespace: my-namespace 7 | data: 8 | this: thing 9 | --- 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: configmap-extra 14 | namespace: my-namespace 15 | data: 16 | this: thing 17 | --- 18 | apiVersion: v1 19 | kind: ConfigMap 20 | metadata: 21 | name: configmap-other-ns 22 | namespace: my-other-namespace 23 | data: 24 | this: thing 25 | -------------------------------------------------------------------------------- /test/dryrun/no_name/mustnothave_noncompliant_related_obj_1/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case37-test-policy-mustnothave 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_object_templates/input_pods.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 80 12 | --- 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod 17 | namespace: another 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 8080 24 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-no-diff-object-templates 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Namespace 12 | metadata: 13 | name: default 14 | annotations: 15 | message: '{{ fromSecret "default" "case39-secret" "message" }}' 16 | -------------------------------------------------------------------------------- /test/resources/case17_evaluation_interval/policy-never-reevaluate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-c17-create-ns-never 5 | spec: 6 | evaluationInterval: 7 | compliant: never 8 | noncompliant: 10s 9 | remediationAction: enforce 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | kind: Namespace 14 | apiVersion: v1 15 | metadata: 16 | name: case17-test-never 17 | -------------------------------------------------------------------------------- /test/resources/case33_empty_label_handling/empty-labels-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case33-empty-labels 5 | spec: 6 | remediationAction: enforce 7 | severity: high 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: case33-configmap 15 | namespace: managed 16 | labels: 17 | new-label: "" 18 | -------------------------------------------------------------------------------- /test/resources/case3_imgvuln/case3_vuln.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-imagemanifestvulnpolicy-example-imv 5 | spec: 6 | namespaceSelector: 7 | exclude: 8 | - kube-* 9 | include: 10 | - '*' 11 | object-templates: 12 | - complianceType: mustnothave 13 | objectDefinition: 14 | apiVersion: secscan.quay.redhat.com/v1alpha1 15 | kind: ImageManifestVuln 16 | remediationAction: inform 17 | severity: high -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_mustonlyhave_nolabels.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-ignore-labels 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: 9 | - kube-* 10 | include: 11 | - default 12 | object-templates: 13 | - complianceType: musthave 14 | objectDefinition: 15 | kind: Namespace 16 | apiVersion: v1 17 | metadata: 18 | name: case9-test 19 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_operatorpolicies.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: operatorpolicies.policy.open-cluster-management.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_resources/input_stdin.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | --- 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-2 17 | namespace: default 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 8080 24 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_no_nsselector/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: templated-ns-configmap 6 | namespace: my-namespace 7 | data: 8 | this: thing 9 | --- 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: configmap-extra 14 | namespace: my-namespace 15 | data: 16 | this: thing 17 | --- 18 | apiVersion: v1 19 | kind: ConfigMap 20 | metadata: 21 | name: configmap-other-ns 22 | namespace: my-other-namespace 23 | data: 24 | this: thing 25 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/musthave_mixed_noncompliant/input_good.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: default 5 | name: good-ingress 6 | labels: 7 | test.dev/foo: ismatch 8 | spec: 9 | ingressClassName: test 10 | rules: 11 | - http: 12 | paths: 13 | - path: /testpath 14 | pathType: Prefix 15 | backend: 16 | service: 17 | name: test 18 | port: 19 | number: 80 20 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_unmatched/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] matches 3 | .compliancyDetails matches 4 | .compliant: 'Compliant' does match 'Compliant' 5 | .history[0] matches 6 | .history matches 7 | .relatedObjects[0] matches 8 | .relatedObjects matches 9 | Expected status matches the actual status 10 | 11 | # Diffs: 12 | v1 ConfigMap default/good-configmap: 13 | 14 | # Compliance messages: 15 | Compliant; notification - configmaps missing as expected in namespace default 16 | -------------------------------------------------------------------------------- /test/resources/case28_metric/case28_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case28-policy-cfgmap-watch 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: ["default"] 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: case28-configmap 16 | data: 17 | fieldToUpdate: "1" 18 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_namespaced/output_from_cluster.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 ConfigMap mega-mart/inventory: 3 | --- mega-mart/inventory : existing 4 | +++ mega-mart/inventory : updated 5 | @@ -2,10 +2,12 @@ 6 | data: 7 | inventory.yaml: 'appliance: toaster' 8 | kind: ConfigMap 9 | metadata: 10 | + labels: 11 | + new-label: toaster 12 | name: inventory 13 | namespace: mega-mart 14 | 15 | # Compliance messages: 16 | NonCompliant; violation - configmaps [inventory] found but not as specified in namespace mega-mart 17 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_mixed_noncompliant/input_good.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | namespace: default 5 | name: good-ingress 6 | labels: 7 | test.dev/foo: ismatch 8 | spec: 9 | ingressClassName: test 10 | rules: 11 | - http: 12 | paths: 13 | - path: /testpath 14 | pathType: Prefix 15 | backend: 16 | service: 17 | name: test 18 | port: 19 | number: 80 20 | -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: grc-policy-propagator-metrics 5 | namespace: managed 6 | spec: 7 | internalTrafficPolicy: Cluster 8 | ipFamilies: 9 | - IPv4 10 | ipFamilyPolicy: SingleStack 11 | ports: 12 | - name: metrics-https 13 | port: 8443 14 | protocol: TCP 15 | targetPort: 8443 16 | selector: 17 | app: grc 18 | component: ocm-policy-propagator 19 | release: grc 20 | sessionAffinity: None 21 | type: ClusterIP 22 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_directory_input/input_directory/input_1-2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx-pod-e2e 5 | namespace: default 6 | spec: 7 | containers: 8 | - image: nginx:1.7.9 9 | name: nginx 10 | ports: 11 | - containerPort: 8080 12 | --- 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | namespace: default-2 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 8080 24 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_namespaced/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 ConfigMap mega-mart/inventory: 3 | --- mega-mart/inventory : existing 4 | +++ mega-mart/inventory : updated 5 | @@ -1,8 +1,10 @@ 6 | apiVersion: v1 7 | data: 8 | inventory.yaml: 'appliance: toaster' 9 | kind: ConfigMap 10 | metadata: 11 | + labels: 12 | + new-label: toaster 13 | name: inventory 14 | namespace: mega-mart 15 | 16 | # Compliance messages: 17 | NonCompliant; violation - configmaps [inventory] found but not as specified in namespace mega-mart 18 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp_raw/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-no-diff-object-templates-raw 5 | spec: 6 | remediationAction: inform 7 | object-templates-raw: | 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Namespace 12 | metadata: 13 | name: default 14 | annotations: 15 | message: '{{ fromSecret "default" "case39-secret" "message" }}' 16 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_unwatchable_mappings/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: template.openshift.io/v1 14 | kind: Template 15 | metadata: 16 | name: something 17 | spec: 18 | foo: bar 19 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | relatedObjects: 3 | - compliant: NonCompliant 4 | object: 5 | apiVersion: v1 6 | kind: Namespace 7 | properties: 8 | diff: '# The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override.' 9 | -------------------------------------------------------------------------------- /test/resources/case26_user_error_metric/case26-missing-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case26-test-policy-1 5 | spec: 6 | remediationAction: enforce 7 | pruneObjectBehavior: DeleteAll 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: CrdDoesNotExist 13 | metadata: 14 | name: case26-configmap 15 | namespace: default 16 | data: 17 | name: testvalue -------------------------------------------------------------------------------- /test/resources/case29_trigger_uninstall/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case29-trigger-uninstall 5 | spec: 6 | remediationAction: enforce 7 | pruneObjectBehavior: DeleteAll 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: case29-trigger-uninstall 15 | namespace: default 16 | data: 17 | city: Raleigh 18 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_cluster_scoped/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectSelector: 10 | matchLabels: 11 | box: big 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Namespace 15 | metadata: 16 | labels: 17 | new-label: '{{ .ObjectNamespace }}' 18 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_mustnothave/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] matches 3 | .compliancyDetails matches 4 | .compliant: 'NonCompliant' does match 'NonCompliant' 5 | .relatedObjects[0] matches 6 | .relatedObjects[1] matches 7 | .relatedObjects matches 8 | Expected status matches the actual status 9 | 10 | # Diffs: 11 | networking.k8s.io/v1 Ingress default/one: 12 | 13 | networking.k8s.io/v1 Ingress default/two: 14 | 15 | # Compliance messages: 16 | NonCompliant; violation - ingresses [one, two] found in namespace default 17 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-namespace-create 5 | annotations: 6 | policy.open-cluster-management.io/encryption-iv: SUlJSUlJSUlJSUlJSUlJSQ== 7 | spec: 8 | remediationAction: enforce 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: $ocm_encrypted:KvXvh1dkDR4DFReWYL8Jtg== 16 | -------------------------------------------------------------------------------- /test/resources/case44_template_vars/case44_objectns_var_invalid_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case44-invalid-ns 5 | spec: 6 | namespaceSelector: 7 | include: 8 | - default 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: case44-invalid-ns 16 | namespace: '{{ .ObjectNamespace }}-some-random-suffix' 17 | remediationAction: enforce 18 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=open-cluster-management_config-policy-controller 2 | sonar.projectName=config-policy-controller 3 | sonar.sources=. 4 | sonar.exclusions=**/*_test.go,**/*_generated*.go,**/*_generated/**,**/vendor/**,/test/**,/build/**,/vbh/**,/version/** 5 | sonar.tests=test 6 | sonar.test.inclusions=**/*_test.go 7 | sonar.test.exclusions=**/*_generated*.go,**/*_generated/**,**/vendor/**,**/test/e2e/** 8 | sonar.go.tests.reportPaths=report.json 9 | sonar.go.coverage.reportPaths=coverage.out 10 | sonar.externalIssuesReportPaths=gosec.json 11 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_empty/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | recordDiff: InStatus 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: templated-ns-configmap 15 | namespace: '{{ "" }}' 16 | data: 17 | this: thing 18 | -------------------------------------------------------------------------------- /test/resources/case30_multiline_templatization/case30_policy_notemplate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case30-configpolicy-notemplate 5 | spec: 6 | remediationAction: enforce 7 | severity: low 8 | object-templates-raw: | 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: 30config1 15 | namespace: default 16 | data: 17 | extraData: exists! 18 | -------------------------------------------------------------------------------- /test/resources/case36_empty_map/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: case36-deployment 5 | namespace: default 6 | labels: 7 | test: case36-deployment 8 | spec: 9 | replicas: 0 10 | selector: 11 | matchLabels: 12 | test: case36-deployment 13 | template: 14 | metadata: 15 | labels: 16 | test: case36-deployment 17 | spec: 18 | securityContext: {} 19 | containers: 20 | - image: nginx:1.7.9 21 | imagePullPolicy: Never 22 | name: nginx 23 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_cluster_scoped/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Namespace 12 | metadata: 13 | name: mega-mart 14 | labels: 15 | new-label: '{{ .Object.metadata.annotations.city }}' 16 | name: '{{ .ObjectName }}' 17 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_default_func/output_from_cluster.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod dangler/nginx-pod: 3 | 4 | v1 Pod default/nginx-pod: 5 | --- default/nginx-pod : existing 6 | +++ default/nginx-pod : updated 7 | @@ -1,9 +1,11 @@ 8 | apiVersion: v1 9 | kind: Pod 10 | metadata: 11 | + labels: 12 | + image: nginx:1.7.9 13 | name: nginx-pod 14 | namespace: default 15 | spec: 16 | # Compliance messages: 17 | NonCompliant; violation - pods [nginx-pod] not found in namespace dangler; pods [nginx-pod] found but not as specified in namespace default 18 | -------------------------------------------------------------------------------- /test/dryrun/diff/secret_obj_temp/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | relatedObjects: 3 | - compliant: NonCompliant 4 | object: 5 | apiVersion: v1 6 | kind: Secret 7 | properties: 8 | diff: |- 9 | # The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override. 10 | -------------------------------------------------------------------------------- /test/resources/case47_ratelimit/case47-cfgpolicy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case47-cfgpolicy 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: case47-configmap-from-policy 14 | namespace: default 15 | data: 16 | bar: '{{ fromConfigMap "default" "case47-configmap-to-watch" "foo" }}' 17 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_desired_status/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] does not match any elements 3 | .compliancyDetails does not match the elements 4 | .compliant: 'Compliant' does not match 'NonCompliant' 5 | .relatedObjects[0] matches 6 | .relatedObjects matches 7 |  Expected status does not match the actual status 8 | 9 | # Diffs: 10 | v1 Pod default/nginx-pod-e2e: 11 | 12 | # Compliance messages: 13 | NonCompliant; violation - pods [nginx-pod-e2e] not found in namespace default 14 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_prune_template_error.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case13-prune-template-error 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: case13-prune-template-error-configmap 14 | namespace: default 15 | data: 16 | test: '{{ print "doraemong" }}' 17 | 18 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/policy-invalid-iv.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-namespace-create-invalid-iv 5 | annotations: 6 | policy.open-cluster-management.io/encryption-iv: bm90IHJpZ2h0Cg== 7 | spec: 8 | remediationAction: enforce 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: $ocm_encrypted:KvXvh1dkDR4DFReWYL8Jtg== 16 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_resources/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | 4 | v1 Pod default/nginx-pod-e2e-2: 5 | 6 | v1 Pod default/nginx-pod-e2e-3: 7 | 8 | v1 Pod default/nginx-pod-e2e-4: 9 | 10 | # Compliance messages: 11 | Compliant; notification - pods [nginx-pod-e2e] found as specified in namespace default; notification - pods [nginx-pod-e2e-2] found as specified in namespace default; notification - pods [nginx-pod-e2e-3] found as specified in namespace default; notification - pods [nginx-pod-e2e-4] found as specified in namespace default 12 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp_raw/desired_status.yaml: -------------------------------------------------------------------------------- 1 | compliant: NonCompliant 2 | relatedObjects: 3 | - compliant: NonCompliant 4 | object: 5 | apiVersion: v1 6 | kind: Namespace 7 | properties: 8 | diff: >- 9 | # The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override. 10 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/policy-diff-key.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-namespace-create-diff-key 5 | annotations: 6 | policy.open-cluster-management.io/encryption-iv: SUlJSUlJSUlJSUlJSUlJSQ== 7 | spec: 8 | remediationAction: enforce 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: $ocm_encrypted:+L6TZkbZvMRvvjPv0QGAOA== 16 | -------------------------------------------------------------------------------- /test/resources/case39_diff_generation/case39-create-cfgmap-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-policy-cfgmap-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | include: ["default"] 9 | object-templates: 10 | - complianceType: musthave 11 | recordDiff: Log 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case39-map 17 | data: 18 | fieldToUpdate: "1" 19 | -------------------------------------------------------------------------------- /test/resources/case39_diff_generation/case39-update-cfgmap-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-policy-cfgmap-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | include: ["default"] 9 | object-templates: 10 | - complianceType: musthave 11 | recordDiff: Log 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case39-map 17 | data: 18 | fieldToUpdate: "2" 19 | -------------------------------------------------------------------------------- /test/resources/case3_imgvuln/case3_vuln_object.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-imagemanifestvulnpolicy-example-imv-obj 5 | spec: 6 | namespaceSelector: 7 | exclude: 8 | - kube-* 9 | include: 10 | - '*' 11 | object-templates: 12 | - complianceType: mustnothave 13 | objectDefinition: 14 | apiVersion: secscan.quay.redhat.com/v1alpha1 15 | kind: ImageManifestVuln 16 | name: e2eNonExistentVuln 17 | remediationAction: inform 18 | severity: high -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-v0.8.0.md: -------------------------------------------------------------------------------- 1 | # v0.8.0 2 | 3 | - Add the `pruneObjectBehavior` field to be able to delete objects after the policy is deleted. 4 | - Allow an alternative kubeconfig for evaluating policies. 5 | - Make the metrics bind address configurable. 6 | - Add the option for label selectors in the policy `namespaceSelector`. 7 | - Add a metric to record the duration of evaluating all configuration policies. 8 | - Add the option to evaluate policies concurrently. 9 | - Status in a policy no longer prevents spec updates. 10 | - Use a volume mounted secret for the Hub kubeconfig. 11 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectns_templated_no_nsselector/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | recordDiff: InStatus 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: templated-ns-configmap 15 | namespace: '{{ "my-namespace" }}' 16 | data: 17 | this: thing 18 | -------------------------------------------------------------------------------- /test/resources/case16_policy_template_decryption/policy-invalid-key.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-namespace-create-invalid-key 5 | annotations: 6 | policy.open-cluster-management.io/encryption-iv: SUlJSUlJSUlJSUlJSUlJSQ== 7 | spec: 8 | remediationAction: enforce 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Namespace 14 | metadata: 15 | name: $ocm_encrypted:HJCVfwZ2S23LqMg8vECH0g== 16 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check-mh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-mh-list 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - name: nginx 20 | -------------------------------------------------------------------------------- /test/resources/case27_showupdateinstatus/case27-create-cfgmap-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case27-policy-cfgmap-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case27-map 17 | data: 18 | fieldToUpdate: "1" 19 | -------------------------------------------------------------------------------- /test/resources/case27_showupdateinstatus/case27-update-cfgmap-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case27-policy-cfgmap-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case27-map 17 | data: 18 | fieldToUpdate: "2" 19 | -------------------------------------------------------------------------------- /test/resources/case34_enforce_w_status/config-policy-updated.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case34-cfgpol 5 | spec: 6 | remediationAction: enforce 7 | severity: low 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Namespace 13 | metadata: 14 | name: case34-ns 15 | labels: 16 | policy.open-cluster-management.io/test: case34 17 | status: 18 | phase: Terminating 19 | -------------------------------------------------------------------------------- /test/resources/case39_diff_generation/case39-status-cfgmap-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-policy-cfgmap-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | include: ["default"] 9 | object-templates: 10 | - complianceType: musthave 11 | recordDiff: InStatus 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case39-map 17 | data: 18 | fieldToUpdate: "3" 19 | -------------------------------------------------------------------------------- /test/resources/case43_standalone_hub_templates/hub-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: ocm-standalone-template-test-src 5 | --- 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | namespace: ocm-standalone-template-test-src 10 | name: test 11 | stringData: 12 | tls.crt: 'certificate' 13 | tls.key: 'skullkey' 14 | --- 15 | apiVersion: v1 16 | kind: Secret 17 | metadata: 18 | namespace: ocm-standalone-template-test-src 19 | name: long-named-secret-to-test-more 20 | stringData: 21 | tls.crt: 'certificate' 22 | tls.key: 'skullkey' 23 | -------------------------------------------------------------------------------- /test/resources/case44_template_vars/case44_objectname_var_noselector_ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case44-no-selector-ns 5 | spec: 6 | object-templates: 7 | - complianceType: musthave 8 | objectDefinition: 9 | apiVersion: v1 10 | kind: Namespace 11 | metadata: 12 | labels: 13 | case44: passed 14 | name: '{{ .ObjectName }}' 15 | namespace: '{{ .ObjectNamespace }}' 16 | name: '{{ .ObjectName }}' 17 | remediationAction: enforce 18 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_unmatched/desired_status.yaml: -------------------------------------------------------------------------------- 1 | relatedObjects: 2 | - compliant: Compliant 3 | object: 4 | apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: good-configmap 8 | namespace: default 9 | compliancyDetails: 10 | - Compliant: Compliant 11 | conditions: 12 | - message: configmaps missing as expected in namespace default 13 | status: "True" 14 | type: notification 15 | compliant: Compliant 16 | history: 17 | - message: Compliant; notification - configmaps missing as expected in namespace default 18 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | domain: open-cluster-management.io 2 | layout: 3 | - go.kubebuilder.io/v3 4 | plugins: 5 | manifests.sdk.operatorframework.io/v2: {} 6 | scorecard.sdk.operatorframework.io/v2: {} 7 | projectName: config-policy-controller 8 | repo: open-cluster-management.io/config-policy-controller 9 | resources: 10 | - api: 11 | crdVersion: v1 12 | namespaced: true 13 | controller: true 14 | domain: open-cluster-management.io 15 | group: policy 16 | kind: ConfigurationPolicy 17 | path: open-cluster-management.io/config-policy-controller/api/v1 18 | version: v1 19 | version: "3" 20 | -------------------------------------------------------------------------------- /test/resources/case18_discovery_refresh/policy-template.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-c18-template 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: c18-configmap 14 | namespace: default 15 | data: 16 | topping: '{{ index (lookup "diner.example.com/v1" "PizzaSlice" "default" "mypizza").spec.toppings 0 }}' 17 | -------------------------------------------------------------------------------- /test/resources/case29_trigger_uninstall/policy2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case29-trigger-uninstall2 5 | spec: 6 | remediationAction: enforce 7 | pruneObjectBehavior: DeleteAll 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: case29-trigger-uninstall 15 | namespace: default 16 | data: 17 | state: NC # will be patched to '{{hub something hub}}' 18 | -------------------------------------------------------------------------------- /test/resources/case40_recreate_option/policy-always-recreate-option.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case40 5 | spec: 6 | pruneObjectBehavior: DeleteAll 7 | remediationAction: enforce 8 | object-templates: 9 | - complianceType: musthave 10 | recreateOption: Always 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: case40 16 | namespace: default 17 | data: 18 | city: Raleigh 19 | state: NC 20 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_default_func/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod dangler/nginx-pod: 3 | 4 | v1 Pod default/nginx-pod: 5 | --- default/nginx-pod : existing 6 | +++ default/nginx-pod : updated 7 | @@ -1,8 +1,10 @@ 8 | apiVersion: v1 9 | kind: Pod 10 | metadata: 11 | + labels: 12 | + image: nginx:1.7.9 13 | name: nginx-pod 14 | namespace: default 15 | spec: 16 | containers: 17 | - image: nginx:1.7.9 18 | # Compliance messages: 19 | NonCompliant; violation - pods [nginx-pod] not found in namespace dangler; pods [nginx-pod] found but not as specified in namespace default 20 | -------------------------------------------------------------------------------- /test/dryrun/obj_tmpl_raw/invalid_yaml/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: invalid-otr-yaml 5 | spec: 6 | remediationAction: inform 7 | severity: low 8 | namespaceSelector: 9 | include: ["default"] 10 | object-templates-raw: | 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: sample 17 | namespace: default 18 | data: 19 | something: *odd 20 | another: valid 21 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_copysecret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: tmplt-policy-secret-duplicate 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Secret 15 | metadata: 16 | name: e2esecret2 17 | type: Opaque 18 | data: '{{ copySecretData "default" "e2esecret" }}' 19 | -------------------------------------------------------------------------------- /.github/workflows/go-postsubmit.yml: -------------------------------------------------------------------------------- 1 | name: GoPostSubmit 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | verify: 10 | name: images 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: checkout code 14 | uses: actions/checkout@v6 15 | - name: images 16 | run: make build-images 17 | - name: push 18 | run: | 19 | echo ${{ secrets.DOCKER_PASSWORD }} | docker login quay.io --username ${{ secrets.DOCKER_USER }} --password-stdin 20 | docker push quay.io/open-cluster-management/config-policy-controller:latest 21 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-v0.7.0.md: -------------------------------------------------------------------------------- 1 | # v0.7.0 2 | 3 | * Added support for the `metadataComplianceType` field to change the compliance type when evaluating the `metadata` field 4 | * Added support for the `evaluationInterval` field to customize how often policies are evaluated 5 | * Added support for decrypting content encrypted using the Hub `protect` template function 6 | * Changed the log level flag to `--log-level` and `-v` for library logs 7 | * Improved logging 8 | * Improved performance 9 | * Updated the dependencies 10 | * Fixed a bug that could cause policy status updates not to be sent under heavy load 11 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: 9 | - default 10 | object-templates: 11 | - complianceType: musthave 12 | recordDiff: InStatus 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod 18 | labels: 19 | image: '{{ index .Object.spec.containers 0 "image" }}' 20 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_mismatch/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-kind-labels-fail 5 | spec: 6 | remediationAction: inform # will be overridden by remediationAction in parent policy 7 | severity: low 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Pod 13 | metadata: 14 | namespace: managed 15 | annotations: 16 | test: fail 17 | labels: 18 | test: fail 19 | -------------------------------------------------------------------------------- /test/resources/case44_template_vars/case44_objectns_var_prereqs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: case44-e2e-objectns-variables 6 | --- 7 | apiVersion: v1 8 | kind: ConfigMap 9 | metadata: 10 | name: case44-e2e-objectns-variables 11 | namespace: case44-e2e-objectns-variables 12 | --- 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: case44-e2e-objectns-variables 17 | namespace: default 18 | --- 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | name: case44-e2e-objectns-variables2 23 | namespace: case44-e2e-objectns-variables 24 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectname_nsselector/input.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: inventory 6 | namespace: mega-mart 7 | data: {} 8 | --- 9 | apiVersion: v1 10 | kind: ConfigMap 11 | metadata: 12 | name: nininventory 13 | namespace: mega-mart 14 | data: {} 15 | --- 16 | apiVersion: v1 17 | kind: ConfigMap 18 | metadata: 19 | name: inventory 20 | namespace: mega-mart-2 21 | data: 22 | things: original-stuff 23 | --- 24 | apiVersion: v1 25 | kind: ConfigMap 26 | metadata: 27 | name: inventory-2 28 | namespace: mega-mart-2 29 | data: 30 | things: stuff 31 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_label_invalid/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-kind-labels-fail 5 | spec: 6 | remediationAction: inform # will be overridden by remediationAction in parent policy 7 | severity: low 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Pod 13 | metadata: 14 | namespace: managed 15 | name: nginx-pod-e2e-10 16 | labels: 17 | problem: yes 18 | test: fail 19 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_unnamed_objdef/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | matchlabels: 9 | box: big 10 | object-templates: 11 | - complianceType: musthave 12 | recordDiff: InStatus 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: ConfigMap 16 | metadata: 17 | labels: 18 | new-label: '{{ (fromYAML (index .Object.data "inventory.yaml")).appliance }}' 19 | -------------------------------------------------------------------------------- /test/dryrun/kind_field/pod_annotation_invalid/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-kind-labels-fail 5 | spec: 6 | remediationAction: inform # will be overridden by remediationAction in parent policy 7 | severity: low 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Pod 13 | metadata: 14 | namespace: managed 15 | name: nginx-pod-e2e-10 16 | annotations: 17 | case: 10 18 | test: fail 19 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check-mnh-incomplete.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-mnh-incomplete 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustnothave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_status_check.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-status-checker 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["managed"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: policy.open-cluster-management.io/v1 14 | kind: ConfigurationPolicy 15 | metadata: 16 | name: policy-pod-to-check 17 | status: 18 | compliant: Compliant 19 | -------------------------------------------------------------------------------- /test/dryrun/diff/secret_obj_temp/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case39-no-diff-on-secret 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Secret 12 | metadata: 13 | name: case39-secret 14 | namespace: default 15 | annotations: 16 | riddle: "If I have it, I don't share it. If I share it, I don't have it. What am I?" 17 | hint: "See the value of the kind field" 18 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_mixed_noncompliant/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliancyDetails[0] matches 3 | .compliancyDetails matches 4 | .compliant: 'NonCompliant' does match 'NonCompliant' 5 | .relatedObjects[0] matches 6 | .relatedObjects[1] matches 7 | .relatedObjects matches 8 | Expected status matches the actual status 9 | 10 | # Diffs: 11 | networking.k8s.io/v1 Ingress default/wrong-1-ingress: 12 | 13 | networking.k8s.io/v1 Ingress default/wrong-2-ingress: 14 | 15 | # Compliance messages: 16 | NonCompliant; violation - ingresses [wrong-1-ingress, wrong-2-ingress] found in namespace default 17 | -------------------------------------------------------------------------------- /test/resources/case14_namespaces/case14_configmaps_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case14-configmaps 5 | spec: 6 | evaluationInterval: 7 | compliant: 30m 8 | noncompliant: 30m 9 | namespaceSelector: 10 | include: 11 | - 'case14-*' 12 | object-templates: 13 | - complianceType: musthave 14 | objectDefinition: 15 | apiVersion: v1 16 | kind: ConfigMap 17 | metadata: 18 | name: case14-cm 19 | data: 20 | foo: bar 21 | remediationAction: enforce 22 | severity: high 23 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check-moh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-moh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustonlyhave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/ns_deleting.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case1-ns-deleting 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Pod 12 | metadata: 13 | name: nginx-pod-e2e 14 | namespace: case1-deleting 15 | spec: 16 | containers: 17 | - image: nginx:1.7.9 18 | name: nginx 19 | ports: 20 | - containerPort: 80 21 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/ns_nonexist.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case1-ns-nonexist 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Pod 12 | metadata: 13 | name: nginx-pod-e2e 14 | namespace: case1-nonexist 15 | spec: 16 | containers: 17 | - image: nginx:1.7.9 18 | name: nginx 19 | ports: 20 | - containerPort: 80 21 | -------------------------------------------------------------------------------- /test/resources/case4_clusterversion/case4_clusterversion_inform.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: openshift-upgrade-channel-inform 5 | namespace: managed 6 | spec: 7 | remediationAction: inform 8 | namespaceSelector: 9 | exclude: 10 | - kube-* 11 | include: 12 | - "*" 13 | object-templates: 14 | - complianceType: musthave 15 | objectDefinition: 16 | apiVersion: config.openshift.io/v1 17 | kind: ClusterVersion 18 | metadata: 19 | name: version 20 | spec: 21 | channel: fast-4.4 -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_stdin/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | --- default/nginx-pod-e2e : existing 4 | +++ default/nginx-pod-e2e : updated 5 | @@ -4,9 +4,13 @@ 6 | name: nginx-pod-e2e 7 | namespace: default 8 | spec: 9 | containers: 10 | - image: nginx:1.7.9 11 | + name: nginx 12 | + ports: 13 | + - containerPort: 80 14 | + - image: nginx:1.7.9 15 | name: engine-x 16 | ports: 17 | - containerPort: 8080 18 | 19 | # Compliance messages: 20 | NonCompliant; violation - pods [nginx-pod-e2e] found but not as specified in namespace default 21 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_nsselector/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: 9 | - default 10 | - dangler 11 | object-templates: 12 | - complianceType: musthave 13 | recordDiff: InStatus 14 | objectDefinition: 15 | apiVersion: v1 16 | kind: Pod 17 | metadata: 18 | name: nginx-pod 19 | labels: 20 | image: '{{ index .Object.spec.containers 0 "image" }}' 21 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/musthave_mixed_noncompliant/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-1 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: test 16 | objectSelector: 17 | matchExpressions: 18 | - key: test.dev/foo 19 | operator: Exists 20 | -------------------------------------------------------------------------------- /test/resources/case21_alternative_kubeconfig/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: create-ns 5 | ownerReferences: 6 | - apiVersion: policy.open-cluster-management.io/v1 7 | kind: Policy 8 | name: parent-create-ns 9 | uid: 12345678-90ab-cdef-1234-567890abcdef # must be replaced before creation 10 | spec: 11 | remediationAction: enforce 12 | object-templates: 13 | - complianceType: musthave 14 | objectDefinition: 15 | apiVersion: v1 16 | kind: Namespace 17 | metadata: 18 | name: e2e-test-ns 19 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_noncompliant/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | --- default/nginx-pod-e2e : existing 4 | +++ default/nginx-pod-e2e : updated 5 | @@ -4,9 +4,13 @@ 6 | name: nginx-pod-e2e 7 | namespace: default 8 | spec: 9 | containers: 10 | - image: nginx:1.7.9 11 | + name: nginx 12 | + ports: 13 | + - containerPort: 80 14 | + - image: nginx:1.7.9 15 | name: engine-x 16 | ports: 17 | - containerPort: 8080 18 | 19 | # Compliance messages: 20 | NonCompliant; violation - pods [nginx-pod-e2e] found but not as specified in namespace default 21 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_wrapped_in_policy/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | --- default/nginx-pod-e2e : existing 4 | +++ default/nginx-pod-e2e : updated 5 | @@ -4,9 +4,13 @@ 6 | name: nginx-pod-e2e 7 | namespace: default 8 | spec: 9 | containers: 10 | - image: nginx:1.7.9 11 | + name: nginx 12 | + ports: 13 | + - containerPort: 80 14 | + - image: nginx:1.7.9 15 | name: engine-x 16 | ports: 17 | - containerPort: 8080 18 | 19 | # Compliance messages: 20 | NonCompliant; violation - pods [nginx-pod-e2e] found but not as specified in namespace default 21 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_mixed_noncompliant/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-1 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | spec: 15 | ingressClassName: wrong-name 16 | objectSelector: 17 | matchExpressions: 18 | - key: test.dev/foo 19 | operator: Exists 20 | -------------------------------------------------------------------------------- /test/resources/case22_pod_update_image/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case22-pod-create 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | recordDiff: Log 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Pod 13 | metadata: 14 | name: pod-case22 15 | namespace: default 16 | spec: 17 | containers: 18 | - image: nginx:1.7.8 19 | name: nginx 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_behavior_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case42-selector-behavior-e2e 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectSelector: 10 | matchExpressions: 11 | - key: case42 12 | operator: Exists 13 | objectDefinition: 14 | apiVersion: config-policy-controller.io/v1 15 | kind: FakeAPI 16 | metadata: 17 | labels: 18 | selected: "true" 19 | namespace: case42-e2e-2 20 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_checkns-md-mh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-check-ns-mdcomptype-mh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: 9 | - kube-* 10 | include: 11 | - default 12 | object-templates: 13 | - complianceType: mustonlyhave 14 | metadataComplianceType: musthave 15 | objectDefinition: 16 | kind: Namespace 17 | apiVersion: v1 18 | metadata: 19 | name: case9-test-multi-annotation 20 | annotations: 21 | test: e2e 22 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_mustnothave/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: test-policy-1 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: mustnothave 9 | objectDefinition: 10 | apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | metadata: 13 | namespace: default 14 | name: '{{ .ObjectName }}' 15 | spec: 16 | ingressClassName: test 17 | objectSelector: 18 | matchExpressions: 19 | - key: test.dev/foo 20 | operator: Exists 21 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_checkns-md-moh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-check-ns-mdcomptype-moh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: 9 | - kube-* 10 | include: 11 | - default 12 | object-templates: 13 | - complianceType: musthave 14 | metadataComplianceType: mustonlyhave 15 | objectDefinition: 16 | kind: Namespace 17 | apiVersion: v1 18 | metadata: 19 | name: case9-test-multi-annotation 20 | annotations: 21 | test: e2e 22 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_multianno_ns_create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-create-ns-multiple-annotations 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: 9 | - kube-* 10 | include: 11 | - default 12 | object-templates: 13 | - complianceType: musthave 14 | objectDefinition: 15 | kind: Namespace 16 | apiVersion: v1 17 | metadata: 18 | name: case9-test-multi-annotation 19 | annotations: 20 | test: e2e 21 | missing: notintemplate 22 | -------------------------------------------------------------------------------- /test/resources/case19_ns_selector/case19_behavior_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: selector-behavior-e2e 5 | spec: 6 | evaluationInterval: 7 | compliant: 2h 8 | noncompliant: 2h 9 | namespaceSelector: 10 | exclude: 11 | - "kube-*" 12 | matchExpressions: 13 | - key: case19b 14 | operator: Exists 15 | remediationAction: inform 16 | object-templates: 17 | - complianceType: musthave 18 | objectDefinition: 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | name: configmap-selector-e2e 23 | -------------------------------------------------------------------------------- /test/resources/case43_standalone_hub_templates/config-policy-modified.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case43-with-hub-template 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | namespace: default 14 | name: case43-output 15 | data: 16 | outfo: '{{hub fromConfigMap "default" "case43-input" "info" hub}}' 17 | other: '{{hub fromConfigMap "default" "case43-input" "info" hub}}' 18 | -------------------------------------------------------------------------------- /deploy/crds/kustomize_configurationpolicy/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - policy.open-cluster-management.io_configurationpolicies.yaml 3 | 4 | # Add validation more complicated than Kubebuilder markers can provide 5 | patches: 6 | - path: obj-template-validation.json 7 | target: 8 | group: apiextensions.k8s.io 9 | version: v1 10 | kind: CustomResourceDefinition 11 | name: configurationpolicies.policy.open-cluster-management.io 12 | - path: template-label.json 13 | target: 14 | group: apiextensions.k8s.io 15 | version: v1 16 | kind: CustomResourceDefinition 17 | name: configurationpolicies.policy.open-cluster-management.io 18 | -------------------------------------------------------------------------------- /deploy/rbac/metrics_reader.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: config-policy-controller-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - "/metrics" 9 | verbs: 10 | - get 11 | --- 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: ClusterRoleBinding 14 | metadata: 15 | name: config-policy-controller-metrics-reader 16 | subjects: 17 | - kind: ServiceAccount 18 | name: config-policy-controller 19 | namespace: open-cluster-management-agent-addon 20 | roleRef: 21 | kind: ClusterRole 22 | name: config-policy-controller-metrics-reader 23 | apiGroup: rbac.authorization.k8s.io 24 | -------------------------------------------------------------------------------- /test/resources/case30_multiline_templatization/case30_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case30-configpolicy 5 | spec: 6 | remediationAction: enforce 7 | severity: low 8 | object-templates-raw: | 9 | {{ range (lookup "v1" "ConfigMap" "default" "" "testcase=30").items }} 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: {{ .metadata.name }} 16 | namespace: default 17 | data: 18 | extraData: exists! 19 | {{ end }} 20 | -------------------------------------------------------------------------------- /test/resources/case2_role_handling/case2_rolebinding_create_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-rolebinding-create 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: ["default"] 9 | object-templates: 10 | - complianceType: mustonlyhave 11 | objectDefinition: 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: RoleBinding 14 | metadata: 15 | name: pod-reader-e2e-binding 16 | roleRef: 17 | apiGroup: rbac.authorization.k8s.io 18 | kind: Role 19 | name: pod-reader-e2e 20 | -------------------------------------------------------------------------------- /test/resources/case30_multiline_templatization/case30_no_object.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case30-configpolicy-no-object 5 | spec: 6 | remediationAction: inform 7 | severity: low 8 | object-templates-raw: | 9 | {{ range (lookup "v1" "ConfigMap" "default" "doesnotexist").items }} 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: {{ .metadata.name }} 16 | namespace: default 17 | data: 18 | extraData: exists! 19 | {{ end }} -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_verifysecret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: tmplt-policy-secret-duplicate-check 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Secret 15 | metadata: 16 | name: e2esecret2 17 | type: Opaque 18 | data: 19 | USER_NAME: YWRtaW4= 20 | PASSWORD: '{{ fromSecret "default" "e2esecret" "PASSWORD" }}' 21 | -------------------------------------------------------------------------------- /test/resources/case4_clusterversion/case4_clusterversion_create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: openshift-upgrade-channel-e2e 5 | namespace: managed 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: 10 | - kube-* 11 | include: 12 | - default 13 | object-templates: 14 | - complianceType: musthave 15 | objectDefinition: 16 | apiVersion: config.openshift.io/v1 17 | kind: ClusterVersion 18 | metadata: 19 | name: version 20 | spec: 21 | clusterID: example-cluster-id 22 | channel: fast-4.3 -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_status_check_fail.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-status-checker-fail 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["managed"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: policy.open-cluster-management.io/v1 14 | kind: ConfigurationPolicy 15 | metadata: 16 | name: policy-pod-to-check 17 | status: 18 | compliant: NonCompliant 19 | compliancyDetails: [] 20 | -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_status_enforce_fail.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-status-enforce-fail 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["managed"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: policy.open-cluster-management.io/v1 14 | kind: ConfigurationPolicy 15 | metadata: 16 | name: policy-pod-to-check 17 | status: 18 | compliant: NonCompliant 19 | compliancyDetails: [] 20 | -------------------------------------------------------------------------------- /test/resources/case12_list_compare/case12_role_create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-role-create-listinspec 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: Role 15 | metadata: 16 | name: role-policy-e2e 17 | rules: 18 | - apiGroups: [""] 19 | resources: ["pods"] 20 | verbs: ["get", "watch", "list"] 21 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_copy_referenced_configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-copy-referenced-configmap 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: configmap-copy-configmap-object-repl 17 | namespace: default 18 | data: '{{ copyConfigMapData "default" "configmap-copy-configmap-object" }}' 19 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_unterminated.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-create-unterminated 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: '{{' 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_create_empty_list.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-emptycontainerlist 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-empty 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: [] 22 | -------------------------------------------------------------------------------- /test/resources/case4_clusterversion/case4_clusterversion_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: openshift-upgrade-channel-patch 5 | namespace: managed 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: 10 | - kube-* 11 | include: 12 | - default 13 | object-templates: 14 | - complianceType: musthave 15 | objectDefinition: 16 | apiVersion: config.openshift.io/v1 17 | kind: ClusterVersion 18 | metadata: 19 | name: version 20 | spec: 21 | #clusterID: example-cluster-id 22 | channel: fast-4.4 -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_directory_input/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod default/nginx-pod-e2e: 3 | 4 | v1 Pod default-2/nginx-pod-e2e: 5 | 6 | v1 Pod default-3/nginx-pod-e2e: 7 | 8 | v1 Pod default-4/nginx-pod-e2e: 9 | 10 | v1 Pod nonexist/nginx-pod-e2e: 11 | 12 | # Compliance messages: 13 | NonCompliant; notification - pods [nginx-pod-e2e] found as specified in namespace default; notification - pods [nginx-pod-e2e] found as specified in namespace default-2; notification - pods [nginx-pod-e2e] found as specified in namespace default-3; notification - pods [nginx-pod-e2e] found as specified in namespace default-4; violation - pods [nginx-pod-e2e] not found in namespace nonexist 14 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/objectname_nsselector/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: ["*"] 9 | object-templates: 10 | - complianceType: musthave 11 | recordDiff: InStatus 12 | objectSelector: {} 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: ConfigMap 16 | metadata: 17 | name: '{{ not (hasPrefix "inv" .ObjectName) | skipObject }}' 18 | data: '{{ set (.Object.data | default (dict)) "hocus" "pocus" | toJSON | toLiteral }}' 19 | -------------------------------------------------------------------------------- /test/resources/case2_role_handling/case2_role_check-moh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-role-check-moh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustonlyhave 12 | objectDefinition: 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: Role 15 | metadata: 16 | name: pod-reader-e2e 17 | rules: 18 | - apiGroups: ["extensions", "apps"] 19 | resources: ["deployments"] 20 | verbs: ["get", "list"] -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_mnh_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case42-selector-mnh-e2e 5 | spec: 6 | evaluationInterval: 7 | compliant: watch 8 | noncompliant: watch 9 | remediationAction: inform 10 | object-templates: 11 | - complianceType: mustnothave 12 | objectSelector: 13 | matchExpressions: 14 | - key: case42 15 | operator: Exists 16 | objectDefinition: 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | namespace: case42-e2e-4 21 | data: 22 | test: match 23 | -------------------------------------------------------------------------------- /test/resources/case44_template_vars/case44_objectns_var.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case44-objectns-variable 5 | spec: 6 | namespaceSelector: 7 | include: 8 | - default 9 | - case44-e2e-objectns-variables 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | labels: 17 | case44: passed 18 | namespace: '{{ .ObjectNamespace }}' 19 | name: case44-e2e-objectns-variables 20 | namespace: '{{ .ObjectNamespace }}' 21 | remediationAction: enforce 22 | -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-to-check 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustnothave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-8 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_no_annos.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-no-anno 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-9 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_pod_default_func/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | include: 9 | - default 10 | - dangler 11 | object-templates: 12 | - complianceType: musthave 13 | recordDiff: InStatus 14 | objectDefinition: 15 | apiVersion: v1 16 | kind: Pod 17 | metadata: 18 | name: nginx-pod 19 | labels: 20 | image: '{{ if empty .Object }}nginx:latest{{ else }}{{ index .Object.spec.containers 0 "image" }}{{ end }}' 21 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_lookup_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: tmplt-policy-secret-lookup-check 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Secret 15 | metadata: 16 | name: e2esecret2 17 | type: Opaque 18 | data: 19 | USER_NAME: YWRtaW4= 20 | PASSWORD: '{{ (lookup "v1" "Secret" "default" "e2esecret").data.PASSWORD }}' 21 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_pod_name_verify.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-templatized-name-verify 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: c13-pod 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case44_template_vars/case44_objectname_var_invalid_name.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case44-invalid-name 5 | spec: 6 | namespaceSelector: 7 | include: 8 | - case44-e2e-objectname-var 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: ConfigMap 14 | metadata: 15 | name: '{{ .ObjectName }}-some-random-suffix' 16 | namespace: '{{ .ObjectNamespace }}' 17 | objectSelector: 18 | matchExpressions: 19 | - key: case44 20 | operator: Exists 21 | remediationAction: enforce 22 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_pod_create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-c9-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-9 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_object_templates/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod another/nginx-pod: 3 | 4 | v1 Pod default/nginx-pod: 5 | --- default/nginx-pod : existing 6 | +++ default/nginx-pod : updated 7 | @@ -6,7 +6,8 @@ 8 | spec: 9 | containers: 10 | - image: nginx:1.7.9 11 | name: nginx 12 | ports: 13 | + - containerPort: 8080 14 | - containerPort: 80 15 | 16 | v1 Pod nonexist/nginx-pod: 17 | 18 | # Compliance messages: 19 | NonCompliant; notification - pods [nginx-pod] found as specified in namespace another; violation - pods [nginx-pod] found but not as specified in namespace default; violation - pods [nginx-pod] not found in namespace nonexist 20 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check-mnh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-mnh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustnothave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_create_enforce.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-create 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case45_set_empty_field/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case45-policy 5 | spec: 6 | object-templates: 7 | - complianceType: musthave 8 | objectDefinition: 9 | apiVersion: sriovnetwork.openshift.io/v1 10 | kind: SriovOperatorConfig 11 | metadata: 12 | name: default 13 | namespace: default 14 | spec: 15 | configDaemonNodeSelector: 16 | node-role.kubernetes.io/master: "" 17 | disableDrain: true 18 | enableInjector: false 19 | enableOperatorWebhook: false 20 | logLevel: 0 21 | remediationAction: inform 22 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_mappings/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: LimitRange # limit memory usage 15 | metadata: 16 | name: mem-limit-range 17 | spec: 18 | limits: 19 | - default: 20 | memory: 512Mi 21 | defaultRequest: 22 | memory: 256Mi 23 | type: Container 24 | -------------------------------------------------------------------------------- /test/dryrun/context_vars/object_templated_ns/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-object-var-templated-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | matchlabels: 9 | box: big 10 | object-templates: 11 | - complianceType: musthave 12 | recordDiff: InStatus 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: ConfigMap 16 | metadata: 17 | name: inventory 18 | namespace: '{{ .ObjectNamespace }}-extra' 19 | labels: 20 | new-label: '{{ (fromYAML (index .Object.data "inventory.yaml")).appliance }}' 21 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_create_inform.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-create-inform 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case5_multi/case5_single_mh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-multi-mh 5 | namespace: managed 6 | spec: 7 | remediationAction: inform 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: case5-nginx-pod-1 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_fromsecret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: tmplt-policy-secret-duplicate 5 | spec: 6 | pruneObjectBehavior: DeleteAll 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Secret 16 | metadata: 17 | name: e2esecret2 18 | type: Opaque 19 | data: 20 | USER_NAME: YWRtaW4= 21 | PASSWORD: '{{ fromSecret "default" "e2esecret" "PASSWORD" }}' 22 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check_multiple_mh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-multiple-mh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-multi 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case36_empty_map/policy-should-not-add-empty-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case36-check-node-selector 5 | spec: 6 | remediationAction: inform 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | metadata: 13 | name: case36-deployment 14 | namespace: default 15 | spec: 16 | template: 17 | spec: 18 | # This is omitempty and is type map[string]string, so an empty value will not be returned by the API. 19 | nodeSelector: {} 20 | -------------------------------------------------------------------------------- /test/resources/case40_recreate_option/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: case40 5 | namespace: default 6 | spec: 7 | replicas: 0 8 | selector: 9 | matchLabels: 10 | app: case40 11 | strategy: 12 | type: Recreate 13 | template: 14 | metadata: 15 | labels: 16 | app: case40 17 | spec: 18 | containers: 19 | - args: 20 | - do-not-start 21 | command: 22 | - config-policy-controller 23 | image: quay.io/open-cluster-management/config-policy-controller:latest 24 | imagePullPolicy: IfNotPresent 25 | name: case40 26 | restartPolicy: Always 27 | -------------------------------------------------------------------------------- /test/resources/case43_standalone_hub_templates/operator-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1beta1 2 | kind: OperatorPolicy 3 | metadata: 4 | name: case43-oppol-with-hub-template 5 | ownerReferences: 6 | - apiVersion: policy.open-cluster-management.io/v1 7 | kind: Policy 8 | name: case43-parent 9 | uid: 12345678-90ab-cdef-1234-567890abcdef # must be replaced before creation 10 | spec: 11 | remediationAction: inform 12 | severity: medium 13 | complianceType: musthave 14 | subscription: 15 | name: strimzi-kafka-operator 16 | namespace: '{{hub fromConfigMap "default" "case43-input" "info" hub}}' 17 | upgradeApproval: None 18 | versions: [] 19 | -------------------------------------------------------------------------------- /test/resources/grc-operators/catalog.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: CatalogSource 3 | metadata: 4 | name: grc-mock-source 5 | # The OLM namespace has all the permissions required by the subscription. 6 | # Use `openshift-marketplace` namespace in openshift 7 | # e.g For example, you can install an operator in the namespace of your choice. 8 | namespace: olm 9 | spec: 10 | sourceType: grpc 11 | image: quay.io/stolostron-grc/grc-mock-operators-catalog:latest 12 | displayName: GRC mock operators 13 | grpcPodConfig: 14 | securityContextConfig: restricted 15 | publisher: grc-mock.io 16 | updateStrategy: 17 | registryPoll: 18 | interval: 60m 19 | 20 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_stdin/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e 18 | namespace: default 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /test/resources/case12_list_compare/case12_pod_inform.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-mh-listinform 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | recordDiff: Log 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e-12 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx2 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_compliant/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e 18 | namespace: default 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_desired_status/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e 18 | namespace: default 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | v1 Namespace default: 9 | # The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override. 10 | # Compliance messages: 11 | NonCompliant; violation - namespaces [default] found but not as specified 12 | -------------------------------------------------------------------------------- /test/resources/case1_pod_handling/case1_pod_check_empty_list.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-check-emptycontainerlist 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-empty 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 23 | -------------------------------------------------------------------------------- /test/resources/case2_role_handling/case2_role_check-mnh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-role-check-mnh 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: mustnothave 12 | objectDefinition: 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: Role 15 | metadata: 16 | name: pod-reader-e2e 17 | rules: 18 | - apiGroups: ["extensions", "apps"] 19 | resources: ["deployments"] 20 | verbs: ["get", "list", "watch", "create", "delete","patch"] -------------------------------------------------------------------------------- /test/resources/case30_multiline_templatization/case30_unterminated.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case30-configpolicy 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates-raw: | 11 | {{ range (lookup "v1" "ConfigMap" "default" "" "testcase=30").items }} 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: ConfigMap 16 | metadata: 17 | name: '{{' 18 | namespace: default 19 | data: 20 | extraData: exists! 21 | {{ end }} 22 | -------------------------------------------------------------------------------- /test/resources/case42_resource_selector/case42_eval_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case42-selector-eval-e2e 5 | spec: 6 | evaluationInterval: 7 | compliant: watch 8 | noncompliant: watch 9 | remediationAction: inform 10 | object-templates: 11 | - complianceType: musthave 12 | objectSelector: 13 | matchExpressions: 14 | - key: case42 15 | operator: Exists 16 | objectDefinition: 17 | apiVersion: config-policy-controller.io/v1 18 | kind: FakeAPI 19 | metadata: 20 | labels: 21 | selected: "true" 22 | namespace: case42-e2e-3 23 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_basic_noncompliant/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | namespaceSelector: 9 | exclude: ["kube-*"] 10 | include: ["default"] 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e 18 | namespace: default 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /test/dryrun/diff/from_secret_obj_temp_raw/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | v1 Namespace default: 9 | # The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override. 10 | # Compliance messages: 11 | NonCompliant; violation - namespaces [default] found but not as specified 12 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_inform_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-inform-c20 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteAll 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case2_role_handling/case2_role_create_inform.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-role-create-inform 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: Role 15 | metadata: 16 | name: pod-reader-e2e 17 | rules: 18 | - apiGroups: ["extensions", "apps"] 19 | resources: ["deployments"] 20 | verbs: ["get", "list", "watch", "create", "delete","patch"] -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_update_referenced_object.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-update-referenced-object 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: configmap-update-referenced-object-repl 17 | namespace: default 18 | data: 19 | message: | 20 | {{ fromConfigMap "default" "configmap-update-referenced-object" "message" }} 21 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_change_config_policy_not_prune.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case20-2-name-changed 5 | namespace: managed 6 | spec: 7 | remediationAction: enforce 8 | object-templates: 9 | - complianceType: musthave 10 | objectDefinition: 11 | apiVersion: v1 12 | kind: Pod 13 | metadata: 14 | name: case20-2-name-changed-pod 15 | namespace: default 16 | spec: 17 | containers: 18 | - name: nginx 19 | imagePullPolicy: Never 20 | image: nginx:1.7.9 21 | ports: 22 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_create_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-create-c20 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteIfCreated 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_annos.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-anno 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-9 17 | annotations: 18 | test: e2e 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-v0.9.0.md: -------------------------------------------------------------------------------- 1 | # v0.9.0 2 | 3 | - Switch leader election default 4 | - Enable foreground deletion 5 | - Send compliance events in more situations 6 | - Update named objects in arrays instead of appending 7 | - Perform validation of object definitions 8 | - Evaluate policies on every loop when evaluationInterval isn't set 9 | - Add metrics to record how long each config policy takes to be evaluated 10 | - Add metrics to time the compare algorithm 11 | - Send compliance state events synchronously for reliable ordering of compliance events 12 | - Allow enforcing policies that define a status with missing required fields 13 | - Update to Go v1.19 14 | - Favor the existing array ordering and content when comparing arrays 15 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_no_color/actual.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - lastTransitionTime: "2025-01-30T15:15:56Z" 6 | message: namespaces [test1] found as specified 7 | reason: K8s `must have` object already exists 8 | status: "True" 9 | type: notification 10 | compliant: Compliant 11 | lastEvaluated: "2025-01-30T15:15:56Z" 12 | lastEvaluatedGeneration: 1 13 | relatedObjects: 14 | - compliant: Compliant 15 | object: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: test1 20 | properties: 21 | createdByPolicy: true 22 | uid: e40a8473-dfcc-4826-bd5f-7df81cc79f5f 23 | reason: Resource found as expected 24 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_simple/actual.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - lastTransitionTime: "2025-01-30T15:15:56Z" 6 | message: namespaces [test1] found as specified 7 | reason: K8s `must have` object already exists 8 | status: "True" 9 | type: notification 10 | compliant: Compliant 11 | lastEvaluated: "2025-01-30T15:15:56Z" 12 | lastEvaluatedGeneration: 1 13 | relatedObjects: 14 | - compliant: Compliant 15 | object: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: test1 20 | properties: 21 | createdByPolicy: true 22 | uid: e40a8473-dfcc-4826-bd5f-7df81cc79f5f 23 | reason: Resource found as expected 24 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_pod_name_verify_configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-configmap-name 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: '{{ fromConfigMap "default" "e2e13config" "name" }}' 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case17_evaluation_interval/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-c17-create-ns 5 | ownerReferences: 6 | - apiVersion: policy.open-cluster-management.io/v1 7 | kind: Policy 8 | name: parent-policy-c17-create-ns 9 | uid: 12345678-90ab-cdef-1234-567890abcdef # must be replaced before creation 10 | spec: 11 | evaluationInterval: 12 | compliant: 10s 13 | noncompliant: 10s 14 | remediationAction: inform 15 | object-templates: 16 | - complianceType: musthave 17 | objectDefinition: 18 | kind: Namespace 19 | apiVersion: v1 20 | metadata: 21 | name: case17-test 22 | -------------------------------------------------------------------------------- /test/resources/case8_status_check/case8_pod_fail.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-invalid 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-badpod-e2e-8 17 | spec: 18 | containers: 19 | - name: nginx 20 | image: nginx:0.0.800 21 | ports: 22 | - containerPort: 80 23 | status: 24 | phase: Running 25 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_label_check.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-label-check 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-9 17 | labels: 18 | test: e2e 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_label_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-label-patch 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: nginx-pod-e2e-9 17 | labels: 18 | test: e2e 19 | spec: 20 | containers: 21 | - image: nginx:1.7.9 22 | name: nginx 23 | ports: 24 | - containerPort: 80 25 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_match/actual.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - lastTransitionTime: "2025-01-30T15:15:56Z" 6 | message: namespaces [test1] found as specified 7 | reason: K8s `must have` object already exists 8 | status: "True" 9 | type: notification 10 | compliant: Compliant 11 | lastEvaluated: "2025-01-30T15:15:56Z" 12 | lastEvaluatedGeneration: 1 13 | relatedObjects: 14 | - compliant: Compliant 15 | object: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: test1 20 | properties: 21 | createdByPolicy: true 22 | uid: e40a8473-dfcc-4826-bd5f-7df81cc79f5f 23 | reason: Resource found as expected 24 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_no_match/actual.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - lastTransitionTime: "2025-01-30T15:15:56Z" 6 | message: namespaces [test1] found as specified 7 | reason: K8s `must have` object already exists 8 | status: "True" 9 | type: notification 10 | compliant: Compliant 11 | lastEvaluated: "2025-01-30T15:15:56Z" 12 | lastEvaluatedGeneration: 1 13 | relatedObjects: 14 | - compliant: Compliant 15 | object: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: test1 20 | properties: 21 | createdByPolicy: true 22 | uid: e40a8473-dfcc-4826-bd5f-7df81cc79f5f 23 | reason: Resource found as expected 24 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_change_enforce.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-change-remediation-c20 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteAll 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_change_inform.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-change-remediation-c20 5 | spec: 6 | remediationAction: inform 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteAll 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_musthave_pod_deleteall.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-mhpda-c20 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteAll 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20-mhpda 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /test/dryrun/no_name/with_object_selector/mustnothave_unmatched/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-mustnothave-objselector 5 | spec: 6 | object-templates: 7 | - complianceType: mustnothave 8 | objectDefinition: 9 | apiVersion: v1 10 | kind: ConfigMap 11 | metadata: 12 | labels: 13 | isLower: 'true' 14 | privileged: 'yes' 15 | namespace: default 16 | objectSelector: 17 | matchLabels: 18 | isLower: 'true' 19 | recordDiff: InStatus 20 | recreateOption: None 21 | pruneObjectBehavior: DeleteAll 22 | remediationAction: inform 23 | severity: low 24 | -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_enforce_noncreated_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-already-created-c20 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | pruneObjectBehavior: DeleteAll 11 | object-templates: 12 | - complianceType: musthave 13 | objectDefinition: 14 | apiVersion: v1 15 | kind: Pod 16 | metadata: 17 | name: nginx-pod-e2e20 18 | spec: 19 | containers: 20 | - image: nginx:1.7.9 21 | name: nginx 22 | ports: 23 | - containerPort: 80 24 | -------------------------------------------------------------------------------- /pkg/dryrun/testdata/test_multiple_object_templates/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: example-config-policy 5 | namespace: default 6 | spec: 7 | remediationAction: enforce 8 | object-templates-raw: | 9 | {{range $ns := (list "another" "default" "nonexist")}} 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Pod 14 | metadata: 15 | name: nginx-pod 16 | namespace: {{$ns}} 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 8080 23 | {{end}} 24 | -------------------------------------------------------------------------------- /pkg/dryrun/utils_testdata/test_array_user_input_error/actual.yaml: -------------------------------------------------------------------------------- 1 | compliancyDetails: 2 | - Compliant: Compliant 3 | Validity: {} 4 | conditions: 5 | - lastTransitionTime: "2025-01-30T15:15:56Z" 6 | message: namespaces [test1] found as specified 7 | reason: K8s `must have` object already exists 8 | status: "True" 9 | type: notification 10 | compliant: Compliant 11 | lastEvaluated: "2025-01-30T15:15:56Z" 12 | lastEvaluatedGeneration: 1 13 | relatedObjects: 14 | - compliant: Compliant 15 | object: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: test1 20 | properties: 21 | createdByPolicy: true 22 | uid: e40a8473-dfcc-4826-bd5f-7df81cc79f5f 23 | reason: Resource found as expected 24 | -------------------------------------------------------------------------------- /test/dryrun/diff/secret_obj_temp/output.txt: -------------------------------------------------------------------------------- 1 | # Status compare: 2 | .compliant: 'NonCompliant' does match 'NonCompliant' 3 | .relatedObjects[0] matches 4 | .relatedObjects matches 5 | Expected status matches the actual status 6 | 7 | # Diffs: 8 | v1 Secret default/case39-secret: 9 | # The difference is redacted because it contains sensitive data. To override, the spec["object-templates"][].recordDiff field must be set to "InStatus" for the difference to be recorded in the policy status. Consider existing access to the ConfigurationPolicy objects and the etcd encryption configuration before you proceed with an override. 10 | # Compliance messages: 11 | NonCompliant; violation - secrets [case39-secret] found but not as specified in namespace default 12 | -------------------------------------------------------------------------------- /test/dryrun/no_ns/ns_role/policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case6-role-policy-no-ns 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: mustonlyhave 9 | objectDefinition: 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | kind: Role 12 | metadata: 13 | name: case6-role-policy-e2e 14 | rules: 15 | - apiGroups: ["extensions", "apps"] 16 | resources: ["deployments"] 17 | verbs: ["get", "list", "watch", "create", "delete","patch"] 18 | - apiGroups: [""] 19 | resources: ["pods"] 20 | verbs: ["get", "watch", "list"] 21 | -------------------------------------------------------------------------------- /test/resources/case13_templatization/case13_pod_nameFromClusterClaim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-pod-templatized-name 5 | spec: 6 | remediationAction: enforce 7 | namespaceSelector: 8 | exclude: ["kube-*"] 9 | include: ["default"] 10 | object-templates: 11 | - complianceType: musthave 12 | objectDefinition: 13 | apiVersion: v1 14 | kind: Pod 15 | metadata: 16 | name: '{{ fromClusterClaim "testclaim.open-cluster-management.io" }}' 17 | spec: 18 | containers: 19 | - image: nginx:1.7.9 20 | name: nginx 21 | ports: 22 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case20_delete_objects/case20_change_config_policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case20-name-changed 5 | namespace: managed 6 | spec: 7 | remediationAction: enforce 8 | pruneObjectBehavior: DeleteAll 9 | object-templates: 10 | - complianceType: musthave 11 | objectDefinition: 12 | apiVersion: v1 13 | kind: Pod 14 | metadata: 15 | name: case20-name-changed-pod 16 | namespace: default 17 | spec: 18 | containers: 19 | - name: nginx 20 | imagePullPolicy: Never 21 | image: nginx:1.7.9 22 | ports: 23 | - containerPort: 80 -------------------------------------------------------------------------------- /test/resources/case23_invalid_field/policy-ignore-status-field.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case23-pod-missing-status-fields 5 | spec: 6 | remediationAction: enforce 7 | object-templates: 8 | - complianceType: musthave 9 | objectDefinition: 10 | apiVersion: v1 11 | kind: Pod 12 | metadata: 13 | name: nginx-case23-missing-status 14 | namespace: default 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx:1.7.9 19 | ports: 20 | - containerPort: 80 21 | status: 22 | conditions: 23 | - status: "True" 24 | -------------------------------------------------------------------------------- /test/resources/case34_enforce_w_status/config-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: case34-cfgpol 5 | ownerReferences: 6 | - apiVersion: policy.open-cluster-management.io/v1 7 | blockOwnerDeletion: false 8 | controller: true 9 | kind: Policy 10 | name: case34-parent 11 | uid: 08bae967-4262-498a-84e9-d1f0e321b41e # to be replaced! 12 | spec: 13 | remediationAction: enforce 14 | severity: low 15 | object-templates: 16 | - complianceType: musthave 17 | objectDefinition: 18 | apiVersion: v1 19 | kind: Namespace 20 | metadata: 21 | name: case34-ns 22 | status: 23 | phase: Terminating 24 | -------------------------------------------------------------------------------- /test/resources/case38_operator_install/operator-policy-all-defaults.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1beta1 2 | kind: OperatorPolicy 3 | metadata: 4 | name: oppol-all-defaults 5 | labels: 6 | policy.open-cluster-management.io/cluster-name: "managed" 7 | policy.open-cluster-management.io/cluster-namespace: "managed" 8 | ownerReferences: 9 | - apiVersion: policy.open-cluster-management.io/v1 10 | kind: Policy 11 | name: parent-policy 12 | uid: 12345678-90ab-cdef-1234-567890abcdef # must be replaced before creation 13 | spec: 14 | remediationAction: enforce 15 | severity: medium 16 | complianceType: musthave 17 | subscription: 18 | name: airflow-helm-operator 19 | upgradeApproval: Automatic 20 | -------------------------------------------------------------------------------- /test/dryrun/multiple/multiple_obj_template/output.txt: -------------------------------------------------------------------------------- 1 | # Diffs: 2 | v1 Pod n1/multi-obj-temp-pod-11: 3 | 4 | v1 Pod n1/multi-obj-temp-pod-22: 5 | 6 | v1 Pod n1/multi-obj-temp-pod-33: 7 | 8 | v1 Pod n2/multi-obj-temp-pod-11: 9 | 10 | v1 Pod n2/multi-obj-temp-pod-22: 11 | 12 | v1 Pod n2/multi-obj-temp-pod-33: 13 | 14 | v1 Pod n3/multi-obj-temp-pod-11: 15 | 16 | v1 Pod n3/multi-obj-temp-pod-22: 17 | 18 | v1 Pod n3/multi-obj-temp-pod-33: 19 | 20 | # Compliance messages: 21 | Compliant; notification - pods [multi-obj-temp-pod-11] found as specified in namespaces: n1, n2, n3; notification - pods [multi-obj-temp-pod-22] found as specified in namespaces: n1, n2, n3; notification - pods [multi-obj-temp-pod-33] found as specified in namespaces: n1, n2, n3 22 | -------------------------------------------------------------------------------- /test/resources/case15_event_format/case15_mh_pod_nevercompliant.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: mh-pod-nevercompliant 5 | ownerReferences: 6 | - apiVersion: policy.open-cluster-management.io/v1 7 | kind: Policy 8 | name: parent-nevercompliant 9 | uid: 12345678-90ab-cdef-1234-567890abcdef # must be replaced before creation 10 | spec: 11 | remediationAction: inform 12 | namespaceSelector: 13 | exclude: ["kube-*"] 14 | include: ["default"] 15 | object-templates: 16 | - complianceType: musthave 17 | objectDefinition: 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | name: case15-nevercompliant 22 | -------------------------------------------------------------------------------- /test/resources/case21_alternative_kubeconfig/parent-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: Policy 3 | metadata: 4 | name: parent-create-ns 5 | spec: 6 | remediationAction: inform 7 | disabled: false 8 | policy-templates: 9 | - objectDefinition: 10 | apiVersion: policy.open-cluster-management.io/v1 11 | kind: ConfigurationPolicy 12 | metadata: 13 | name: create-ns 14 | spec: 15 | remediationAction: enforce 16 | object-templates: 17 | - complianceType: musthave 18 | objectDefinition: 19 | apiVersion: v1 20 | kind: Namespace 21 | metadata: 22 | name: e2e-test-ns 23 | -------------------------------------------------------------------------------- /test/resources/case9_md_check/case9_ns_create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.open-cluster-management.io/v1 2 | kind: ConfigurationPolicy 3 | metadata: 4 | name: policy-c9-create-ns 5 | labels: 6 | test: e2e 7 | annotations: 8 | test: e2e 9 | spec: 10 | remediationAction: enforce 11 | namespaceSelector: 12 | exclude: 13 | - kube-* 14 | include: 15 | - default 16 | object-templates: 17 | - complianceType: musthave 18 | metadataComplianceType: mustonlyhave 19 | objectDefinition: 20 | kind: Namespace 21 | apiVersion: v1 22 | metadata: 23 | name: case9-test 24 | annotations: 25 | foo.bar/baz: hello world 26 | openshift.io/sa.scc.policy: keep 27 | --------------------------------------------------------------------------------