From 78f24497fada790aaa0c0d7248154aeb8c217ba1 Mon Sep 17 00:00:00 2001 From: Frank Jogeleit Date: Mon, 7 Oct 2024 11:10:46 +0200 Subject: [PATCH] Policy Reporter v3 (#482) Policy Reporter v3 Signed-off-by: Frank Jogeleit --- .github/dependabot.yaml | 10 + .github/workflows/ci.yaml | 59 +- .github/workflows/cr.yaml | 29 - .github/workflows/docs.yaml | 7 +- .github/workflows/helm-chart.yaml | 16 +- .github/workflows/release-chart.yaml | 65 + .../{image.yaml => release-image.yaml} | 41 +- .gitignore | 1 + CHANGELOG.md | 2 +- DEMO.md | 144 ++ Dockerfile | 2 +- Makefile | 153 +- README.md | 71 +- charts/policy-reporter/Chart.lock | 12 - charts/policy-reporter/Chart.yaml | 15 +- charts/policy-reporter/README.md | 558 +++++- charts/policy-reporter/README.md.gotmpl | 50 + .../charts/kyvernoPlugin/Chart.yaml | 7 - .../charts/kyvernoPlugin/config.yaml | 21 - .../kyvernoPlugin/templates/_helpers.tpl | 105 -- .../templates/clusterrolebinding.yaml | 20 - .../templates/config-secret.yaml | 14 - .../kyvernoPlugin/templates/deployment.yaml | 129 -- .../kyvernoPlugin/templates/ingress.yaml | 61 - .../templates/networkpolicy.yaml | 33 - .../templates/poddisruptionbudget.yaml | 22 - .../charts/kyvernoPlugin/templates/role.yaml | 24 - .../kyvernoPlugin/templates/rolebinding.yaml | 21 - .../kyvernoPlugin/templates/secret-role.yaml | 19 - .../templates/secret-rolebinding.yaml | 21 - .../kyvernoPlugin/templates/service.yaml | 30 - .../templates/serviceaccount.yaml | 18 - .../charts/kyvernoPlugin/values.yaml | 211 --- .../charts/monitoring/Chart.yaml | 7 - .../charts/monitoring/templates/_helpers.tpl | 85 - .../monitoring/templates/auth-secret.yaml | 17 - ...lusterpolicy-details.grafanadashboard.yaml | 20 - .../templates/kyverno-servicemonitor.yaml | 63 - .../templates/overview.grafanadashboard.yaml | 20 - .../policy-details.grafanadashboard.yaml | 20 - .../charts/monitoring/values.yaml | 150 -- charts/policy-reporter/charts/ui/Chart.yaml | 7 - .../charts/ui/templates/_helpers.tpl | 140 -- .../charts/ui/templates/config.yaml | 52 - .../charts/ui/templates/deployment.yaml | 123 -- .../charts/ui/templates/extra-manifests.yaml | 4 - .../charts/ui/templates/networkpolicy.yaml | 44 - .../charts/ui/templates/service.yaml | 33 - .../charts/ui/templates/serviceaccount.yaml | 18 - charts/policy-reporter/charts/ui/values.yaml | 279 --- charts/policy-reporter/config.yaml | 416 ----- charts/policy-reporter/configs/core.tmpl | 176 ++ .../email-reports.tmpl} | 0 .../configs/kyverno-plugin.tmpl | 27 + .../policy-reporter/configs/trivy-plugin.tmpl | 20 + charts/policy-reporter/configs/ui.tmpl | 70 + charts/policy-reporter/templates/_helpers.tpl | 142 +- .../templates/cluster-secret.yaml | 26 + .../templates/clusterrole.yaml | 18 + .../config-email-reports-secret.yaml | 2 +- .../templates/config-secret.yaml | 4 +- .../templates/cronjob-summary-report.yaml | 2 +- .../templates/cronjob-violations-report.yaml | 2 +- .../policy-reporter/templates/deployment.yaml | 10 +- .../templates/monitoring/_helpers.tpl | 56 + .../templates/monitoring/auth-secret.yaml | 19 + .../clusterpolicy-details.dashboard.yaml | 74 +- ...lusterpolicy-details.grafanadashboard.yaml | 19 + .../monitoring}/overview.dashboard.yaml | 58 +- .../monitoring/overview.grafanadashboard.yaml | 19 + .../monitoring}/policy-details.dashboard.yaml | 82 +- .../policy-details.grafanadashboard.yaml | 19 + .../monitoring}/servicemonitor.yaml | 37 +- .../templates/networkpolicy.yaml | 20 +- .../templates/plugins/kyverno/_helpers.tpl | 68 + .../plugins/kyverno}/clusterrole.yaml | 26 +- .../plugins/kyverno/clusterrolebinding.yaml | 18 + .../plugins/kyverno/config-secret.yaml | 12 + .../templates/plugins/kyverno/deployment.yaml | 103 ++ .../templates/plugins/kyverno/ingress.yaml | 61 + .../plugins/kyverno/networkpolicy.yaml | 24 + .../plugins/kyverno/poddisruptionbudget.yaml | 19 + .../templates/plugins/kyverno/role.yaml | 22 + .../plugins/kyverno/rolebinding.yaml | 19 + .../plugins/kyverno/secret-role.yaml | 17 + .../plugins/kyverno/secret-rolebinding.yaml | 19 + .../templates/plugins/kyverno/service.yaml | 25 + .../plugins/kyverno/serviceaccount.yaml | 16 + .../templates/plugins/trivy/_helpers.tpl | 68 + .../plugins/trivy/config-secret.yaml | 12 + .../templates/plugins/trivy/deployment.yaml | 97 + .../templates/plugins/trivy/ingress.yaml | 61 + .../plugins/trivy/networkpolicy.yaml | 31 + .../plugins/trivy/poddisruptionbudget.yaml | 20 + .../templates/plugins/trivy/secret-role.yaml | 17 + .../plugins/trivy/secret-rolebinding.yaml | 19 + .../templates/plugins/trivy/service.yaml | 25 + .../plugins/trivy/serviceaccount.yaml | 16 + charts/policy-reporter/templates/role.yaml | 2 +- .../templates/rolebinding.yaml | 2 +- .../templates/secret-role.yaml | 2 + .../policy-reporter/templates/ui/_helpers.tpl | 68 + .../templates/ui/config-secret.yaml | 12 + .../templates/ui/deployment.yaml | 112 ++ .../templates/ui/extra-manifests.yaml | 6 + .../templates => templates/ui}/ingress.yaml | 35 +- .../templates/ui/networkpolicy.yaml | 53 + .../ui}/poddisruptionbudget.yaml | 14 +- .../ui}/secret-role.yaml | 12 +- .../ui}/secret-rolebinding.yaml | 12 +- .../policy-reporter/templates/ui/service.yaml | 28 + .../templates/ui/serviceaccount.yaml | 16 + charts/policy-reporter/values.yaml | 1635 +++++++++++++---- cmd/run.go | 64 +- cmd/send/summary.go | 8 +- cmd/send/violations.go | 8 +- docs/CUSTOM_BOARDS.md | 70 + docs/EXCEPTIONS.md | 64 + docs/SETUP.md | 30 + docs/UI_AUTH.md | 104 ++ docs/images/custom-boards/cluster.png | Bin 0 -> 200428 bytes docs/images/custom-boards/list.png | Bin 0 -> 186963 bytes docs/images/custom-boards/selector.png | Bin 0 -> 189467 bytes docs/images/custom-boards/source.png | Bin 0 -> 194909 bytes docs/images/exceptions/exception-dialog.png | Bin 0 -> 435951 bytes docs/images/exceptions/resource-list.png | Bin 0 -> 199119 bytes docs/images/screen.png | Bin 0 -> 207773 bytes go.mod | 198 +- go.sum | 443 +++-- .../policy-reporter-kyverno-ui-ha/README.md | 2 +- pkg/api/basic_auth.go | 41 - pkg/api/basic_auth_test.go | 63 - pkg/api/gzip.go | 50 - pkg/api/gzip_test.go | 85 - pkg/api/handler.go | 49 - pkg/api/handler_test.go | 75 - pkg/api/healthz.go | 25 + pkg/api/healthz_test.go | 71 + pkg/api/metrics.go | 14 + pkg/api/metrics_test.go | 61 + pkg/api/server.go | 240 +-- pkg/api/server_test.go | 195 +- pkg/api/utils.go | 103 ++ pkg/api/utils_test.go | 112 ++ pkg/api/v1/api.go | 267 +++ pkg/api/v1/api_test.go | 301 +++ pkg/api/v1/finder.go | 81 - pkg/api/v1/handler.go | 310 ---- pkg/api/v1/handler_test.go | 667 ------- pkg/api/v1/html_report.go | 146 -- pkg/api/v1/model.go | 195 +- pkg/api/v1/model_test.go | 44 + pkg/api/v2/api.go | 286 +++ pkg/api/v2/api_test.go | 481 +++++ pkg/api/v2/views.go | 754 ++++++++ pkg/api/v2/views_test.go | 362 ++++ pkg/cache/redis_test.go | 1 + pkg/config/config.go | 417 ++--- pkg/config/database_factory.go | 3 + pkg/config/database_factory_test.go | 40 + pkg/config/readinessprobe.go | 5 +- pkg/config/resolver.go | 226 ++- pkg/config/resolver_test.go | 617 ++++--- pkg/config/target_factory.go | 984 ---------- pkg/config/target_factory_test.go | 816 -------- .../v1alpha2/clusterpolicyreport_types.go | 14 + .../clusterpolicyreport_types_test.go | 3 +- pkg/crd/api/policyreport/v1alpha2/common.go | 98 +- .../api/policyreport/v1alpha2/common_test.go | 175 -- .../v1alpha2/policyreport_types.go | 15 + .../v1alpha2/policyreport_types_test.go | 3 +- pkg/database/builder.go | 229 +++ pkg/database/bun.go | 1495 ++++++++------- pkg/database/bun_test.go | 678 ------- pkg/database/model.go | 185 +- pkg/database/views.go | 71 + pkg/email/filter.go | 27 +- pkg/email/filter_test.go | 2 +- pkg/email/summary/fixtures_test.go | 2 +- pkg/email/summary/generator_test.go | 8 +- pkg/email/violations/fixtures_test.go | 2 +- pkg/email/violations/generator_test.go | 8 +- pkg/fixtures/policy_reports.go | 37 + pkg/fixtures/policy_results.go | 10 - pkg/fixtures/target_results.go | 49 +- pkg/helper/chunk_slice.go | 16 + pkg/helper/http_test.go | 43 + pkg/helper/title.go | 12 + pkg/helper/utils.go | 65 +- pkg/helper/utils_test.go | 75 + pkg/kubernetes/jobs/client.go | 32 + pkg/kubernetes/namespaces/client.go | 54 + pkg/kubernetes/namespaces/client_test.go | 100 + pkg/kubernetes/pods/client.go | 31 + pkg/kubernetes/policy_report_client.go | 4 +- pkg/kubernetes/policy_report_client_test.go | 11 +- pkg/kubernetes/queue.go | 16 +- pkg/kubernetes/retry.go | 41 + pkg/kubernetes/retry_test.go | 152 ++ pkg/kubernetes/secrets/client.go | 40 +- pkg/kubernetes/secrets/client_test.go | 12 +- pkg/kubernetes/secrets/informer.go | 122 ++ pkg/kubernetes/secrets/informer_test.go | 67 + pkg/leaderelection/client.go | 12 +- pkg/leaderelection/client_test.go | 36 +- pkg/listener/cleanup.go | 8 +- pkg/listener/cleanup_test.go | 12 +- pkg/listener/metrics.go | 18 +- pkg/listener/metrics/cluster_policy_report.go | 50 - .../metrics/cluster_policy_report_test.go | 173 -- pkg/listener/metrics/policy_report.go | 50 - pkg/listener/metrics/policy_report_test.go | 143 -- pkg/listener/metrics_test.go | 53 +- pkg/listener/new_result.go | 122 +- pkg/listener/new_result_test.go | 33 +- pkg/listener/scope_results.go | 39 + pkg/listener/scope_results_test.go | 38 + pkg/listener/send_result.go | 4 +- pkg/listener/send_result_test.go | 45 +- pkg/listener/sync_results.go | 52 + pkg/report/client.go | 6 + pkg/report/filter.go | 77 - pkg/report/filter_test.go | 94 - pkg/report/meta_filter.go | 26 + pkg/report/meta_filter_test.go | 60 + pkg/report/report_filter.go | 29 + pkg/report/report_filter_test.go | 24 + pkg/report/result/id_generator.go | 3 +- pkg/report/result/id_generator_test.go | 5 +- pkg/report/result/mapper.go | 29 - pkg/report/result/mapper_test.go | 75 - pkg/report/result/reconditioner.go | 1 - pkg/report/result/reconditioner_test.go | 11 +- pkg/report/result/resource.go | 3 +- pkg/report/result/resource_test.go | 3 +- pkg/report/result_filter.go | 31 + pkg/report/result_filter_test.go | 25 + pkg/report/source_filter.go | 154 ++ pkg/target/client.go | 125 +- pkg/target/client_test.go | 308 ++-- pkg/target/collection.go | 144 ++ pkg/target/collection_test.go | 88 + pkg/target/discord/discord.go | 24 +- pkg/target/elasticsearch/elasticsearch.go | 7 +- pkg/target/factory.go | 172 ++ pkg/target/factory/factory.go | 960 ++++++++++ pkg/target/factory/factory_test.go | 1006 ++++++++++ pkg/target/factory_test.go | 96 + pkg/target/formatting/resource.go | 19 + pkg/target/gcs/gcs.go | 11 +- pkg/target/googlechat/googlechat.go | 15 +- pkg/target/http/logroundtripper.go | 5 +- pkg/target/http/logroundtripper_test.go | 33 + pkg/target/http/utils.go | 5 +- pkg/target/http/utils_test.go | 94 + pkg/target/kinesis/kinesis.go | 14 +- pkg/target/loki/loki.go | 96 +- pkg/target/loki/loki_test.go | 165 +- pkg/{helper => target/provider/aws}/aws.go | 8 +- pkg/target/provider/aws/aws_test.go | 28 + .../gcp.go => target/provider/gcs/gcs.go} | 18 +- pkg/target/s3/s3.go | 14 +- pkg/target/securityhub/securityhub.go | 489 ++++- pkg/target/securityhub/securityhub_test.go | 31 +- pkg/target/slack/slack.go | 333 ++-- pkg/target/teams/card.go | 55 + pkg/target/teams/teams.go | 199 +- pkg/target/teams/teams_test.go | 38 +- pkg/target/telegram/telegram.go | 20 +- pkg/target/ui/ui.go | 43 - pkg/target/ui/ui_test.go | 63 - pkg/target/webhook/webhook.go | 8 +- pkg/target/webhook/webhook_test.go | 16 + pkg/validate/model.go | 9 +- policy.yaml | 22 + scripts/kind.yaml | 34 + test | 2 + 277 files changed, 15718 insertions(+), 11040 deletions(-) create mode 100644 .github/dependabot.yaml delete mode 100644 .github/workflows/cr.yaml create mode 100644 .github/workflows/release-chart.yaml rename .github/workflows/{image.yaml => release-image.yaml} (67%) create mode 100644 DEMO.md delete mode 100644 charts/policy-reporter/Chart.lock create mode 100644 charts/policy-reporter/README.md.gotmpl delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/Chart.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/config.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/_helpers.tpl delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrolebinding.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/config-secret.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/deployment.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/ingress.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/networkpolicy.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/poddisruptionbudget.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/role.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/rolebinding.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/secret-role.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/secret-rolebinding.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/service.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/templates/serviceaccount.yaml delete mode 100644 charts/policy-reporter/charts/kyvernoPlugin/values.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/Chart.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/templates/_helpers.tpl delete mode 100644 charts/policy-reporter/charts/monitoring/templates/auth-secret.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.grafanadashboard.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/templates/kyverno-servicemonitor.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/templates/overview.grafanadashboard.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/templates/policy-details.grafanadashboard.yaml delete mode 100644 charts/policy-reporter/charts/monitoring/values.yaml delete mode 100644 charts/policy-reporter/charts/ui/Chart.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/_helpers.tpl delete mode 100644 charts/policy-reporter/charts/ui/templates/config.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/deployment.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/extra-manifests.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/networkpolicy.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/service.yaml delete mode 100644 charts/policy-reporter/charts/ui/templates/serviceaccount.yaml delete mode 100644 charts/policy-reporter/charts/ui/values.yaml delete mode 100644 charts/policy-reporter/config.yaml create mode 100644 charts/policy-reporter/configs/core.tmpl rename charts/policy-reporter/{config-email-reports.yaml => configs/email-reports.tmpl} (100%) create mode 100644 charts/policy-reporter/configs/kyverno-plugin.tmpl create mode 100644 charts/policy-reporter/configs/trivy-plugin.tmpl create mode 100644 charts/policy-reporter/configs/ui.tmpl create mode 100644 charts/policy-reporter/templates/cluster-secret.yaml create mode 100644 charts/policy-reporter/templates/monitoring/_helpers.tpl create mode 100644 charts/policy-reporter/templates/monitoring/auth-secret.yaml rename charts/policy-reporter/{charts/monitoring/templates => templates/monitoring}/clusterpolicy-details.dashboard.yaml (82%) create mode 100644 charts/policy-reporter/templates/monitoring/clusterpolicy-details.grafanadashboard.yaml rename charts/policy-reporter/{charts/monitoring/templates => templates/monitoring}/overview.dashboard.yaml (84%) create mode 100644 charts/policy-reporter/templates/monitoring/overview.grafanadashboard.yaml rename charts/policy-reporter/{charts/monitoring/templates => templates/monitoring}/policy-details.dashboard.yaml (81%) create mode 100644 charts/policy-reporter/templates/monitoring/policy-details.grafanadashboard.yaml rename charts/policy-reporter/{charts/monitoring/templates => templates/monitoring}/servicemonitor.yaml (50%) create mode 100644 charts/policy-reporter/templates/plugins/kyverno/_helpers.tpl rename charts/policy-reporter/{charts/kyvernoPlugin/templates => templates/plugins/kyverno}/clusterrole.yaml (57%) create mode 100644 charts/policy-reporter/templates/plugins/kyverno/clusterrolebinding.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/config-secret.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/deployment.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/ingress.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/networkpolicy.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/poddisruptionbudget.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/role.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/rolebinding.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/secret-role.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/secret-rolebinding.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/service.yaml create mode 100644 charts/policy-reporter/templates/plugins/kyverno/serviceaccount.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/_helpers.tpl create mode 100644 charts/policy-reporter/templates/plugins/trivy/config-secret.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/deployment.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/ingress.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/networkpolicy.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/poddisruptionbudget.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/secret-role.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/secret-rolebinding.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/service.yaml create mode 100644 charts/policy-reporter/templates/plugins/trivy/serviceaccount.yaml create mode 100644 charts/policy-reporter/templates/ui/_helpers.tpl create mode 100644 charts/policy-reporter/templates/ui/config-secret.yaml create mode 100644 charts/policy-reporter/templates/ui/deployment.yaml create mode 100644 charts/policy-reporter/templates/ui/extra-manifests.yaml rename charts/policy-reporter/{charts/ui/templates => templates/ui}/ingress.yaml (55%) create mode 100644 charts/policy-reporter/templates/ui/networkpolicy.yaml rename charts/policy-reporter/{charts/ui/templates => templates/ui}/poddisruptionbudget.yaml (52%) rename charts/policy-reporter/{charts/ui/templates => templates/ui}/secret-role.yaml (50%) rename charts/policy-reporter/{charts/ui/templates => templates/ui}/secret-rolebinding.yaml (59%) create mode 100644 charts/policy-reporter/templates/ui/service.yaml create mode 100644 charts/policy-reporter/templates/ui/serviceaccount.yaml create mode 100644 docs/CUSTOM_BOARDS.md create mode 100644 docs/EXCEPTIONS.md create mode 100644 docs/SETUP.md create mode 100644 docs/UI_AUTH.md create mode 100644 docs/images/custom-boards/cluster.png create mode 100644 docs/images/custom-boards/list.png create mode 100644 docs/images/custom-boards/selector.png create mode 100644 docs/images/custom-boards/source.png create mode 100644 docs/images/exceptions/exception-dialog.png create mode 100644 docs/images/exceptions/resource-list.png create mode 100644 docs/images/screen.png delete mode 100644 pkg/api/basic_auth.go delete mode 100644 pkg/api/basic_auth_test.go delete mode 100644 pkg/api/gzip.go delete mode 100644 pkg/api/gzip_test.go delete mode 100644 pkg/api/handler.go delete mode 100644 pkg/api/handler_test.go create mode 100644 pkg/api/healthz.go create mode 100644 pkg/api/healthz_test.go create mode 100644 pkg/api/metrics.go create mode 100644 pkg/api/metrics_test.go create mode 100644 pkg/api/utils.go create mode 100644 pkg/api/utils_test.go create mode 100644 pkg/api/v1/api.go create mode 100644 pkg/api/v1/api_test.go delete mode 100644 pkg/api/v1/finder.go delete mode 100644 pkg/api/v1/handler.go delete mode 100644 pkg/api/v1/handler_test.go delete mode 100644 pkg/api/v1/html_report.go create mode 100644 pkg/api/v1/model_test.go create mode 100644 pkg/api/v2/api.go create mode 100644 pkg/api/v2/api_test.go create mode 100644 pkg/api/v2/views.go create mode 100644 pkg/api/v2/views_test.go delete mode 100644 pkg/config/target_factory.go delete mode 100644 pkg/config/target_factory_test.go delete mode 100644 pkg/crd/api/policyreport/v1alpha2/common_test.go create mode 100644 pkg/database/builder.go delete mode 100644 pkg/database/bun_test.go create mode 100644 pkg/database/views.go create mode 100644 pkg/helper/chunk_slice.go create mode 100644 pkg/helper/http_test.go create mode 100644 pkg/helper/title.go create mode 100644 pkg/helper/utils_test.go create mode 100644 pkg/kubernetes/jobs/client.go create mode 100644 pkg/kubernetes/namespaces/client.go create mode 100644 pkg/kubernetes/namespaces/client_test.go create mode 100644 pkg/kubernetes/pods/client.go create mode 100644 pkg/kubernetes/retry.go create mode 100644 pkg/kubernetes/retry_test.go create mode 100644 pkg/kubernetes/secrets/informer.go create mode 100644 pkg/kubernetes/secrets/informer_test.go delete mode 100644 pkg/listener/metrics/cluster_policy_report.go delete mode 100644 pkg/listener/metrics/cluster_policy_report_test.go delete mode 100644 pkg/listener/metrics/policy_report.go delete mode 100644 pkg/listener/metrics/policy_report_test.go create mode 100644 pkg/listener/scope_results.go create mode 100644 pkg/listener/scope_results_test.go create mode 100644 pkg/listener/sync_results.go delete mode 100644 pkg/report/filter.go delete mode 100644 pkg/report/filter_test.go create mode 100644 pkg/report/meta_filter.go create mode 100644 pkg/report/meta_filter_test.go create mode 100644 pkg/report/report_filter.go create mode 100644 pkg/report/report_filter_test.go delete mode 100644 pkg/report/result/mapper.go delete mode 100644 pkg/report/result/mapper_test.go create mode 100644 pkg/report/result_filter.go create mode 100644 pkg/report/result_filter_test.go create mode 100644 pkg/report/source_filter.go create mode 100644 pkg/target/collection.go create mode 100644 pkg/target/collection_test.go create mode 100644 pkg/target/factory.go create mode 100644 pkg/target/factory/factory.go create mode 100644 pkg/target/factory/factory_test.go create mode 100644 pkg/target/factory_test.go create mode 100644 pkg/target/formatting/resource.go create mode 100644 pkg/target/http/logroundtripper_test.go create mode 100644 pkg/target/http/utils_test.go rename pkg/{helper => target/provider/aws}/aws.go (97%) create mode 100644 pkg/target/provider/aws/aws_test.go rename pkg/{helper/gcp.go => target/provider/gcs/gcs.go} (72%) create mode 100644 pkg/target/teams/card.go delete mode 100644 pkg/target/ui/ui.go delete mode 100644 pkg/target/ui/ui_test.go create mode 100644 policy.yaml create mode 100644 scripts/kind.yaml create mode 100644 test diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 00000000..2fccaad8 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: daily + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dfec104c..55f0985b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,7 +4,7 @@ on: push: branches: - main - - development + - 3.x paths-ignore: - README.md @@ -14,25 +14,62 @@ on: pull_request: branches: - main + - 3.x jobs: coverage: runs-on: ubuntu-latest steps: - - name: Set up Go 1.22 - uses: actions/setup-go@v2 + - name: Checkout + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + + - name: Set up Go + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.2.0 with: - go-version: 1.22 - - name: Checkout code - uses: actions/checkout@v2 - - name: Get dependencies - run: go get -v -t -d ./... + go-version-file: go.mod + cache-dependency-path: go.sum + + - name: Check go.mod + run: | + set -e + go mod tidy && git diff --exit-code + + - name: Check code format + run: | + set -e + make fmt + git diff --exit-code + + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.24.0 + with: + scan-type: 'fs' + ignore-unfixed: true + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH' + - name: Calc coverage run: make coverage + - name: Convert coverage to lcov - uses: jandelgado/gcov2lcov-action@v1.0.9 + uses: jandelgado/gcov2lcov-action@c680c0f7c7442485f1749eb2a13e54a686e76eb5 #v1.0.9 + - name: Coveralls - uses: coverallsapp/github-action@v2.0.0 + uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 # v2.3.0 with: github-token: ${{ secrets.github_token }} - file: coverage.lcov \ No newline at end of file + file: coverage.lcov + + check-actions: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - name: Ensure SHA pinned actions + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@b8f9a25a51fe633d9215ac7734854dc11cd299cb # v3.0.13 + with: + # slsa-github-generator requires using a semver tag for reusable workflows. + # See: https://github.com/slsa-framework/slsa-github-generator#referencing-slsa-builders-and-generators + allowlist: | + slsa-framework/slsa-github-generator \ No newline at end of file diff --git a/.github/workflows/cr.yaml b/.github/workflows/cr.yaml deleted file mode 100644 index 129ad600..00000000 --- a/.github/workflows/cr.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Release Charts - -on: - push: - branches: - - main - paths: - - 'charts/**' - - 'manifests/**' - -jobs: - release: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Configure Git - run: | - git config user.name "$GITHUB_ACTOR" - git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - - name: Install Helm - uses: azure/setup-helm@v1 - - - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.2.1 - env: - CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 18853b2f..912f3c8d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Setup node env - uses: actions/setup-node@v2.1.2 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 #v4.0.4 with: node-version: 16 @@ -32,9 +32,8 @@ jobs: cp index.yaml ./dist/index.yaml cp artifacthub-repo.yml ./dist/artifacthub-repo.yml - - name: Deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e #v4.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist diff --git a/.github/workflows/helm-chart.yaml b/.github/workflows/helm-chart.yaml index b5f4fa3b..9c74a826 100644 --- a/.github/workflows/helm-chart.yaml +++ b/.github/workflows/helm-chart.yaml @@ -5,7 +5,6 @@ on: # run pipeline on push on master branches: - main - - development paths: - "charts/**" @@ -18,16 +17,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: "0" - name: chart-testing (ct lint) - uses: helm/chart-testing-action@v2.0.1 + uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1 - name: Run Helm Chart lint run: | - ct lint --lint-conf=.github/ct_lintconf.yaml \ - --chart-yaml-schema=.github/ct_chart_schema.yaml \ - --target-branch=main --validate-maintainers=false \ - --chart-dirs charts + set -e + ct lint --lint-conf=.github/ct_lintconf.yaml \ + --chart-yaml-schema=.github/ct_chart_schema.yaml \ + --target-branch=main \ + --validate-maintainers=false \ + --check-version-increment=false \ + --chart-dirs charts diff --git a/.github/workflows/release-chart.yaml b/.github/workflows/release-chart.yaml new file mode 100644 index 00000000..1326640e --- /dev/null +++ b/.github/workflows/release-chart.yaml @@ -0,0 +1,65 @@ +name: release-chart + +on: + push: + tags: + - 'policy-reporter-chart-v*' + +jobs: + helm-chart: + runs-on: ubuntu-latest + permissions: + contents: write + pages: write + steps: + - name: Checkout + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + fetch-depth: 0 + + - name: Verify Helm Docs + run: | + set -e + make verify-helm-docs + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 + with: + version: v3.16.1 + + - name: Prepare GPG key + run: | + gpg_dir=.cr-gpg + mkdir "$gpg_dir" + keyring="$gpg_dir/secring.gpg" + base64 -d <<< "$GPG_KEYRING_BASE64" > "$keyring" + passphrase_file="$gpg_dir/passphrase" + echo "$GPG_PASSPHRASE" > "$passphrase_file" + echo "CR_PASSPHRASE_FILE=$passphrase_file" >> "$GITHUB_ENV" + echo "CR_KEYRING=$keyring" >> "$GITHUB_ENV" + env: + GPG_KEYRING_BASE64: "${{ secrets.GPG_KEYRING_BASE64 }}" #Referring secrets of github above + GPG_PASSPHRASE: "${{ secrets.GPG_PASSPHRASE }}" + + - name: Run chart-releaser + uses: helm/chart-releaser-action@a917fd15b20e8b64b94d9158ad54cd6345335584 # v1.6.0 + id: cr + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + CR_KEY: "${{ secrets.CR_KEY }}" + CR_SIGN: true + + - name: Install Cosign + uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 # v3.2.0 + + - name: Push to OCI + run: | + set -e + output=$(helm push .cr-release-packages/policy-reporter-{{ steps.cr.outputs.chart_version }}.tgz oci://ghcr.io/kyverno/charts 2>&1) + digest=$( echo "$output" | grep Digest | cut -c9-) + cosign sign --yes ghcr.io/kyverno/charts/policy-reporter@$digest \ No newline at end of file diff --git a/.github/workflows/image.yaml b/.github/workflows/release-image.yaml similarity index 67% rename from .github/workflows/image.yaml rename to .github/workflows/release-image.yaml index 1dee0dfe..c99d1cc3 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/release-image.yaml @@ -1,9 +1,16 @@ -name: image +name: release-image on: push: + branches: + - main + tags: - - v* - - dev + - 'v*' + + paths-ignore: + - README.md + - charts/** + - manifest/** permissions: contents: read @@ -15,58 +22,58 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Push image id: params run: | # Strip git ref prefix from version - VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + VERSION=$(git rev-parse --short "$GITHUB_SHA") # Strip "v" prefix from tag name [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') echo VERSION=$VERSION - echo "::set-output name=version::$VERSION" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" - name: Login to Github Packages - uses: docker/login-action@v2 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.CR_PAT }} - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 #v3.7.1 id: buildx with: install: true version: latest - name: Build image and push to GitHub Container Registry - uses: docker/build-push-action@v3 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0 id: push with: push: true - platforms: linux/arm64,linux/amd64,linux/s390x + platforms: linux/arm64,linux/amd64 cache-from: type=registry,ref=ghcr.io/kyverno/policy-reporter:buildcache cache-to: type=registry,ref=ghcr.io/kyverno/policy-reporter:buildcache,mode=max tags: | - ghcr.io/kyverno/policy-reporter:latest - ghcr.io/kyverno/policy-reporter:${{ steps.params.outputs.version }} + ghcr.io/kyverno/policy-reporter:${{ env.VERSION }} - - name: Set up Go 1.22 - uses: actions/setup-go@v2 + - name: Set up Go + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.2.0 with: - go-version: 1.22 + go-version-file: go.mod + cache-dependency-path: go.sum - uses: CycloneDX/gh-gomod-generate-sbom@efc74245d6802c8cefd925620515442756c70d8f # v2.0.0 with: version: v1 args: app -licenses -json -output policy-reporter-bom.cdx.json -main . - - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: policy-reporter-bom-cdx path: policy-reporter-bom.cdx.json diff --git a/.gitignore b/.gitignore index a7fb23a6..2d92d65d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build /test.yaml *.db values*.yaml +monitoring.yaml coverage.out* heap* /.env* diff --git a/CHANGELOG.md b/CHANGELOG.md index 94fda6ae..76cb34f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -309,7 +309,7 @@ * Policy Reporter * New `certificate` config for `loki`, `elasticsearch`, `teams`, `webhook` and `ui`, to set the path to your custom certificate for the related client. * New `skipTLS` config for `loki`, `elasticsearch`, `teams`, `webhook` and `ui`, to skip tls if needed for the given target. - * New `secretRef` for targets to reference a secret with the related `username`, `password`, `webhook`, `host`, `accessKeyID`, `secretAccessKey` information of the given target, instead of configure your credentials directly. + * New `secretRef` for targets to reference a secret with the related `username`, `password`, `webhook`, `host`, `accessKeyId`, `secretAccessKey` information of the given target, instead of configure your credentials directly. * Policy Reporter UI * New value `refreshInterval` to configure the default refresh interval for API polling. Set `0` to disable polling. * Policy Reporter Kyverno Plugin diff --git a/DEMO.md b/DEMO.md new file mode 100644 index 00000000..bb1a3ffc --- /dev/null +++ b/DEMO.md @@ -0,0 +1,144 @@ +# Demo Instructions + +## Kind Cluster + +```bash +make kind-create-cluster +``` + +## Kyverno + +### Add Repository + +```bash +helm repo add kyverno https://kyverno.github.io/kyverno +``` + +### Install + +```bash +helm upgrade --install kyverno kyverno/kyverno -n kyverno --create-namespace +helm upgrade --install kyverno-policies kyverno/kyverno-policies --set podSecurityStandard=restricted +``` + +## Falco + +### Add Repository + +```bash +helm repo add falcosecurity https://falcosecurity.github.io/charts +``` + +### Install + +```bash +helm upgrade --install falco falcosecurity/falco --set falcosidekick.enabled=true --set falcosidekick.config.policyreport.enabled=true --set falcosidekick.image.tag=latest --namespace falco --create-namespace +``` + +## Trivy Operator + +### Add Repository + +```bash +helm repo add aqua https://aquasecurity.github.io/helm-charts/ +helm repo add trivy-operator-polr-adapter https://fjogeleit.github.io/trivy-operator-polr-adapter +``` + +### Install + +```bash +helm upgrade --install trivy-operator aqua/trivy-operator -n trivy-system --create-namespace --set="trivy.ignoreUnfixed=true" +helm upgrade --install trivy-operator-polr-adapter trivy-operator-polr-adapter/trivy-operator-polr-adapter -n trivy-system +``` + +## Policy Reporter + +### Add Repository + +```bash +helm repo add policy-reporter https://kyverno.github.io/policy-reporter +``` + +### Install + +#### Slack Secret + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: webhook-secret + namespace: policy-reporter +type: Opaque +data: + webhook: aHR0cHM6Ly9ob29rcy5z... +``` + +#### Values + +```yaml +plugin: + kyverno: + enabled: true + + trivy: + enabled: true + +ui: + enabled: true + + ingress: + enabled: true + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 + className: nginx + hosts: + - host: localhost + paths: + - path: "/ui/(.*)" + pathType: ImplementationSpecific + + sources: + - name: Trivy ConfigAudit + type: severity + excludes: + results: + - pass + - error + + - name: Trivy Vulnerability + type: severity + excludes: + results: + - pass + - error + + - name: Falco + excludes: + results: + - pass + - skip + +target: + slack: + name: Kyverno Channel + channel: kyverno + secretRef: webhook-secret + minimumSeverity: warning + skipExistingOnStartup: true + sources: [kyverno] + filter: + namespaces: + exclude: ['trivy-system'] + channels: + - name: Trivy Operator + channel: trivy-operator + sources: [Trivy Vulnerability] + filter: + namespaces: + exclude: ['trivy-system'] +``` + +```bash +helm upgrade --install policy-reporter policy-reporter/policy-reporter --create-namespace -n policy-reporter -f values.yaml --devel +``` diff --git a/Dockerfile b/Dockerfile index 4e36b9a6..b600bedc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.23 AS builder ARG LD_FLAGS='-s -w -linkmode external -extldflags "-static"' ARG TARGETPLATFORM diff --git a/Makefile b/Makefile index f31b1cb9..773e76d0 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,142 @@ -GO ?= go -BUILD ?= build -REPO ?= ghcr.io/kyverno/policy-reporter -IMAGE_TAG ?= 2.20.1 -LD_FLAGS=-s -w -linkmode external -extldflags "-static" -PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x +############ +# DEFAULTS # +############ + +KIND_IMAGE ?= kindest/node:v1.30.2 +KIND_NAME ?= kyverno +USE_CONFIG ?= standard,no-ingress,in-cluster,all-read-rbac +KUBECONFIG ?= "" +PIP ?= "pip3" +GO ?= go +BUILD ?= build +IMAGE_TAG ?= 3.0.0 + +############# +# VARIABLES # +############# + +GIT_SHA := $(shell git rev-parse HEAD) +TIMESTAMP := $(shell date '+%Y-%m-%d_%I:%M:%S%p') +GOOS ?= $(shell go env GOOS) +GOARCH ?= $(shell go env GOARCH) +REGISTRY ?= ghcr.io +OWNER ?= kyverno +KO_REGISTRY := ko.local +IMAGE ?= policy-reporter +LD_FLAGS := -s -w -linkmode external -extldflags "-static" +LOCAL_PLATFORM := linux/$(GOARCH) +PLATFORMS := linux/arm64,linux/amd64,linux/s390x +REPO := $(REGISTRY)/$(OWNER)/$(IMAGE) +COMMA := , + +ifndef VERSION +APP_VERSION := $(GIT_SHA) +else +APP_VERSION := $(VERSION) +endif + +######### +# TOOLS # +######### + +TOOLS_DIR := $(PWD)/.tools +KIND := $(TOOLS_DIR)/kind +KIND_VERSION := v0.24.0 +KO := $(TOOLS_DIR)/ko +KO_VERSION := v0.15.1 +HELM := $(TOOLS_DIR)/helm +HELM_VERSION := v3.10.1 +HELM_DOCS := $(TOOLS_DIR)/helm-docs +HELM_DOCS_VERSION := v1.11.0 +GCI := $(TOOLS_DIR)/gci +GCI_VERSION := v0.9.1 +GOFUMPT := $(TOOLS_DIR)/gofumpt +GOFUMPT_VERSION := v0.4.0 +TOOLS := $(HELM) $(HELM_DOCS) $(GCI) $(GOFUMPT) + +$(HELM): + @echo Install helm... >&2 + @GOBIN=$(TOOLS_DIR) go install helm.sh/helm/v3/cmd/helm@$(HELM_VERSION) + +$(HELM_DOCS): + @echo Install helm-docs... >&2 + @GOBIN=$(TOOLS_DIR) go install github.com/norwoodj/helm-docs/cmd/helm-docs@$(HELM_DOCS_VERSION) + +$(GCI): + @echo Install gci... >&2 + @GOBIN=$(TOOLS_DIR) go install github.com/daixiang0/gci@$(GCI_VERSION) + +$(GOFUMPT): + @echo Install gofumpt... >&2 + @GOBIN=$(TOOLS_DIR) go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) + +$(KIND): + @echo Install kind... >&2 + @GOBIN=$(TOOLS_DIR) go install sigs.k8s.io/kind@$(KIND_VERSION) + +$(KO): + @echo Install ko... >&2 + @GOBIN=$(TOOLS_DIR) go install github.com/google/ko@$(KO_VERSION) + +.PHONY: gci +gci: $(GCI) + @echo "Running gci" + @$(GCI) write -s standard -s default -s "prefix(github.com/kyverno/policy-reporter)" . + +.PHONY: gofumpt +gofumpt: $(GOFUMPT) + @echo "Running gofumpt" + @$(GOFUMPT) -w . + +.PHONY: fmt +fmt: gci gofumpt + +.PHONY: install-tools +install-tools: $(TOOLS) ## Install tools + +.PHONY: clean-tools +clean-tools: ## Remove installed tools + @echo Clean tools... >&2 + @rm -rf $(TOOLS_DIR) + +######## +# KIND # +######## + +.PHONY: kind-create-cluster +kind-create-cluster: $(KIND) ## Create kind cluster + @echo Create kind cluster... >&2 + @$(KIND) create cluster --name $(KIND_NAME) --image $(KIND_IMAGE) --config ./scripts/kind.yaml + @kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + @sleep 15 + @kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=90s + +.PHONY: kind-delete-cluster +kind-delete-cluster: $(KIND) ## Delete kind cluster + @echo Delete kind cluster... >&2 + @$(KIND) delete cluster --name $(KIND_NAME) + +.PHONY: kind-load +kind-load: $(KIND) ko-build ## Build playground image and load it in kind cluster + @echo Load playground image... >&2 + @$(KIND) load docker-image --name $(KIND_NAME) ko.local/github.com/kyverno/policy-reporter:$(GIT_SHA) + +########### +# CODEGEN # +########### + +.PHONY: codegen-helm-docs +codegen-helm-docs: ## Generate helm docs + @echo Generate helm docs... >&2 + @docker run -v ${PWD}/charts:/work -w /work jnorwood/helm-docs:v1.11.0 -s file + +.PHONY: verify-helm-docs +verify-helm-docs: codegen-helm-docs ## Check Helm charts are up to date + @echo Checking helm charts are up to date... >&2 + @git --no-pager diff -- charts + @echo 'If this test fails, it is because the git diff is non-empty after running "make codegen-helm-docs".' >&2 + @echo 'To correct this, locally run "make codegen-helm-docs", commit the changes, and re-run tests.' >&2 + @git diff --quiet --exit-code -- charts all: build @@ -41,11 +174,3 @@ docker-push: .PHONY: docker-push-dev docker-push-dev: @docker buildx build --progress plane --platform $(PLATFORMS) --tag $(REPO):dev . --build-arg LD_FLAGS='$(LD_FLAGS) -X main.Version=$(IMAGE_TAG)-dev' --push - -.PHONY: fmt -fmt: - $(call print-target) - @echo "Running gci" - @go run github.com/daixiang0/gci@v0.9.1 write -s standard -s default -s "prefix(github.com/kyverno/policy-reporter)" . - @echo "Running gofumpt" - @go run mvdan.cc/gofumpt@v0.4.0 -w . diff --git a/README.md b/README.md index 896ce4fe..af4b3e37 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,20 @@ -# Policy Reporter +# Policy Reporter 3.x Preview [![CI](https://github.com/kyverno/policy-reporter/actions/workflows/ci.yaml/badge.svg)](https://github.com/kyverno/policy-reporter/actions/workflows/ci.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/kyverno/policy-reporter)](https://goreportcard.com/report/github.com/kyverno/policy-reporter) [![Coverage Status](https://coveralls.io/repos/github/kyverno/policy-reporter/badge.svg?branch=main)](https://coveralls.io/github/kyverno/policy-reporter?branch=main) -## Motivation -Kyverno ships with two types of validation. You can either enforce a rule or audit it. If you don't want to block developers or if you want to try out a new rule, you can use the audit functionality. The audit configuration creates [PolicyReports](https://kyverno.io/docs/policy-reports/) which you can access with `kubectl`. Because I can't find a simple solution to get a general overview of this PolicyReports and PolicyReportResults, I created this tool to send information about PolicyReports to different targets like [Grafana Loki](https://grafana.com/oss/loki/), [Elasticsearch](https://www.elastic.co/de/elasticsearch/) or [Slack](https://slack.com/). +![Screenshot Policy Reporter UI v2](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/screen.png) -Policy Reporter provides also a Prometheus Metrics API as well as an standalone mode along with the [Policy Reporter UI](https://kyverno.github.io/policy-reporter/guide/getting-started#core--policy-reporter-ui). - -This project is in an early stage. Please let me know if anything did not work as expected or if you want to send your audits to unsupported targets. ## Documentation -You can find detailed Information and Screens about Features and Configurations in the [Documentation](https://kyverno.github.io/policy-reporter). +Documentation for upcoming features and changes for the new Policy Reporter UI v2 are located in [Docs](https://github.com/kyverno/policy-reporter/tree/3.x/docs) + +* [Installation](https://github.com/kyverno/policy-reporter/blob/3.x/docs/SETUP.md) +* [OAUth2 / OpenIDConnect](https://github.com/kyverno/policy-reporter/blob/3.x/docs/UI_AUTH.md) +* [UI CustomBoards](https://github.com/kyverno/policy-reporter/blob/3.x/docs/CUSTOM_BOARDS.md) +* [Kyverno PolicyExceptions](https://github.com/kyverno/policy-reporter/blob/3.x/docs/EXCEPTIONS.md) + +The new documentation page for Policy Reporter v3 can be found here: [https://kyverno.github.io/policy-reporter-docs/](https://kyverno.github.io/policy-reporter-docs/) ## Getting Started @@ -25,60 +28,10 @@ helm repo add policy-reporter https://kyverno.github.io/policy-reporter helm repo update ``` -### Basic Installation - -The basic installation provides optional Prometheus Metrics and/or optional REST APIs, for more details have a look at the [Documentation](https://kyverno.github.io/policy-reporter/guide/getting-started). - -```bash -helm install policy-reporter policy-reporter/policy-reporter -n policy-reporter --set metrics.enabled=true --set rest.enabled=true --create-namespace -``` - -### Installation without Helm or Kustomize - -To install Policy Reporter without Helm or Kustomize have a look at [manifests](https://github.com/kyverno/policy-reporter/tree/main/manifest). - -## Policy Reporter UI - -You can use the Policy Reporter as standalone Application along with the optional UI SubChart. - ### Installation with Policy Reporter UI and Kyverno Plugin enabled ```bash -helm install policy-reporter policy-reporter/policy-reporter --set kyvernoPlugin.enabled=true --set ui.enabled=true --set ui.plugins.kyverno=true -n policy-reporter --create-namespace +helm install policy-reporter policy-reporter/policy-reporter --create-namespace -n policy-reporter --devel --set ui.enabled=true --set kyverno-plugin.enabled=true kubectl port-forward service/policy-reporter-ui 8082:8080 -n policy-reporter ``` -Open `http://localhost:8082/` in your browser. -Check the [Documentation](https://kyverno.github.io/policy-reporter/guide/getting-started#core--policy-reporter-ui) for Screens and additional Information - -## Targets - -Policy Reporter supports the following [Targets](https://kyverno.github.io/policy-reporter/core/targets) to send new (Cluster)PolicyReport Results too: -* [Grafana Loki](https://kyverno.github.io/policy-reporter/core/targets#grafana-loki) -* [Elasticsearch](https://kyverno.github.io/policy-reporter/core/targets#elasticsearch) -* [Microsoft Teams](https://kyverno.github.io/policy-reporter/core/targets#microsoft-teams) -* [Slack](https://kyverno.github.io/policy-reporter/core/targets#slack) -* [Discord](https://kyverno.github.io/policy-reporter/core/targets#discord) -* [Policy Reporter UI](https://kyverno.github.io/policy-reporter/core/targets#policy-reporter-ui) -* [Webhook](https://kyverno.github.io/policy-reporter/core/targets#webhook) -* [S3](https://kyverno.github.io/policy-reporter/core/targets#s3-compatible-storage) -* [AWS Kinesis compatible Services](https://kyverno.github.io/policy-reporter/core/targets#kinesis-compatible-services) -* [AWS SecurityHub](https://kyverno.github.io/policy-reporter/core/targets#aws-securityhub) -* [Google Cloud Storage](https://kyverno.github.io/policy-reporter/core/targets/#google-cloud-storage) -* [Telegram](https://kyverno.github.io/policy-reporter/core/targets#telegram) -* [Google Chat](https://kyverno.github.io/policy-reporter/core/targets#google-chat) - -## Monitoring - -The Helm Chart includes optional SubChart for [Prometheus Operator](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) Integration. The provided Dashboards working without Loki and are only based on the Prometheus Metrics. - -Have a look into the [Documentation](https://kyverno.github.io/policy-reporter/guide/helm-chart-core/#configure-the-servicemonitor) for details. - -### Grafana Dashboard Import - -If you are not using the MonitoringStack you can import the dashboards from [Grafana](https://grafana.com/orgs/policyreporter/dashboards) - -## Resources - -* [[Video] 37. #EveryoneCanContribute cafe: Policy reporter for Kyverno](https://youtu.be/1mKywg9f5Fw) -* [[Video] Rawkode Live: Hands on Policy Reporter](https://www.youtube.com/watch?v=ZrOtTELNLyg) -* [[Blog] Monitor Security and Best Practices with Kyverno and Policy Reporter](https://blog.webdev-jogeleit.de/blog/monitor-security-with-kyverno-and-policy-reporter/) +Open `http://localhost:8082/` in your browser. \ No newline at end of file diff --git a/charts/policy-reporter/Chart.lock b/charts/policy-reporter/Chart.lock deleted file mode 100644 index 640b55e4..00000000 --- a/charts/policy-reporter/Chart.lock +++ /dev/null @@ -1,12 +0,0 @@ -dependencies: -- name: monitoring - repository: "" - version: 2.8.2 -- name: ui - repository: "" - version: 2.10.5 -- name: kyvernoPlugin - repository: "" - version: 1.6.5 -digest: sha256:5ee2b291bc447466442a8ea81f94fc852352ac8ae15045525778fdea3769c7c2 -generated: "2024-02-04T10:42:39.448841+01:00" diff --git a/charts/policy-reporter/Chart.yaml b/charts/policy-reporter/Chart.yaml index 631df010..761c5065 100644 --- a/charts/policy-reporter/Chart.yaml +++ b/charts/policy-reporter/Chart.yaml @@ -5,8 +5,8 @@ description: | It creates Prometheus Metrics and can send rule validation events to different targets like Loki, Elasticsearch, Slack or Discord type: application -version: 2.24.2 -appVersion: 2.20.2 +version: 3.0.0-rc.1 +appVersion: 3.0.0-rc.1 icon: https://github.com/kyverno/kyverno/raw/main/img/logo.png home: https://kyverno.github.io/policy-reporter @@ -14,14 +14,3 @@ sources: - https://github.com/kyverno/policy-reporter maintainers: - name: Frank Jogeleit - -dependencies: - - name: monitoring - condition: monitoring.enabled - version: "2.8.2" - - name: ui - condition: ui.enabled - version: "2.10.5" - - name: kyvernoPlugin - condition: kyvernoPlugin.enabled - version: "1.6.5" diff --git a/charts/policy-reporter/README.md b/charts/policy-reporter/README.md index bc423490..a48b408c 100644 --- a/charts/policy-reporter/README.md +++ b/charts/policy-reporter/README.md @@ -1,16 +1,13 @@ -# Policy Reporter +# policy-reporter -![Version: v2.24.1](https://img.shields.io/badge/Version-v2.24.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v2.20.1](https://img.shields.io/badge/AppVersion-v2.20.1-informational?style=flat-square) +Policy Reporter watches for PolicyReport Resources. +It creates Prometheus Metrics and can send rule validation events to different targets like Loki, Elasticsearch, Slack or Discord -## Motivation - -Kyverno ships with two types of validation. You can either enforce a rule or audit it. If you don't want to block developers or if you want to try out a new rule, you can use the audit functionality. The audit configuration creates [PolicyReports](https://kyverno.io/docs/policy-reports/) which you can access with `kubectl`. Because I can't find a simple solution to get a general overview of this PolicyReports and PolicyReportResults, I created this tool to send information about PolicyReports to different targets like [Grafana Loki](https://grafana.com/oss/loki/), [Elasticsearch](https://www.elastic.co/de/elasticsearch/) or [Slack](https://slack.com/). +![Version: 3.0.0-rc.1](https://img.shields.io/badge/Version-3.0.0--rc.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.0.0-rc.1](https://img.shields.io/badge/AppVersion-3.0.0--rc.1-informational?style=flat-square) ## Documentation -You can find detailed Information and Screens about Features and Configurations in the [Documentation](https://kyverno.github.io/policy-reporter/guide/02-getting-started#core--policy-reporter-ui). - -## Getting Started +You can find detailed Information and Screens about Features and Configurations in the [Documentation](https://kyverno.github.io/policy-reporter-docs). ## Installation with Helm v3 @@ -35,16 +32,549 @@ helm install policy-reporter policy-reporter/policy-reporter -n policy-reporter You can use the Policy Reporter as standalone Application along with the optional UI SubChart. ### Installation with Policy Reporter UI and Kyverno Plugin enabled + ```bash -helm install policy-reporter policy-reporter/policy-reporter --set kyvernoPlugin.enabled=true --set ui.enabled=true --set ui.plugins.kyverno=true -n policy-reporter --create-namespace +helm install policy-reporter policy-reporter/policy-reporter --set plugin.kyverno.enabled=true --set ui.enabled=true -n policy-reporter --create-namespace kubectl port-forward service/policy-reporter-ui 8082:8080 -n policy-reporter ``` Open `http://localhost:8082/` in your browser. -Check the [Documentation](https://kyverno.github.io/policy-reporter/guide/02-getting-started#core--policy-reporter-ui) for Screens and additional Information +## Values -## Resources +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| nameOverride | string | `""` | Override the chart name used for all resources | +| fullnameOverride | string | `"policy-reporter"` | Overwrite the fullname of all resources | +| namespaceOverride | string | `""` | Overwrite the namespace of all resources | +| image.registry | string | `"ghcr.io"` | Image registry | +| image.repository | string | `"kyverno/policy-reporter"` | Image repository | +| image.pullPolicy | string | `"IfNotPresent"` | Image pullPolicy | +| image.tag | string | `"12da466"` | Image tag | +| imagePullSecrets | list | `[]` | Image pullSecrets | +| priorityClassName | string | `""` | Deployment priorityClassName | +| replicaCount | int | `1` | Deployment replica count | +| revisionHistoryLimit | int | `10` | The number of revisions to keep | +| updateStrategy | object | `{}` | Deployment strategy | +| port | object | `{"name":"http","number":8080}` | Container port | +| annotations | object | `{}` | Key/value pairs that are attached to all resources. | +| rbac.enabled | bool | `true` | Create RBAC resources | +| serviceAccount.create | bool | `true` | Create ServiceAccount | +| serviceAccount.automount | bool | `true` | Enable ServiceAccount automaount | +| serviceAccount.annotations | object | `{}` | Annotations for the ServiceAccount | +| serviceAccount.name | string | `""` | The ServiceAccount name | +| service.enabled | bool | `true` | Create Service | +| service.type | string | `"ClusterIP"` | Service type | +| service.port | int | `8080` | Service port | +| service.annotations | object | `{}` | Service annotations | +| service.labels | object | `{}` | Service labels | +| podSecurityContext | object | `{"fsGroup":1234}` | Security context for the pod | +| securityContext.runAsUser | int | `1234` | | +| securityContext.runAsNonRoot | bool | `true` | | +| securityContext.privileged | bool | `false` | | +| securityContext.allowPrivilegeEscalation | bool | `false` | | +| securityContext.readOnlyRootFilesystem | bool | `true` | | +| securityContext.capabilities.drop[0] | string | `"ALL"` | | +| securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| securityContext.podAnnotations | object | `{}` | Additional annotations to add to each pod | +| securityContext.podLabels | object | `{}` | Additional labels to add to each pod | +| resources | object | `{}` | Resource constraints | +| networkPolicy.enabled | bool | `false` | Create NetworkPolicy | +| networkPolicy.egress | list | `[{"ports":[{"port":6443,"protocol":"TCP"}],"to":null}]` | Egress rule to allowe Kubernetes API Server access | +| networkPolicy.ingress | list | `[]` | | +| ingress.enabled | bool | `false` | Create Ingress This ingress exposes the policy-reporter core app. | +| ingress.className | string | `""` | Ingress className | +| ingress.labels | object | `{}` | Labels for the Ingress | +| ingress.annotations | object | `{}` | Annotations for the Ingress | +| ingress.hosts | string | `nil` | Ingress host list | +| ingress.tls | list | `[]` | Ingress tls list | +| logging.server | bool | `false` | Enables server access logging | +| logging.encoding | string | `"console"` | Log encoding possible encodings are console and json | +| logging.logLevel | int | `0` | Log level default info | +| rest.enabled | bool | `false` | Enables the REST API | +| metrics.enabled | bool | `false` | Enables Prometheus Metrics | +| metrics.mode | string | `"detailed"` | Metric Mode allowes to customize labels Allowed values: detailed, simple, custom | +| metrics.customLabels | list | `[]` | List of used labels in custom mode Supported fields are: ["namespace", "rule", "policy", "report" // PolicyReport name, "kind" // resource kind, "name" // resource name, "status", "severity", "category", "source"] | +| metrics.filter | object | `{}` | Filter results to reduce cardinality | +| profiling.enabled | bool | `false` | Enable profiling with pprof | +| worker | int | `5` | Amount of queue workers for PolicyReport resource processing | +| reportFilter | object | `{}` | Filter PolicyReport resources to process | +| sourceConfig | list | `[]` | Customize source specific logic like result ID generation | +| sourceFilters[0].selector.source | string | `"kyverno"` | select PolicyReport by source | +| sourceFilters[0].uncontrolledOnly | bool | `true` | Filter out PolicyReports of controlled Pods and Jobs, only works for PolicyReport with scope resource | +| sourceFilters[0].disableClusterReports | bool | `false` | Filter out ClusterPolicyReports | +| sourceFilters[0].kinds | object | `{"exclude":["ReplicaSet"]}` | Filter out PolicyReports based on the scope resource kind | +| global.labels | object | `{}` | additional labels added on each resource | +| basicAuth.username | string | `""` | HTTP BasicAuth username | +| basicAuth.password | string | `""` | HTTP BasicAuth password | +| basicAuth.secretRef | optional | `""` | Secret reference to get username and/or password from | +| emailReports.clusterName | optional | `""` | - Displayed in the email report if configured | +| emailReports.titlePrefix | string | `"Report"` | Title prefix in the email subject | +| emailReports.resources | object | `{}` | Resource constraints for the created CronJobs | +| emailReports.smtp.secret | optional | `""` | Secret reference to provide the complete or partial SMTP configuration | +| emailReports.smtp.host | string | `""` | SMTP Server Host | +| emailReports.smtp.port | int | `465` | SMTP Server Port | +| emailReports.smtp.username | string | `""` | SMTP Username | +| emailReports.smtp.password | string | `""` | SMTP Password | +| emailReports.smtp.from | string | `""` | Displayed from email address | +| emailReports.smtp.encryption | string | `""` | SMTP Encryption Default is none, supports ssl/tls and starttls | +| emailReports.smtp.skipTLS | bool | `false` | Skip SMTP TLS verification | +| emailReports.smtp.certificate | string | `""` | SMTP Server Certificate file path | +| emailReports.summary.enabled | bool | `false` | Enable Summary E-Mail reports | +| emailReports.summary.schedule | string | `"0 8 * * *"` | CronJob schedule | +| emailReports.summary.activeDeadlineSeconds | int | `300` | CronJob activeDeadlineSeconds | +| emailReports.summary.backoffLimit | int | `3` | CronJob backoffLimit | +| emailReports.summary.ttlSecondsAfterFinished | int | `0` | CronJob ttlSecondsAfterFinished | +| emailReports.summary.restartPolicy | string | `"Never"` | CronJob restartPolicy | +| emailReports.summary.to | list | `[]` | List of receiver email addresses | +| emailReports.summary.filter | optional | `{}` | Report filter | +| emailReports.summary.channels | optional | `[]` | Channels can be used to to send only a subset of namespaces / sources to dedicated email addresses | +| emailReports.violations.enabled | bool | `false` | Enable Violation Summary E-Mail reports | +| emailReports.violations.schedule | string | `"0 8 * * *"` | CronJob schedule | +| emailReports.violations.activeDeadlineSeconds | int | `300` | CronJob activeDeadlineSeconds | +| emailReports.violations.backoffLimit | int | `3` | CronJob backoffLimit | +| emailReports.violations.ttlSecondsAfterFinished | int | `0` | CronJob ttlSecondsAfterFinished | +| emailReports.violations.restartPolicy | string | `"Never"` | CronJob restartPolicy | +| emailReports.violations.to | list | `[]` | List of receiver email addresses | +| emailReports.violations.filter | optional | `{}` | Report filter | +| emailReports.violations.channels | optional | `[]` | Channels can be used to to send only a subset of namespaces / sources to dedicated email addresses | +| existingTargetConfig.enabled | bool | `false` | Use an already existing configuration | +| existingTargetConfig.name | string | `""` | Name of the secret with the config | +| existingTargetConfig.subPath | string | `""` | SubPath within the secret (defaults to config.yaml) | +| target.loki.host | string | `""` | Host Address | +| target.loki.path | string | `""` | Loki API, defaults to "/loki/api/v1/push" | +| target.loki.certificate | string | `""` | Server Certificate file path Can be added under extraVolumes | +| target.loki.skipTLS | bool | `false` | Skip TLS verification | +| target.loki.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.loki.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.loki.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.loki.sources | list | `[]` | List of sources which should send | +| target.loki.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.loki.customFields | object | `{}` | Added as additional labels | +| target.loki.headers | object | `{}` | Additional HTTP Headers | +| target.loki.username | string | `""` | HTTP BasicAuth username | +| target.loki.password | string | `""` | HTTP BasicAuth password | +| target.loki.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.loki.channels | list | `[]` | List of channels to route results to different configurations | +| target.elasticsearch.host | string | `""` | Host address | +| target.elasticsearch.certificate | string | `""` | Server Certificate file path Can be added under extraVolumes | +| target.elasticsearch.skipTLS | bool | `false` | Skip TLS verification | +| target.elasticsearch.index | string | `"policy-reporter"` | Elasticsearch index (default: policy-reporter) | +| target.elasticsearch.rotation | string | `"daily"` | Elasticsearch index rotation and index suffix Possible values: daily, monthly, annually, none (default: daily) | +| target.elasticsearch.typelessApi | bool | `false` | Enables Elasticsearch typless API https://www.elastic.co/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0 keeping as false for retrocompatibility. | +| target.elasticsearch.username | string | `""` | HTTP BasicAuth username | +| target.elasticsearch.password | string | `""` | HTTP BasicAuth password | +| target.elasticsearch.apiKey | string | `""` | Elasticsearch API Key for api key authentication | +| target.elasticsearch.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.elasticsearch.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.elasticsearch.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.elasticsearch.sources | list | `[]` | List of sources which should send | +| target.elasticsearch.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.elasticsearch.customFields | object | `{}` | Added as additional labels | +| target.elasticsearch.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.elasticsearch.channels | list | `[]` | List of channels to route results to different configurations | +| target.slack.webhook | string | `""` | Webhook Address | +| target.slack.channel | string | `""` | Slack Channel | +| target.slack.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.slack.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.slack.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.slack.sources | list | `[]` | List of sources which should send | +| target.slack.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.slack.customFields | object | `{}` | Added as additional labels | +| target.slack.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.slack.channels | list | `[]` | List of channels to route results to different configurations | +| target.discord.webhook | string | `""` | Webhook Address | +| target.discord.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.discord.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.discord.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.discord.sources | list | `[]` | List of sources which should send | +| target.discord.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.discord.customFields | object | `{}` | Added as additional labels | +| target.discord.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.discord.channels | list | `[]` | List of channels to route results to different configurations | +| target.teams.webhook | string | `""` | Webhook Address | +| target.teams.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.teams.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.teams.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.teams.sources | list | `[]` | List of sources which should send | +| target.teams.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.teams.customFields | object | `{}` | Added as additional labels | +| target.teams.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.teams.channels | list | `[]` | List of channels to route results to different configurations | +| target.webhook.host | string | `""` | Webhook Address | +| target.webhook.headers | object | `{}` | Additional HTTP Headers | +| target.webhook.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.webhook.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.webhook.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.webhook.sources | list | `[]` | List of sources which should send | +| target.webhook.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.webhook.customFields | object | `{}` | Added as additional labels | +| target.webhook.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.webhook.channels | list | `[]` | List of channels to route results to different configurations | +| target.telegram.token | string | `""` | Telegram bot token | +| target.telegram.chatId | string | `""` | Telegram chat id | +| target.telegram.host | optional | `""` | Telegram proxy host | +| target.telegram.headers | object | `{}` | Additional HTTP Headers | +| target.telegram.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.telegram.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.telegram.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.telegram.sources | list | `[]` | List of sources which should send | +| target.telegram.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.telegram.customFields | object | `{}` | Added as additional labels | +| target.telegram.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.telegram.channels | list | `[]` | List of channels to route results to different configurations | +| target.googleChat.webhook | string | `""` | Webhook Address | +| target.googleChat.headers | object | `{}` | Additional HTTP Headers | +| target.googleChat.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.googleChat.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.googleChat.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.googleChat.sources | list | `[]` | List of sources which should send | +| target.googleChat.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.googleChat.customFields | object | `{}` | Added as additional labels | +| target.googleChat.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.googleChat.channels | list | `[]` | List of channels to route results to different configurations | +| target.s3.accessKeyId | optional | `""` | S3 Access key | +| target.s3.secretAccessKey | optional | `""` | S3 SecretAccess key | +| target.s3.region | optional | `""` | S3 Storage region | +| target.s3.endpoint | optional | `""` | S3 Storage endpoint | +| target.s3.bucket | required | `""` | S3 Storage bucket name | +| target.s3.bucketKeyEnabled | bool | `false` | S3 Storage to use an S3 Bucket Key for object encryption with SSE-KMS | +| target.s3.kmsKeyId | string | `""` | S3 Storage KMS Key ID for object encryption with SSE-KMS | +| target.s3.serverSideEncryption | string | `""` | S3 Storage server-side encryption algorithm used when storing this object in Amazon S3, AES256, aws:kms | +| target.s3.pathStyle | bool | `false` | S3 Storage, force path style configuration | +| target.s3.prefix | string | `""` | Used prefix, keys will have format: s3:////YYYY-MM-DD/YYYY-MM-DDTHH:mm:ss.s+01:00.json | +| target.s3.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.s3.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.s3.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.s3.sources | list | `[]` | List of sources which should send | +| target.s3.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.s3.customFields | object | `{}` | Added as additional labels | +| target.s3.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.s3.channels | list | `[]` | List of channels to route results to different configurations | +| target.kinesis.accessKeyId | optional | `""` | Access key | +| target.kinesis.secretAccessKey | optional | `""` | SecretAccess key | +| target.kinesis.region | optional | `""` | Region | +| target.kinesis.endpoint | optional | `""` | Endpoint | +| target.kinesis.streamName | required | `""` | StreamName | +| target.kinesis.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.kinesis.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.kinesis.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.kinesis.sources | list | `[]` | List of sources which should send | +| target.kinesis.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.kinesis.customFields | object | `{}` | Added as additional labels | +| target.kinesis.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.kinesis.channels | list | `[]` | List of channels to route results to different configurations | +| target.securityHub.accessKeyId | optional | `""` | Access key | +| target.securityHub.secretAccessKey | optional | `""` | SecretAccess key | +| target.securityHub.region | optional | `""` | Region | +| target.securityHub.endpoint | optional | `""` | Endpoint | +| target.securityHub.accountId | required | `""` | AccountId | +| target.securityHub.productName | optional | `""` | Used product name, defaults to "Polilcy Reporter" | +| target.securityHub.companyName | optional | `""` | Used company name, defaults to "Kyverno" | +| target.securityHub.synchronize | bool | `true` | Enable cleanup listener for SecurityHub | +| target.securityHub.delayInSeconds | int | `2` | Delay between AWS GetFindings API calls, to avoid hitting the API RequestLimit | +| target.securityHub.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.securityHub.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.securityHub.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.securityHub.sources | list | `[]` | List of sources which should send | +| target.securityHub.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.securityHub.customFields | object | `{}` | Added as additional labels | +| target.securityHub.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.securityHub.channels | list | `[]` | List of channels to route results to different configurations | +| target.gcs.credentials | optional | `""` | GCS (Google Cloud Storage) Service Accout Credentials | +| target.gcs.bucket | required | `""` | GCS Bucket | +| target.gcs.secretRef | string | `""` | Read configuration from an already existing Secret | +| target.gcs.mountedSecret | string | `""` | Mounted secret path by Secrets Controller, secret should be in json format | +| target.gcs.minimumSeverity | string | `""` | Minimum severity: "" < info < low < medium < high < critical | +| target.gcs.sources | list | `[]` | List of sources which should send | +| target.gcs.skipExistingOnStartup | bool | `true` | Skip already existing PolicyReportResults on startup | +| target.gcs.customFields | object | `{}` | Added as additional labels | +| target.gcs.filter | object | `{}` | Filter Results which should send to this target Wildcars for namespaces and policies are supported, you can either define exclude or include values Filters are available for all targets except the UI | +| target.gcs.channels | list | `[]` | List of channels to route results to different configurations | +| leaderElection.releaseOnCancel | bool | `true` | | +| leaderElection.leaseDuration | int | `15` | | +| leaderElection.renewDeadline | int | `10` | | +| leaderElection.retryPeriod | int | `2` | | +| redis.enabled | bool | `false` | Enables Redis as external result cache, uses in memory cache by default | +| redis.address | string | `""` | Redis host | +| redis.database | int | `0` | Redis database | +| redis.prefix | string | `"policy-reporter"` | Redis key prefix | +| redis.username | optional | `""` | Username | +| redis.password | optional | `""` | Password | +| database.type | string | `""` | Use an external Database, supported: mysql, postgres, mariadb | +| database.database | string | `""` | Database | +| database.username | string | `""` | Username | +| database.password | string | `""` | Password | +| database.host | string | `""` | Host Address | +| database.enableSSL | bool | `false` | Enables SSL | +| database.dsn | string | `""` | Instead of configure the individual values you can also provide an DSN string example postgres: postgres://postgres:password@localhost:5432/postgres?sslmode=disable example mysql: root:password@tcp(localhost:3306)/test?tls=false | +| database.secretRef | string | `""` | Read configuration from an existing Secret supported fields: username, password, host, dsn, database | +| database.mountedSecret | string | `""` | | +| podDisruptionBudget.minAvailable | int | `1` | Configures the minimum available pods for policy-reporter disruptions. Cannot be used if `maxUnavailable` is set. | +| podDisruptionBudget.maxUnavailable | string | `nil` | Configures the maximum unavailable pods for policy-reporter disruptions. Cannot be used if `minAvailable` is set. | +| nodeSelector | object | `{}` | Node labels for pod assignment ref: https://kubernetes.io/docs/user-guide/node-selection/ | +| tolerations | list | `[]` | Tolerations for pod assignment ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ | +| affinity | object | `{}` | Anti-affinity to disallow deploying client and master nodes on the same worker node | +| topologySpreadConstraints | list | `[]` | Topology Spread Constraints to better spread pods | +| livenessProbe | object | `{"httpGet":{"path":"/ready","port":"http"}}` | Deployment livenessProbe for policy-reporter | +| readinessProbe | object | `{"httpGet":{"path":"/healthz","port":"http"}}` | Deployment readinessProbe for policy-reporter | +| extraVolumes.volumeMounts | list | `[]` | Deployment volumeMounts | +| extraVolumes.volumes | list | `[]` | Deployment values | +| sqliteVolume | object | `{}` | If set the volume for sqlite is freely configurable below "- name: sqlite". If no value is set an emptyDir is used. | +| envVars | list | `[]` | Allow additional env variables to be added | +| tmpVolume | object | `{}` | Allow custom configuration of the /tmp volume | +| ui.enabled | bool | `false` | Enable Policy Reporter UI | +| ui.image.registry | string | `"ghcr.io"` | Image registry | +| ui.image.repository | string | `"kyverno/policy-reporter-ui"` | Image repository | +| ui.image.pullPolicy | string | `"IfNotPresent"` | Image PullPolicy | +| ui.image.tag | string | `"2.0.0-rc.1"` | Image tag | +| ui.replicaCount | int | `1` | Deployment replica count | +| ui.tempDir | string | `"/tmp"` | Temporary Directory to persist session data for authentication | +| ui.logging.api | bool | `false` | Enables external api request logging | +| ui.logging.server | bool | `false` | Enables server access logging | +| ui.logging.encoding | string | `"console"` | Log encoding possible encodings are console and json | +| ui.logging.logLevel | int | `0` | Log level default info | +| ui.server.port | int | `8080` | Application port | +| ui.server.cors | bool | `true` | Enabled CORS header | +| ui.server.overwriteHost | bool | `true` | Overwrites Request Host with Proxy Host and adds `X-Forwarded-Host` and `X-Origin-Host` headers | +| ui.openIDConnect.enabled | bool | `false` | Enable openID Connect authentication | +| ui.openIDConnect.discoveryUrl | string | `""` | OpenID Connect Discovery URL | +| ui.openIDConnect.callbackUrl | string | `""` | OpenID Connect Callback URL | +| ui.openIDConnect.clientId | string | `""` | OpenID Connect ClientID | +| ui.openIDConnect.clientSecret | string | `""` | OpenID Connect ClientSecret | +| ui.openIDConnect.scopes | list | `[]` | OpenID Connect allowed Scopes | +| ui.openIDConnect.secretRef | string | `""` | Provide OpenID Connect configuration via Secret supported keys: `discoveryUrl`, `clientId`, `clientSecret` | +| ui.oauth.enabled | bool | `false` | Enable openID Connect authentication | +| ui.oauth.provider | string | `""` | OAuth2 Provider supported: amazon, gitlab, github, apple, google, yandex, azuread | +| ui.oauth.callbackUrl | string | `""` | OpenID Connect Callback URL | +| ui.oauth.clientId | string | `""` | OpenID Connect ClientID | +| ui.oauth.clientSecret | string | `""` | OpenID Connect ClientSecret | +| ui.oauth.scopes | list | `[]` | OpenID Connect allowed Scopes | +| ui.oauth.secretRef | string | `""` | Provide OpenID Connect configuration via Secret supported keys: `provider`, `clientId`, `clientSecret` | +| ui.banner | string | `""` | optional banner text | +| ui.displayMode | string | `""` | DisplayMode dark/light/colorblind/colorblinddark uses the OS configured prefered color scheme as default | +| ui.customBoards | list | `[]` | Additional customizable dashboards | +| ui.sources | list | `[]` | source specific configurations | +| ui.name | string | `"Default"` | | +| ui.clusters | list | `[]` | Connected Policy Reporter APIs | +| ui.imagePullSecrets | list | `[]` | Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument | +| ui.serviceAccount.create | bool | `true` | Create ServiceAccount | +| ui.serviceAccount.automount | bool | `true` | Enable ServiceAccount automaount | +| ui.serviceAccount.annotations | object | `{}` | Annotations for the ServiceAccount | +| ui.serviceAccount.name | string | `""` | The ServiceAccount name | +| ui.extraManifests | list | `[]` | list of extra manifests | +| ui.sidecarContainers | object | `{}` | Add sidecar containers to the UI deployment sidecarContainers: oauth-proxy: image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 args: - --upstream=http://127.0.0.1:8080 - --http-address=0.0.0.0:8081 - ... ports: - containerPort: 8081 name: oauth-proxy protocol: TCP resources: {} | +| ui.podAnnotations | object | `{}` | Additional annotations to add to each pod | +| ui.podLabels | object | `{}` | Additional labels to add to each pod | +| ui.updateStrategy | object | `{}` | Deployment update strategy. Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy | +| ui.revisionHistoryLimit | int | `10` | The number of revisions to keep | +| ui.podSecurityContext | object | `{"runAsGroup":1234,"runAsUser":1234}` | Security context for the pod | +| ui.envVars | list | `[]` | Allow additional env variables to be added | +| ui.rbac.enabled | bool | `true` | Create RBAC resources | +| ui.securityContext.runAsUser | int | `1234` | | +| ui.securityContext.runAsNonRoot | bool | `true` | | +| ui.securityContext.privileged | bool | `false` | | +| ui.securityContext.allowPrivilegeEscalation | bool | `false` | | +| ui.securityContext.readOnlyRootFilesystem | bool | `true` | | +| ui.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| ui.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| ui.service.type | string | `"ClusterIP"` | Service type. | +| ui.service.port | int | `8080` | Service port. | +| ui.service.annotations | object | `{}` | Service annotations. | +| ui.service.labels | object | `{}` | Service labels. | +| ui.service.additionalPorts | list | `[]` | Additional service ports for e.g. Sidecars # - name: authenticated additionalPorts: - name: authenticated port: 8081 targetPort: 8081 | +| ui.ingress.enabled | bool | `false` | Create ingress resource. | +| ui.ingress.port | string | `nil` | Redirect ingress to an additional defined port on the service | +| ui.ingress.className | string | `""` | Ingress class name. | +| ui.ingress.labels | object | `{}` | Ingress labels. | +| ui.ingress.annotations | object | `{}` | Ingress annotations. | +| ui.ingress.hosts | list | `[]` | List of ingress host configurations. | +| ui.ingress.tls | list | `[]` | List of ingress TLS configurations. | +| ui.networkPolicy.enabled | bool | `false` | When true, use a NetworkPolicy to allow ingress to the webhook This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. | +| ui.networkPolicy.egress | list | `[{"ports":[{"port":6443,"protocol":"TCP"}]}]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. Enables Kubernetes API Server by default | +| ui.networkPolicy.ingress | list | `[]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. | +| ui.resources | object | `{}` | Resource constraints | +| ui.podDisruptionBudget.minAvailable | int | `1` | Configures the minimum available pods for kyvernoPlugin disruptions. Cannot be used if `maxUnavailable` is set. | +| ui.podDisruptionBudget.maxUnavailable | string | `nil` | Configures the maximum unavailable pods for kyvernoPlugin disruptions. Cannot be used if `minAvailable` is set. | +| ui.nodeSelector | object | `{}` | Node labels for pod assignment | +| ui.tolerations | list | `[]` | List of node taints to tolerate | +| ui.affinity | object | `{}` | Affinity constraints. | +| plugin.kyverno.enabled | bool | `false` | Enable Kyverno Plugin | +| plugin.kyverno.image.registry | string | `"ghcr.io"` | Image registry | +| plugin.kyverno.image.repository | string | `"kyverno/policy-reporter/kyverno-plugin"` | Image repository | +| plugin.kyverno.image.pullPolicy | string | `"IfNotPresent"` | Image PullPolicy | +| plugin.kyverno.image.tag | string | `"0.3.0"` | Image tag Defaults to `Chart.AppVersion` if omitted | +| plugin.kyverno.replicaCount | int | `1` | Deployment replica count | +| plugin.kyverno.logging.api | bool | `false` | Enables external API request logging | +| plugin.kyverno.logging.server | bool | `false` | Enables Server access logging | +| plugin.kyverno.logging.encoding | string | `"console"` | log encoding possible encodings are console and json | +| plugin.kyverno.logging.logLevel | int | `0` | log level default info | +| plugin.kyverno.server.port | int | `8080` | Application port | +| plugin.kyverno.blockReports.enabled | bool | `false` | Enables he BlockReport feature | +| plugin.kyverno.blockReports.eventNamespace | string | `"default"` | Watches for Kyverno Events in the configured namespace leave blank to watch in all namespaces | +| plugin.kyverno.blockReports.results.maxPerReport | int | `200` | Max items per PolicyReport resource | +| plugin.kyverno.blockReports.results.keepOnlyLatest | bool | `false` | Keep only the latest of duplicated events | +| plugin.kyverno.imagePullSecrets | list | `[]` | Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument | +| plugin.kyverno.serviceAccount.create | bool | `true` | Create ServiceAccount | +| plugin.kyverno.serviceAccount.automount | bool | `true` | Enable ServiceAccount automaount | +| plugin.kyverno.serviceAccount.annotations | object | `{}` | Annotations for the ServiceAccount | +| plugin.kyverno.serviceAccount.name | string | `""` | The ServiceAccount name | +| plugin.kyverno.podAnnotations | object | `{}` | Additional annotations to add to each pod | +| plugin.kyverno.podLabels | object | `{}` | Additional labels to add to each pod | +| plugin.kyverno.updateStrategy | object | `{}` | Deployment update strategy. Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy | +| plugin.kyverno.revisionHistoryLimit | int | `10` | The number of revisions to keep | +| plugin.kyverno.podSecurityContext | object | `{"runAsGroup":1234,"runAsUser":1234}` | Security context for the pod | +| plugin.kyverno.envVars | list | `[]` | Allow additional env variables to be added | +| plugin.kyverno.rbac.enabled | bool | `true` | Create RBAC resources | +| plugin.kyverno.securityContext.runAsUser | int | `1234` | | +| plugin.kyverno.securityContext.runAsNonRoot | bool | `true` | | +| plugin.kyverno.securityContext.privileged | bool | `false` | | +| plugin.kyverno.securityContext.allowPrivilegeEscalation | bool | `false` | | +| plugin.kyverno.securityContext.readOnlyRootFilesystem | bool | `true` | | +| plugin.kyverno.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| plugin.kyverno.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| plugin.kyverno.service.type | string | `"ClusterIP"` | Service type. | +| plugin.kyverno.service.port | int | `8080` | Service port. | +| plugin.kyverno.service.annotations | object | `{}` | Service annotations. | +| plugin.kyverno.service.labels | object | `{}` | Service labels. | +| plugin.kyverno.ingress.enabled | bool | `false` | Create ingress resource. | +| plugin.kyverno.ingress.className | string | `""` | Ingress class name. | +| plugin.kyverno.ingress.labels | object | `{}` | Ingress labels. | +| plugin.kyverno.ingress.annotations | object | `{}` | Ingress annotations. | +| plugin.kyverno.ingress.hosts | list | `[]` | List of ingress host configurations. | +| plugin.kyverno.ingress.tls | list | `[]` | List of ingress TLS configurations. | +| plugin.kyverno.networkPolicy.enabled | bool | `false` | When true, use a NetworkPolicy to allow ingress to the webhook This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. | +| plugin.kyverno.networkPolicy.egress | list | `[{"ports":[{"port":6443,"protocol":"TCP"}]}]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. Enables Kubernetes API Server by default | +| plugin.kyverno.networkPolicy.ingress | list | `[]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. | +| plugin.kyverno.resources | object | `{}` | Resource constraints | +| plugin.kyverno.leaderElection.lockName | string | `"kyverno-plugin"` | Lock Name | +| plugin.kyverno.leaderElection.releaseOnCancel | bool | `true` | Released lock when the run context is cancelled. | +| plugin.kyverno.leaderElection.leaseDuration | int | `15` | LeaseDuration is the duration that non-leader candidates will wait to force acquire leadership. | +| plugin.kyverno.leaderElection.renewDeadline | int | `10` | RenewDeadline is the duration that the acting master will retry refreshing leadership before giving up. | +| plugin.kyverno.leaderElection.retryPeriod | int | `2` | RetryPeriod is the duration the LeaderElector clients should wait between tries of actions. | +| plugin.kyverno.podDisruptionBudget.minAvailable | int | `1` | Configures the minimum available pods for kyvernoPlugin disruptions. Cannot be used if `maxUnavailable` is set. | +| plugin.kyverno.podDisruptionBudget.maxUnavailable | string | `nil` | Configures the maximum unavailable pods for kyvernoPlugin disruptions. Cannot be used if `minAvailable` is set. | +| plugin.kyverno.nodeSelector | object | `{}` | Node labels for pod assignment | +| plugin.kyverno.tolerations | list | `[]` | List of node taints to tolerate | +| plugin.kyverno.affinity | object | `{}` | Affinity constraints. | +| plugin.trivy.enabled | bool | `false` | Enable Trivy Operator Plugin | +| plugin.trivy.image.registry | string | `"ghcr.io"` | Image registry | +| plugin.trivy.image.repository | string | `"kyverno/policy-reporter/trivy-plugin"` | Image repository | +| plugin.trivy.image.pullPolicy | string | `"IfNotPresent"` | Image PullPolicy | +| plugin.trivy.image.tag | string | `"0.2.0"` | Image tag Defaults to `Chart.AppVersion` if omitted | +| plugin.trivy.replicaCount | int | `1` | Deployment replica count | +| plugin.trivy.logging.api | bool | `false` | Enables external API request logging | +| plugin.trivy.logging.server | bool | `false` | Enables Server access logging | +| plugin.trivy.logging.encoding | string | `"console"` | log encoding possible encodings are console and json | +| plugin.trivy.logging.logLevel | int | `0` | log level default info | +| plugin.trivy.server.port | int | `8080` | Application port | +| plugin.trivy.policyReporter.skipTLS | bool | `false` | Skip TLS Verification | +| plugin.trivy.policyReporter.certificate | string | `""` | TLS Certificate | +| plugin.trivy.policyReporter.secretRef | string | `""` | Secret to read the API configuration from supports `host`, `certificate`, `skipTLS`, `username`, `password` key | +| plugin.trivy.imagePullSecrets | list | `[]` | Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument | +| plugin.trivy.serviceAccount.create | bool | `true` | Create ServiceAccount | +| plugin.trivy.serviceAccount.automount | bool | `true` | Enable ServiceAccount automaount | +| plugin.trivy.serviceAccount.annotations | object | `{}` | Annotations for the ServiceAccount | +| plugin.trivy.serviceAccount.name | string | `""` | The ServiceAccount name | +| plugin.trivy.podAnnotations | object | `{}` | Additional annotations to add to each pod | +| plugin.trivy.podLabels | object | `{}` | Additional labels to add to each pod | +| plugin.trivy.updateStrategy | object | `{}` | Deployment update strategy. Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy | +| plugin.trivy.revisionHistoryLimit | int | `10` | The number of revisions to keep | +| plugin.trivy.podSecurityContext | object | `{"runAsGroup":1234,"runAsUser":1234}` | Security context for the pod | +| plugin.trivy.envVars | list | `[]` | Allow additional env variables to be added | +| plugin.trivy.rbac.enabled | bool | `true` | Create RBAC resources | +| plugin.trivy.securityContext.runAsUser | int | `1234` | | +| plugin.trivy.securityContext.runAsNonRoot | bool | `true` | | +| plugin.trivy.securityContext.privileged | bool | `false` | | +| plugin.trivy.securityContext.allowPrivilegeEscalation | bool | `false` | | +| plugin.trivy.securityContext.readOnlyRootFilesystem | bool | `true` | | +| plugin.trivy.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| plugin.trivy.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| plugin.trivy.service.type | string | `"ClusterIP"` | Service type. | +| plugin.trivy.service.port | int | `8080` | Service port. | +| plugin.trivy.service.annotations | object | `{}` | Service annotations. | +| plugin.trivy.service.labels | object | `{}` | Service labels. | +| plugin.trivy.ingress.enabled | bool | `false` | Create ingress resource. | +| plugin.trivy.ingress.className | string | `""` | Ingress class name. | +| plugin.trivy.ingress.labels | object | `{}` | Ingress labels. | +| plugin.trivy.ingress.annotations | object | `{}` | Ingress annotations. | +| plugin.trivy.ingress.hosts | list | `[]` | List of ingress host configurations. | +| plugin.trivy.ingress.tls | list | `[]` | List of ingress TLS configurations. | +| plugin.trivy.networkPolicy.enabled | bool | `false` | When true, use a NetworkPolicy to allow ingress to the webhook This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. | +| plugin.trivy.networkPolicy.egress | list | `[{"ports":[{"port":6443,"protocol":"TCP"}]}]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. Enables Kubernetes API Server by default | +| plugin.trivy.networkPolicy.ingress | list | `[]` | A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. | +| plugin.trivy.resources | object | `{}` | Resource constraints | +| plugin.trivy.podDisruptionBudget.minAvailable | int | `1` | Configures the minimum available pods for kyvernoPlugin disruptions. Cannot be used if `maxUnavailable` is set. | +| plugin.trivy.podDisruptionBudget.maxUnavailable | string | `nil` | Configures the maximum unavailable pods for kyvernoPlugin disruptions. Cannot be used if `minAvailable` is set. | +| plugin.trivy.nodeSelector | object | `{}` | Node labels for pod assignment | +| plugin.trivy.tolerations | list | `[]` | List of node taints to tolerate | +| plugin.trivy.affinity | object | `{}` | Affinity constraints. | +| monitoring.enabled | bool | `false` | Enables the Prometheus Operator integration | +| monitoring.annotations | object | `{}` | Key/value pairs that are attached to all resources. | +| monitoring.serviceMonitor.honorLabels | bool | `false` | HonorLabels chooses the metrics labels on collisions with target labels | +| monitoring.serviceMonitor.namespace | string | `nil` | Allow to override the namespace for serviceMonitor | +| monitoring.serviceMonitor.labels | object | `{}` | Labels to match the serviceMonitorSelector of the Prometheus Resource | +| monitoring.serviceMonitor.relabelings | list | `[]` | ServiceMonitor Relabelings https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig | +| monitoring.serviceMonitor.metricRelabelings | list | `[]` | See serviceMonitor.relabelings | +| monitoring.serviceMonitor.namespaceSelector | optional | `{}` | NamespaceSelector | +| monitoring.serviceMonitor.scrapeTimeout | optional | `nil` | ScrapeTimeout | +| monitoring.serviceMonitor.interval | optional | `nil` | Scrape interval | +| monitoring.grafana.namespace | string | `nil` | Naamespace for configMap of grafana dashboards | +| monitoring.grafana.dashboards.enabled | bool | `true` | Enable the deployment of grafana dashboards | +| monitoring.grafana.dashboards.label | string | `"grafana_dashboard"` | Label to find dashboards using the k8s sidecar | +| monitoring.grafana.dashboards.value | string | `"1"` | Label value to find dashboards using the k8s sidecar | +| monitoring.grafana.dashboards.labelFilter | list | `[]` | List of custom label filter Used to add filter for report label based metric labels defined in custom mode | +| monitoring.grafana.dashboards.multicluster.enabled | bool | `false` | Enable cluster filter in all dashboards | +| monitoring.grafana.dashboards.multicluster.label | string | `"cluster"` | Metric Label which is used to filter clusters | +| monitoring.grafana.dashboards.enable.overview | bool | `true` | Enable the Overview Dashboard | +| monitoring.grafana.dashboards.enable.policyReportDetails | bool | `true` | Enable the PolicyReport Dashboard | +| monitoring.grafana.dashboards.enable.clusterPolicyReportDetails | bool | `true` | Enable the ClusterPolicyReport Dashboard | +| monitoring.grafana.folder.annotation | string | `"grafana_folder"` | Annotation to enable folder storage using the k8s sidecar | +| monitoring.grafana.folder.name | string | `"Policy Reporter"` | Grafana folder in which to store the dashboards | +| monitoring.grafana.datasource.label | string | `"Prometheus"` | Grafana Datasource Label | +| monitoring.grafana.datasource.pluginId | string | `"prometheus"` | Grafana Datasource PluginId | +| monitoring.grafana.datasource.pluginName | string | `"Prometheus"` | Grafana Datasource PluginName | +| monitoring.grafana.grafanaDashboard.enabled | bool | `false` | Create GrafanaDashboard custom resource referencing to the configMap. according to https://grafana-operator.github.io/grafana-operator/docs/examples/dashboard_from_configmap/readme/ | +| monitoring.grafana.grafanaDashboard.folder | string | `"kyverno"` | Dashboard folder | +| monitoring.grafana.grafanaDashboard.allowCrossNamespaceImport | bool | `true` | Allow cross Namespace import | +| monitoring.grafana.grafanaDashboard.matchLabels | object | `{"dashboards":"grafana"}` | Label match selector | +| monitoring.policyReportDetails.firstStatusRow.height | int | `8` | | +| monitoring.policyReportDetails.secondStatusRow.enabled | bool | `true` | | +| monitoring.policyReportDetails.secondStatusRow.height | int | `2` | | +| monitoring.policyReportDetails.statusTimeline.enabled | bool | `true` | | +| monitoring.policyReportDetails.statusTimeline.height | int | `8` | | +| monitoring.policyReportDetails.passTable.enabled | bool | `true` | | +| monitoring.policyReportDetails.passTable.height | int | `8` | | +| monitoring.policyReportDetails.failTable.enabled | bool | `true` | | +| monitoring.policyReportDetails.failTable.height | int | `8` | | +| monitoring.policyReportDetails.warningTable.enabled | bool | `true` | | +| monitoring.policyReportDetails.warningTable.height | int | `4` | | +| monitoring.policyReportDetails.errorTable.enabled | bool | `true` | | +| monitoring.policyReportDetails.errorTable.height | int | `4` | | +| monitoring.clusterPolicyReportDetails.statusRow.height | int | `6` | | +| monitoring.clusterPolicyReportDetails.statusTimeline.enabled | bool | `true` | | +| monitoring.clusterPolicyReportDetails.statusTimeline.height | int | `8` | | +| monitoring.clusterPolicyReportDetails.passTable.enabled | bool | `true` | | +| monitoring.clusterPolicyReportDetails.passTable.height | int | `8` | | +| monitoring.clusterPolicyReportDetails.failTable.enabled | bool | `true` | | +| monitoring.clusterPolicyReportDetails.failTable.height | int | `8` | | +| monitoring.clusterPolicyReportDetails.warningTable.enabled | bool | `true` | | +| monitoring.clusterPolicyReportDetails.warningTable.height | int | `4` | | +| monitoring.clusterPolicyReportDetails.errorTable.enabled | bool | `true` | | +| monitoring.clusterPolicyReportDetails.errorTable.height | int | `4` | | +| monitoring.policyReportOverview.failingSummaryRow.height | int | `8` | | +| monitoring.policyReportOverview.failingTimeline.height | int | `10` | | +| monitoring.policyReportOverview.failingPolicyRuleTable.height | int | `10` | | +| monitoring.policyReportOverview.failingClusterPolicyRuleTable.height | int | `10` | | -* [[Video] 37. #EveryoneCanContribute cafe: Policy reporter for Kyverno](https://youtu.be/1mKywg9f5Fw) -* [[Video] Rawkode Live: Hands on Policy Reporter](https://www.youtube.com/watch?v=ZrOtTELNLyg) -* [[Blog] Monitor Security and Best Practices with Kyverno and Policy Reporter](https://blog.webdev-jogeleit.de/blog/monitor-security-with-kyverno-and-policy-reporter/) +## Source Code + +* + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Frank Jogeleit | | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/charts/policy-reporter/README.md.gotmpl b/charts/policy-reporter/README.md.gotmpl new file mode 100644 index 00000000..86c13c7a --- /dev/null +++ b/charts/policy-reporter/README.md.gotmpl @@ -0,0 +1,50 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} +{{ template "chart.description" . }} + +{{ template "chart.badgesSection" . }} + +## Documentation + +You can find detailed Information and Screens about Features and Configurations in the [Documentation](https://kyverno.github.io/policy-reporter-docs). + +## Installation with Helm v3 + +Installation via Helm Repository + +### Add the Helm repository +```bash +helm repo add policy-reporter https://kyverno.github.io/policy-reporter +helm repo update +``` + +### Basic Installation + +The basic installation provides an Prometheus Metrics Endpoint and different REST APIs, for more details have a look at the [Documentation](https://kyverno.github.io/policy-reporter/guide/02-getting-started). + +```bash +helm install policy-reporter policy-reporter/policy-reporter -n policy-reporter --create-namespace +``` + +## Policy Reporter UI + +You can use the Policy Reporter as standalone Application along with the optional UI SubChart. + +### Installation with Policy Reporter UI and Kyverno Plugin enabled + +```bash +helm install policy-reporter policy-reporter/policy-reporter --set plugin.kyverno.enabled=true --set ui.enabled=true -n policy-reporter --create-namespace +kubectl port-forward service/policy-reporter-ui 8082:8080 -n policy-reporter +``` +Open `http://localhost:8082/` in your browser. + + +{{ template "chart.valuesSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "helm-docs.versionFooter" . }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/Chart.yaml b/charts/policy-reporter/charts/kyvernoPlugin/Chart.yaml deleted file mode 100644 index b8067688..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: kyvernoPlugin -description: Policy Reporter Kyverno Plugin - -type: application -version: 1.6.5 -appVersion: 1.6.3 \ No newline at end of file diff --git a/charts/policy-reporter/charts/kyvernoPlugin/config.yaml b/charts/policy-reporter/charts/kyvernoPlugin/config.yaml deleted file mode 100644 index 428403c7..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/config.yaml +++ /dev/null @@ -1,21 +0,0 @@ -blockReports: - {{- toYaml .Values.blockReports | nindent 2 }} - -leaderElection: - enabled: {{ or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1) }} - releaseOnCancel: {{ .Values.leaderElection.releaseOnCancel }} - leaseDuration: {{ .Values.leaderElection.leaseDuration }} - renewDeadline: {{ .Values.leaderElection.renewDeadline }} - retryPeriod: {{ .Values.leaderElection.retryPeriod }} - -logging: - encoding: {{ .Values.logging.encoding }} - logLevel: {{ include "kyvernoplugin.logLevel" . }} - development: {{ .Values.logging.development }} - -api: - logging: {{ .Values.api.logging }} - basicAuth: - username: {{ .Values.global.basicAuth.username }} - password: {{ .Values.global.basicAuth.password }} - secretRef: {{ .Values.global.basicAuth.secretRef }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/_helpers.tpl b/charts/policy-reporter/charts/kyvernoPlugin/templates/_helpers.tpl deleted file mode 100644 index a198d3c4..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/_helpers.tpl +++ /dev/null @@ -1,105 +0,0 @@ -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "kyvernoplugin.fullname" -}} -{{- $name := "kyverno-plugin" }} -{{- if .Values.global.fullnameOverride }} -{{- printf "%s-%s" .Values.global.fullnameOverride $name | trunc 63 | trimSuffix "-" }} -{{- else if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} - -{{- define "kyvernoplugin.name" -}} -{{- "kyverno-plugin" }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "kyvernoplugin.chart" -}} -{{- printf "kyverno-plugin-%s" .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "kyvernoplugin.labels" -}} -helm.sh/chart: {{ include "kyvernoplugin.chart" . }} -{{ include "kyvernoplugin.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/component: plugin -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/part-of: policy-reporter -{{- with .Values.global.labels }} -{{ toYaml . }} -{{- end -}} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "kyvernoplugin.selectorLabels" -}} -app.kubernetes.io/name: {{ include "kyvernoplugin.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Pod labels -*/}} -{{- define "kyvernoplugin.podLabels" -}} -helm.sh/chart: {{ include "kyvernoplugin.chart" . }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -app.kubernetes.io/part-of: policy-reporter -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "kyvernoplugin.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "kyvernoplugin.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "ui.selectorLabels" -}} -app.kubernetes.io/name: ui -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{- define "kyvernoplugin.securityContext" -}} -{{- if semverCompare "<1.19" .Capabilities.KubeVersion.Version }} -{{ toYaml (omit .Values.securityContext "seccompProfile") }} -{{- else }} -{{ toYaml .Values.securityContext }} -{{- end }} -{{- end }} - -{{/* Get the namespace name. */}} -{{- define "kyvernoplugin.namespace" -}} -{{- if .Values.global.namespace -}} - {{- .Values.global.namespace -}} -{{- else -}} - {{- .Release.Namespace -}} -{{- end -}} -{{- end -}} - -{{/* Get the namespace name. */}} -{{- define "kyvernoplugin.logLevel" -}} -{{- if .Values.api.logging -}} --1 -{{- else -}} -{{- .Values.logging.logLevel -}} -{{- end -}} -{{- end -}} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrolebinding.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrolebinding.yaml deleted file mode 100644 index 168b0a85..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "kyvernoplugin.fullname" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} -roleRef: - kind: ClusterRole - name: {{ include "kyvernoplugin.fullname" . }} - apiGroup: rbac.authorization.k8s.io -subjects: -- kind: "ServiceAccount" - name: {{ include "kyvernoplugin.serviceAccountName" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} -{{- end -}} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/config-secret.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/config-secret.yaml deleted file mode 100644 index b1152ea4..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/config-secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "kyvernoplugin.fullname" . }}-config - namespace: {{ include "kyvernoplugin.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} -type: Opaque -data: - config.yaml: {{ tpl (.Files.Get "config.yaml") . | b64enc }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/deployment.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/deployment.yaml deleted file mode 100644 index d460cf84..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/deployment.yaml +++ /dev/null @@ -1,129 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "kyvernoplugin.fullname" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - {{- if .Values.deploymentStrategy }} - strategy: - {{- toYaml .Values.deploymentStrategy | nindent 4 }} - {{- end }} - selector: - matchLabels: - {{- include "kyvernoplugin.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "kyvernoplugin.selectorLabels" . | nindent 8 }} - {{- include "kyvernoplugin.podLabels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.global.labels }} - {{- toYaml . | nindent 8 }} - {{- end }} - annotations: - checksum/secret: {{ include (print .Template.BasePath "/config-secret.yaml") . | sha256sum | quote }} - {{- with .Values.annotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.priorityClassName }} - priorityClassName: {{ . }} - {{- end }} - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- if .Values.podSecurityContext }} - securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "kyvernoplugin.serviceAccountName" . }} - automountServiceAccountToken: true - containers: - - name: "kyverno-plugin" - image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.securityContext }} - securityContext: {{ include "kyvernoplugin.securityContext" . | nindent 12 }} - {{- end }} - args: - - --port={{ .Values.port.number }} - - --metrics-enabled={{ .Values.metrics.enabled }} - - --rest-enabled={{ .Values.rest.enabled }} - - --lease-name={{ include "kyvernoplugin.fullname" . }} - ports: - - name: {{ .Values.port.name }} - containerPort: {{ .Values.port.number }} - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - - name: config-file - mountPath: /app/config.yaml - subPath: config.yaml - readOnly: true - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - {{- if or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1) }} - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - {{- end }} - {{- if .Values.global.basicAuth.secretRef }} - - name: API_AUTH_USERNAME - valueFrom: - secretKeyRef: - name: {{ .Values.global.basicAuth.secretRef }} - key: username - optional: false - - name: API_AUTH_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.global.basicAuth.secretRef }} - key: password - optional: false - {{- end }} - {{- with .Values.envVars }} - {{- . | toYaml | trim | nindent 10 }} - {{- end }} - volumes: - - name: config-file - secret: - secretName: {{ include "kyvernoplugin.fullname" . }}-config - optional: true - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.topologySpreadConstraints }} - topologySpreadConstraints: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/ingress.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/ingress.yaml deleted file mode 100644 index 23da5ad8..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/ingress.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "kyvernoplugin.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - namespace: {{ include "kyvernoplugin.namespace" . }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - {{- if or .Values.annotations .Values.ingress.annotations }} - annotations: - {{- with .Values.ingress.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.annotations }} - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- toYaml .Values.ingress.tls | nindent 4 }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/networkpolicy.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/networkpolicy.yaml deleted file mode 100644 index f65b5c8d..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/networkpolicy.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - labels: {{- include "kyvernoplugin.labels" . | nindent 4 }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - name: {{ include "kyvernoplugin.fullname" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} -spec: - podSelector: - matchLabels: {{- include "kyvernoplugin.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - {{- include "ui.selectorLabels" . | nindent 10 }} - ports: - - protocol: TCP - port: 8080 - {{- with .Values.networkPolicy.ingress }} - {{- toYaml . | nindent 2 }} - {{- end }} - {{- with .Values.networkPolicy.egress }} - egress: - {{- toYaml . | nindent 2 }} - {{- end }} -{{- end }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/poddisruptionbudget.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/poddisruptionbudget.yaml deleted file mode 100644 index d876b727..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if (gt (int .Values.replicaCount) 1) }} -{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} -apiVersion: policy/v1 -{{- else }} -apiVersion: policy/v1beta1 -{{- end }} -kind: PodDisruptionBudget -metadata: - name: {{ template "kyvernoplugin.fullname" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} -spec: -{{- include "policyreporter.podDisruptionBudget" . | indent 2 }} - selector: - matchLabels: - {{- include "kyvernoplugin.selectorLabels" . | nindent 6 }} -{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/role.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/role.yaml deleted file mode 100644 index 380ad021..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/role.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and (and .Values.serviceAccount.create .Values.rbac.enabled) (and .Values.blockReports.enabled (or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1))) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - name: {{ include "kyvernoplugin.fullname" . }}-leaderelection - namespace: {{ include "kyvernoplugin.namespace" . }} -rules: -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - get - - patch - - update -{{- end -}} \ No newline at end of file diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/rolebinding.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/rolebinding.yaml deleted file mode 100644 index 9ae8b1f6..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/rolebinding.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and (and .Values.serviceAccount.create .Values.rbac.enabled) (and .Values.blockReports.enabled (or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1))) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ include "kyvernoplugin.fullname" . }}-leaderelection - namespace: {{ include "kyvernoplugin.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} -roleRef: - kind: Role - name: {{ include "kyvernoplugin.fullname" . }}-leaderelection - apiGroup: rbac.authorization.k8s.io -subjects: -- kind: "ServiceAccount" - name: {{ include "kyvernoplugin.serviceAccountName" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} -{{- end -}} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-role.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-role.yaml deleted file mode 100644 index 1c33ed35..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-role.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - name: {{ include "kyvernoplugin.fullname" . }}-secret-reader - namespace: {{ include "kyvernoplugin.namespace" . }} -rules: -- apiGroups: [''] - resources: - - secrets - verbs: - - get -{{- end -}} \ No newline at end of file diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-rolebinding.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-rolebinding.yaml deleted file mode 100644 index 26e3363c..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/secret-rolebinding.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.enabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ include "kyvernoplugin.fullname" . }}-secret-reader - namespace: {{ include "kyvernoplugin.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} -roleRef: - kind: Role - name: {{ include "kyvernoplugin.fullname" . }}-secret-reader - apiGroup: rbac.authorization.k8s.io -subjects: -- kind: "ServiceAccount" - name: {{ include "kyvernoplugin.serviceAccountName" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} -{{- end -}} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/service.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/service.yaml deleted file mode 100644 index ef0dc337..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/service.yaml +++ /dev/null @@ -1,30 +0,0 @@ -{{- if .Values.service.enabled -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "kyvernoplugin.fullname" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - {{- with .Values.service.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.annotations .Values.service.annotations }} - annotations: - {{- with .Values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.service.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: {{ .Values.port.name }} - protocol: TCP - name: rest - selector: - {{- include "kyvernoplugin.selectorLabels" . | nindent 4 }} -{{- end }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/serviceaccount.yaml b/charts/policy-reporter/charts/kyvernoPlugin/templates/serviceaccount.yaml deleted file mode 100644 index 79bddf8f..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/serviceaccount.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "kyvernoplugin.serviceAccountName" . }} - namespace: {{ include "kyvernoplugin.namespace" . }} - labels: - {{- include "kyvernoplugin.labels" . | nindent 4 }} - {{- if or .Values.annotations .Values.serviceAccount.annotations }} - annotations: - {{- with .Values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccount.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/values.yaml b/charts/policy-reporter/charts/kyvernoPlugin/values.yaml deleted file mode 100644 index 3d36363b..00000000 --- a/charts/policy-reporter/charts/kyvernoPlugin/values.yaml +++ /dev/null @@ -1,211 +0,0 @@ -image: - registry: ghcr.io - repository: kyverno/policy-reporter-kyverno-plugin - pullPolicy: IfNotPresent - tag: 1.6.3 - -imagePullSecrets: [] - -priorityClassName: "" - -replicaCount: 1 - -revisionHistoryLimit: 10 - -deploymentStrategy: {} - # rollingUpdate: - # maxSurge: 25% - # maxUnavailable: 25% - # type: RollingUpdate - -# When using a custom port together with the PolicyReporter UI -# the port has also to be changed in the UI subchart as well because it can't access values of other subcharts. -# You can change the port under `ui.kyvernoPlugin.port` -port: - name: rest - number: 8080 - -# Key/value pairs that are attached to all resources. -annotations: {} - -# Create cluster role policies -rbac: - enabled: true - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -service: - enabled: true - ## configuration of service - # key/value - annotations: {} - # key/value - labels: {} - port: 8080 - type: ClusterIP - -## Set to true to enable ingress record generation -# ref to: https://kubernetes.io/docs/concepts/services-networking/ingress/ -ingress: - enabled: false - className: "" - # key/value - labels: {} - # key/value - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local -podSecurityContext: - runAsUser: 1234 - runAsGroup: 1234 - -securityContext: - runAsUser: 1234 - runAsNonRoot: true - privileged: false - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: - - ALL - seccompProfile: - type: RuntimeDefault - -# Key/value pairs that are attached to pods. -podAnnotations: {} - -# Key/value pairs that are attached to pods. -podLabels: {} - -# Allow additional env variables to be added -envVars: [] - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # memory: 30Mi - # cpu: 10m - # requests: - # memory: 20Mi - # cpu: 5m - -# Node labels for pod assignment -# ref: https://kubernetes.io/docs/user-guide/node-selection/ -nodeSelector: {} - -# Tolerations for pod assignment -# ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -tolerations: [] - -# Anti-affinity to disallow deploying client and master nodes on the same worker node -affinity: {} - -# Topology Spread Constraints to better spread pods -topologySpreadConstraints: [] - -# livenessProbe for policy-reporter-kyverno-plugin -livenessProbe: - httpGet: - path: /healthz - port: rest - -# readinessProbe for policy-reporter-kyverno-plugin -readinessProbe: - httpGet: - path: /ready - port: rest - -# REST API -rest: - enabled: true - -# Prometheus Metrics API -metrics: - enabled: true - -logging: - encoding: console # possible encodings are console and json - logLevel: 0 # default info - development: false # more human readable structure, enables stacktraces and removes log sampling - -api: - logging: false # enable debug API access logging, sets logLevel to debug - -# create PolicyReports for enforce policies, -# based on Events created by Kyverno (>= v1.7.0) -blockReports: - enabled: false - eventNamespace: default - results: - maxPerReport: 200 - keepOnlyLatest: false - -# required if policy-reporter-kyverno-plugin should run in HA mode and the "blockReports" feature is enabled -# if "blockReports" is disabled, leaderElection is also disabled automatically -# will be enabled when replicaCount > 1 -leaderElection: - enabled: false - releaseOnCancel: true - leaseDuration: 15 - renewDeadline: 10 - retryPeriod: 2 - -# enabled if replicaCount > 1 -podDisruptionBudget: - # -- Configures the minimum available pods for kyvernoPlugin disruptions. - # Cannot be used if `maxUnavailable` is set. - minAvailable: 1 - # -- Configures the maximum unavailable pods for kyvernoPlugin disruptions. - # Cannot be used if `minAvailable` is set. - maxUnavailable: - -# Enable a NetworkPolicy for this chart. Useful on clusters where Network Policies are -# used and configured in a default-deny fashion. -networkPolicy: - enabled: false - # Kubernetes API Server - egress: - - to: - ports: - - protocol: TCP - port: 6443 - ingress: [] - -# Should be set in the parent chart only -global: - # available plugins - plugins: - # enable kyverno for Policy Reporter UI and monitoring - kyverno: false - # overwrite the fullname of all resources including subcharts - fullnameOverride: "" - # configure the namespace of all resources including subcharts - namespace: "" - # additional labels added on each resource - labels: {} - # basicAuth for APIs and metrics - basicAuth: - # HTTP BasicAuth username - username: "" - # HTTP BasicAuth password - password: "" - # read credentials from secret - secretRef: "" - diff --git a/charts/policy-reporter/charts/monitoring/Chart.yaml b/charts/policy-reporter/charts/monitoring/Chart.yaml deleted file mode 100644 index d0f0ff1e..00000000 --- a/charts/policy-reporter/charts/monitoring/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: monitoring -description: Policy Reporter Monitoring with predefined ServiceMonitor and Grafana Dashboards - -type: application -version: 2.8.2 -appVersion: 0.0.0 diff --git a/charts/policy-reporter/charts/monitoring/templates/_helpers.tpl b/charts/policy-reporter/charts/monitoring/templates/_helpers.tpl deleted file mode 100644 index 25404c02..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/_helpers.tpl +++ /dev/null @@ -1,85 +0,0 @@ -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "monitoring.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if .Values.global.fullnameOverride }} -{{- printf "%s-%s" .Values.global.fullnameOverride $name | trunc 63 | trimSuffix "-" }} -{{- else if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "monitoring.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "monitoring.labels" -}} -helm.sh/chart: {{ include "monitoring.chart" . }} -{{ include "monitoring.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/component: monitoring -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/part-of: kyverno -{{- with .Values.global.labels }} -{{ toYaml . }} -{{- end -}} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "monitoring.selectorLabels" -}} -app.kubernetes.io/name: {{ include "monitoring.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{- define "monitoring.name" -}} -{{- "monitoring" }} -{{- end }} - -{{- define "monitoring.namespace" -}} -{{- if .Values.grafana.namespace -}} -{{- .Values.grafana.namespace -}} -{{- else if .Values.global.namespace -}} - {{- .Values.global.namespace -}} -{{- else -}} -{{- .Release.Namespace -}} -{{- end }} -{{- end }} - -{{- define "kyvernoplugin.selectorLabels" -}} -app.kubernetes.io/name: kyverno-plugin -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* Get the namespace name. */}} -{{- define "monitoring.smNamespace" -}} -{{- if .Values.serviceMonitor.namespace -}} -{{- .Values.serviceMonitor.namespace -}} -{{- else if .Values.global.namespace -}} - {{- .Values.global.namespace -}} -{{- else -}} -{{- .Release.Namespace -}} -{{- end }} -{{- end }} - -{{/* -Policy Reporter Selector labels -*/}} -{{- define "policyreporter.selectorLabels" -}} -app.kubernetes.io/name: policy-reporter -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} diff --git a/charts/policy-reporter/charts/monitoring/templates/auth-secret.yaml b/charts/policy-reporter/charts/monitoring/templates/auth-secret.yaml deleted file mode 100644 index 6737f023..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/auth-secret.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.global.basicAuth.username .Values.global.basicAuth.password }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "monitoring.fullname" . }}-auth - namespace: {{ include "monitoring.smNamespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "monitoring.labels" . | nindent 4 }} -type: Opaque -data: - username: {{ .Values.global.basicAuth.username | b64enc }} - password: {{ .Values.global.basicAuth.password | b64enc }} -{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.grafanadashboard.yaml b/charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.grafanadashboard.yaml deleted file mode 100644 index 48d11793..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.grafanadashboard.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.clusterPolicyReportDetails $.Values.grafana.grafanaDashboard.enabled }} ---- -apiVersion: grafana.integreatly.org/v1beta1 -kind: GrafanaDashboard -metadata: - labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} - {{- include "monitoring.labels" . | nindent 4 }} - name: {{ include "monitoring.fullname" . }}-clusterpolicy-details-dashboard - namespace: {{ include "monitoring.namespace" . }} -spec: - allowCrossNamespaceImport: {{ $.Values.grafana.grafanaDashboard.allowCrossNamespaceImport }} - folder: {{ $.Values.grafana.grafanaDashboard.folder }} - instanceSelector: - matchLabels: - {{- toYaml $.Values.grafana.grafanaDashboard.matchLabels | nindent 6 }} - configMapRef: - name: {{ include "monitoring.fullname" . }}-clusterpolicy-details-dashboard - key: cluster-policy-reporter-details-dashboard.json -{{- end }} diff --git a/charts/policy-reporter/charts/monitoring/templates/kyverno-servicemonitor.yaml b/charts/policy-reporter/charts/monitoring/templates/kyverno-servicemonitor.yaml deleted file mode 100644 index 4ad1c816..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/kyverno-servicemonitor.yaml +++ /dev/null @@ -1,63 +0,0 @@ -{{- if or .Values.plugins.kyverno .Values.global.plugins.kyverno -}} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "monitoring.fullname" . }}-kyverno-plugin - namespace: {{ include "monitoring.smNamespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- with .Values.serviceMonitor.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- include "monitoring.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - {{- include "kyvernoplugin.selectorLabels" . | nindent 8 }} - {{- with .Values.kyverno.serviceMonitor.namespaceSelector }} - namespaceSelector: - {{- toYaml . | nindent 4 }} - {{- end }} - endpoints: - - port: rest - {{- if and .Values.global.basicAuth.username .Values.global.basicAuth.password }} - basicAuth: - password: - name: {{ include "monitoring.fullname" . }}-auth - key: password - username: - name: {{ include "monitoring.fullname" . }}-auth - key: username - {{- else if .Values.global.basicAuth.secretRef }} - basicAuth: - password: - name: {{ .Values.global.basicAuth.secretRef }} - key: password - username: - name: {{ .Values.global.basicAuth.secretRef }} - key: username - {{- end }} - honorLabels: {{ .Values.kyverno.serviceMonitor.honorLabels }} - {{- if .Values.kyverno.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.kyverno.serviceMonitor.scrapeTimeout }} - {{- end }} - {{- if .Values.kyverno.serviceMonitor.interval }} - interval: {{ .Values.kyverno.serviceMonitor.interval }} - {{- end }} - relabelings: - - action: labeldrop - regex: pod|service|container - - targetLabel: instance - replacement: policy-reporter - action: replace - {{- with .Values.kyverno.serviceMonitor.relabelings }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.kyverno.serviceMonitor.metricRelabelings }} - metricRelabelings: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/charts/policy-reporter/charts/monitoring/templates/overview.grafanadashboard.yaml b/charts/policy-reporter/charts/monitoring/templates/overview.grafanadashboard.yaml deleted file mode 100644 index b4a29b6f..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/overview.grafanadashboard.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.overview $.Values.grafana.grafanaDashboard.enabled }} ---- -apiVersion: grafana.integreatly.org/v1beta1 -kind: GrafanaDashboard -metadata: - labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} - {{- include "monitoring.labels" . | nindent 4 }} - name: {{ include "monitoring.fullname" . }}-overview-dashboard - namespace: {{ include "monitoring.namespace" . }} -spec: - allowCrossNamespaceImport: {{ $.Values.grafana.grafanaDashboard.allowCrossNamespaceImport }} - folder: {{ $.Values.grafana.grafanaDashboard.folder }} - instanceSelector: - matchLabels: - {{- toYaml $.Values.grafana.grafanaDashboard.matchLabels | nindent 6 }} - configMapRef: - name: {{ include "monitoring.fullname" . }}-overview-dashboard - key: policy-reporter-dashboard.json -{{- end }} diff --git a/charts/policy-reporter/charts/monitoring/templates/policy-details.grafanadashboard.yaml b/charts/policy-reporter/charts/monitoring/templates/policy-details.grafanadashboard.yaml deleted file mode 100644 index c4a5b9f7..00000000 --- a/charts/policy-reporter/charts/monitoring/templates/policy-details.grafanadashboard.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.policyReportDetails $.Values.grafana.grafanaDashboard.enabled }} ---- -apiVersion: grafana.integreatly.org/v1beta1 -kind: GrafanaDashboard -metadata: - labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} - {{- include "monitoring.labels" . | nindent 4 }} - name: {{ include "monitoring.fullname" . }}-policy-details-dashboard - namespace: {{ include "monitoring.namespace" . }} -spec: - allowCrossNamespaceImport: {{ $.Values.grafana.grafanaDashboard.allowCrossNamespaceImport }} - folder: {{ $.Values.grafana.grafanaDashboard.folder }} - instanceSelector: - matchLabels: - {{- toYaml $.Values.grafana.grafanaDashboard.matchLabels | nindent 6 }} - configMapRef: - name: {{ include "monitoring.fullname" . }}-policy-details-dashboard - key: policy-reporter-details-dashboard.json -{{- end }} diff --git a/charts/policy-reporter/charts/monitoring/values.yaml b/charts/policy-reporter/charts/monitoring/values.yaml deleted file mode 100644 index 2c7c4fcb..00000000 --- a/charts/policy-reporter/charts/monitoring/values.yaml +++ /dev/null @@ -1,150 +0,0 @@ -# Override the chart name used for all resources -nameOverride: "" - -plugins: - kyverno: false - -# Key/value pairs that are attached to all resources. -annotations: {} - -serviceMonitor: - # HonorLabels chooses the metrics labels on collisions with target labels - honorLabels: false - # allow to override the namespace for serviceMonitor - namespace: - # labels to match the serviceMonitorSelector of the Prometheus Resource - labels: {} - # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig - relabelings: [] - # see serviceMonitor.relabelings - metricRelabelings: [] - # optional namespaceSelector - namespaceSelector: {} - # optional scrapeTimeout - scrapeTimeout: - # optional scrape interval - interval: - -kyverno: - serviceMonitor: - # HonorLabels chooses the metrics labels on collisions with target labels - honorLabels: false - # see serviceMonitor.relabelings - relabelings: [] - # see serviceMonitor.relabelings - metricRelabelings: [] - # optional namespaceSelector - namespaceSelector: {} - # optional scrapeTimeout - scrapeTimeout: - # optional scrape interval - interval: - -grafana: - # namespace for configMap of grafana dashboards - namespace: - dashboards: - # Enable the deployment of grafana dashboards - enabled: true - # Label to find dashboards using the k8s sidecar - label: grafana_dashboard - value: "1" - labelFilter: [] - multicluster: - enabled: false - label: cluster - enable: - overview: true - policyReportDetails: true - clusterPolicyReportDetails: true - folder: - # Annotation to enable folder storage using the k8s sidecar - annotation: grafana_folder - # Grafana folder in which to store the dashboards - name: Policy Reporter - datasource: - label: Prometheus - pluginId: prometheus - pluginName: Prometheus - - # -- create GrafanaDashboard custom resource referencing to the configMap. - # according to https://grafana-operator.github.io/grafana-operator/docs/examples/dashboard_from_configmap/readme/ - grafanaDashboard: - enabled: false - folder: kyverno - allowCrossNamespaceImport: true - matchLabels: - dashboards: "grafana" - - -policyReportDetails: - firstStatusRow: - height: 8 - secondStatusRow: - enabled: true - height: 2 - statusTimeline: - enabled: true - height: 8 - passTable: - enabled: true - height: 8 - failTable: - enabled: true - height: 8 - warningTable: - enabled: true - height: 4 - errorTable: - enabled: true - height: 4 - -clusterPolicyReportDetails: - statusRow: - height: 6 - statusTimeline: - enabled: true - height: 8 - passTable: - enabled: true - height: 8 - failTable: - enabled: true - height: 8 - warningTable: - enabled: true - height: 4 - errorTable: - enabled: true - height: 4 - -policyReportOverview: - failingSummaryRow: - height: 8 - failingTimeline: - height: 10 - failingPolicyRuleTable: - height: 10 - failingClusterPolicyRuleTable: - height: 10 - -# Should be set in the parent chart only -global: - # available plugins - plugins: - # enable kyverno for Policy Reporter UI and monitoring - kyverno: false - # overwrite the fullname of all resources including subcharts - fullnameOverride: "" - # configure the namespace of all resources including subcharts - namespace: "" - # additional labels added on each resource - labels: {} - # basicAuth for APIs and metrics - basicAuth: - # HTTP BasicAuth username - username: "" - # HTTP BasicAuth password - password: "" - # read credentials from secret - secretRef: "" diff --git a/charts/policy-reporter/charts/ui/Chart.yaml b/charts/policy-reporter/charts/ui/Chart.yaml deleted file mode 100644 index 7cca02c9..00000000 --- a/charts/policy-reporter/charts/ui/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: ui -description: Policy Reporter UI - -type: application -version: 2.10.5 -appVersion: 1.9.2 diff --git a/charts/policy-reporter/charts/ui/templates/_helpers.tpl b/charts/policy-reporter/charts/ui/templates/_helpers.tpl deleted file mode 100644 index cf814751..00000000 --- a/charts/policy-reporter/charts/ui/templates/_helpers.tpl +++ /dev/null @@ -1,140 +0,0 @@ -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "ui.fullname" -}} -{{- $name := "ui" }} -{{- if .Values.global.fullnameOverride }} -{{- printf "%s-%s" .Values.global.fullnameOverride $name | trunc 63 | trimSuffix "-" }} -{{- else if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} - -{{- define "ui.name" -}} -{{- "ui" }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "ui.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "ui.labels" -}} -helm.sh/chart: {{ include "ui.chart" . }} -{{ include "ui.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/component: ui -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/part-of: policy-reporter -{{- with .Values.global.labels }} -{{ toYaml . }} -{{- end -}} -{{- with .Values.ingress.labels }} -{{ toYaml . }} -{{- end -}} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "ui.selectorLabels" -}} -app.kubernetes.io/name: {{ include "ui.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Pod labels -*/}} -{{- define "ui.podLabels" -}} -helm.sh/chart: {{ include "ui.chart" . }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -app.kubernetes.io/part-of: policy-reporter -{{- end }} - -{{/* -Policy Reporter Selector labels -*/}} -{{- define "policyreporter.selectorLabels" -}} -app.kubernetes.io/name: policy-reporter -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Kyverno Plugin Selector labels -*/}} -{{- define "kyvernoplugin.selectorLabels" -}} -app.kubernetes.io/name: kyverno-plugin -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "ui.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "ui.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{- define "ui.kyvernoPluginServiceName" -}} -{{- $name := "kyverno-plugin" }} -{{- if .Values.global.fullnameOverride }} -{{- printf "%s-%s" .Values.global.fullnameOverride $name | trunc 63 | trimSuffix "-" }} -{{- else if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} - -{{- define "ui.policyReportServiceName" -}} -{{- $name := "policy-reporter" }} -{{- if .Values.global.backend }} -{{- .Values.global.backend }} -{{- else if .Values.global.fullnameOverride }} -{{- .Values.global.fullnameOverride }} -{{- else if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} - -{{- define "ui.securityContext" -}} -{{- if semverCompare "<1.19" .Capabilities.KubeVersion.Version }} -{{ toYaml (omit .Values.securityContext "seccompProfile") }} -{{- else }} -{{ toYaml .Values.securityContext }} -{{- end }} -{{- end }} - -{{/* Get the namespace name. */}} -{{- define "ui.namespace" -}} -{{- if .Values.global.namespace -}} - {{- .Values.global.namespace -}} -{{- else -}} - {{- .Release.Namespace -}} -{{- end -}} -{{- end -}} - -{{/* Get the namespace name. */}} -{{- define "ui.logLevel" -}} -{{- if .Values.api.logging -}} --1 -{{- else -}} -{{- .Values.logging.logLevel -}} -{{- end -}} -{{- end -}} diff --git a/charts/policy-reporter/charts/ui/templates/config.yaml b/charts/policy-reporter/charts/ui/templates/config.yaml deleted file mode 100644 index eef0df74..00000000 --- a/charts/policy-reporter/charts/ui/templates/config.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "ui.fullname" . }}-config - namespace: {{ include "ui.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "ui.labels" . | nindent 4 }} -data: - config.yaml: |- - logSize: {{ .Values.log.size }} - displayMode: {{ .Values.displayMode | quote }} - refreshInterval: {{ .Values.refreshInterval }} - clusterName: {{ .Values.clusterName | quote }} - views: - dashboard: - policyReports: {{ .Values.views.dashboard.policyReports }} - clusterPolicyReports: {{ .Values.views.dashboard.clusterPolicyReports }} - logs: {{ .Values.views.logs }} - policyReports: {{ .Values.views.policyReports }} - clusterPolicyReports: {{ .Values.views.clusterPolicyReports }} - kyvernoPolicies: {{ .Values.views.kyvernoPolicies }} - kyvernoVerifyImages: {{ .Values.views.kyvernoVerifyImages }} - {{- with .Values.clusters }} - clusters: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.labelFilter }} - labelFilter: - {{- toYaml . | nindent 4 }} - {{- end }} - - {{- with .Values.redis }} - redis: - {{- toYaml . | nindent 6 }} - {{- end }} - - logging: - encoding: {{ .Values.logging.encoding }} - logLevel: {{ include "ui.logLevel" . }} - development: {{ .Values.logging.development }} - - apiConfig: - logging: {{ .Values.api.logging }} - overwriteHost: {{ .Values.api.overwriteHost }} - basicAuth: - username: {{ .Values.global.basicAuth.username }} - password: {{ .Values.global.basicAuth.password }} - secretRef: {{ .Values.global.basicAuth.secretRef }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/deployment.yaml b/charts/policy-reporter/charts/ui/templates/deployment.yaml deleted file mode 100644 index 701ba65c..00000000 --- a/charts/policy-reporter/charts/ui/templates/deployment.yaml +++ /dev/null @@ -1,123 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "ui.fullname" . }} - namespace: {{ include "ui.namespace" . }} - labels: - {{- include "ui.labels" . | nindent 4 }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} -spec: - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - {{- if .Values.deploymentStrategy }} - strategy: - {{- toYaml .Values.deploymentStrategy | nindent 4 }} - {{- end }} - selector: - matchLabels: - {{- include "ui.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "ui.selectorLabels" . | nindent 8 }} - {{- include "ui.podLabels" . | nindent 8 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.global.labels }} - {{- toYaml . | nindent 8 }} - {{- end }} - annotations: - checksum/config: {{ include (print .Template.BasePath "/config.yaml") . | sha256sum | quote }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.priorityClassName }} - priorityClassName: {{ . }} - {{- end }} - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "ui.serviceAccountName" . }} - automountServiceAccountToken: true - containers: - - name: {{ default .Chart.Name .Values.nameOverride }} - image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.securityContext }} - securityContext: {{ include "ui.securityContext" . | nindent 12 }} - {{- end }} - args: - - -config=/app/config.yaml - - -policy-reporter=http://{{ include "ui.policyReportServiceName" . }}:{{ .Values.policyReporter.port }} - {{- if or .Values.plugins.kyverno .Values.global.plugins.kyverno }} - - -kyverno-plugin=http://{{ include "ui.kyvernoPluginServiceName" . }}:{{ .Values.kyvernoPlugin.port }} - {{- end }} - ports: - - name: http - containerPort: 8080 - protocol: TCP - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http - volumeMounts: - - name: config-file - mountPath: /app/config.yaml - subPath: config.yaml - readOnly: true - {{- if .Values.volumes }} - {{- toYaml .Values.volumeMounts | nindent 10 }} - {{- end }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - {{- with .Values.envVars }} - {{- . | toYaml | trim | nindent 10 }} - {{- end }} - {{- if .Values.sidecarContainers }} - {{- range $name, $spec := .Values.sidecarContainers }} - - name: {{ $name }} - {{- if kindIs "string" $spec }} - {{- tpl $spec $ | nindent 10 }} - {{- else }} - {{- toYaml $spec | nindent 10 }} - {{- end }} - {{- end }} - {{- end }} - volumes: - - name: config-file - configMap: - name: {{ include "ui.fullname" . }}-config - {{- if .Values.volumes }} - {{- toYaml .Values.volumes | nindent 6 }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.topologySpreadConstraints }} - topologySpreadConstraints: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/charts/policy-reporter/charts/ui/templates/extra-manifests.yaml b/charts/policy-reporter/charts/ui/templates/extra-manifests.yaml deleted file mode 100644 index 9059d7d0..00000000 --- a/charts/policy-reporter/charts/ui/templates/extra-manifests.yaml +++ /dev/null @@ -1,4 +0,0 @@ -{{ range .Values.extraManifests }} ---- -{{ tpl . $ }} -{{ end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/networkpolicy.yaml b/charts/policy-reporter/charts/ui/templates/networkpolicy.yaml deleted file mode 100644 index 42650085..00000000 --- a/charts/policy-reporter/charts/ui/templates/networkpolicy.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "ui.fullname" . }} - namespace: {{ include "ui.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - labels: - {{- include "ui.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: {{- include "ui.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - ports: - - protocol: TCP - port: {{ .Values.service.port }} - egress: - - to: - - podSelector: - matchLabels: - {{- include "policyreporter.selectorLabels" . | nindent 10 }} - ports: - - protocol: TCP - port: 8080 - {{- if or .Values.plugins.kyverno .Values.global.plugins.kyverno }} - - to: - - podSelector: - matchLabels: - {{- include "kyvernoplugin.selectorLabels" . | nindent 10 }} - ports: - - protocol: TCP - port: 8080 - {{- end }} - {{- with .Values.networkPolicy.egress }} - {{- toYaml . | nindent 2 }} - {{- end }} -{{- end }} diff --git a/charts/policy-reporter/charts/ui/templates/service.yaml b/charts/policy-reporter/charts/ui/templates/service.yaml deleted file mode 100644 index d413677d..00000000 --- a/charts/policy-reporter/charts/ui/templates/service.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.service.enabled -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "ui.fullname" . }} - namespace: {{ include "ui.namespace" . }} - labels: - {{- include "ui.labels" . | nindent 4 }} - {{- with .Values.service.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.annotations .Values.service.annotations }} - annotations: - {{- with .Values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.service.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http -{{- if .Values.service.additionalPorts }} -{{ toYaml .Values.service.additionalPorts | indent 4 }} -{{- end }} - selector: - {{- include "ui.selectorLabels" . | nindent 4 }} -{{- end }} diff --git a/charts/policy-reporter/charts/ui/templates/serviceaccount.yaml b/charts/policy-reporter/charts/ui/templates/serviceaccount.yaml deleted file mode 100644 index ce349a1e..00000000 --- a/charts/policy-reporter/charts/ui/templates/serviceaccount.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "ui.serviceAccountName" . }} - namespace: {{ include "ui.namespace" . }} - labels: - {{- include "ui.labels" . | nindent 4 }} - {{- if or .Values.annotations .Values.serviceAccount.annotations }} - annotations: - {{- with .Values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccount.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/policy-reporter/charts/ui/values.yaml b/charts/policy-reporter/charts/ui/values.yaml deleted file mode 100644 index d3e0a189..00000000 --- a/charts/policy-reporter/charts/ui/values.yaml +++ /dev/null @@ -1,279 +0,0 @@ -enabled: false - -# Override the chart name used for all resources -nameOverride: "" - -priorityClassName: "" - -image: - registry: ghcr.io - repository: kyverno/policy-reporter-ui - pullPolicy: IfNotPresent - tag: 1.9.2 - -# sidecarContainers - add more containers to Kyverno ui -# Key/Value where Key is the sidecar `- name: ` -# Example: -# for adding OAuth authentication to Kyverno ui -# sidecarContainers: -# oauth-proxy: -# image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 -# args: -# - --upstream=http://127.0.0.1:8080 -# - --http-address=0.0.0.0:8081 -# - ... -# ports: -# - containerPort: 8081 -# name: oauth-proxy -# protocol: TCP -# resources: {} -sidecarContainers: {} - -# possible default displayModes: light/dark -displayMode: "" - -# default refreshInterval, set 0 to disable it -refreshInterval: 10000 - -# Key/value pairs that are attached to all resources. -annotations: {} - -log: - # holds the latest 200 validation results in the UI Log - size: 200 - -# enable/disable views as needed in the Policy Reporter UI -# disabled log view will also disable the UI as push target -views: - dashboard: - policyReports: true - clusterPolicyReports: true - logs: true - policyReports: true - clusterPolicyReports: true - kyvernoPolicies: true - kyvernoVerifyImages: true - -plugins: - kyverno: false - -# Custom Cluster Name which is used in the ClusterSelect, if you configured additional clusters below. -clusterName: "" - -# Attention: be sure that your APIs are not accessable for the outside world -# Use tools like VPN, private Networks or internal Network Load Balancer to expose your APIs in a secure way to the UI -clusters: [] -# - name: External Cluster -# api: https://policy-reporter.external.cluster # reachable external Policy Reporter REST API -# kyvernoApi: https://policy-reporter-kyverno-plugin.external.cluster # (optional) reachable external Policy Reporter Kyverno Plugin REST API -# skipTLS: false -# certificate: "/app/certs/root.ca" -# secreRef: "" # name of an existing secret to read the clusterconfiguration from, supported keys: api, kyvernoApi, username, password, skipTLS, certificate -# basicAuth: # added as HTTP BasicAuthentication Header for all requests against api and kyvernoApi -# username: "" -# password: "" - -# define custom filter for policy report results based on (Cluster)PolicyReport labels -# exmaple - use a owner label on all reports belonging to a dedicated team and add the label as additional custom filter -# -# apiVersion: wgpolicyk8s.io/v1alpha2 -# kind: PolicyReport -# metadata: -# labels: -# app.kubernetes.io/managed-by: kyverno -# owner: team-a -# name: cpol-disallow-capabilities -# namespace: default -# results: [...] -# -# labelFilter: ["owner"] -labelFilter: [] - -# Proxy request logging -logging: - encoding: console # possible encodings are console and json - logLevel: 0 # default info - development: false # more human readable structure, removes log sampling - -api: - logging: false # enables access logging for proxy requests, sets log level to debug - overwriteHost: true # overwrites request host and sets X-Forwarded--Host and X-Origin-Host headers - -# use redis as external log storage instead of an in memory store -# recommended when using a HA setup with more then one replica -# to get all logs on each instance -redis: - enabled: false - address: "" - database: 0 - prefix: "policy-reporter-ui" - username: "" - password: "" - -# configurations related to the PolicyReporter API -policyReporter: - port: 8080 - -# configurations related to the RolicyReporter KyvernoPlugin API -kyvernoPlugin: - port: 8080 - -# configure additional volumes to e.g. mount custom certificate for proxy TLS -volumes: [] -volumeMounts: [] - -imagePullSecrets: [] - -replicaCount: 1 - -revisionHistoryLimit: 10 - -deploymentStrategy: {} - # rollingUpdate: - # maxSurge: 25% - # maxUnavailable: 25% - # type: RollingUpdate - -securityContext: - runAsUser: 1234 - runAsNonRoot: true - privileged: false - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: - - ALL - seccompProfile: - type: RuntimeDefault - -# Key/value pairs that are attached to pods. -podAnnotations: {} - -# Key/value pairs that are attached to pods. -podLabels: {} - -# Allow additional env variables to be added -envVars: [] - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # memory: 100Mi - # cpu: 50m - # requests: - # memory: 50Mi - # cpu: 10m - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -# Create secret reader role and rolebinding -rbac: - enabled: true - -service: - enabled: true - ## configuration of service - # key/value - annotations: {} - # key/value - labels: {} - type: ClusterIP - # integer nubmer. This is port for service - port: 8080 - # additionalPorts: - # - name: authenticated - # port: 8081 - # targetPort: 8081 - additionalPorts: [] - -# enabled if replicaCount > 1 -podDisruptionBudget: - # -- Configures the minimum available pods for policy-reporter-ui disruptions. - # Cannot be used if `maxUnavailable` is set. - minAvailable: 1 - # -- Configures the maximum unavailable pods for policy-reporter-ui disruptions. - # Cannot be used if `minAvailable` is set. - maxUnavailable: - -## Set to true to enable ingress record generation -# ref to: https://kubernetes.io/docs/concepts/services-networking/ingress/ -ingress: - enabled: false - className: "" - # key/value - labels: {} - # key/value - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - ## Redirect ingress to an additional defined port on the service - # port: 8081 - hosts: - - host: chart-example.local - paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -# Node labels for pod assignment -# ref: https://kubernetes.io/docs/user-guide/node-selection/ -nodeSelector: {} - -# Tolerations for pod assignment -# ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -tolerations: [] - -# Anti-affinity to disallow deploying client and master nodes on the same worker node -affinity: {} - -# Topology Spread Constraints to better spread pods -topologySpreadConstraints: [] - -# enable a NetworkPolicy for this chart. Useful on clusters where Network Policies are -# used and configured in a default-deny fashion. -networkPolicy: - enabled: false - egress: [] - -# Should be set in the parent chart only -global: - # available plugins - plugins: - # enable kyverno for Policy Reporter UI and monitoring - kyverno: false - # overwrite the fullname of all resources including subcharts - fullnameOverride: "" - # configure the namespace of all resources including subcharts - namespace: "" - # additional labels added on each resource - labels: {} - # basicAuth for APIs and metrics - basicAuth: - # HTTP BasicAuth username - username: "" - # HTTP BasicAuth password - password: "" - # read credentials from secret - secretRef: "" - -# Extra manifests to deploy as an array -extraManifests: [] - # - | - # apiVersion: v1 - # kind: ConfigMap - # metadata: - # labels: - # name: kyverno-extra - # data: - # extra-data: "value" \ No newline at end of file diff --git a/charts/policy-reporter/config.yaml b/charts/policy-reporter/config.yaml deleted file mode 100644 index 04cae54c..00000000 --- a/charts/policy-reporter/config.yaml +++ /dev/null @@ -1,416 +0,0 @@ -loki: - host: {{ .Values.target.loki.host | quote }} - certificate: {{ .Values.target.loki.certificate | quote }} - skipTLS: {{ .Values.target.loki.skipTLS }} - path: {{ .Values.target.loki.path | quote }} - secretRef: {{ .Values.target.loki.secretRef | quote }} - mountedSecret: {{ .Values.target.loki.mountedSecret | quote }} - minimumPriority: {{ .Values.target.loki.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.loki.skipExistingOnStartup }} - username: {{ .Values.target.loki.username | quote }} - password: {{ .Values.target.loki.password | quote }} - {{- with .Values.target.loki.customLabels }} - customLabels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.loki.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.loki.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.loki.headers }} - headers: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.loki.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -elasticsearch: - host: {{ .Values.target.elasticsearch.host | quote }} - certificate: {{ .Values.target.elasticsearch.certificate | quote }} - skipTLS: {{ .Values.target.elasticsearch.skipTLS }} - username: {{ .Values.target.elasticsearch.username | quote }} - password: {{ .Values.target.elasticsearch.password | quote }} - apiKey: {{ .Values.target.elasticsearch.apiKey | quote }} - secretRef: {{ .Values.target.elasticsearch.secretRef | quote }} - mountedSecret: {{ .Values.target.elasticsearch.mountedSecret | quote }} - index: {{ .Values.target.elasticsearch.index | default "policy-reporter" | quote }} - rotation: {{ .Values.target.elasticsearch.rotation | default "daily" | quote }} - minimumPriority: {{ .Values.target.elasticsearch.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.elasticsearch.skipExistingOnStartup }} - typelessApi: {{ .Values.target.elasticsearch.typelessApi }} - {{- with .Values.target.elasticsearch.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.elasticsearch.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.elasticsearch.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.elasticsearch.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -slack: - webhook: {{ .Values.target.slack.webhook | quote }} - channel: {{ .Values.target.slack.channel | quote }} - secretRef: {{ .Values.target.slack.secretRef | quote }} - mountedSecret: {{ .Values.target.slack.mountedSecret | quote }} - minimumPriority: {{ .Values.target.slack.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.slack.skipExistingOnStartup }} - {{- with .Values.target.slack.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.slack.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.slack.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.slack.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -discord: - webhook: {{ .Values.target.discord.webhook | quote }} - secretRef: {{ .Values.target.discord.secretRef | quote }} - mountedSecret: {{ .Values.target.discord.mountedSecret | quote }} - minimumPriority: {{ .Values.target.discord.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.discord.skipExistingOnStartup }} - {{- with .Values.target.discord.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.discord.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.discord.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.discord.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -teams: - webhook: {{ .Values.target.teams.webhook | quote }} - certificate: {{ .Values.target.teams.certificate | quote }} - skipTLS: {{ .Values.target.teams.skipTLS }} - secretRef: {{ .Values.target.teams.secretRef | quote }} - mountedSecret: {{ .Values.target.teams.mountedSecret | quote }} - minimumPriority: {{ .Values.target.teams.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.teams.skipExistingOnStartup }} - {{- with .Values.target.teams.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.teams.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.teams.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.teams.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -webhook: - host: {{ .Values.target.webhook.host | quote }} - certificate: {{ .Values.target.webhook.certificate | quote }} - skipTLS: {{ .Values.target.webhook.skipTLS }} - secretRef: {{ .Values.target.webhook.secretRef | quote }} - mountedSecret: {{ .Values.target.webhook.mountedSecret | quote }} - minimumPriority: {{ .Values.target.webhook.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.webhook.skipExistingOnStartup }} - {{- with .Values.target.webhook.headers }} - headers: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.webhook.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.webhook.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.webhook.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.webhook.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -telegram: - token: {{ .Values.target.telegram.token | quote }} - chatID: {{ .Values.target.telegram.chatID | quote }} - host: {{ .Values.target.telegram.host | quote }} - certificate: {{ .Values.target.telegram.certificate | quote }} - skipTLS: {{ .Values.target.telegram.skipTLS }} - secretRef: {{ .Values.target.telegram.secretRef | quote }} - mountedSecret: {{ .Values.target.telegram.mountedSecret | quote }} - minimumPriority: {{ .Values.target.telegram.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.telegram.skipExistingOnStartup }} - {{- with .Values.target.telegram.headers }} - headers: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.telegram.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.telegram.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.telegram.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.telegram.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -googleChat: - webhook: {{ .Values.target.googleChat.webhook | quote }} - certificate: {{ .Values.target.googleChat.certificate | quote }} - skipTLS: {{ .Values.target.googleChat.skipTLS }} - secretRef: {{ .Values.target.googleChat.secretRef | quote }} - mountedSecret: {{ .Values.target.googleChat.mountedSecret | quote }} - minimumPriority: {{ .Values.target.googleChat.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.googleChat.skipExistingOnStartup }} - {{- with .Values.target.googleChat.headers }} - headers: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.googleChat.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.googleChat.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.googleChat.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.googleChat.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -ui: - host: {{ include "policyreporter.uihost" . }} - certificate: {{ .Values.target.ui.certificate | quote }} - skipTLS: {{ .Values.target.ui.skipTLS }} - minimumPriority: {{ .Values.target.ui.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.ui.skipExistingOnStartup }} - {{- with .Values.target.ui.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - -s3: - accessKeyID: {{ .Values.target.s3.accessKeyID }} - secretAccessKey: {{ .Values.target.s3.secretAccessKey }} - secretRef: {{ .Values.target.s3.secretRef | quote }} - mountedSecret: {{ .Values.target.s3.mountedSecret }} - region: {{ .Values.target.s3.region }} - endpoint: {{ .Values.target.s3.endpoint }} - bucket: {{ .Values.target.s3.bucket }} - bucketKeyEnabled: {{ .Values.target.s3.bucketKeyEnabled }} - kmsKeyId: {{ .Values.target.s3.kmsKeyId }} - serverSideEncryption: {{ .Values.target.s3.serverSideEncryption }} - pathStyle: {{ .Values.target.s3.pathStyle }} - prefix: {{ .Values.target.s3.prefix }} - minimumPriority: {{ .Values.target.s3.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.s3.skipExistingOnStartup }} - {{- with .Values.target.s3.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.s3.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.s3.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.s3.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -kinesis: - accessKeyID: {{ .Values.target.kinesis.accessKeyID }} - secretAccessKey: {{ .Values.target.kinesis.secretAccessKey }} - secretRef: {{ .Values.target.kinesis.secretRef | quote }} - mountedSecret: {{ .Values.target.kinesis.mountedSecret | quote }} - region: {{ .Values.target.kinesis.region }} - endpoint: {{ .Values.target.kinesis.endpoint }} - streamName: {{ .Values.target.kinesis.streamName }} - minimumPriority: {{ .Values.target.kinesis.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.kinesis.skipExistingOnStartup }} - {{- with .Values.target.kinesis.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.kinesis.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.kinesis.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.kinesis.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -securityHub: - accountID: {{ .Values.target.securityHub.accountID }} - accessKeyID: {{ .Values.target.securityHub.accessKeyID }} - secretAccessKey: {{ .Values.target.securityHub.secretAccessKey }} - delayInSeconds: {{ .Values.target.securityHub.delayInSeconds }} - cleanup: {{ .Values.target.securityHub.cleanup }} - secretRef: {{ .Values.target.securityHub.secretRef | quote }} - mountedSecret: {{ .Values.target.securityHub.mountedSecret | quote }} - productName: {{ .Values.target.securityHub.productName | quote }} - companyName: {{ .Values.target.securityHub.companyName | quote }} - region: {{ .Values.target.securityHub.region }} - endpoint: {{ .Values.target.securityHub.endpoint }} - minimumPriority: {{ .Values.target.securityHub.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.securityHub.skipExistingOnStartup }} - {{- with .Values.target.securityHub.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.securityHub.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.securityHub.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.securityHub.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -gcs: - credentials: {{ .Values.target.gcs.credentials }} - secretRef: {{ .Values.target.gcs.secretRef | quote }} - mountedSecret: {{ .Values.target.gcs.mountedSecret | quote }} - bucket: {{ .Values.target.gcs.bucket }} - prefix: {{ .Values.target.gcs.prefix }} - minimumPriority: {{ .Values.target.gcs.minimumPriority | quote }} - skipExistingOnStartup: {{ .Values.target.gcs.skipExistingOnStartup }} - {{- with .Values.target.gcs.sources }} - sources: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.gcs.customFields }} - customFields: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.gcs.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.target.gcs.channels }} - channels: - {{- toYaml . | nindent 4 }} - {{- end }} - -worker: {{ .Values.worker }} - -metrics: - mode: {{ .Values.metrics.mode }} - {{- with .Values.metrics.filter }} - filter: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.metrics.customLabels }} - customLabels: - {{- toYaml . | nindent 4 }} - {{- end }} - -reportFilter: - namespaces: - {{- with .Values.reportFilter.namespaces.include }} - include: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.reportFilter.namespaces.exclude }} - exclude: - {{- toYaml . | nindent 6 }} - {{- end }} - clusterReports: - disabled: {{ .Values.reportFilter.clusterReports.disabled }} - -leaderElection: - enabled: {{ or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1) }} - releaseOnCancel: {{ .Values.leaderElection.releaseOnCancel }} - leaseDuration: {{ .Values.leaderElection.leaseDuration }} - renewDeadline: {{ .Values.leaderElection.renewDeadline }} - retryPeriod: {{ .Values.leaderElection.retryPeriod }} - -{{- with .Values.redis }} -redis: - {{- toYaml . | nindent 2 }} -{{- end }} - -{{- with .Values.sourceConfig }} -sourceConfig: - {{- toYaml . | nindent 2 }} -{{- end }} - - -logging: - encoding: {{ .Values.logging.encoding }} - logLevel: {{ include "policyreporter.logLevel" . }} - development: {{ .Values.logging.development }} - -api: - logging: {{ .Values.api.logging }} - basicAuth: - username: {{ .Values.global.basicAuth.username }} - password: {{ .Values.global.basicAuth.password }} - secretRef: {{ .Values.global.basicAuth.secretRef }} - -database: - type: {{ .Values.database.type }} - database: {{ .Values.database.database }} - username: {{ .Values.database.username }} - password: {{ .Values.database.password }} - host: {{ .Values.database.host }} - enableSSL: {{ .Values.database.enableSSL }} - dsn: {{ .Values.database.dsn }} - secretRef: {{ .Values.database.secretRef }} - mountedSecret: {{ .Values.database.mountedSecret }} diff --git a/charts/policy-reporter/configs/core.tmpl b/charts/policy-reporter/configs/core.tmpl new file mode 100644 index 00000000..2b5f111c --- /dev/null +++ b/charts/policy-reporter/configs/core.tmpl @@ -0,0 +1,176 @@ +target: + loki: + {{- include "target.loki" .Values.target.loki | nindent 4 }} + {{- if and .Values.target.loki .Values.target.loki.channels }} + channels: + {{- range .Values.target.loki.channels }} + - + {{- include "target.loki" . | nindent 8 }} + {{- end }} + {{- end }} + + elasticsearch: + {{- include "target.elasticsearch" .Values.target.elasticsearch | nindent 4 }} + {{- if and .Values.target.elasticsearch .Values.target.elasticsearch.channels }} + channels: + {{- range .Values.target.elasticsearch.channels }} + - + {{- include "target.elasticsearch" . | nindent 8 }} + {{- end }} + {{- end }} + + slack: + {{- include "target.slack" .Values.target.slack | nindent 4 }} + {{- if and .Values.target.slack .Values.target.slack.channels }} + channels: + {{- range .Values.target.slack.channels }} + - + {{- include "target.slack" . | nindent 8 }} + {{- end }} + {{- end }} + + discord: + {{- include "target.webhook" .Values.target.discord | nindent 4 }} + {{- if and .Values.target.discord .Values.target.discord.channels }} + channels: + {{- range .Values.target.discord.channels }} + - + {{- include "target.webhook" . | nindent 8 }} + {{- end }} + {{- end }} + + teams: + {{- include "target.webhook" .Values.target.teams | nindent 4 }} + {{- if and .Values.target.teams .Values.target.teams.channels }} + channels: + {{- range .Values.target.teams.channels }} + - + {{- include "target.webhook" . | nindent 8 }} + {{- end }} + {{- end }} + + webhook: + {{- include "target.webhook" .Values.target.webhook | nindent 4 }} + {{- if and .Values.target.webhook .Values.target.webhook.channels }} + channels: + {{- range .Values.target.webhook.channels }} + - + {{- include "target.webhook" . | nindent 8 }} + {{- end }} + {{- end }} + + telegram: + {{- include "target.telegram" .Values.target.telegram | nindent 4 }} + {{- if and .Values.target.telegram .Values.target.telegram.channels }} + channels: + {{- range .Values.target.telegram.channels }} + - + {{- include "target.telegram" . | nindent 8 }} + {{- end }} + {{- end }} + + googleChat: + {{- include "target.webhook" .Values.target.googleChat | nindent 4 }} + {{- if and .Values.target.webhook .Values.target.googleChat.channels }} + channels: + {{- range .Values.target.googleChat.channels }} + - + {{- include "target.webhook" . | nindent 8 }} + {{- end }} + {{- end }} + + s3: + {{- include "target.s3" .Values.target.s3 | nindent 4 }} + {{- if and .Values.target.s3 .Values.target.s3.channels }} + channels: + {{- range .Values.target.s3.channels }} + - + {{- include "target.s3" . | nindent 8 }} + {{- end }} + {{- end }} + + kinesis: + {{- include "target.kinesis" .Values.target.kinesis | nindent 4 }} + {{- if and .Values.target.kinesis .Values.target.kinesis.channels }} + channels: + {{- range .Values.target.kinesis.channels }} + - + {{- include "target.kinesis" . | nindent 8 }} + {{- end }} + {{- end }} + + securityHub: + {{- include "target.securityhub" .Values.target.securityHub | nindent 4 }} + {{- if and .Values.target.securityHub .Values.target.securityHub.channels }} + channels: + {{- range .Values.target.securityHub.channels }} + - + {{- include "target.securityhub" . | nindent 8 }} + {{- end }} + {{- end }} + + gcs: + {{- include "target.gcs" .Values.target.gcs | nindent 4 }} + {{- if and .Values.target.gcs .Values.target.gcs.channels }} + channels: + {{- range .Values.target.gcs.channels }} + - + {{- include "target.gcs" . | nindent 8 }} + {{- end }} + {{- end }} + +worker: {{ .Values.worker }} + +{{- with .Values.metrics }} +metrics: + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- with .Values.reportFilter }} +reportFilter: + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- with .Values.sourceFilters }} +sourceFilters: + {{- toYaml . | nindent 2 }} +{{- end }} + +leaderElection: + enabled: {{ gt (int .Values.replicaCount) 1 }} + releaseOnCancel: {{ .Values.leaderElection.releaseOnCancel }} + leaseDuration: {{ .Values.leaderElection.leaseDuration }} + renewDeadline: {{ .Values.leaderElection.renewDeadline }} + retryPeriod: {{ .Values.leaderElection.retryPeriod }} + +{{- with .Values.redis }} +redis: + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- with .Values.sourceConfig }} +sourceConfig: + {{- toYaml . | nindent 2 }} +{{- end }} + +logging: + server: {{ .Values.logging.server }} + encoding: {{ .Values.logging.encoding }} + logLevel: {{ include "policyreporter.logLevel" . }} + +api: + basicAuth: + username: {{ .Values.basicAuth.username }} + password: {{ .Values.basicAuth.password }} + secretRef: {{ .Values.basicAuth.secretRef }} + +database: + type: {{ .Values.database.type }} + database: {{ .Values.database.database }} + username: {{ .Values.database.username }} + password: {{ .Values.database.password }} + host: {{ .Values.database.host }} + enableSSL: {{ .Values.database.enableSSL }} + dsn: {{ .Values.database.dsn }} + secretRef: {{ .Values.database.secretRef }} + mountedSecret: {{ .Values.database.mountedSecret }} diff --git a/charts/policy-reporter/config-email-reports.yaml b/charts/policy-reporter/configs/email-reports.tmpl similarity index 100% rename from charts/policy-reporter/config-email-reports.yaml rename to charts/policy-reporter/configs/email-reports.tmpl diff --git a/charts/policy-reporter/configs/kyverno-plugin.tmpl b/charts/policy-reporter/configs/kyverno-plugin.tmpl new file mode 100644 index 00000000..491a7925 --- /dev/null +++ b/charts/policy-reporter/configs/kyverno-plugin.tmpl @@ -0,0 +1,27 @@ +leaderElection: + enabled: {{ gt (int .Values.plugin.kyverno.replicaCount) 1 }} + releaseOnCancel: {{ .Values.plugin.kyverno.leaderElection.releaseOnCancel }} + leaseDuration: {{ .Values.plugin.kyverno.leaderElection.leaseDuration }} + renewDeadline: {{ .Values.plugin.kyverno.leaderElection.renewDeadline }} + retryPeriod: {{ .Values.plugin.kyverno.leaderElection.retryPeriod }} + lockName: {{ .Values.plugin.kyverno.leaderElection.lockName }} + +logging: + api: {{ .Values.plugin.kyverno.logging.api }} + server: {{ .Values.plugin.kyverno.logging.server }} + encoding: {{ .Values.plugin.kyverno.logging.encoding }} + logLevel: {{ .Values.plugin.kyverno.logging.logLevel }} + +server: + basicAuth: + username: {{ .Values.basicAuth.username }} + password: {{ .Values.basicAuth.password }} + secretRef: {{ .Values.basicAuth.secretRef }} + +core: + host: {{ printf "http://%s:%d" (include "policyreporter.fullname" .) (.Values.service.port | int) }} + +{{- with .Values.plugin.kyverno.blockReports }} +blockReports: + {{- toYaml . | nindent 4 }} +{{- end }} diff --git a/charts/policy-reporter/configs/trivy-plugin.tmpl b/charts/policy-reporter/configs/trivy-plugin.tmpl new file mode 100644 index 00000000..5ba89d39 --- /dev/null +++ b/charts/policy-reporter/configs/trivy-plugin.tmpl @@ -0,0 +1,20 @@ +logging: + api: {{ .Values.plugin.trivy.logging.api }} + server: {{ .Values.plugin.trivy.logging.server }} + encoding: {{ .Values.plugin.trivy.logging.encoding }} + logLevel: {{ .Values.plugin.trivy.logging.logLevel }} + +server: + basicAuth: + username: {{ .Values.basicAuth.username }} + password: {{ .Values.basicAuth.password }} + secretRef: {{ .Values.basicAuth.secretRef }} + +core: + host: {{ printf "http://%s:%d" (include "policyreporter.fullname" .) (.Values.service.port | int) }} + skipTLS: {{ .Values.plugin.trivy.policyReporter.skipTLS }} + certificate: {{ .Values.plugin.trivy.policyReporter.certificate }} + secretRef: {{ .Values.plugin.trivy.policyReporter.secretRef }} + basicAuth: + username: {{ .Values.basicAuth.username }} + password: {{ .Values.basicAuth.password }} diff --git a/charts/policy-reporter/configs/ui.tmpl b/charts/policy-reporter/configs/ui.tmpl new file mode 100644 index 00000000..8f5f3ef6 --- /dev/null +++ b/charts/policy-reporter/configs/ui.tmpl @@ -0,0 +1,70 @@ +namespace: {{ .Release.Namespace }} + +tempDir: {{ .Values.ui.tempDir }} + +logging: + api: {{ .Values.ui.logging.api }} + server: {{ .Values.ui.logging.server }} + encoding: {{ .Values.ui.logging.encoding }} + logLevel: {{ .Values.ui.logging.logLevel }} + +server: + port: {{ .Values.ui.server.port }} + cors: {{ .Values.ui.server.cors }} + overwriteHost: {{ .Values.ui.server.overwriteHost }} + +ui: + displayMode: {{ .Values.ui.displayMode }} + banner: {{ .Values.ui.banner }} + +{{- $default := false -}} +{{- range .Values.ui.clusters }} + {{- if eq .name .Values.ui.name -}} + {{- $default = true -}} + {{- end -}} +{{- end }} + +clusters: +{{- if not $default }} + - name: {{ .Values.ui.name }} + secretRef: {{ include "ui.fullname" . }}-default-cluster +{{- end }} +{{- with .Values.ui.clusters }} + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- with .Values.ui.customBoards }} +customBoards: + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- $kyverno := false -}} +{{- range .Values.ui.sources }} + {{- if eq .name "kyverno" -}} + {{- $kyverno = true -}} + {{- end -}} +{{- end }} + +sources: +{{- if not $kyverno }} + - name: kyverno + chartType: result + exceptions: false + excludes: + results: + - warn + - error +{{- end }} +{{- with .Values.ui.sources }} + {{- toYaml . | nindent 2 }} +{{- end }} + +{{- with .Values.ui.openIDConnect }} +openIDConnect: + {{- toYaml . | nindent 4 }} +{{- end }} + +{{- with .Values.ui.oauth }} +oauth: + {{- toYaml . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/_helpers.tpl b/charts/policy-reporter/templates/_helpers.tpl index 644d1935..ea498ee5 100644 --- a/charts/policy-reporter/templates/_helpers.tpl +++ b/charts/policy-reporter/templates/_helpers.tpl @@ -9,8 +9,8 @@ If release name contains chart name it will be used as a full name. */}} {{- define "policyreporter.fullname" -}} {{- $name := default .Chart.Name .Values.nameOverride }} -{{- if .Values.global.fullnameOverride }} -{{- .Values.global.fullnameOverride }} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride }} {{- else if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} @@ -78,8 +78,6 @@ Create UI target host based on configuration {{- .Values.target.ui.host }} {{- else if not .Values.ui.enabled }} {{- "" }} -{{- else if and .Values.ui.enabled (and .Values.ui.views.logs .Values.ui.service.enabled) }} -{{- printf "http://%s:%s" (include "ui.fullname" .) (.Values.ui.service.port | toString) }} {{- else }} {{- "" }} {{- end }} @@ -95,7 +93,7 @@ Create UI target host based on configuration {{- define "policyreporter.podDisruptionBudget" -}} {{- if and .Values.podDisruptionBudget.minAvailable .Values.podDisruptionBudget.maxUnavailable }} -{{- fail "Cannot set both .Values.podDisruptionBudget.minAvailable and .Values.podDisruptionBudget.maxUnavailable" -}} +{{- fail "Cannot set both minAvailable and maxUnavailable" -}} {{- end }} {{- if not .Values.podDisruptionBudget.maxUnavailable }} minAvailable: {{ default 1 .Values.podDisruptionBudget.minAvailable }} @@ -107,8 +105,8 @@ maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} {{/* Get the namespace name. */}} {{- define "policyreporter.namespace" -}} -{{- if .Values.global.namespace -}} - {{- .Values.global.namespace -}} +{{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} {{- else -}} {{- .Release.Namespace -}} {{- end -}} @@ -116,9 +114,137 @@ maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} {{/* Get the namespace name. */}} {{- define "policyreporter.logLevel" -}} -{{- if .Values.api.logging -}} +{{- if .Values.logging.server -}} -1 {{- else -}} {{- .Values.logging.logLevel -}} {{- end -}} {{- end -}} + +{{- define "target" -}} +name: {{ .name | quote }} +secretRef: {{ .secretRef | quote }} +mountedSecret: {{ .mountedSecret | quote }} +minimumSeverity: {{ .minimumSeverity | quote }} +skipExistingOnStartup: {{ .skipExistingOnStartup }} +{{- with .customFields }} +customFields: +{{- toYaml . | nindent 2 }} +{{- end }} +{{- with .sources }} +sources: +{{- toYaml . | nindent 2 }} +{{- end }} +{{- with .filter }} +filter: +{{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} + +{{- define "target.loki" -}} +config: + host: {{ .host | quote }} + certificate: {{ .certificate | quote }} + skipTLS: {{ .skipTLS }} + path: {{ .path | quote }} +{{ include "target" . }} +{{- end }} + +{{- define "target.elasticsearch" -}} +config: + host: {{ .host | quote }} + certificate: {{ .certificate | quote }} + skipTLS: {{ .skipTLS }} + username: {{ .username | quote }} + password: {{ .password | quote }} + apiKey: {{ .apiKey | quote }} + index: {{ .index| quote }} + rotation: {{ .rotation | quote }} +{{ include "target" . }} +{{- end }} + +{{- define "target.slack" -}} +config: + webhook: {{ .webhook | quote }} + channel: {{ .channel | quote }} + certificate: {{ .certificate | quote }} + skipTLS: {{ .skipTLS }} + {{- with .headers }} + headers: + {{- toYaml . | nindent 4 }} + {{- end }} +{{ include "target" . }} +{{- end }} + +{{- define "target.webhook" -}} +config: + webhook: {{ .webhook | quote }} + certificate: {{ .certificate | quote }} + skipTLS: {{ .skipTLS }} + {{- with .headers }} + headers: + {{- toYaml . | nindent 4 }} + {{- end }} +{{ include "target" . }} +{{- end }} + +{{- define "target.telegram" -}} +config: + chatId: {{ .chatId | quote }} + token: {{ .token | quote }} + webhook: {{ .webhook | quote }} + certificate: {{ .certificate | quote }} + skipTLS: {{ .skipTLS }} + {{- with .headers }} + headers: + {{- toYaml . | nindent 4 }} + {{- end }} +{{ include "target" . }} +{{- end }} + +{{- define "target.s3" -}} +config: + accessKeyId: {{ .accessKeyId }} + secretAccessKey: {{ .secretAccessKey }} + region: {{ .region }} + endpoint: {{ .endpoint }} + bucket: {{ .bucket }} + bucketKeyEnabled: {{ .bucketKeyEnabled }} + kmsKeyId: {{ .kmsKeyId }} + serverSideEncryption: {{ .serverSideEncryption }} + pathStyle: {{ .pathStyle }} + prefix: {{ .prefix }} +{{ include "target" . }} +{{- end }} + +{{- define "target.kinesis" -}} +config: + accessKeyId: {{ .accessKeyId }} + secretAccessKey: {{ .secretAccessKey }} + region: {{ .region }} + endpoint: {{ .endpoint }} + streamName: {{ .streamName }} +{{ include "target" . }} +{{- end }} + +{{- define "target.securityhub" -}} +config: + accessKeyId: {{ .accessKeyId }} + secretAccessKey: {{ .secretAccessKey }} + region: {{ .region }} + endpoint: {{ .endpoint }} + accountId: {{ .accountId }} + productName: {{ .productName }} + companyName: {{ .companyName }} + delayInSeconds: {{ .delayInSeconds }} + synchronize: {{ .synchronize }} +{{ include "target" . }} +{{- end }} + +{{- define "target.gcs" -}} +config: + credentials: {{ .credentials }} + bucket: {{ .bucket }} + prefix: {{ .prefix }} +{{ include "target" . }} +{{- end }} diff --git a/charts/policy-reporter/templates/cluster-secret.yaml b/charts/policy-reporter/templates/cluster-secret.yaml new file mode 100644 index 00000000..7ca7c347 --- /dev/null +++ b/charts/policy-reporter/templates/cluster-secret.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ui.fullname" . }}-default-cluster + namespace: {{ include "policyreporter.namespace" . }} + {{- if .Values.annotations }} + annotations: + {{- toYaml .Values.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "policyreporter.labels" . | nindent 4 }} +type: Opaque +data: + {{- $username := .Values.basicAuth.username }} + {{- $password := .Values.basicAuth.password }} + host: {{ printf "http://%s:%d" (include "policyreporter.fullname" .) (.Values.service.port | int) | b64enc }} + {{- if .Values.plugin.kyverno.enabled }} + {{- $host := printf "http://%s:%d" (include "kyverno-plugin.fullname" .) (.Values.plugin.kyverno.service.port | int) }} + plugin.kyverno: {{ (printf "{\"host\":\"%s\", \"name\":\"kyverno\", \"username\":\"%s\", \"password\":\"%s\"}" $host $username $password) | b64enc }} + {{- end }} + {{- if .Values.plugin.trivy.enabled }} + {{- $host := printf "http://%s:%d/vulnr" (include "trivy-plugin.fullname" .) (.Values.plugin.trivy.service.port | int) }} + plugin.trivy: {{ (printf "{\"host\":\"%s\", \"name\":\"Trivy Vulnerability\", \"username\":\"%s\", \"password\":\"%s\"}" $host $username $password) | b64enc }} + username: {{ $username | b64enc }} + password: {{ $password | b64enc }} + {{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/clusterrole.yaml b/charts/policy-reporter/templates/clusterrole.yaml index d0505c41..41c5f56d 100644 --- a/charts/policy-reporter/templates/clusterrole.yaml +++ b/charts/policy-reporter/templates/clusterrole.yaml @@ -22,4 +22,22 @@ rules: - get - list - watch +- apiGroups: + - '' + resources: + - namespaces + verbs: + - list +- apiGroups: + - '' + resources: + - pods + verbs: + - get +- apiGroups: + - 'batch' + resources: + - jobs + verbs: + - get {{- end -}} diff --git a/charts/policy-reporter/templates/config-email-reports-secret.yaml b/charts/policy-reporter/templates/config-email-reports-secret.yaml index e08555d4..9fd7947f 100644 --- a/charts/policy-reporter/templates/config-email-reports-secret.yaml +++ b/charts/policy-reporter/templates/config-email-reports-secret.yaml @@ -12,5 +12,5 @@ metadata: {{- include "policyreporter.labels" . | nindent 4 }} type: Opaque data: - config.yaml: {{ tpl (.Files.Get "config-email-reports.yaml") . | b64enc }} + config.yaml: {{ tpl (.Files.Get "configs/email-reports.tmpl") . | b64enc }} {{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/config-secret.yaml b/charts/policy-reporter/templates/config-secret.yaml index 88c7b614..37a97929 100644 --- a/charts/policy-reporter/templates/config-secret.yaml +++ b/charts/policy-reporter/templates/config-secret.yaml @@ -12,5 +12,5 @@ metadata: {{- include "policyreporter.labels" . | nindent 4 }} type: Opaque data: - config.yaml: {{ tpl (.Files.Get "config.yaml") . | b64enc }} -{{- end }} \ No newline at end of file + config.yaml: {{ tpl (.Files.Get "configs/core.tmpl") . | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/cronjob-summary-report.yaml b/charts/policy-reporter/templates/cronjob-summary-report.yaml index 93d67f9c..cfec66e6 100644 --- a/charts/policy-reporter/templates/cronjob-summary-report.yaml +++ b/charts/policy-reporter/templates/cronjob-summary-report.yaml @@ -51,7 +51,7 @@ spec: {{- end }} restartPolicy: {{ .Values.emailReports.summary.restartPolicy }} containers: - - name: {{ default .Chart.Name .Values.nameOverride }} + - name: policy-reporter image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- if .Values.securityContext }} diff --git a/charts/policy-reporter/templates/cronjob-violations-report.yaml b/charts/policy-reporter/templates/cronjob-violations-report.yaml index 9288365d..656d0c85 100644 --- a/charts/policy-reporter/templates/cronjob-violations-report.yaml +++ b/charts/policy-reporter/templates/cronjob-violations-report.yaml @@ -51,7 +51,7 @@ spec: {{- end }} restartPolicy: {{ .Values.emailReports.violations.restartPolicy }} containers: - - name: {{ default .Chart.Name .Values.nameOverride }} + - name: policy-reporter image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- if .Values.securityContext }} diff --git a/charts/policy-reporter/templates/deployment.yaml b/charts/policy-reporter/templates/deployment.yaml index 4dd740ab..6351d865 100644 --- a/charts/policy-reporter/templates/deployment.yaml +++ b/charts/policy-reporter/templates/deployment.yaml @@ -12,9 +12,9 @@ metadata: spec: replicas: {{ .Values.replicaCount }} revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - {{- if .Values.deploymentStrategy }} + {{- with .Values.plugin.kyverno.updateStrategy }} strategy: - {{- toYaml .Values.deploymentStrategy | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} selector: matchLabels: @@ -53,11 +53,11 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} {{- end }} containers: - - name: {{ default .Chart.Name .Values.nameOverride }} + - name: policy-reporter image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- if .Values.securityContext }} - securityContext: {{ include "policyreporter.securityContext" . | nindent 12 }} + securityContext: {{- include "policyreporter.securityContext" . | nindent 12 }} {{- end }} args: - --port={{ .Values.port.number }} @@ -99,7 +99,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - {{- if or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1) }} + {{- if gt (int .Values.replicaCount) 1 }} - name: POD_NAME valueFrom: fieldRef: diff --git a/charts/policy-reporter/templates/monitoring/_helpers.tpl b/charts/policy-reporter/templates/monitoring/_helpers.tpl new file mode 100644 index 00000000..3f4c63b6 --- /dev/null +++ b/charts/policy-reporter/templates/monitoring/_helpers.tpl @@ -0,0 +1,56 @@ +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "monitoring.fullname" -}} +{{ template "policyreporter.fullname" . }}-monitoring +{{- end }} + +{{- define "monitoring.name" -}} +{{ template "policyreporter.name" . }}-monitoring +{{- end }} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "monitoring.chart" -}} +{{ template "policyreporter.chart" . }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "monitoring.labels" -}} +helm.sh/chart: {{ include "monitoring.chart" . }} +{{ include "monitoring.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/component: monitoring +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/part-of: kyverno +{{- with .Values.global.labels }} +{{ toYaml . }} +{{- end -}} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "monitoring.selectorLabels" -}} +app.kubernetes.io/name: {{ include "monitoring.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* Get the namespace name. */}} +{{- define "monitoring.smNamespace" -}} +{{- if .Values.monitoring.serviceMonitor.namespace -}} +{{- .Values.monitoring.serviceMonitor.namespace -}} +{{- else if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} +{{- else -}} +{{- .Release.Namespace -}} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/monitoring/auth-secret.yaml b/charts/policy-reporter/templates/monitoring/auth-secret.yaml new file mode 100644 index 00000000..c9b72db1 --- /dev/null +++ b/charts/policy-reporter/templates/monitoring/auth-secret.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.monitoring.enabled }} +{{- if and .Values.basicAuth.username .Values.basicAuth.password }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "monitoring.fullname" . }}-auth + namespace: {{ include "monitoring.smNamespace" . }} + {{- if .Values.monitoring.annotations }} + annotations: + {{- toYaml .Values.monitoring.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "monitoring.labels" . | nindent 4 }} +type: Opaque +data: + username: {{ .Values.basicAuth.username | b64enc }} + password: {{ .Values.basicAuth.password | b64enc }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.dashboard.yaml b/charts/policy-reporter/templates/monitoring/clusterpolicy-details.dashboard.yaml similarity index 82% rename from charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.dashboard.yaml rename to charts/policy-reporter/templates/monitoring/clusterpolicy-details.dashboard.yaml index 8003a1c9..626de0e4 100644 --- a/charts/policy-reporter/charts/monitoring/templates/clusterpolicy-details.dashboard.yaml +++ b/charts/policy-reporter/templates/monitoring/clusterpolicy-details.dashboard.yaml @@ -1,11 +1,13 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.clusterPolicyReportDetails }} -{{- $filters := .Values.grafana.dashboards.labelFilter }} -{{- if and .Values.grafana.dashboards.multicluster.enabled .Values.grafana.dashboards.multicluster.label }} -{{- $filters = append $filters .Values.grafana.dashboards.multicluster.label }} +{{ $root := .Values.monitoring }} + +{{- if and $root.grafana.dashboards.enabled $root.grafana.dashboards.enable.clusterPolicyReportDetails }} +{{- $filters := $root.grafana.dashboards.labelFilter }} +{{- if and $root.grafana.dashboards.multicluster.enabled $root.grafana.dashboards.multicluster.label }} +{{- $filters = append $filters $root.grafana.dashboards.multicluster.label }} {{- end }} {{- $nsLabel := "exported_namespace" }} -{{- if .Values.serviceMonitor.honorLabels }} +{{- if $root.serviceMonitor.honorLabels }} {{- $nsLabel = "namespace" }} {{- end }} @@ -13,14 +15,14 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ include "monitoring.fullname" . }}-clusterpolicy-details-dashboard - namespace: {{ include "monitoring.namespace" . }} + namespace: {{ include "policyreporter.namespace" . }} annotations: - {{ .Values.grafana.folder.annotation }}: {{ .Values.grafana.folder.name }} + {{ $root.grafana.folder.annotation }}: {{ $root.grafana.folder.name }} {{- with .Values.annotations }} {{- toYaml . | nindent 4 }} {{- end }} labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} + {{ $root.grafana.dashboards.label }}: {{ $root.grafana.dashboards.value | quote }} {{- include "monitoring.labels" . | nindent 4 }} data: cluster-policy-reporter-details-dashboard.json: | @@ -28,11 +30,11 @@ data: "__inputs": [ { "name": "DS_PROMETHEUS", - "label": "{{ .Values.grafana.datasource.label }}", + "label": "{{ $root.grafana.datasource.label }}", "description": "", "type": "datasource", - "pluginId": "{{ .Values.grafana.datasource.pluginId }}", - "pluginName": "{{ .Values.grafana.datasource.pluginName }}" + "pluginId": "{{ $root.grafana.datasource.pluginId }}", + "pluginName": "{{ $root.grafana.datasource.pluginName }}" } ], "__requires": [ @@ -101,7 +103,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.statusRow.height }}, + "h": {{ $root.clusterPolicyReportDetails.statusRow.height }}, "w": 6, "x": 0, "y": 0 @@ -124,7 +126,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} })", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod))", "instant": true, "interval": "", "legendFormat": "", @@ -158,7 +160,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.statusRow.height }}, + "h": {{ $root.clusterPolicyReportDetails.statusRow.height }}, "w": 6, "x": 6, "y": 0 @@ -181,7 +183,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} })", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod))", "instant": true, "interval": "", "legendFormat": "", @@ -215,7 +217,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.statusRow.height }}, + "h": {{ $root.clusterPolicyReportDetails.statusRow.height }}, "w": 6, "x": 12, "y": 0 @@ -238,7 +240,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} })", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod))", "instant": true, "interval": "", "legendFormat": "", @@ -272,7 +274,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.statusRow.height }}, + "h": {{ $root.clusterPolicyReportDetails.statusRow.height }}, "w": 6, "x": 18, "y": 0 @@ -295,7 +297,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} })", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod))", "instant": true, "interval": "", "legendFormat": "", @@ -307,7 +309,7 @@ data: "title": "Policy Error Status", "type": "stat" } -{{- if .Values.clusterPolicyReportDetails.statusTimeline.enabled }} +{{- if $root.clusterPolicyReportDetails.statusTimeline.enabled }} ,{ "datasource": { "uid": "${DS_PROMETHEUS}", @@ -412,7 +414,7 @@ data: ] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.statusTimeline.height }}, + "h": {{ $root.clusterPolicyReportDetails.statusTimeline.height }}, "w": 24, "x": 0, "y": 6 @@ -421,7 +423,7 @@ data: "pluginVersion": "10.4.1", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status)", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status, pod)) by (status)", "interval": "", "legendFormat": "{{`{{ status }}`}}", "refId": "A", @@ -451,7 +453,7 @@ data: "timeShift": null } {{- end }} -{{- if .Values.clusterPolicyReportDetails.passTable.enabled }} +{{- if $root.clusterPolicyReportDetails.passTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -477,7 +479,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.passTable.height }}, + "h": {{ $root.clusterPolicyReportDetails.passTable.height }}, "w": 24, "x": 0, "y": 15 @@ -489,7 +491,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", kind=~\"$kind\", source=~\"$source\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", kind=~\"$kind\", source=~\"$source\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod,policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -506,7 +508,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -530,7 +531,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.clusterPolicyReportDetails.failTable.enabled }} +{{- if $root.clusterPolicyReportDetails.failTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -556,7 +557,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.failTable.height }}, + "h": {{ $root.clusterPolicyReportDetails.failTable.height }}, "w": 24, "x": 0, "y": 23 @@ -568,7 +569,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod, policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -585,7 +586,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -609,7 +609,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.clusterPolicyReportDetails.warningTable.enabled }} +{{- if $root.clusterPolicyReportDetails.warningTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -632,7 +632,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.warningTable.height }}, + "h": {{ $root.clusterPolicyReportDetails.warningTable.height }}, "w": 24, "x": 0, "y": 31 @@ -644,7 +644,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }} )", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod,policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -661,7 +661,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -685,7 +684,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.clusterPolicyReportDetails.errorTable.enabled }} +{{- if $root.clusterPolicyReportDetails.errorTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -708,7 +707,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.clusterPolicyReportDetails.errorTable.height }}, + "h": {{ $root.clusterPolicyReportDetails.errorTable.height }}, "w": 24, "x": 0, "y": 36 @@ -720,7 +719,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod, policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})) by (policy,rule,kind,name,status,severity,category,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -737,7 +736,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { diff --git a/charts/policy-reporter/templates/monitoring/clusterpolicy-details.grafanadashboard.yaml b/charts/policy-reporter/templates/monitoring/clusterpolicy-details.grafanadashboard.yaml new file mode 100644 index 00000000..21f5e22b --- /dev/null +++ b/charts/policy-reporter/templates/monitoring/clusterpolicy-details.grafanadashboard.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.monitoring.grafana.dashboards.enabled .Values.monitoring.grafana.dashboards.enable.clusterPolicyReportDetails .Values.monitoring.grafana.grafanaDashboard.enabled }} +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + labels: + {{ .Values.monitoring.grafana.dashboards.label }}: {{ .Values.monitoring.grafana.dashboards.value | quote }} + {{- include "monitoring.labels" . | nindent 4 }} + name: {{ include "monitoring.fullname" . }}-clusterpolicy-details-dashboard + namespace: {{ include "policyreporter.namespace" . }} +spec: + allowCrossNamespaceImport: {{ .Values.monitoring.grafana.grafanaDashboard.allowCrossNamespaceImport }} + folder: {{ .Values.monitoring.grafana.grafanaDashboard.folder }} + instanceSelector: + matchLabels: + {{- toYaml .Values.monitoring.grafana.grafanaDashboard.matchLabels | nindent 6 }} + configMapRef: + name: {{ include "monitoring.fullname" . }}-clusterpolicy-details-dashboard + key: cluster-policy-reporter-details-dashboard.json +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/monitoring/templates/overview.dashboard.yaml b/charts/policy-reporter/templates/monitoring/overview.dashboard.yaml similarity index 84% rename from charts/policy-reporter/charts/monitoring/templates/overview.dashboard.yaml rename to charts/policy-reporter/templates/monitoring/overview.dashboard.yaml index 0a1a37f6..4fa1375b 100644 --- a/charts/policy-reporter/charts/monitoring/templates/overview.dashboard.yaml +++ b/charts/policy-reporter/templates/monitoring/overview.dashboard.yaml @@ -1,11 +1,13 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.overview }} -{{- $filters := .Values.grafana.dashboards.labelFilter }} -{{- if and .Values.grafana.dashboards.multicluster.enabled .Values.grafana.dashboards.multicluster.label }} -{{- $filters = append $filters .Values.grafana.dashboards.multicluster.label }} +{{ $root := .Values.monitoring }} + +{{- if and $root.grafana.dashboards.enabled $root.grafana.dashboards.enable.overview }} +{{- $filters := $root.grafana.dashboards.labelFilter }} +{{- if and $root.grafana.dashboards.multicluster.enabled $root.grafana.dashboards.multicluster.label }} +{{- $filters = append $filters $root.grafana.dashboards.multicluster.label }} {{- end }} {{- $nsLabel := "exported_namespace" }} -{{- if .Values.serviceMonitor.honorLabels }} +{{- if $root.serviceMonitor.honorLabels }} {{- $nsLabel = "namespace" }} {{- end }} @@ -13,15 +15,15 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ include "monitoring.fullname" . }}-overview-dashboard - namespace: {{ include "monitoring.namespace" . }} + namespace: {{ include "policyreporter.namespace" . }} annotations: - {{ .Values.grafana.folder.annotation }}: {{ .Values.grafana.folder.name }} + {{ $root.grafana.folder.annotation }}: {{ $root.grafana.folder.name }} {{- with .Values.annotations }} {{- toYaml . | nindent 4 }} {{- end }} labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} - {{- with .Values.serviceMonitor.labels }} + {{ $root.grafana.dashboards.label }}: {{ $root.grafana.dashboards.value | quote }} + {{- with $root.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} {{- include "monitoring.labels" . | nindent 4 }} @@ -31,11 +33,11 @@ data: "__inputs": [ { "name": "DS_PROMETHEUS", - "label": "{{ .Values.grafana.datasource.label }}", + "label": "{{ $root.grafana.datasource.label }}", "description": "", "type": "datasource", - "pluginId": "{{ .Values.grafana.datasource.pluginId }}", - "pluginName": "{{ .Values.grafana.datasource.pluginName }}" + "pluginId": "{{ $root.grafana.datasource.pluginId }}", + "pluginName": "{{ $root.grafana.datasource.pluginName }}" } ], "__requires": [ @@ -94,7 +96,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportOverview.failingSummaryRow.height }}, + "h": {{ $root.policyReportOverview.failingSummaryRow.height }}, "w": 15, "x": 0, "y": 0 @@ -115,7 +117,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }}, pod)) by ({{ $nsLabel }})", "instant": true, "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }}", @@ -153,7 +155,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportOverview.failingSummaryRow.height }}, + "h": {{ $root.policyReportOverview.failingSummaryRow.height }}, "w": 9, "x": 15, "y": 0 @@ -176,7 +178,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status)", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status, pod)) by (status)", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -292,7 +294,7 @@ data: ] }, "gridPos": { - "h": {{ .Values.policyReportOverview.failingTimeline.height }}, + "h": {{ $root.policyReportOverview.failingTimeline.height }}, "w": 24, "x": 0, "y": 8 @@ -301,7 +303,7 @@ data: "pluginVersion": "10.4.1", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (policy)", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (policy, pod)) by (policy)", "interval": "", "legendFormat": "{{`{{ policy }}`}}", "refId": "A", @@ -310,7 +312,7 @@ data: } }, { - "expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (policy)", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (policy, pod)) by (policy)", "interval": "", "legendFormat": "{{`{{ policy }}`}}", "refId": "B", @@ -363,7 +365,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportOverview.failingPolicyRuleTable.height }}, + "h": {{ $root.policyReportOverview.failingPolicyRuleTable.height }}, "w": 24, "x": 0, "y": 18 @@ -375,7 +377,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (pod,{{ $nsLabel }},policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})) by ({{ $nsLabel }},policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -391,8 +393,7 @@ data: "id": "organize", "options": { "excludeByName": { - "Time": true, - "Value": true + "Time": true }, "indexByName": { "source": 0, @@ -403,7 +404,8 @@ data: "name": 5, "policy": 6, "rule": 7, - "status": 8 + "status": 8, + "Value": 9 }, "renameByName": { "{{ $nsLabel }}": "namespace" @@ -438,7 +440,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportOverview.failingClusterPolicyRuleTable.height }}, + "h": {{ $root.policyReportOverview.failingClusterPolicyRuleTable.height }}, "w": 24, "x": 0, "y": 28 @@ -450,7 +452,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by (policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(cluster_policy_report_result{policy=~\"$policy\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", status=~\"fail|error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} })by (pod,policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})) by (policy,rule,kind,name,status,category,severity,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -467,7 +469,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "__name__": true, "endpoint": true, "instance": true, @@ -486,7 +487,8 @@ data: "name": 4, "policy": 5, "rule": 6, - "status": 7 + "status": 7, + "Value": 8 }, "renameByName": {} } diff --git a/charts/policy-reporter/templates/monitoring/overview.grafanadashboard.yaml b/charts/policy-reporter/templates/monitoring/overview.grafanadashboard.yaml new file mode 100644 index 00000000..462d6a22 --- /dev/null +++ b/charts/policy-reporter/templates/monitoring/overview.grafanadashboard.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.monitoring.grafana.dashboards.enabled .Values.monitoring.grafana.dashboards.enable.overview .Values.monitoring.grafana.grafanaDashboard.enabled }} +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + labels: + {{ .Values.monitoring.grafana.dashboards.label }}: {{ .Values.monitoring.grafana.dashboards.value | quote }} + {{- include "monitoring.labels" . | nindent 4 }} + name: {{ include "monitoring.fullname" . }}-overview-dashboard + namespace: {{ include "policyreporter.namespace" . }} +spec: + allowCrossNamespaceImport: {{ .Values.monitoring.grafana.grafanaDashboard.allowCrossNamespaceImport }} + folder: {{ .Values.monitoring.grafana.grafanaDashboard.folder }} + instanceSelector: + matchLabels: + {{- toYaml .Values.monitoring.grafana.grafanaDashboard.matchLabels | nindent 6 }} + configMapRef: + name: {{ include "monitoring.fullname" . }}-overview-dashboard + key: policy-reporter-dashboard.json +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/monitoring/templates/policy-details.dashboard.yaml b/charts/policy-reporter/templates/monitoring/policy-details.dashboard.yaml similarity index 81% rename from charts/policy-reporter/charts/monitoring/templates/policy-details.dashboard.yaml rename to charts/policy-reporter/templates/monitoring/policy-details.dashboard.yaml index 6cac5901..024a2238 100644 --- a/charts/policy-reporter/charts/monitoring/templates/policy-details.dashboard.yaml +++ b/charts/policy-reporter/templates/monitoring/policy-details.dashboard.yaml @@ -1,11 +1,13 @@ -{{- if and $.Values.grafana.dashboards.enabled $.Values.grafana.dashboards.enable.policyReportDetails }} -{{- $filters := .Values.grafana.dashboards.labelFilter }} -{{- if and .Values.grafana.dashboards.multicluster.enabled .Values.grafana.dashboards.multicluster.label }} -{{- $filters = append $filters .Values.grafana.dashboards.multicluster.label }} +{{ $root := .Values.monitoring }} + +{{- if and $root.grafana.dashboards.enabled $root.grafana.dashboards.enable.policyReportDetails }} +{{- $filters := $root.grafana.dashboards.labelFilter }} +{{- if and $root.grafana.dashboards.multicluster.enabled $root.grafana.dashboards.multicluster.label }} +{{- $filters = append $filters $root.grafana.dashboards.multicluster.label }} {{- end }} {{- $nsLabel := "exported_namespace" }} -{{- if .Values.serviceMonitor.honorLabels }} +{{- if $root.serviceMonitor.honorLabels }} {{- $nsLabel = "namespace" }} {{- end }} @@ -13,15 +15,15 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ include "monitoring.fullname" . }}-policy-details-dashboard - namespace: {{ include "monitoring.namespace" . }} + namespace: {{ include "policyreporter.namespace" . }} annotations: - {{ .Values.grafana.folder.annotation }}: {{ .Values.grafana.folder.name }} + {{ $root.grafana.folder.annotation }}: {{ $root.grafana.folder.name }} {{- with .Values.annotations }} {{- toYaml . | nindent 4 }} {{- end }} labels: - {{ .Values.grafana.dashboards.label }}: {{ .Values.grafana.dashboards.value | quote }} - {{- with .Values.serviceMonitor.labels }} + {{ $root.grafana.dashboards.label }}: {{ $root.grafana.dashboards.value | quote }} + {{- with $root.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} {{- include "monitoring.labels" . | nindent 4 }} @@ -31,11 +33,11 @@ data: "__inputs": [ { "name": "DS_PROMETHEUS", - "label": "{{ .Values.grafana.datasource.label }}", + "label": "{{ $root.grafana.datasource.label }}", "description": "", "type": "datasource", - "pluginId": "{{ .Values.grafana.datasource.pluginId }}", - "pluginName": "{{ .Values.grafana.datasource.pluginName }}" + "pluginId": "{{ $root.grafana.datasource.pluginId }}", + "pluginName": "{{ $root.grafana.datasource.pluginName }}" } ], "__requires": [ @@ -104,7 +106,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.firstStatusRow.height }}, + "h": {{ $root.policyReportDetails.firstStatusRow.height }}, "w": 12, "x": 0, "y": 0 @@ -125,7 +127,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }}, pod)) by ({{ $nsLabel }})", "instant": true, "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }}", @@ -159,7 +161,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.firstStatusRow.height }}, + "h": {{ $root.policyReportDetails.firstStatusRow.height }}, "w": 12, "x": 12, "y": 0 @@ -180,7 +182,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }}, pod)) by ({{ $nsLabel }})", "instant": true, "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }}", @@ -192,7 +194,7 @@ data: "title": "Policy Fail Status", "type": "bargauge" } -{{- if .Values.policyReportDetails.secondStatusRow.enabled }} +{{- if $root.policyReportDetails.secondStatusRow.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -215,7 +217,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.secondStatusRow.height }}, + "h": {{ $root.policyReportDetails.secondStatusRow.height }}, "w": 12, "x": 0, "y": 7 @@ -236,7 +238,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }}, pod)) by ({{ $nsLabel }})", "instant": true, "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }}", @@ -270,7 +272,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.secondStatusRow.height }}, + "h": {{ $root.policyReportDetails.secondStatusRow.height }}, "w": 12, "x": 12, "y": 7 @@ -291,7 +293,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by ({{ $nsLabel }}, pod)) by ({{ $nsLabel }})", "instant": true, "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }}", @@ -304,7 +306,7 @@ data: "type": "bargauge" } {{- end }} -{{- if .Values.policyReportDetails.statusTimeline.enabled }} +{{- if $root.policyReportDetails.statusTimeline.enabled }} ,{ "datasource": { "uid": "${DS_PROMETHEUS}" @@ -408,7 +410,7 @@ data: ] }, "gridPos": { - "h": {{ .Values.policyReportDetails.statusTimeline.height }}, + "h": {{ $root.policyReportDetails.statusTimeline.height }}, "w": 24, "x": 0, "y": 10 @@ -417,7 +419,7 @@ data: "pluginVersion": "10.4.1", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status, {{ $nsLabel }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} } > 0) by (status, pod, {{ $nsLabel }})) by (status, {{ $nsLabel }})", "interval": "", "legendFormat": "{{ printf `{{%s}}` $nsLabel }} {{`{{ status }}`}}", "refId": "A", @@ -446,7 +448,7 @@ data: "timeShift": null } {{- end }} -{{- if .Values.policyReportDetails.passTable.enabled }} +{{- if $root.policyReportDetails.passTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -472,7 +474,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.passTable.height }}, + "h": {{ $root.policyReportDetails.passTable.height }}, "w": 24, "x": 0, "y": 19 @@ -484,7 +486,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }} )", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"pass\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -501,7 +503,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -526,7 +527,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.policyReportDetails.failTable.enabled }} +{{- if $root.policyReportDetails.failTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -552,7 +553,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.failTable.height }}, + "h": {{ $root.policyReportDetails.failTable.height }}, "w": 24, "x": 0, "y": 27 @@ -564,7 +565,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"fail\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -581,7 +582,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -606,7 +606,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.policyReportDetails.warningTable.enabled }} +{{- if $root.policyReportDetails.warningTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -629,7 +629,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.warningTable.height }}, + "h": {{ $root.policyReportDetails.warningTable.height }}, "w": 24, "x": 0, "y": 35 @@ -641,7 +641,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }} )", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"warn\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }} )", "format": "table", "instant": true, "interval": "", @@ -658,7 +658,6 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { @@ -683,7 +682,7 @@ data: "type": "table" } {{- end }} -{{- if .Values.policyReportDetails.errorTable.enabled }} +{{- if $root.policyReportDetails.errorTable.enabled }} ,{ "datasource": "${DS_PROMETHEUS}", "fieldConfig": { @@ -706,7 +705,7 @@ data: "overrides": [] }, "gridPos": { - "h": {{ .Values.policyReportDetails.errorTable.height }}, + "h": {{ $root.policyReportDetails.errorTable.height }}, "w": 24, "x": 0, "y": 40 @@ -718,7 +717,7 @@ data: "pluginVersion": "7.1.5", "targets": [ { - "expr": "sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }} )", + "expr": "max(sum(policy_report_result{policy=~\"$policy\", rule=~\"$rule\", category=~\"$category\", severity=~\"$severity\", source=~\"$source\", kind=~\"$kind\", {{ $nsLabel }}=~\"$namespace\", status=\"error\"{{ range $filters }}, {{.}}=~\"${{.}}\"{{ end }} }) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})) by ({{ $nsLabel }},category,policy,rule,kind,name,severity,status,source{{ range $filters }},{{.}}{{ end }})", "format": "table", "instant": true, "interval": "", @@ -735,12 +734,10 @@ data: "options": { "excludeByName": { "Time": true, - "Value": true, "status": false }, "indexByName": { "Time": 0, - "Value": 9, "category": 1, "{{ $nsLabel }}": 3, "kind": 4, @@ -748,7 +745,8 @@ data: "policy": 6, "rule": 7, "severity": 2, - "status": 8 + "status": 8, + "Value": 9 }, "renameByName": { "{{ $nsLabel }}": "namespace" diff --git a/charts/policy-reporter/templates/monitoring/policy-details.grafanadashboard.yaml b/charts/policy-reporter/templates/monitoring/policy-details.grafanadashboard.yaml new file mode 100644 index 00000000..ce8b66fe --- /dev/null +++ b/charts/policy-reporter/templates/monitoring/policy-details.grafanadashboard.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.monitoring.grafana.dashboards.enabled .Values.monitoring.grafana.dashboards.enable.policyReportDetails .Values.monitoring.grafana.grafanaDashboard.enabled }} +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + labels: + {{ .Values.monitoring.grafana.dashboards.label }}: {{ .Values.monitoring.grafana.dashboards.value | quote }} + {{- include "monitoring.labels" . | nindent 4 }} + name: {{ include "monitoring.fullname" . }}-policy-details-dashboard + namespace: {{ include "policyreporter.namespace" . }} +spec: + allowCrossNamespaceImport: {{ .Values.monitoring.grafana.grafanaDashboard.allowCrossNamespaceImport }} + folder: {{ .Values.monitoring.grafana.grafanaDashboard.folder }} + instanceSelector: + matchLabels: + {{- toYaml .Values.monitoring.grafana.grafanaDashboard.matchLabels | nindent 6 }} + configMapRef: + name: {{ include "monitoring.fullname" . }}-policy-details-dashboard + key: policy-reporter-details-dashboard.json +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/monitoring/templates/servicemonitor.yaml b/charts/policy-reporter/templates/monitoring/servicemonitor.yaml similarity index 50% rename from charts/policy-reporter/charts/monitoring/templates/servicemonitor.yaml rename to charts/policy-reporter/templates/monitoring/servicemonitor.yaml index 16a0f489..8f5e3fa8 100644 --- a/charts/policy-reporter/charts/monitoring/templates/servicemonitor.yaml +++ b/charts/policy-reporter/templates/monitoring/servicemonitor.yaml @@ -1,28 +1,29 @@ +{{- if and .Values.monitoring.enabled }} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: {{ include "monitoring.fullname" . }} namespace: {{ include "monitoring.smNamespace" . }} - {{- if .Values.annotations }} + {{- if .Values.monitoring.annotations }} annotations: - {{- toYaml .Values.annotations | nindent 4 }} + {{- toYaml .Values.monitoring.annotations | nindent 4 }} {{- end }} labels: {{- include "monitoring.labels" . | nindent 4 }} - {{- with .Values.serviceMonitor.labels }} + {{- with .Values.monitoring.serviceMonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} spec: selector: matchLabels: {{- include "policyreporter.selectorLabels" . | nindent 8 }} - {{- with .Values.serviceMonitor.namespaceSelector }} + {{- with .Values.monitoring.serviceMonitor.namespaceSelector }} namespaceSelector: {{- toYaml . | nindent 4 }} {{- end }} endpoints: - port: http - {{- if and .Values.global.basicAuth.username .Values.global.basicAuth.password }} + {{- if and .Values.basicAuth.username .Values.basicAuth.password }} basicAuth: password: name: {{ include "monitoring.fullname" . }}-auth @@ -30,32 +31,28 @@ spec: username: name: {{ include "monitoring.fullname" . }}-auth key: username - {{- else if .Values.global.basicAuth.secretRef }} + {{- else if .Values.basicAuth.secretRef }} basicAuth: password: - name: {{ .Values.global.basicAuth.secretRef }} + name: {{ .Values.basicAuth.secretRef }} key: password username: - name: {{ .Values.global.basicAuth.secretRef }} + name: {{ .Values.basicAuth.secretRef }} key: username {{- end }} - honorLabels: {{ .Values.serviceMonitor.honorLabels }} - {{- if .Values.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + honorLabels: {{ .Values.monitoring.serviceMonitor.honorLabels }} + {{- if .Values.monitoring.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.monitoring.serviceMonitor.scrapeTimeout }} {{- end }} - {{- if .Values.serviceMonitor.interval }} - interval: {{ .Values.serviceMonitor.interval }} + {{- if .Values.monitoring.serviceMonitor.interval }} + interval: {{ .Values.monitoring.serviceMonitor.interval }} {{- end }} + {{- with .Values.monitoring.serviceMonitor.relabelings }} relabelings: - - action: labeldrop - regex: pod|service|container - - targetLabel: instance - replacement: policy-reporter - action: replace - {{- with .Values.serviceMonitor.relabelings }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.serviceMonitor.metricRelabelings }} + {{- with .Values.monitoring.serviceMonitor.metricRelabelings }} metricRelabelings: {{- toYaml . | nindent 4 }} {{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/networkpolicy.yaml b/charts/policy-reporter/templates/networkpolicy.yaml index ac09030a..b1ffdad6 100644 --- a/charts/policy-reporter/templates/networkpolicy.yaml +++ b/charts/policy-reporter/templates/networkpolicy.yaml @@ -22,21 +22,21 @@ spec: matchLabels: {{- include "ui.selectorLabels" . | nindent 10 }} ports: - protocol: TCP - port: 8080 + port: {{ .Values.ui.service.port }} + {{- end }} + {{- if .Values.plugin.trivy.enabled }} + - from: + - podSelector: + matchLabels: {{- include "trivy-plugin.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.plugin.trivy.service.port }} {{- end }} {{- with .Values.networkPolicy.ingress }} {{- toYaml . | nindent 2 }} {{- end }} - egress: - {{- if .Values.ui.enabled }} - - to: - - podSelector: - matchLabels: {{- include "ui.selectorLabels" . | nindent 10 }} - ports: - - protocol: TCP - port: {{ .Values.ui.service.port }} - {{- end }} {{- with .Values.networkPolicy.egress }} + egress: {{- toYaml . | nindent 2 }} {{- end }} {{- end }} diff --git a/charts/policy-reporter/templates/plugins/kyverno/_helpers.tpl b/charts/policy-reporter/templates/plugins/kyverno/_helpers.tpl new file mode 100644 index 00000000..d462c0fd --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "kyverno-plugin.name" -}} +{{ template "policyreporter.name" . }}-kyverno-plugin +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "kyverno-plugin.fullname" -}} +{{ template "policyreporter.fullname" . }}-kyverno-plugin +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kyverno-plugin.chart" -}} +{{ template "policyreporter.chart" . }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "kyverno-plugin.labels" -}} +helm.sh/chart: {{ include "kyverno-plugin.chart" . }} +{{ include "kyverno-plugin.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.labels }} +{{ toYaml . }} +{{- end -}} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kyverno-plugin.selectorLabels" -}} +app.kubernetes.io/name: {{ include "kyverno-plugin.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kyverno-plugin.serviceAccountName" -}} +{{- if .Values.plugin.kyverno.serviceAccount.create }} +{{- default (include "kyverno-plugin.fullname" .) .Values.plugin.kyverno.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.plugin.kyverno.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "kyverno-plugin.podDisruptionBudget" -}} +{{- if and .Values.plugin.kyverno.podDisruptionBudget.minAvailable .Values.plugin.kyverno.podDisruptionBudget.maxUnavailable }} +{{- fail "Cannot set both" -}} +{{- end }} +{{- if not .Values.plugin.kyverno.podDisruptionBudget.maxUnavailable }} +minAvailable: {{ default 1 .Values.plugin.kyverno.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.plugin.kyverno.podDisruptionBudget.maxUnavailable }} +maxUnavailable: {{ .Values.plugin.kyverno.podDisruptionBudget.maxUnavailable }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrole.yaml b/charts/policy-reporter/templates/plugins/kyverno/clusterrole.yaml similarity index 57% rename from charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrole.yaml rename to charts/policy-reporter/templates/plugins/kyverno/clusterrole.yaml index 94002565..128b33e0 100644 --- a/charts/policy-reporter/charts/kyvernoPlugin/templates/clusterrole.yaml +++ b/charts/policy-reporter/templates/plugins/kyverno/clusterrole.yaml @@ -1,15 +1,12 @@ -{{- if .Values.rbac.enabled -}} +{{- if .Values.plugin.kyverno.enabled -}} +{{- if .Values.plugin.kyverno.rbac.enabled -}} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} labels: rbac.authorization.k8s.io/aggregate-to-admin: "true" - {{- include "kyvernoplugin.labels" . | nindent 4 }} - name: {{ include "kyvernoplugin.fullname" . }} + {{- include "kyverno-plugin.labels" . | nindent 4 }} + name: {{ include "kyverno-plugin.fullname" . }} rules: - apiGroups: - '*' @@ -21,8 +18,7 @@ rules: verbs: - get - list - - watch -{{- if .Values.blockReports.enabled }} +{{- if .Values.plugin.kyverno.blockReports.enabled }} - apiGroups: - "" resources: @@ -44,14 +40,6 @@ rules: - create - update - delete -{{- else }} -- apiGroups: - - '*' - resources: - - policyreports - - clusterpolicyreports - verbs: - - get - - list {{- end }} -{{- end -}} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/clusterrolebinding.yaml b/charts/policy-reporter/templates/plugins/kyverno/clusterrolebinding.yaml new file mode 100644 index 00000000..fb7ed840 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/clusterrolebinding.yaml @@ -0,0 +1,18 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if and .Values.plugin.kyverno.serviceAccount.create .Values.plugin.kyverno.rbac.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "kyverno-plugin.fullname" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +roleRef: + kind: ClusterRole + name: {{ include "kyverno-plugin.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: "ServiceAccount" + name: {{ include "kyverno-plugin.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/config-secret.yaml b/charts/policy-reporter/templates/plugins/kyverno/config-secret.yaml new file mode 100644 index 00000000..6fcc3698 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/config-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.plugin.kyverno.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "kyverno-plugin.fullname" . }}-config + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +type: Opaque +data: + config.yaml: {{ tpl (.Files.Get "configs/kyverno-plugin.tmpl") . | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/deployment.yaml b/charts/policy-reporter/templates/plugins/kyverno/deployment.yaml new file mode 100644 index 00000000..64e10133 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/deployment.yaml @@ -0,0 +1,103 @@ +{{- if .Values.plugin.kyverno.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "kyverno-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.plugin.kyverno.replicaCount }} + revisionHistoryLimit: {{ .Values.plugin.kyverno.revisionHistoryLimit }} + {{- with .Values.plugin.kyverno.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "kyverno-plugin.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/secret: {{ include (print .Template.BasePath "/plugins/kyverno/config-secret.yaml") . | sha256sum | quote }} + {{- with .Values.plugin.kyverno.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 8 }} + {{- with .Values.plugin.kyverno.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.plugin.kyverno.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "kyverno-plugin.serviceAccountName" . }} + {{- if .Values.plugin.kyverno.podSecurityContext }} + securityContext: + {{- toYaml .Values.plugin.kyverno.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: policy-reporter-kyverno-plugin + {{- if .Values.plugin.kyverno.securityContext }} + securityContext: + {{- toYaml .Values.plugin.kyverno.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.plugin.kyverno.image.registry }}/{{ .Values.plugin.kyverno.image.repository }}:{{ .Values.plugin.kyverno.image.tag }}" + imagePullPolicy: {{ .Values.plugin.kyverno.image.pullPolicy }} + args: + - run + - --config=/app/config.yaml + - --port={{ .Values.plugin.kyverno.server.port }} + ports: + - name: http + containerPort: {{ .Values.plugin.kyverno.server.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /api/v1/policies + port: http + readinessProbe: + httpGet: + path: /api/v1/policies + port: http + resources: + {{- toYaml .Values.plugin.kyverno.resources | nindent 12 }} + volumeMounts: + - name: config-file + mountPath: /app/config.yaml + subPath: config.yaml + readOnly: true + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if gt (int .Values.plugin.kyverno.replicaCount) 1 }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- end }} + {{- with .Values.plugin.kyverno.envVars }} + {{- . | toYaml | trim | nindent 10 }} + {{- end }} + volumes: + - name: config-file + secret: + secretName: {{ include "kyverno-plugin.fullname" . }}-config + optional: true + {{- with .Values.plugin.kyverno.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.plugin.kyverno.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.plugin.kyverno.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/plugins/kyverno/ingress.yaml b/charts/policy-reporter/templates/plugins/kyverno/ingress.yaml new file mode 100644 index 00000000..36f7ce05 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if .Values.plugin.kyverno.ingress.enabled -}} +{{- $fullName := include "kyverno-plugin.fullname" . -}} +{{- $svcPort := .Values.plugin.kyverno.service.port -}} +{{- if and .Values.plugin.kyverno.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.plugin.kyverno.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.plugin.kyverno.ingress.annotations "kubernetes.io/ingress.class" .Values.plugin.kyverno.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.kyverno.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.plugin.kyverno.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.plugin.kyverno.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.plugin.kyverno.ingress.className }} + {{- end }} + {{- if .Values.plugin.kyverno.ingress.tls }} + tls: + {{- toYaml .Values.plugin.kyverno.ingress.tls | nindent 4 }} + {{- end }} + rules: + {{- range .Values.plugin.kyverno.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/plugins/kyverno/networkpolicy.yaml b/charts/policy-reporter/templates/plugins/kyverno/networkpolicy.yaml new file mode 100644 index 00000000..f08234fa --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/networkpolicy.yaml @@ -0,0 +1,24 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if .Values.plugin.kyverno.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: {{- include "kyverno-plugin.labels" . | nindent 4 }} + name: {{ include "kyverno-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} +spec: + podSelector: + matchLabels: {{- include "kyverno-plugin.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + {{- with .Values.plugin.kyverno.networkPolicy.ingress }} + ingress: + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.plugin.kyverno.networkPolicy.egress }} + egress: + {{- toYaml . | nindent 2 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/poddisruptionbudget.yaml b/charts/policy-reporter/templates/plugins/kyverno/poddisruptionbudget.yaml new file mode 100644 index 00000000..ce439f73 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if (gt (int .Values.plugin.kyverno.replicaCount) 1) }} +{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ include "kyverno-plugin.fullname" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +spec: +{{- include "kyverno-plugin.podDisruptionBudget" . | indent 2 }} + selector: + matchLabels: + {{- include "kyverno-plugin.selectorLabels" . | nindent 6 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/role.yaml b/charts/policy-reporter/templates/plugins/kyverno/role.yaml new file mode 100644 index 00000000..be0b8585 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/role.yaml @@ -0,0 +1,22 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if and (and .Values.plugin.kyverno.serviceAccount.create .Values.plugin.kyverno.rbac.enabled) (and .Values.plugin.kyverno.blockReports.enabled (gt (int .Values.plugin.kyverno.replicaCount) 1)) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} + name: {{ include "kyverno-plugin.fullname" . }}-leaderelection + namespace: {{ include "policyreporter.namespace" . }} +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - patch + - update +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/rolebinding.yaml b/charts/policy-reporter/templates/plugins/kyverno/rolebinding.yaml new file mode 100644 index 00000000..0af9ec97 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if and (and .Values.plugin.kyverno.serviceAccount.create .Values.plugin.kyverno.rbac.enabled) (and .Values.plugin.kyverno.blockReports.enabled (gt (int .Values.plugin.kyverno.replicaCount) 1)) -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "kyverno-plugin.fullname" . }}-leaderelection + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +roleRef: + kind: Role + name: {{ include "kyverno-plugin.fullname" . }}-leaderelection + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: "ServiceAccount" + name: {{ include "kyverno-plugin.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/secret-role.yaml b/charts/policy-reporter/templates/plugins/kyverno/secret-role.yaml new file mode 100644 index 00000000..41e20ed2 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/secret-role.yaml @@ -0,0 +1,17 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if and .Values.plugin.kyverno.serviceAccount.create .Values.plugin.kyverno.rbac.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} + name: {{ include "kyverno-plugin.fullname" . }}-secret-reader + namespace: {{ include "policyreporter.namespace" . }} +rules: +- apiGroups: [''] + resources: + - secrets + verbs: + - get +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/secret-rolebinding.yaml b/charts/policy-reporter/templates/plugins/kyverno/secret-rolebinding.yaml new file mode 100644 index 00000000..47a096f9 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/secret-rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if and .Values.plugin.kyverno.serviceAccount.create .Values.plugin.kyverno.rbac.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "kyverno-plugin.fullname" . }}-secret-reader + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} +roleRef: + kind: Role + name: {{ include "kyverno-plugin.fullname" . }}-secret-reader + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: "ServiceAccount" + name: {{ include "kyverno-plugin.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/kyverno/service.yaml b/charts/policy-reporter/templates/plugins/kyverno/service.yaml new file mode 100644 index 00000000..8f9229e9 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.plugin.kyverno.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "kyverno-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.kyverno.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.plugin.kyverno.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.plugin.kyverno.service.type }} + ports: + - port: {{ .Values.plugin.kyverno.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "kyverno-plugin.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/policy-reporter/templates/plugins/kyverno/serviceaccount.yaml b/charts/policy-reporter/templates/plugins/kyverno/serviceaccount.yaml new file mode 100644 index 00000000..f790bc81 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/kyverno/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.plugin.kyverno.enabled -}} +{{- if .Values.plugin.kyverno.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "kyverno-plugin.serviceAccountName" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "kyverno-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.kyverno.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.plugin.kyverno.serviceAccount.automount }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/plugins/trivy/_helpers.tpl b/charts/policy-reporter/templates/plugins/trivy/_helpers.tpl new file mode 100644 index 00000000..2beb8335 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "trivy-plugin.name" -}} +{{ template "policyreporter.name" . }}-trivy-plugin +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "trivy-plugin.fullname" -}} +{{ template "policyreporter.fullname" . }}-trivy-plugin +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "trivy-plugin.chart" -}} +{{ template "policyreporter.chart" . }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "trivy-plugin.labels" -}} +helm.sh/chart: {{ include "trivy-plugin.chart" . }} +{{ include "trivy-plugin.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.labels }} +{{ toYaml . }} +{{- end -}} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "trivy-plugin.selectorLabels" -}} +app.kubernetes.io/name: {{ include "trivy-plugin.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "trivy-plugin.serviceAccountName" -}} +{{- if .Values.plugin.trivy.serviceAccount.create }} +{{- default (include "trivy-plugin.fullname" .) .Values.plugin.trivy.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.plugin.trivy.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "trivy-plugin.podDisruptionBudget" -}} +{{- if and .Values.plugin.trivy.podDisruptionBudget.minAvailable .Values.plugin.trivy.podDisruptionBudget.maxUnavailable }} +{{- fail "Cannot set both" -}} +{{- end }} +{{- if not .Values.plugin.trivy.podDisruptionBudget.maxUnavailable }} +minAvailable: {{ default 1 .Values.plugin.trivy.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.plugin.trivy.podDisruptionBudget.maxUnavailable }} +maxUnavailable: {{ .Values.plugin.trivy.podDisruptionBudget.maxUnavailable }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/plugins/trivy/config-secret.yaml b/charts/policy-reporter/templates/plugins/trivy/config-secret.yaml new file mode 100644 index 00000000..15b86c4a --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/config-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.plugin.trivy.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "trivy-plugin.fullname" . }}-config + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} +type: Opaque +data: + config.yaml: {{ tpl (.Files.Get "configs/trivy-plugin.tmpl") . | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/deployment.yaml b/charts/policy-reporter/templates/plugins/trivy/deployment.yaml new file mode 100644 index 00000000..b19184d8 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/deployment.yaml @@ -0,0 +1,97 @@ +{{- if .Values.plugin.trivy.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "trivy-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.plugin.trivy.replicaCount }} + revisionHistoryLimit: {{ .Values.plugin.trivy.revisionHistoryLimit }} + {{- with .Values.plugin.trivy.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "trivy-plugin.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/secret: {{ include (print .Template.BasePath "/plugins/trivy/config-secret.yaml") . | sha256sum | quote }} + {{- with .Values.plugin.trivy.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "trivy-plugin.labels" . | nindent 8 }} + {{- with .Values.plugin.trivy.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.plugin.trivy.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "trivy-plugin.serviceAccountName" . }} + {{- if .Values.plugin.trivy.podSecurityContext }} + securityContext: + {{- toYaml .Values.plugin.trivy.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: policy-reporter-trivy-plugin + {{- if .Values.plugin.trivy.securityContext }} + securityContext: + {{- toYaml .Values.plugin.trivy.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.plugin.trivy.image.registry }}/{{ .Values.plugin.trivy.image.repository }}:{{ .Values.plugin.trivy.image.tag }}" + imagePullPolicy: {{ .Values.plugin.trivy.image.pullPolicy }} + args: + - run + - --config=/app/config.yaml + - --port={{ .Values.plugin.trivy.server.port }} + ports: + - name: http + containerPort: {{ .Values.plugin.trivy.server.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /api/vulnr/v1/policies + port: http + readinessProbe: + httpGet: + path: /api/vulnr/v1/policies + port: http + resources: + {{- toYaml .Values.plugin.trivy.resources | nindent 12 }} + volumeMounts: + - name: config-file + mountPath: /app/config.yaml + subPath: config.yaml + readOnly: true + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.plugin.trivy.envVars }} + {{- . | toYaml | trim | nindent 10 }} + {{- end }} + volumes: + - name: config-file + secret: + secretName: {{ include "trivy-plugin.fullname" . }}-config + optional: true + {{- with .Values.plugin.trivy.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.plugin.trivy.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.plugin.trivy.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/ingress.yaml b/charts/policy-reporter/templates/plugins/trivy/ingress.yaml new file mode 100644 index 00000000..d7a61acc --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if .Values.plugin.trivy.ingress.enabled -}} +{{- $fullName := include "trivy-plugin.fullname" . -}} +{{- $svcPort := .Values.plugin.trivy.service.port -}} +{{- if and .Values.plugin.trivy.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.plugin.trivy.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.plugin.trivy.ingress.annotations "kubernetes.io/ingress.class" .Values.plugin.trivy.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.trivy.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.plugin.trivy.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.plugin.trivy.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.plugin.trivy.ingress.className }} + {{- end }} + {{- if .Values.plugin.trivy.ingress.tls }} + tls: + {{- toYaml .Values.plugin.trivy.ingress.tls | nindent 4 }} + {{- end }} + rules: + {{- range .Values.plugin.trivy.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/networkpolicy.yaml b/charts/policy-reporter/templates/plugins/trivy/networkpolicy.yaml new file mode 100644 index 00000000..011753a9 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/networkpolicy.yaml @@ -0,0 +1,31 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if .Values.plugin.trivy.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: {{- include "trivy-plugin.labels" . | nindent 4 }} + name: {{ include "trivy-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} +spec: + podSelector: + matchLabels: {{- include "trivy-plugin.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + {{- with .Values.plugin.trivy.networkPolicy.ingress }} + ingress: + {{- toYaml . | nindent 2 }} + {{- end }} + egress: + - to: + - podSelector: + matchLabels: + {{- include "policyreporter.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + {{- with .Values.plugin.trivy.networkPolicy.egress }} + {{- toYaml . | nindent 2 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/poddisruptionbudget.yaml b/charts/policy-reporter/templates/plugins/trivy/poddisruptionbudget.yaml new file mode 100644 index 00000000..52853660 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/poddisruptionbudget.yaml @@ -0,0 +1,20 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if (gt (int .Values.plugin.trivy.replicaCount) 1) }} +{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ include "trivy-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} +spec: +{{- include "trivy-plugin.podDisruptionBudget" . | indent 2 }} + selector: + matchLabels: + {{- include "trivy-plugin.selectorLabels" . | nindent 6 }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/secret-role.yaml b/charts/policy-reporter/templates/plugins/trivy/secret-role.yaml new file mode 100644 index 00000000..bde89f85 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/secret-role.yaml @@ -0,0 +1,17 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if and .Values.plugin.trivy.serviceAccount.create .Values.plugin.trivy.rbac.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} + name: {{ include "trivy-plugin.fullname" . }}-secret-reader + namespace: {{ include "policyreporter.namespace" . }} +rules: +- apiGroups: [''] + resources: + - secrets + verbs: + - get +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/secret-rolebinding.yaml b/charts/policy-reporter/templates/plugins/trivy/secret-rolebinding.yaml new file mode 100644 index 00000000..d81d76cb --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/secret-rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if and .Values.plugin.trivy.serviceAccount.create .Values.plugin.trivy.rbac.enabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "trivy-plugin.fullname" . }}-secret-reader + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} +roleRef: + kind: Role + name: {{ include "trivy-plugin.fullname" . }}-secret-reader + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: "ServiceAccount" + name: {{ include "trivy-plugin.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/service.yaml b/charts/policy-reporter/templates/plugins/trivy/service.yaml new file mode 100644 index 00000000..22e19462 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.plugin.trivy.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "trivy-plugin.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.trivy.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.plugin.trivy.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.plugin.trivy.service.type }} + ports: + - port: {{ .Values.plugin.trivy.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "trivy-plugin.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/plugins/trivy/serviceaccount.yaml b/charts/policy-reporter/templates/plugins/trivy/serviceaccount.yaml new file mode 100644 index 00000000..288e0201 --- /dev/null +++ b/charts/policy-reporter/templates/plugins/trivy/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.plugin.trivy.enabled -}} +{{- if .Values.plugin.trivy.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "trivy-plugin.serviceAccountName" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "trivy-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.trivy.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.plugin.trivy.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/role.yaml b/charts/policy-reporter/templates/role.yaml index 93473ccd..ba46dab3 100644 --- a/charts/policy-reporter/templates/role.yaml +++ b/charts/policy-reporter/templates/role.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.rbac.enabled (or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1)) -}} +{{- if and .Values.rbac.enabled (gt (int .Values.replicaCount) 1) -}} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: diff --git a/charts/policy-reporter/templates/rolebinding.yaml b/charts/policy-reporter/templates/rolebinding.yaml index 7690104a..6d2b1e4e 100644 --- a/charts/policy-reporter/templates/rolebinding.yaml +++ b/charts/policy-reporter/templates/rolebinding.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.rbac.enabled (or .Values.leaderElection.enabled (gt (int .Values.replicaCount) 1)) -}} +{{- if and .Values.rbac.enabled (gt (int .Values.replicaCount) 1) -}} apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: diff --git a/charts/policy-reporter/templates/secret-role.yaml b/charts/policy-reporter/templates/secret-role.yaml index a6338164..0aa8a271 100644 --- a/charts/policy-reporter/templates/secret-role.yaml +++ b/charts/policy-reporter/templates/secret-role.yaml @@ -16,4 +16,6 @@ rules: - secrets verbs: - get + - list + - watch {{- end -}} diff --git a/charts/policy-reporter/templates/ui/_helpers.tpl b/charts/policy-reporter/templates/ui/_helpers.tpl new file mode 100644 index 00000000..bd424b57 --- /dev/null +++ b/charts/policy-reporter/templates/ui/_helpers.tpl @@ -0,0 +1,68 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ui.name" -}} +{{ template "policyreporter.name" . }}-ui +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ui.fullname" -}} +{{ template "policyreporter.fullname" . }}-ui +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ui.chart" -}} +{{ template "policyreporter.chart" . }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ui.labels" -}} +helm.sh/chart: {{ include "ui.chart" . }} +{{ include "ui.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.global.labels }} +{{ toYaml . }} +{{- end -}} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ui.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ui.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ui.serviceAccountName" -}} +{{- if .Values.plugin.kyverno.serviceAccount.create }} +{{- default (include "ui.fullname" .) .Values.plugin.kyverno.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.plugin.kyverno.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "ui.podDisruptionBudget" -}} +{{- if and .Values.plugin.kyverno.ui.podDisruptionBudget.minAvailable .Values.plugin.kyverno.ui.podDisruptionBudget.maxUnavailable }} +{{- fail "Cannot set both" -}} +{{- end }} +{{- if not .Values.plugin.kyverno.ui.podDisruptionBudget.maxUnavailable }} +minAvailable: {{ default 1 .Values.plugin.kyverno.ui.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.plugin.kyverno.ui.podDisruptionBudget.maxUnavailable }} +maxUnavailable: {{ .Values.plugin.kyverno.ui.podDisruptionBudget.maxUnavailable }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/templates/ui/config-secret.yaml b/charts/policy-reporter/templates/ui/config-secret.yaml new file mode 100644 index 00000000..cd469930 --- /dev/null +++ b/charts/policy-reporter/templates/ui/config-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.ui.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ui.fullname" . }}-config + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "ui.labels" . | nindent 4 }} +type: Opaque +data: + config.yaml: {{ tpl (.Files.Get "configs/ui.tmpl") . | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/ui/deployment.yaml b/charts/policy-reporter/templates/ui/deployment.yaml new file mode 100644 index 00000000..86fcd21a --- /dev/null +++ b/charts/policy-reporter/templates/ui/deployment.yaml @@ -0,0 +1,112 @@ +{{- if .Values.ui.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ui.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "ui.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.ui.replicaCount }} + revisionHistoryLimit: {{ .Values.ui.revisionHistoryLimit }} + {{- with .Values.ui.updateStrategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "ui.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/secret: {{ include (print .Template.BasePath "/ui/config-secret.yaml") . | sha256sum | quote }} + checksum/cluster-secret: {{ include (print .Template.BasePath "/cluster-secret.yaml") . | sha256sum | quote }} + {{- with .Values.ui.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "ui.labels" . | nindent 8 }} + {{- with .Values.ui.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.ui.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ui.serviceAccountName" . }} + {{- if .Values.ui.podSecurityContext }} + securityContext: + {{- toYaml .Values.ui.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: policy-reporter-ui + {{- if .Values.ui.securityContext }} + securityContext: + {{- toYaml .Values.ui.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.ui.image.registry }}/{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag }}" + imagePullPolicy: {{ .Values.ui.image.pullPolicy }} + args: + - run + - --config=/app/config.yaml + - --port={{ .Values.ui.server.port }} + ports: + - name: http + containerPort: {{ .Values.ui.server.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: http + readinessProbe: + httpGet: + path: /healthz + port: http + resources: + {{- toYaml .Values.ui.resources | nindent 12 }} + volumeMounts: + - name: config-file + mountPath: /app/config.yaml + subPath: config.yaml + readOnly: true + - name: tmp + mountPath: /tmp + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- with .Values.ui.envVars }} + {{- . | toYaml | trim | nindent 10 }} + {{- end }} + {{- if .Values.ui.sidecarContainers }} + {{- range $name, $spec := .Values.ui.sidecarContainers }} + - name: {{ $name }} + {{- if kindIs "string" $spec }} + {{- tpl $spec $ | nindent 10 }} + {{- else }} + {{- toYaml $spec | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + volumes: + - name: config-file + secret: + secretName: {{ include "ui.fullname" . }}-config + optional: true + - name: tmp + emptyDir: {} + {{- with .Values.ui.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.ui.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/ui/extra-manifests.yaml b/charts/policy-reporter/templates/ui/extra-manifests.yaml new file mode 100644 index 00000000..cb1b0b91 --- /dev/null +++ b/charts/policy-reporter/templates/ui/extra-manifests.yaml @@ -0,0 +1,6 @@ +{{- if .Values.ui.enabled -}} +{{ range .Values.ui.extraManifests }} +--- +{{ tpl . $ }} +{{ end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/ingress.yaml b/charts/policy-reporter/templates/ui/ingress.yaml similarity index 55% rename from charts/policy-reporter/charts/ui/templates/ingress.yaml rename to charts/policy-reporter/templates/ui/ingress.yaml index bcd45441..0df539a9 100644 --- a/charts/policy-reporter/charts/ui/templates/ingress.yaml +++ b/charts/policy-reporter/templates/ui/ingress.yaml @@ -1,9 +1,10 @@ -{{- if .Values.ingress.enabled -}} +{{- if .Values.ui.enabled -}} +{{- if .Values.ui.ingress.enabled -}} {{- $fullName := include "ui.fullname" . -}} -{{- $svcPort := .Values.ingress.port | default .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} +{{- $svcPort := .Values.ui.ingress.port | default .Values.ui.service.port -}} +{{- if and .Values.ui.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ui.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ui.ingress.annotations "kubernetes.io/ingress.class" .Values.ui.ingress.className}} {{- end }} {{- end }} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} @@ -16,33 +17,26 @@ apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ $fullName }} - namespace: {{ include "ui.namespace" . }} + namespace: {{ include "policyreporter.namespace" . }} labels: {{- include "ui.labels" . | nindent 4 }} - {{- if .Values.ingress.labels }} - {{- with .Values.ingress.labels }} + {{- with .Values.ui.ingress.labels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- end }} - {{- if or .Values.annotations .Values.ingress.annotations }} + {{- with .Values.ui.ingress.annotations }} annotations: - {{- with .Values.ingress.annotations }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.annotations }} - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} - {{- end }} spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} + {{- if and .Values.ui.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ui.ingress.className }} {{- end }} - {{- if .Values.ingress.tls }} + {{- if .Values.ui.ingress.tls }} tls: - {{- toYaml .Values.ingress.tls | nindent 4 }} + {{- toYaml .Values.ui.ingress.tls | nindent 4 }} {{- end }} rules: - {{- range .Values.ingress.hosts }} + {{- range .Values.ui.ingress.hosts }} - host: {{ .host | quote }} http: paths: @@ -63,4 +57,5 @@ spec: {{- end }} {{- end }} {{- end }} +{{- end }} {{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/ui/networkpolicy.yaml b/charts/policy-reporter/templates/ui/networkpolicy.yaml new file mode 100644 index 00000000..9278f782 --- /dev/null +++ b/charts/policy-reporter/templates/ui/networkpolicy.yaml @@ -0,0 +1,53 @@ +{{- if .Values.ui.enabled -}} +{{- if .Values.ui.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: {{- include "ui.labels" . | nindent 4 }} + name: {{ include "ui.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} +spec: + podSelector: + matchLabels: {{- include "ui.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + - from: + ports: + - protocol: TCP + port: {{ .Values.ui.service.port }} + {{- with .Values.ui.networkPolicy.ingress }} + {{- toYaml . | nindent 2 }} + {{- end }} + egress: + - to: + - podSelector: + matchLabels: + {{- include "policyreporter.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + {{- if or .Values.plugin.kyverno.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "kyverno-plugin.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.plugin.kyverno.service.port }} + {{- end }} + {{- if or .Values.plugin.trivy.enabled }} + - to: + - podSelector: + matchLabels: + {{- include "trivy-plugin.selectorLabels" . | nindent 10 }} + ports: + - protocol: TCP + port: {{ .Values.plugin.trivy.service.port }} + {{- end }} + {{- with .Values.networkPolicy.egress }} + {{- toYaml . | nindent 2 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/poddisruptionbudget.yaml b/charts/policy-reporter/templates/ui/poddisruptionbudget.yaml similarity index 52% rename from charts/policy-reporter/charts/ui/templates/poddisruptionbudget.yaml rename to charts/policy-reporter/templates/ui/poddisruptionbudget.yaml index b5d8dde1..55d73362 100644 --- a/charts/policy-reporter/charts/ui/templates/poddisruptionbudget.yaml +++ b/charts/policy-reporter/templates/ui/poddisruptionbudget.yaml @@ -1,4 +1,5 @@ -{{- if (gt (int .Values.replicaCount) 1) }} +{{- if .Values.ui.enabled -}} +{{- if (gt (int .Values.ui.replicaCount) 1) }} {{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} apiVersion: policy/v1 {{- else }} @@ -6,17 +7,14 @@ apiVersion: policy/v1beta1 {{- end }} kind: PodDisruptionBudget metadata: - name: {{ template "ui.fullname" . }} - namespace: {{ include "ui.namespace" . }} + name: {{ include "ui.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} labels: {{- include "ui.labels" . | nindent 4 }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} spec: -{{- include "policyreporter.podDisruptionBudget" . | indent 2 }} +{{- include "ui.podDisruptionBudget" . | indent 2 }} selector: matchLabels: {{- include "ui.selectorLabels" . | nindent 6 }} +{{- end }} {{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/secret-role.yaml b/charts/policy-reporter/templates/ui/secret-role.yaml similarity index 50% rename from charts/policy-reporter/charts/ui/templates/secret-role.yaml rename to charts/policy-reporter/templates/ui/secret-role.yaml index 7df123f8..faf39821 100644 --- a/charts/policy-reporter/charts/ui/templates/secret-role.yaml +++ b/charts/policy-reporter/templates/ui/secret-role.yaml @@ -1,19 +1,17 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.enabled -}} +{{- if .Values.ui.enabled -}} +{{- if and .Values.ui.serviceAccount.create .Values.ui.rbac.enabled -}} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} labels: {{- include "ui.labels" . | nindent 4 }} name: {{ include "ui.fullname" . }}-secret-reader - namespace: {{ include "ui.namespace" . }} + namespace: {{ include "policyreporter.namespace" . }} rules: - apiGroups: [''] resources: - secrets verbs: - get -{{- end -}} \ No newline at end of file +{{- end -}} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/charts/ui/templates/secret-rolebinding.yaml b/charts/policy-reporter/templates/ui/secret-rolebinding.yaml similarity index 59% rename from charts/policy-reporter/charts/ui/templates/secret-rolebinding.yaml rename to charts/policy-reporter/templates/ui/secret-rolebinding.yaml index 980799be..ccae6b88 100644 --- a/charts/policy-reporter/charts/ui/templates/secret-rolebinding.yaml +++ b/charts/policy-reporter/templates/ui/secret-rolebinding.yaml @@ -1,13 +1,10 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.enabled -}} +{{- if .Values.ui.enabled -}} +{{- if and .Values.ui.serviceAccount.create .Values.rbac.enabled -}} apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: {{ include "ui.fullname" . }}-secret-reader - namespace: {{ include "ui.namespace" . }} - {{- if .Values.annotations }} - annotations: - {{- toYaml .Values.annotations | nindent 4 }} - {{- end }} + namespace: {{ include "policyreporter.namespace" . }} labels: {{- include "ui.labels" . | nindent 4 }} roleRef: @@ -17,5 +14,6 @@ roleRef: subjects: - kind: "ServiceAccount" name: {{ include "ui.serviceAccountName" . }} - namespace: {{ include "ui.namespace" . }} + namespace: {{ .Release.Namespace }} {{- end -}} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/ui/service.yaml b/charts/policy-reporter/templates/ui/service.yaml new file mode 100644 index 00000000..9cc154be --- /dev/null +++ b/charts/policy-reporter/templates/ui/service.yaml @@ -0,0 +1,28 @@ +{{- if .Values.ui.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ui.fullname" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "ui.labels" . | nindent 4 }} + {{- with .Values.ui.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ui.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.ui.service.type }} + ports: + - port: {{ .Values.ui.service.port }} + targetPort: http + protocol: TCP + name: http + {{- if .Values.ui.service.additionalPorts }} + {{ toYaml .Values.ui.service.additionalPorts | indent 4 }} + {{- end }} + selector: + {{- include "ui.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/policy-reporter/templates/ui/serviceaccount.yaml b/charts/policy-reporter/templates/ui/serviceaccount.yaml new file mode 100644 index 00000000..2cb12420 --- /dev/null +++ b/charts/policy-reporter/templates/ui/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.ui.enabled -}} +{{- if .Values.ui.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ui.serviceAccountName" . }} + namespace: {{ include "policyreporter.namespace" . }} + labels: + {{- include "ui.labels" . | nindent 4 }} + {{- with .Values.ui.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.ui.serviceAccount.automount }} +{{- end }} +{{- end }} diff --git a/charts/policy-reporter/values.yaml b/charts/policy-reporter/values.yaml index 6d4beb91..ec2d31bd 100644 --- a/charts/policy-reporter/values.yaml +++ b/charts/policy-reporter/values.yaml @@ -1,60 +1,76 @@ -# Override the chart name used for all resources +# -- Override the chart name used for all resources nameOverride: "" -image: - registry: ghcr.io - repository: kyverno/policy-reporter - pullPolicy: IfNotPresent - tag: 2.20.2 +# -- Overwrite the fullname of all resources +fullnameOverride: "policy-reporter" +# -- Overwrite the namespace of all resources +namespaceOverride: "" + +image: + # -- (string) Image registry + registry: ghcr.io + # -- (string) Image repository + repository: kyverno/policy-reporter + # -- (string) Image pullPolicy + pullPolicy: IfNotPresent + # -- (string) Image tag + tag: 12da466 + +# -- Image pullSecrets imagePullSecrets: [] +# -- Deployment priorityClassName priorityClassName: "" +# -- Deployment replica count replicaCount: 1 +# -- The number of revisions to keep revisionHistoryLimit: 10 -deploymentStrategy: {} +# -- Deployment strategy +updateStrategy: {} # rollingUpdate: # maxSurge: 25% # maxUnavailable: 25% # type: RollingUpdate -# When using a custom port together with the PolicyReporter UI -# the port has also to be changed in the UI subchart as well because it can't access the parent values. -# You can change the port under `ui.policyReporter.port` +# -- Container port port: name: http number: 8080 -# Key/value pairs that are attached to all resources. +# -- Key/value pairs that are attached to all resources. annotations: {} -# Create cluster role policies rbac: + # -- Create RBAC resources enabled: true serviceAccount: - # Specifies whether a service account should be created + # -- Create ServiceAccount create: true - # Annotations to add to the service account + # -- Enable ServiceAccount automaount + automount: true + # -- Annotations for the ServiceAccount annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template + # -- The ServiceAccount name name: "" service: + # -- Create Service enabled: true - ## configuration of service - # key/value - annotations: {} - # key/value - labels: {} + # -- Service type type: ClusterIP - # integer number. This is port for service + # -- Service port port: 8080 + # -- Service annotations + annotations: {} + # -- Service labels + labels: {} +# -- Security context for the pod podSecurityContext: fsGroup: 1234 @@ -70,20 +86,14 @@ securityContext: seccompProfile: type: RuntimeDefault -# Key/value pairs that are attached to pods. -podAnnotations: {} + # -- Additional annotations to add to each pod + podAnnotations: {} -# Key/value pairs that are attached to pods. -podLabels: {} - -# Allow additional env variables to be added -envVars: [] + # -- Additional labels to add to each pod + podLabels: {} +# -- Resource constraints resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: # memory: 100Mi # cpu: 10m @@ -91,11 +101,10 @@ resources: {} # memory: 75Mi # cpu: 5m -# Enable a NetworkPolicy for this chart. Useful on clusters where Network Policies are -# used and configured in a default-deny fashion. networkPolicy: + # -- Create NetworkPolicy enabled: false - # Kubernetes API Server + # -- Egress rule to allowe Kubernetes API Server access egress: - to: ports: @@ -103,158 +112,163 @@ networkPolicy: port: 6443 ingress: [] -## Set to true to enable ingress record generation -# ref to: https://kubernetes.io/docs/concepts/services-networking/ingress/ ingress: + # -- Create Ingress + # This ingress exposes the policy-reporter core app. enabled: false + # -- Ingress className className: "" - # key/value + # -- Labels for the Ingress labels: {} - # key/value + # -- Annotations for the Ingress annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" + # -- Ingress host list hosts: - - host: chart-example.local - paths: [] + # - host: chart-example.local + # paths: [] + # -- Ingress tls list tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local logging: - encoding: console # possible encodings are console and json - logLevel: 0 # default info - development: false # more human readable structure, enables stacktraces and removes log sampling + # -- Enables server access logging + server: false + # -- Log encoding + # possible encodings are console and json + encoding: console + # -- Log level + # default info + logLevel: 0 -api: - logging: false # enable debug API access logging, sets logLevel to debug - -# REST API rest: + # -- Enables the REST API enabled: false -# Prometheus Metrics API metrics: + # -- Enables Prometheus Metrics enabled: false - mode: detailed # available modes are detailed, simple and custom - customLabels: [] # only used for custom mode. Supported fields are: ["namespace", "rule", "policy", "report" // PolicyReport name, "kind" // resource kind, "name" // resource name, "status", "severity", "category", "source"] -# filter: + # -- Metric Mode allowes to customize labels + # Allowed values: detailed, simple, custom + mode: detailed + # -- List of used labels in custom mode + # Supported fields are: ["namespace", "rule", "policy", "report" // PolicyReport name, "kind" // resource kind, "name" // resource name, "status", "severity", "category", "source"] + customLabels: [] + # -- Filter results to reduce cardinality + filter: {} # sources: # exclude: ["Trivy CIS Kube Bench"] # status: # exclude: ["pass", "skip"] profiling: + # -- Enable profiling with pprof enabled: false -# amount of queue workers for PolicyReport resource processing +# -- Amount of queue workers for PolicyReport resource processing worker: 5 -# Filter PolicyReport resources to process -reportFilter: - namespaces: - # Process only PolicyReport resources from an included namespace, wildcards are supported - include: [] - # Ignore all PolicyReport resources from a excluded namespace, wildcards are supported - # exclude will be ignored if an include filter exists - exclude: [] - clusterReports: - # Disable the processing of ClusterPolicyReports - disabled: false +# -- Filter PolicyReport resources to process +reportFilter: {} + # # -- Filter reports based on an namespace allow- or disallow list, wildcards are supported + # namespaces: + # include: [] + # exclude: [] + # # -- Disable the processing of ClusterPolicyReports + # disableClusterReports: false -# customize source specific logic like result ID generation -sourceConfig: {} -# sourcename: -# customID: +# -- Customize source specific logic like result ID generation +sourceConfig: [] +# - selector: +# source: kyverno +# customId: # enabled: true # fields: ["resource", "policy", "rule", "category", "result", "message"] -# Settings for the Policy Reporter UI subchart (see subchart's values.yaml) -ui: - enabled: false - -kyvernoPlugin: - enabled: false - -# Settings for the monitoring subchart -monitoring: - enabled: false - -database: - # Database Type, supported: mysql, postgres, mariadb - type: "" - database: "" # Database Name - username: "" - password: "" - host: "" - enableSSL: false - # instead of configure the individual values you can also provide an DSN string - # example postgres: postgres://postgres:password@localhost:5432/postgres?sslmode=disable - # example mysql: root:password@tcp(localhost:3306)/test?tls=false - dsn: "" - # configure an existing secret as source for your values - # supported fields: username, password, host, dsn, database - secretRef: "" - # use an mounted secret as source for your values, required the information in JSON format - # supported fields: username, password, host, dsn, database - mountedSecret: "" +# Source based PolicyReport filter +sourceFilters: + - selector: + # -- select PolicyReport by source + source: kyverno + # -- Filter out PolicyReports of controlled Pods and Jobs, only works for PolicyReport with scope resource + uncontrolledOnly: true + # -- Filter out ClusterPolicyReports + disableClusterReports: false + # -- Filter out PolicyReports based on the scope resource kind + kinds: + exclude: [ReplicaSet] global: - # available plugins - plugins: - # enable kyverno for Policy Reporter UI and monitoring - kyverno: false - # The name of service policy-report. Defaults to ReleaseName. - backend: "" - # overwrite the fullname of all resources including subcharts - fullnameOverride: "" - # configure the namespace of all resources including subcharts - namespace: "" - # additional labels added on each resource + # -- additional labels added on each resource labels: {} - # basicAuth for APIs and metrics - basicAuth: - # HTTP BasicAuth username - username: "" - # HTTP BasicAuth password - password: "" - # read credentials from secret - secretRef: "" + +# basicAuth for APIs and metrics +basicAuth: + # -- HTTP BasicAuth username + username: "" + # -- HTTP BasicAuth password + password: "" + # -- (optional) Secret reference to get username and/or password from + secretRef: "" emailReports: - clusterName: "" # (optional) - displayed in the email report if configured - titlePrefix: "Report" # title prefix in the email subject + # -- (optional) - Displayed in the email report if configured + clusterName: "" + # -- Title prefix in the email subject + titlePrefix: "Report" + # -- Resource constraints for the created CronJobs + resources: {} smtp: - secret: "" # (optional) secret name to provide the complete or partial SMTP configuration + # -- (optional) Secret reference to provide the complete or partial SMTP configuration + secret: "" + # -- SMTP Server Host host: "" + # -- SMTP Server Port port: 465 + # -- SMTP Username username: "" + # -- SMTP Password password: "" - from: "" # displayed from email address - encryption: "" # default is none, supports ssl/tls and starttls + # -- Displayed from email address + from: "" + # -- SMTP Encryption + # Default is none, supports ssl/tls and starttls + encryption: "" + # -- Skip SMTP TLS verification skipTLS: false + # -- SMTP Server Certificate file path certificate: "" - # basic summary report summary: + # -- Enable Summary E-Mail reports enabled: false - schedule: "0 8 * * *" # CronJob schedule defines when the report will be send - activeDeadlineSeconds: 300 # timeout in seconds - backoffLimit: 3 # retry counter + # -- CronJob schedule + schedule: "0 8 * * *" + # -- CronJob activeDeadlineSeconds + activeDeadlineSeconds: 300 + # -- CronJob backoffLimit + backoffLimit: 3 + # -- CronJob ttlSecondsAfterFinished ttlSecondsAfterFinished: 0 - restartPolicy: Never # pod restart policy - - to: [] # list of receiver email addresses - filter: {} # optional filters - # disableClusterReports: false # remove ClusterPolicyResults from Reports + # -- CronJob restartPolicy + restartPolicy: Never + # -- List of receiver email addresses + to: [] + # -- (optional) Report filter + filter: {} + # # remove ClusterPolicyResults from Reports + # disableClusterReports: false # namespaces: # include: [] # exclude: [] # sources: # include: [] # exclude: [] - channels: [] # (optional) channels can be used to to send only a subset of namespaces / sources to dedicated email addresses channels: [] # (optional) channels can be used to to send only a subset of namespaces / sources to dedicated email addresses + # -- (optional) Channels can be used to to send only a subset of namespaces / sources to dedicated email addresses + channels: [] # - to: ['team-a@company.org'] # filter: # disableClusterReports: true @@ -262,17 +276,24 @@ emailReports: # include: ['team-a-*'] # sources: # include: ['Kyverno'] - # violation summary report + violations: + # -- Enable Violation Summary E-Mail reports enabled: false - schedule: "0 8 * * *" # CronJob schedule defines when the report will be send - activeDeadlineSeconds: 300 # timeout in seconds - backoffLimit: 3 # retry counter + # -- CronJob schedule + schedule: "0 8 * * *" + # -- CronJob activeDeadlineSeconds + activeDeadlineSeconds: 300 + # -- CronJob backoffLimit + backoffLimit: 3 + # -- CronJob ttlSecondsAfterFinished ttlSecondsAfterFinished: 0 - restartPolicy: Never # pod restart policy - - to: [] # list of receiver email addresses - filter: {} # optional filters + # -- CronJob restartPolicy + restartPolicy: Never + # -- List of receiver email addresses + to: [] + # -- (optional) Report filter + filter: {} # disableClusterReports: false # remove ClusterPolicyResults from Reports # namespaces: # include: [] @@ -280,7 +301,8 @@ emailReports: # sources: # include: [] # exclude: [] - channels: [] # (optional) channels can be used to to send only a subset of namespaces / sources to dedicated email addresses channels: [] # (optional) channels can be used to to send only a subset of namespaces / sources to dedicated email addresses + # -- (optional) Channels can be used to to send only a subset of namespaces / sources to dedicated email addresses + channels: [] # - to: ['team-a@company.org'] # filter: # disableClusterReports: true @@ -288,52 +310,45 @@ emailReports: # include: ['team-a-*'] # sources: # include: ['Kyverno'] - resources: {} - # limits: - # memory: 100Mi - # cpu: 10m - # requests: - # memory: 75Mi - # cpu: 5m -# Reference a configuration which already exists instead of creating one existingTargetConfig: + # -- Use an already existing configuration enabled: false - # Name of the secret with the config + # -- Name of the secret with the config name: "" - # subPath within the secret (defaults to config.yaml) + # -- SubPath within the secret (defaults to config.yaml) subPath: "" -# Supported targets for new PolicyReport Results target: loki: - # loki host address + # -- Host Address host: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # receive the host from an existing secret instead - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # loki api path, defaults to "/api/prom/push" (deprecated) + # -- Loki API, defaults to "/loki/api/v1/push" path: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to loki + # -- Server Certificate file path + # Can be added under extraVolumes + certificate: "" + # -- Skip TLS verification + skipTLS: false + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional labels to each Loki event - customLabels: {} - # Additional custom HTTP Headers + # -- Added as additional labels + customFields: {} + # -- Additional HTTP Headers headers: {} - # HTTP BasicAuth credentials for Loki + # -- HTTP BasicAuth username username: "" + # -- HTTP BasicAuth password password: "" - # Filter Results which should send to this target by report labels, namespaces, priorities or policies + # -- Filter Results which should send to this target # Wildcars for namespaces and policies are supported, you can either define exclude or include values # Filters are available for all targets except the UI filter: {} @@ -343,6 +358,7 @@ target: # exclude: ["debug", "info", "error"] # labels: # include: ["app", "owner:team-a", "monitoring:*"] + # -- List of channels to route results to different configurations channels: [] # - host: "http://loki.loki-stack:3100" # sources: [] @@ -356,63 +372,68 @@ target: # . include: ["app", "owner:team-b"] elasticsearch: - # elasticsearch host address + # -- Host address host: "" - # path to your custom certificate - # can be added under extraVolumes + # -- Server Certificate file path + # Can be added under extraVolumes certificate: "" - # skip TLS verification if necessary + # -- Skip TLS verification skipTLS: false - # elasticsearch index (default: policy-reporter) - index: "" - # elasticsearch username für HTTP Basic Auth - username: "" - # elasticsearch password für HTTP Basic Auth - password: "" - # elasticsearch apiKey für apiKey authentication - apiKey: "" - # receive the host, username and/or password,apiKey from an existing secret instead - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # elasticsearch index rotation and index suffix - # possible values: daily, monthly, annually, none (default: daily) - rotation: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to elasticsearch - sources: [] - # Skip already existing PolicyReportResults on startup - skipExistingOnStartup: true + # -- Elasticsearch index (default: policy-reporter) + index: "policy-reporter" + # -- Elasticsearch index rotation and index suffix + # Possible values: daily, monthly, annually, none (default: daily) + rotation: "daily" + # -- Enables Elasticsearch typless API # https://www.elastic.co/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0 keeping as false for retrocompatibility. typelessApi: false - # Added as additional properties to each elasticsearch event + # -- HTTP BasicAuth username + username: "" + # -- HTTP BasicAuth password + password: "" + # -- Elasticsearch API Key for api key authentication + apiKey: "" + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send + sources: [] + # -- Skip already existing PolicyReportResults on startup + skipExistingOnStartup: true + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional elasticsearch channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] slack: - # slack app webhook address + # -- Webhook Address webhook: "" - # slack channel + # -- Slack Channel channel: "" - # receive the webhook from an existing secret instead + # -- Read configuration from an already existing Secret secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format + # -- Mounted secret path by Secrets Controller, secret should be in json format mountedSecret: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to slack + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional fields to each Slack event + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional slack channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] # - webhook: "https://slack.webhook1" # channel: "" @@ -426,293 +447,313 @@ target: # reportLabels: # . include: ["app", "owner:team-b"] # - webhook: "https://slack.webhook2" -# minimumPriority: "warning" +# minimumSeverity: "warning" # filter: # namespaces: # include: ["team-a-*"] discord: - # discord app webhook address + # -- Webhook Address webhook: "" - # receive the webhook from an existing secret instead + # -- Read configuration from an already existing Secret secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format + # -- Mounted secret path by Secrets Controller, secret should be in json format mountedSecret: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to discord + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # filter results send by namespaces, policies and priorities + # -- Added as additional labels + customFields: {} + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional discord channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] teams: - # teams webhook address + # -- Webhook Address webhook: "" - # receive the webhook from an existing secret instead + # -- Read configuration from an already existing Secret secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format + # -- Mounted secret path by Secrets Controller, secret should be in json format mountedSecret: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to teams + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # filter results send by namespaces, policies and priorities + # -- Added as additional labels + customFields: {} + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional teams channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] - ui: - # ui host address - host: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # minimum priority "" < info < warning < critical < error - minimumPriority: "warning" - # list of sources which should send to the UI Log - sources: [] - # Skip already existing PolicyReportResults on startup - skipExistingOnStartup: true - webhook: - # webhook host address + # -- Webhook Address host: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # receive the host and/or token from an existing secret, the token is added as Authorization header - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # additional http headers + # -- Additional HTTP Headers headers: {} - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to the UI Log + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each webhook event + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional webhook channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] telegram: - # telegram bot token + # -- Telegram bot token token: "" - # telegram chat id - chatID: "" - # optional telegram proxy host + # -- Telegram chat id + chatId: "" + # -- (optional) Telegram proxy host host: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # receive the host and/or token from an existing secret, the token is added as Authorization header - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # additional http headers + # -- Additional HTTP Headers headers: {} - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to telegram + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each notification + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional telegram channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] googleChat: - # GoogleChat webhook + # -- Webhook Address webhook: "" - # path to your custom certificate - # can be added under extraVolumes - certificate: "" - # skip TLS verification if necessary - skipTLS: false - # receive the host and/or token from an existing secret, the token is added as Authorization header - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # additional http headers + # -- Additional HTTP Headers headers: {} - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to telegram + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each notification + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional telegram channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] + # Authentication via PodIdentity or WebIdentity are also supported s3: - # S3 access key - accessKeyID: "" - # S3 secret access key + # -- (optional) S3 Access key + accessKeyId: "" + # -- (optional) S3 SecretAccess key secretAccessKey: "" - # receive the accessKeyID and/or secretAccessKey from an existing secret instead - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # S3 storage region + # -- (optional) S3 Storage region region: "" - # S3 storage endpoint + # -- (optional) S3 Storage endpoint endpoint: "" - # S3 storage, bucket name + # -- (required) S3 Storage bucket name bucket: "" - # S3 storage to use an S3 Bucket Key for object encryption with SSE-KMS + # -- S3 Storage to use an S3 Bucket Key for object encryption with SSE-KMS bucketKeyEnabled: false - # S3 storage KMS Key ID for object encryption with SSE-KMS + # -- S3 Storage KMS Key ID for object encryption with SSE-KMS kmsKeyId: "" - # S3 storage server-side encryption algorithm used when storing this object in Amazon S3, AES256, aws:kms + # -- S3 Storage server-side encryption algorithm used when storing this object in Amazon S3, AES256, aws:kms serverSideEncryption: "" - # S3 storage, force path style configuration + # -- S3 Storage, force path style configuration pathStyle: false - # name of prefix, keys will have format: s3:////YYYY-MM-DD/YYYY-MM-DDTHH:mm:ss.s+01:00.json + # -- Used prefix, keys will have format: s3:////YYYY-MM-DD/YYYY-MM-DDTHH:mm:ss.s+01:00.json prefix: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to S3 + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each s3 event + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional s3 channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] + # Authentication via PodIdentity or WebIdentity are also supported kinesis: - # AWS access key - accessKeyID: "" - # AWS secret access key + # -- (optional) Access key + accessKeyId: "" + # -- (optional) SecretAccess key secretAccessKey: "" - # receive the accessKeyID and/or secretAccessKey from an existing secret instead - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # AWS region + # -- (optional) Region region: "" - # AWS Kinesis endpoint + # -- (optional) Endpoint endpoint: "" - # AWS Kinesis stream name + # -- (required) StreamName streamName: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to S3 + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each kinesis event + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional s3 channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] + # Authentication via PodIdentity or WebIdentity are also supported securityHub: - # AWS access key - accessKeyID: "" - # AWS secret access key + # -- (optional) Access key + accessKeyId: "" + # -- (optional) SecretAccess key secretAccessKey: "" - # receive the accessKeyID and/or secretAccessKey from an existing secret instead - secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format - mountedSecret: "" - # AWS region + # -- (optional) Region region: "" - # AWS SecurityHub endpoint (optional) + # -- (optional) Endpoint endpoint: "" - # AWS accountID - accountID: "" - # Used product name, defaults to "Polilcy Reporter" + # -- (required) AccountId + accountId: "" + # -- (optional) Used product name, defaults to "Polilcy Reporter" productName: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to S3 - sources: [] - # Skip already existing PolicyReportResults on startup - skipExistingOnStartup: true - # Enable cleanup listener for SecurityHub - cleanup: false - # Delay between AWS GetFindings API calls, to avoid hitting the API RequestLimit + # -- (optional) Used company name, defaults to "Kyverno" + companyName: "" + # -- Enable cleanup listener for SecurityHub + synchronize: true + # -- Delay between AWS GetFindings API calls, to avoid hitting the API RequestLimit delayInSeconds: 2 - # Added as additional properties to each securityHub event - customFields: {} - # filter results send by namespaces, policies and priorities - filter: {} - # add additional s3 channels with different configurations and filters - channels: [] - - gcs: - # GCS (Google Cloud Storage) Service Accout Credentials - credentials: "" - # receive the credentials from an existing secret instead + # -- Read configuration from an already existing Secret secretRef: "" - # Mounted secret path by Secrets Controller, secret should be in json format + # -- Mounted secret path by Secrets Controller, secret should be in json format mountedSecret: "" - # GCS Bucket - bucket: "" - # minimum priority "" < info < warning < critical < error - minimumPriority: "" - # list of sources which should send to GCS + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send sources: [] - # Skip already existing PolicyReportResults on startup + # -- Skip already existing PolicyReportResults on startup skipExistingOnStartup: true - # Added as additional properties to each gcs event + # -- Added as additional labels customFields: {} - # filter results send by namespaces, policies and priorities + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI filter: {} - # add additional s3 channels with different configurations and filters + # -- List of channels to route results to different configurations channels: [] -# required when policy-reporter runs in HA mode and you have targets configured -# if no targets are configured, leaderElection is disabled automatically + # Authentication via PodIdentity is also supported + gcs: + # -- (optional) GCS (Google Cloud Storage) Service Accout Credentials + credentials: "" + # -- (required) GCS Bucket + bucket: "" + # -- Read configuration from an already existing Secret + secretRef: "" + # -- Mounted secret path by Secrets Controller, secret should be in json format + mountedSecret: "" + # -- Minimum severity: "" < info < low < medium < high < critical + minimumSeverity: "" + # -- List of sources which should send + sources: [] + # -- Skip already existing PolicyReportResults on startup + skipExistingOnStartup: true + # -- Added as additional labels + customFields: {} + # -- Filter Results which should send to this target + # Wildcars for namespaces and policies are supported, you can either define exclude or include values + # Filters are available for all targets except the UI + filter: {} + # -- List of channels to route results to different configurations + channels: [] + +# LeaderElection configuration for HA mode # will be enabled when replicaCount > 1 leaderElection: - enabled: false releaseOnCancel: true leaseDuration: 15 renewDeadline: 10 retryPeriod: 2 -# use redis as external result cache instead of the in memory cache redis: + # -- Enables Redis as external result cache, uses in memory cache by default enabled: false + # -- Redis host address: "" + # -- Redis database database: 0 + # -- Redis key prefix prefix: "policy-reporter" + # -- (optional) Username username: "" + # -- (optional) Password password: "" +database: + # -- Use an external Database, supported: mysql, postgres, mariadb + type: "" + # -- Database + database: "" + # -- Username + username: "" + # -- Password + password: "" + # -- Host Address + host: "" + # -- Enables SSL + enableSSL: false + # -- Instead of configure the individual values you can also provide an DSN string + # example postgres: postgres://postgres:password@localhost:5432/postgres?sslmode=disable + # example mysql: root:password@tcp(localhost:3306)/test?tls=false + dsn: "" + # -- Read configuration from an existing Secret + # supported fields: username, password, host, dsn, database + secretRef: "" + # Read configuration from a mounted Secret, required the information in JSON format + # supported fields: username, password, host, dsn, database + mountedSecret: "" + # enabled if replicaCount > 1 podDisruptionBudget: # -- Configures the minimum available pods for policy-reporter disruptions. @@ -722,43 +763,823 @@ podDisruptionBudget: # Cannot be used if `minAvailable` is set. maxUnavailable: -# Node labels for pod assignment +# -- Node labels for pod assignment # ref: https://kubernetes.io/docs/user-guide/node-selection/ nodeSelector: {} -# Tolerations for pod assignment +# -- Tolerations for pod assignment # ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ tolerations: [] -# Anti-affinity to disallow deploying client and master nodes on the same worker node +# -- Anti-affinity to disallow deploying client and master nodes on the same worker node affinity: {} -# Topology Spread Constraints to better spread pods +# -- Topology Spread Constraints to better spread pods topologySpreadConstraints: [] -# livenessProbe for policy-reporter +# -- Deployment livenessProbe for policy-reporter livenessProbe: - httpGet: - path: /healthz - port: http - -# readinessProbe for policy-reporter -readinessProbe: httpGet: path: /ready port: http +# -- Deployment readinessProbe for policy-reporter +readinessProbe: + httpGet: + path: /healthz + port: http + extraVolumes: + # -- Deployment volumeMounts volumeMounts: [] + # -- Deployment values volumes: [] -# If set the volume for sqlite is freely configurable below "- name: sqlite". If no value is set an emptyDir is used. +# -- If set the volume for sqlite is freely configurable below "- name: sqlite". If no value is set an emptyDir is used. sqliteVolume: {} # emptyDir: # sizeLimit: 10Mi -# If set the volume for /tmp is freely configurable below "- name: tmp". If no value is set an emptyDir is used. +# -- Allow additional env variables to be added +envVars: [] + +# -- Allow custom configuration of the /tmp volume tmpVolume: {} - # emptyDir: - # sizeLimit: 10Mi + +ui: + # -- (bool) Enable Policy Reporter UI + enabled: false + image: + # -- (string) Image registry + registry: ghcr.io + # -- (string) Image repository + repository: kyverno/policy-reporter-ui + # -- (string) Image PullPolicy + pullPolicy: IfNotPresent + # -- (string) Image tag + tag: "2.0.0-rc.1" + + # -- Deployment replica count + replicaCount: 1 + + # -- Temporary Directory to persist session data for authentication + tempDir: "/tmp" + + logging: + # -- Enables external api request logging + api: false + # -- Enables server access logging + server: false + # -- Log encoding + # possible encodings are console and json + encoding: console + # -- Log level + # default info + logLevel: 0 + + server: + # -- Application port + port: 8080 + # -- Enabled CORS header + cors: true + # -- Overwrites Request Host with Proxy Host and adds `X-Forwarded-Host` and `X-Origin-Host` headers + overwriteHost: true + + openIDConnect: + # -- Enable openID Connect authentication + enabled: false + # -- OpenID Connect Discovery URL + discoveryUrl: "" + # -- OpenID Connect Callback URL + callbackUrl: "" + # -- OpenID Connect ClientID + clientId: "" + # -- OpenID Connect ClientSecret + clientSecret: "" + # -- OpenID Connect allowed Scopes + scopes: [] + # -- Provide OpenID Connect configuration via Secret + # supported keys: `discoveryUrl`, `clientId`, `clientSecret` + secretRef: "" + + oauth: + # -- Enable openID Connect authentication + enabled: false + # -- OAuth2 Provider + # supported: amazon, gitlab, github, apple, google, yandex, azuread + provider: "" + # -- OpenID Connect Callback URL + callbackUrl: "" + # -- OpenID Connect ClientID + clientId: "" + # -- OpenID Connect ClientSecret + clientSecret: "" + # -- OpenID Connect allowed Scopes + scopes: [] + # -- Provide OpenID Connect configuration via Secret + # supported keys: `provider`, `clientId`, `clientSecret` + secretRef: "" + + # -- optional banner text + banner: "" + + # -- DisplayMode dark/light/colorblind/colorblinddark + # uses the OS configured prefered color scheme as default + displayMode: "" + + # -- Additional customizable dashboards + customBoards: [] + # - name: Team A + # namespaces: + # # -- list of displayed namespaces + # list: [] + # # -- selector for displayed namespaces + # selector: + # team: team-a + # sources: + # # -- list of displayed sources + # list: [] + # clusterScope: + # # -- disply cluster scoped resources and results + # enabled: false + + # -- source specific configurations + sources: [] + # -- kyverno specific UI confiurations + # - name: kyverno + # -- show results per category, other option: severity + # chartType: result + # -- enabled action button to generate PolicyExceptions from the UI + # exceptions: false + # -- exclude results or (cluster)kinds per source + # excludes: + # results: + # - warn + # - error + + ## -- Default Cluster name + name: Default + + # -- Connected Policy Reporter APIs + clusters: [] + # - name: default + # host: http://policy-reporter:8080 + # secretRef: "" + # skipTLS: false + # certificate: "" + # plugins: + # - name: kyverno + # host: http://policy-reporter-kyverno-plugin:8080 + + # -- Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument + imagePullSecrets: [] + # regcred: + # registry: foo.example.com + # username: foobar + # password: secret + + serviceAccount: + # -- Create ServiceAccount + create: true + # -- Enable ServiceAccount automaount + automount: true + # -- Annotations for the ServiceAccount + annotations: {} + # -- The ServiceAccount name + name: "" + + # -- list of extra manifests + extraManifests: [] + + # -- Add sidecar containers to the UI deployment + # sidecarContainers: + # oauth-proxy: + # image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 + # args: + # - --upstream=http://127.0.0.1:8080 + # - --http-address=0.0.0.0:8081 + # - ... + # ports: + # - containerPort: 8081 + # name: oauth-proxy + # protocol: TCP + # resources: {} + sidecarContainers: {} + + # -- Additional annotations to add to each pod + podAnnotations: {} + + # -- Additional labels to add to each pod + podLabels: {} + + # -- Deployment update strategy. + # Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + updateStrategy: {} + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 40% + # type: RollingUpdate + + # -- The number of revisions to keep + revisionHistoryLimit: 10 + + # -- Security context for the pod + podSecurityContext: + runAsUser: 1234 + runAsGroup: 1234 + + # -- Allow additional env variables to be added + envVars: [] + + rbac: + # -- Create RBAC resources + enabled: true + + securityContext: + runAsUser: 1234 + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + service: + # -- Service type. + type: ClusterIP + # -- Service port. + port: 8080 + # -- Service annotations. + annotations: {} + # -- Service labels. + labels: {} + # -- Additional service ports for e.g. Sidecars # - name: authenticated + # additionalPorts: + # - name: authenticated + # port: 8081 + # targetPort: 8081 + additionalPorts: [] + + ingress: + # -- Create ingress resource. + enabled: false + # -- Redirect ingress to an additional defined port on the service + port: null + # -- Ingress class name. + className: "" + # -- Ingress labels. + labels: {} + # -- Ingress annotations. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # -- List of ingress host configurations. + hosts: [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific + # -- List of ingress TLS configurations. + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + networkPolicy: + # -- When true, use a NetworkPolicy to allow ingress to the webhook + # This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. + enabled: false + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + # Enables Kubernetes API Server by default + egress: + - ports: + - protocol: TCP + port: 6443 + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + ingress: [] + + # -- Resource constraints + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # enabled if replicaCount > 1 + podDisruptionBudget: + # -- Configures the minimum available pods for kyvernoPlugin disruptions. + # Cannot be used if `maxUnavailable` is set. + minAvailable: 1 + # -- Configures the maximum unavailable pods for kyvernoPlugin disruptions. + # Cannot be used if `minAvailable` is set. + maxUnavailable: + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Affinity constraints. + affinity: {} + +plugin: + kyverno: + # -- (bool) Enable Kyverno Plugin + enabled: false + image: + # -- (string) Image registry + registry: ghcr.io + # -- (string) Image repository + repository: kyverno/policy-reporter/kyverno-plugin + # -- (string) Image PullPolicy + pullPolicy: IfNotPresent + # -- (string) Image tag + # Defaults to `Chart.AppVersion` if omitted + tag: "0.3.0" + + # -- Deployment replica count + replicaCount: 1 + + logging: + # -- Enables external API request logging + api: false + # -- Enables Server access logging + server: false + # -- log encoding + # possible encodings are console and json + encoding: console + # -- log level + # default info + logLevel: 0 + + server: + # -- Application port + port: 8080 + + blockReports: + # -- Enables he BlockReport feature + enabled: false + # -- Watches for Kyverno Events in the configured namespace + # leave blank to watch in all namespaces + eventNamespace: default + results: + # -- Max items per PolicyReport resource + maxPerReport: 200 + # -- Keep only the latest of duplicated events + keepOnlyLatest: false + + # -- Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument + imagePullSecrets: [] + # regcred: + # registry: foo.example.com + # username: foobar + # password: secret + + serviceAccount: + # -- Create ServiceAccount + create: true + # -- Enable ServiceAccount automaount + automount: true + # -- Annotations for the ServiceAccount + annotations: {} + # -- The ServiceAccount name + name: "" + + # -- Additional annotations to add to each pod + podAnnotations: {} + + # -- Additional labels to add to each pod + podLabels: {} + + # -- Deployment update strategy. + # Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + updateStrategy: {} + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 40% + # type: RollingUpdate + + # -- The number of revisions to keep + revisionHistoryLimit: 10 + + # -- Security context for the pod + podSecurityContext: + runAsUser: 1234 + runAsGroup: 1234 + + # -- Allow additional env variables to be added + envVars: [] + + rbac: + # -- Create RBAC resources + enabled: true + + securityContext: + runAsUser: 1234 + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + service: + # -- Service type. + type: ClusterIP + # -- Service port. + port: 8080 + # -- Service annotations. + annotations: {} + # -- Service labels. + labels: {} + + ingress: + # -- Create ingress resource. + enabled: false + # -- Ingress class name. + className: "" + # -- Ingress labels. + labels: {} + # -- Ingress annotations. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # -- List of ingress host configurations. + hosts: [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific + # -- List of ingress TLS configurations. + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + networkPolicy: + # -- When true, use a NetworkPolicy to allow ingress to the webhook + # This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. + enabled: false + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + # Enables Kubernetes API Server by default + egress: + - ports: + - protocol: TCP + port: 6443 + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + ingress: [] + + # -- Resource constraints + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # required for HA mode + # if "blockReports" is disabled, leaderElection is also disabled automatically + # will be enabled when replicaCount > 1 + leaderElection: + # -- Lock Name + lockName: kyverno-plugin + # -- Released lock when the run context is cancelled. + releaseOnCancel: true + # -- LeaseDuration is the duration that non-leader candidates will wait to force acquire leadership. + leaseDuration: 15 + # -- RenewDeadline is the duration that the acting master will retry refreshing leadership before giving up. + renewDeadline: 10 + # -- RetryPeriod is the duration the LeaderElector clients should wait between tries of actions. + retryPeriod: 2 + + # enabled if replicaCount > 1 + podDisruptionBudget: + # -- Configures the minimum available pods for kyvernoPlugin disruptions. + # Cannot be used if `maxUnavailable` is set. + minAvailable: 1 + # -- Configures the maximum unavailable pods for kyvernoPlugin disruptions. + # Cannot be used if `minAvailable` is set. + maxUnavailable: + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Affinity constraints. + affinity: {} + + trivy: + # -- (bool) Enable Trivy Operator Plugin + enabled: false + image: + # -- (string) Image registry + registry: ghcr.io + # -- (string) Image repository + repository: kyverno/policy-reporter/trivy-plugin + # -- (string) Image PullPolicy + pullPolicy: IfNotPresent + # -- (string) Image tag + # Defaults to `Chart.AppVersion` if omitted + tag: "0.2.0" + + # -- Deployment replica count + replicaCount: 1 + + logging: + # -- Enables external API request logging + api: false + # -- Enables Server access logging + server: false + # -- log encoding + # possible encodings are console and json + encoding: console + # -- log level + # default info + logLevel: 0 + + server: + # -- Application port + port: 8080 + + policyReporter: + # -- Skip TLS Verification + skipTLS: false + # -- TLS Certificate + certificate: "" + # -- Secret to read the API configuration from + # supports `host`, `certificate`, `skipTLS`, `username`, `password` key + secretRef: "" + + # -- Image pull secrets for image verification policies, this will define the `--imagePullSecrets` argument + imagePullSecrets: [] + # regcred: + # registry: foo.example.com + # username: foobar + # password: secret + + serviceAccount: + # -- Create ServiceAccount + create: true + # -- Enable ServiceAccount automaount + automount: true + # -- Annotations for the ServiceAccount + annotations: {} + # -- The ServiceAccount name + name: "" + + # -- Additional annotations to add to each pod + podAnnotations: {} + + # -- Additional labels to add to each pod + podLabels: {} + + # -- Deployment update strategy. + # Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy + updateStrategy: {} + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 40% + # type: RollingUpdate + + # -- The number of revisions to keep + revisionHistoryLimit: 10 + + # -- Security context for the pod + podSecurityContext: + runAsUser: 1234 + runAsGroup: 1234 + + # -- Allow additional env variables to be added + envVars: [] + + rbac: + # -- Create RBAC resources + enabled: true + + securityContext: + runAsUser: 1234 + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + service: + # -- Service type. + type: ClusterIP + # -- Service port. + port: 8080 + # -- Service annotations. + annotations: {} + # -- Service labels. + labels: {} + + ingress: + # -- Create ingress resource. + enabled: false + # -- Ingress class name. + className: "" + # -- Ingress labels. + labels: {} + # -- Ingress annotations. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # -- List of ingress host configurations. + hosts: [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific + # -- List of ingress TLS configurations. + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + networkPolicy: + # -- When true, use a NetworkPolicy to allow ingress to the webhook + # This is useful on clusters using Calico and/or native k8s network policies in a default-deny setup. + enabled: false + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + # Enables Kubernetes API Server by default + egress: + - ports: + - protocol: TCP + port: 6443 + # -- A list of valid from selectors according to https://kubernetes.io/docs/concepts/services-networking/network-policies. + ingress: [] + + # -- Resource constraints + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + # enabled if replicaCount > 1 + podDisruptionBudget: + # -- Configures the minimum available pods for kyvernoPlugin disruptions. + # Cannot be used if `maxUnavailable` is set. + minAvailable: 1 + # -- Configures the maximum unavailable pods for kyvernoPlugin disruptions. + # Cannot be used if `minAvailable` is set. + maxUnavailable: + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Affinity constraints. + affinity: {} + +monitoring: + # -- Enables the Prometheus Operator integration + enabled: false + + # -- Key/value pairs that are attached to all resources. + annotations: {} + + serviceMonitor: + # -- HonorLabels chooses the metrics labels on collisions with target labels + honorLabels: false + # -- Allow to override the namespace for serviceMonitor + namespace: + # -- Labels to match the serviceMonitorSelector of the Prometheus Resource + labels: {} + # -- ServiceMonitor Relabelings + # https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig + relabelings: [] + # -- See serviceMonitor.relabelings + metricRelabelings: [] + # -- (optional) NamespaceSelector + namespaceSelector: {} + # -- (optional) ScrapeTimeout + scrapeTimeout: + # -- (optional) Scrape interval + interval: + + grafana: + # -- Naamespace for configMap of grafana dashboards + namespace: + dashboards: + # -- Enable the deployment of grafana dashboards + enabled: true + # -- Label to find dashboards using the k8s sidecar + label: grafana_dashboard + # -- Label value to find dashboards using the k8s sidecar + value: "1" + # -- List of custom label filter + # Used to add filter for report label based metric labels defined in custom mode + labelFilter: [] + multicluster: + # -- Enable cluster filter in all dashboards + enabled: false + # -- Metric Label which is used to filter clusters + label: cluster + enable: + # -- Enable the Overview Dashboard + overview: true + # -- Enable the PolicyReport Dashboard + policyReportDetails: true + # -- Enable the ClusterPolicyReport Dashboard + clusterPolicyReportDetails: true + folder: + # -- Annotation to enable folder storage using the k8s sidecar + annotation: grafana_folder + # -- Grafana folder in which to store the dashboards + name: Policy Reporter + datasource: + # -- Grafana Datasource Label + label: Prometheus + # -- Grafana Datasource PluginId + pluginId: prometheus + # -- Grafana Datasource PluginName + pluginName: Prometheus + + grafanaDashboard: + # -- Create GrafanaDashboard custom resource referencing to the configMap. + # according to https://grafana-operator.github.io/grafana-operator/docs/examples/dashboard_from_configmap/readme/ + enabled: false + # -- Dashboard folder + folder: kyverno + # -- Allow cross Namespace import + allowCrossNamespaceImport: true + # -- Label match selector + matchLabels: + dashboards: "grafana" + + # Customize the Grafana PolicyReport Dashboard + policyReportDetails: + firstStatusRow: + height: 8 + secondStatusRow: + enabled: true + height: 2 + statusTimeline: + enabled: true + height: 8 + passTable: + enabled: true + height: 8 + failTable: + enabled: true + height: 8 + warningTable: + enabled: true + height: 4 + errorTable: + enabled: true + height: 4 + + # Customize the Grafana ClusterPolicyReport Dashboard + clusterPolicyReportDetails: + statusRow: + height: 6 + statusTimeline: + enabled: true + height: 8 + passTable: + enabled: true + height: 8 + failTable: + enabled: true + height: 8 + warningTable: + enabled: true + height: 4 + errorTable: + enabled: true + height: 4 + + # Customize the Grafana Overview Dashboard + policyReportOverview: + failingSummaryRow: + height: 8 + failingTimeline: + height: 10 + failingPolicyRuleTable: + height: 10 + failingClusterPolicyRuleTable: + height: 10 diff --git a/cmd/run.go b/cmd/run.go index 43e00f05..c2bf64a5 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -11,6 +11,9 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + "github.com/kyverno/policy-reporter/pkg/api" + v1 "github.com/kyverno/policy-reporter/pkg/api/v1" + v2 "github.com/kyverno/policy-reporter/pkg/api/v2" "github.com/kyverno/policy-reporter/pkg/config" "github.com/kyverno/policy-reporter/pkg/database" "github.com/kyverno/policy-reporter/pkg/listener" @@ -41,6 +44,8 @@ func newRunCMD(version string) *cobra.Command { k8sConfig.Burst = c.K8sClient.Burst readinessProbe := config.NewReadinessProbe(c) + defer readinessProbe.Close() + resolver := config.NewResolver(c, k8sConfig) logger, err := resolver.Logger() if err != nil { @@ -52,11 +57,25 @@ func newRunCMD(version string) *cobra.Command { return err } - server := resolver.APIServer(cmd.Context(), client.HasSynced) + secretInformer, err := resolver.SecretInformer() + if err != nil { + return err + } g := &errgroup.Group{} var store *database.Store + servOptions := []api.ServerOption{ + api.WithPort(c.API.Port), + api.WithHealthChecks([]api.HealthCheck{ + func() error { + if !client.HasSynced() { + return errors.New("informer not ready") + } + return nil + }, + }), + } if c.REST.Enabled { db := resolver.Database() @@ -65,7 +84,12 @@ func newRunCMD(version string) *cobra.Command { } defer db.Close() - store, err = resolver.PolicyReportStore(db) + store, err = resolver.Store(db) + if err != nil { + return err + } + + nsClient, err := resolver.NamespaceClient() if err != nil { return err } @@ -76,18 +100,18 @@ func newRunCMD(version string) *cobra.Command { } logger.Info("REST api enabled") - server.RegisterV1Handler(store, resolver.ViolationsReporter()) + servOptions = append(servOptions, v1.WithAPI(store, resolver.TargetClients(), resolver.ViolationsReporter()), v2.WithAPI(store, nsClient, c.Targets)) } if c.Metrics.Enabled { logger.Info("metrics enabled") resolver.RegisterMetricsListener() - server.RegisterMetricsHandler() + servOptions = append(servOptions, api.WithMetrics()) } if c.Profiling.Enabled { logger.Info("pprof profiling enabled") - server.RegisterProfilingHandler() + servOptions = append(servOptions, api.WithProfiling()) } if !resolver.ResultCache().Shared() { @@ -145,9 +169,15 @@ func newRunCMD(version string) *cobra.Command { readinessProbe.Ready() } + server, err := resolver.Server(cmd.Context(), servOptions) + if err != nil { + return err + } + g.Go(server.Start) g.Go(func() error { + logger.Info("wait policy informer") readinessProbe.Wait() logger.Info("start client", zap.Int("worker", c.WorkerCount)) @@ -162,6 +192,26 @@ func newRunCMD(version string) *cobra.Command { } }) + g.Go(func() error { + collection := resolver.TargetClients() + if !collection.UsesSecrets() { + return nil + } + + readinessProbe.Wait() + + stop := make(chan struct{}) + if err := secretInformer.Sync(collection, stop); err != nil { + zap.L().Error("secret informer error", zap.Error(err)) + + return err + } + + <-stop + + return nil + }) + return g.Wait() }, } @@ -169,8 +219,8 @@ func newRunCMD(version string) *cobra.Command { // For local usage cmd.PersistentFlags().StringP("kubeconfig", "k", "", "absolute path to the kubeconfig file") cmd.PersistentFlags().StringP("config", "c", "", "target configuration file") - cmd.PersistentFlags().IntP("port", "p", 8080, "http port for the optional rest api") - cmd.PersistentFlags().StringP("dbfile", "d", "sqlite-database.db", "path to the SQLite DB File") + cmd.PersistentFlags().IntP("port", "p", 8001, "http port for the optional rest api") + cmd.PersistentFlags().StringP("dbfile", "d", "sqlite-database-v2.db", "path to the SQLite DB File") cmd.PersistentFlags().BoolP("metrics-enabled", "m", false, "Enable Policy Reporter's Metrics API") cmd.PersistentFlags().BoolP("rest-enabled", "r", false, "Enable Policy Reporter's REST API") cmd.PersistentFlags().Bool("profile", false, "Enable application profiling with pprof") diff --git a/cmd/send/summary.go b/cmd/send/summary.go index 34b2da3f..beeb7bfb 100644 --- a/cmd/send/summary.go +++ b/cmd/send/summary.go @@ -78,6 +78,12 @@ func NewSummaryCMD() *cobra.Command { logger.Sugar().Infof("email sent to %s\n", strings.Join(c.EmailReports.Summary.To, ", ")) }() + nsclient, err := resolver.NamespaceClient() + if err != nil { + logger.Error("failed to get namespace client", zap.Error(err)) + return err + } + for _, ch := range c.EmailReports.Violations.Channels { go func(channel config.EmailReport) { defer wg.Done() @@ -87,7 +93,7 @@ func NewSummaryCMD() *cobra.Command { return } - sources := summary.FilterSources(data, config.EmailReportFilterFromConfig(channel.Filter), !channel.Filter.DisableClusterReports) + sources := summary.FilterSources(data, config.EmailReportFilterFromConfig(nsclient, channel.Filter), !channel.Filter.DisableClusterReports) if len(sources) == 0 { logger.Info("skip email - no results to send") return diff --git a/cmd/send/violations.go b/cmd/send/violations.go index a30cf1c0..edf0c92e 100644 --- a/cmd/send/violations.go +++ b/cmd/send/violations.go @@ -78,6 +78,12 @@ func NewViolationsCMD() *cobra.Command { logger.Sugar().Infof("email sent to %s\n", strings.Join(c.EmailReports.Violations.To, ", ")) }() + nsclient, err := resolver.NamespaceClient() + if err != nil { + logger.Error("failed to get namespace client", zap.Error(err)) + return err + } + for _, ch := range c.EmailReports.Violations.Channels { go func(channel config.EmailReport) { defer wg.Done() @@ -87,7 +93,7 @@ func NewViolationsCMD() *cobra.Command { return } - sources := violations.FilterSources(data, config.EmailReportFilterFromConfig(channel.Filter), !channel.Filter.DisableClusterReports) + sources := violations.FilterSources(data, config.EmailReportFilterFromConfig(nsclient, channel.Filter), !channel.Filter.DisableClusterReports) if len(sources) == 0 { logger.Info("skip email - no results to send") return diff --git a/docs/CUSTOM_BOARDS.md b/docs/CUSTOM_BOARDS.md new file mode 100644 index 00000000..fc5229df --- /dev/null +++ b/docs/CUSTOM_BOARDS.md @@ -0,0 +1,70 @@ +# Policy Reporter UI - Custom Boards + +CustomBoards allows you to configure additional dashboards with a custom subset of sources and namespaces, selected via a list and/or label selector + +## Example CustomBoard Config + +![Custom Boards](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/custom-boards/list.png) + +```yaml +ui: + enabled: true + + customBoards: + - name: System + namespaces: + list: + - kube-system + - kyverno + - policy-reporter +``` + +### CustomBoard with NamespaceSelector + +![Custom Boards](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/custom-boards/selector.png) + +```yaml +ui: + enabled: true + + customBoards: + - name: System + namespaces: + selector: + group: system +``` + +### CustomBoard with ClusterResources +![Custom Boards](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/custom-boards/cluster.png) + +```yaml +ui: + enabled: true + + customBoards: + - name: System + clusterScope: + enabled: true + namespaces: + selector: + group: system +``` + +### CustomBoard with Source List + +![Custom Boards](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/custom-boards/source.png) + +```yaml +ui: + enabled: true + + customBoards: + - name: System + clusterScope: + enabled: true + namespaces: + selector: + group: system + sources: + list: [kyverno] +``` diff --git a/docs/EXCEPTIONS.md b/docs/EXCEPTIONS.md new file mode 100644 index 00000000..923b83a2 --- /dev/null +++ b/docs/EXCEPTIONS.md @@ -0,0 +1,64 @@ +# Policy Reporter UI - Generate Kyverno PolicyExceptions + +The Policy Reporter UI provides a visual overview of the policy status in your cluster, but no action you can take to change the status by default. + +In the case of Kyverno, you have two options for dealing with policy failure. You can either fix it or create an exception for it. While the first option is difficult to automate and not always possible, creating an exception is relatively easy and can help exclude resources from validation that you are not able to fix immediately. + +To support this process, the new Policy Reporter plugin system provides an Exception API that can be used to implement source-specific logic for PolicyException creation. The new Policy Reporter Kyverno plugin utilizes this API to provide an automated method for generating Kyverno PolicyException CRD resources that excludes a single or all failed policies depending on the context in the UI. + +## Configuration + +Because the Exception API is part of the Policy Reporter Kyverno Plugin, its required to install this plugin to use it and enable the exception feature. + +### Helm 3 Configuration + +```yaml +plugin: + kyverno: + enabled: true + +ui: + enabled: true + sources: + - name: kyverno + exceptions: true + excludes: + namespaceKinds: + - Pod + - Job + - ReplicaSet + results: + - warn + - error +``` + +### Alternative manual UI Configuration + +```yaml +# Configure the Kyverno Plugin the Cluster config +clusters: +- name: Default + host: http://policy-reporter:8080 + plugins: + - name: kyverno + host: http://policy-reporter-kyverno-plugin:8080/api + +# Enable `exceptions` in the kyverno source configuration +sources: + - name: kyverno + exceptions: true + excludes: + namespaceKinds: + - Pod + - Job + - ReplicaSet + results: + - warn + - error +``` + +### Examples + +![Exception Resource List](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/exceptions/resource-list.png) + +![Exception Dialog](https://github.com/kyverno/policy-reporter/blob/3.x/docs/images/exceptions/exception-dialog.png) diff --git a/docs/SETUP.md b/docs/SETUP.md new file mode 100644 index 00000000..e49af359 --- /dev/null +++ b/docs/SETUP.md @@ -0,0 +1,30 @@ +# Setup Kyverno and Policy Reporter + +## Install Kyverno + Kyverno PSS Policies + +Add Helm Repo + +```bash +helm repo add kyverno https://kyverno.github.io/kyverno/ +helm repo update +``` + +Install Kyverno + PSS Policies + +```bash +helm upgrade --install kyverno kyverno/kyverno -n kyverno --create-namespace +helm upgrade --install kyverno-policies kyverno/kyverno-policies -n kyverno --create-namespace --set podSecurityStandard=restricted +``` + +## Installing Policy Reporter v3 Preview and Policy Reporter UI v2 + Kyverno Plugin + +```bash +helm repo add policy-reporter https://kyverno.github.io/policy-reporter +helm repo update +``` + +Install the Policy Reporter Preview + +```bash +helm upgrade --install policy-reporter policy-reporter/policy-reporter --create-namespace -n policy-reporter --devel --set ui.enabled=true --set plugin.kyverno.enabled=true +``` \ No newline at end of file diff --git a/docs/UI_AUTH.md b/docs/UI_AUTH.md new file mode 100644 index 00000000..c7d25b18 --- /dev/null +++ b/docs/UI_AUTH.md @@ -0,0 +1,104 @@ +# Configure Authentication for Policy Reporter UI + +With Policy Reporter UI v2 it is possible to use either OAuth2 or OpenIDConnect as authentication mechanism. + +Its not possible to reduce or configure view permission based on roles or any other information yet. +Authentication ensures that no unauthorized person is able to open the UI at all. + +## OAuth2 + +Policy Reporter UI v2 supports a fixed set of oauth2 providers. If the provider of your choice is not yet supported, you can submit a feature request for it. + +### Supported OAuth Provider + +* amazon +* gitlab +* github +* apple +* google +* yandex +* azuread + +### Example Configuration (GitHub Provider) + +Since the callback URL depends on your setup, you must explicitly configure it. + +```yaml +ui: + oauth: + enabled: true + clientId: c79c02881aa1... + clientSecret: fb2035255d0bd182c9... + provider: github + callback: http://localhost:8082/callback + scopes: [] +``` + +### Example SecretRef + +Instead of providing the information directly in the values, you can also fetch the information from an existing secret. + +#### Values + +```yaml +ui: + oauth: + enabled: true + callback: http://localhost:8082/callback + scopes: [] + secretRef: 'github-provider' +``` +#### Secret + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: github-provider +data: + clientId: Yzc5YzAyODgxYWEx + clientSecret: ZmIyMDM1MjU1ZDBiZDE4MmM5 + provider: Z2l0aHVi +``` + +## OpenIDConnect + +This authentication mechanism supports all compatible services and systems. + +### Example Configuration (Keycloak) + +```yaml +ui: + openIDConnect: + enabled: true + clientId: policy-reporter + clientSecret: c11cYF9tNtL94w.... + callbackUrl: http://localhost:8082/callback + discoveryUrl: 'https://keycloak.instance.de/realms/timetracker' +``` + +### Example SecretRef + +Instead of providing the information directly in the values, you can also fetch the information from an existing secret. + +#### Values + +```yaml +ui: + openIDConnect: + enabled: true + callback: http://localhost:8082/callback + secretRef: 'keycloak-provider' +``` +#### Secret + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: keycloak-provider +data: + clientId: Yzc5YzAyODgxYWEx + clientSecret: ZmIyMDM1MjU1ZDBiZDE4MmM5 + discoveryUrl: aHR0cHM6Ly9rZXljbG9hay5pbnN0YW5jZS5kZS9yZWFsbXMvdGltZXRyYWNrZXI= +``` diff --git a/docs/images/custom-boards/cluster.png b/docs/images/custom-boards/cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..ad6fcda52e4ee9b6868adae0aa1991edfd1babbd GIT binary patch literal 200428 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

i-&^^KqM=&`I8;m9dL9= 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 LOL`<-O!R*M<@n3J literal 0 HcmV?d00001 diff --git a/docs/images/custom-boards/list.png b/docs/images/custom-boards/list.png new file mode 100644 index 0000000000000000000000000000000000000000..8e7403f23b0137659f70e799651593b97c2aedb4 GIT binary patch literal 186963 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%0DkWTgdP#doIk9m- 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 z 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⪙6 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 N>MEMbr4NkX{2v$yVAB8q literal 0 HcmV?d00001 diff --git a/docs/images/custom-boards/selector.png b/docs/images/custom-boards/selector.png new file mode 100644 index 0000000000000000000000000000000000000000..d26f56e9549a304a18918b745765c76bdd360acd GIT binary patch literal 189467 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%0Am`=|d(D48ABF$j?mHi~_wW0#N4o&5ek7EneL3j+ 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

    6n>*etf7bh1`hVPFrQbRjBca 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 Mdvd>2#q8bx10T&foB#j- literal 0 HcmV?d00001 diff --git a/docs/images/custom-boards/source.png b/docs/images/custom-boards/source.png new file mode 100644 index 0000000000000000000000000000000000000000..d284975f03432f8011ba63c65ed08b15f209fa90 GIT binary patch literal 194909 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̼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�NuAOu&jtJGwknwz_Go9jNA41Mcno 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%0DJ&o7%93e1z2pO^xGvL6EK=FS+Q+6-NhN>^ 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 literal 0 HcmV?d00001 diff --git a/docs/images/exceptions/resource-list.png b/docs/images/exceptions/resource-list.png new file mode 100644 index 0000000000000000000000000000000000000000..2c722232995d397a90be7e59a1951cecee6447a7 GIT binary patch literal 199119 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
    W>~T3tV$&#AFVBVLpNXR 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�=%VGN1yR>K);0999I}mZ0y7U9JZI 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

    #3ww2%#1;NH;78VS>@~qP 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

    GlST&wEQ{Uv*J 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�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 0, + ClusterPassed: cPass, + ClusterResults: cResults, + NamespacePassed: nsPass, + NamespaceResults: nsResults, + }) + } + + data, err := h.reporter.Report(sources, "HTML") + if err != nil { + zap.L().Error("failed to load data", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + + ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(data.Message)) +} + +func NewAPIHandler(store *db.Store, targets *target.Collection, reporter *violations.Reporter) *APIHandler { + return &APIHandler{store, targets, reporter} +} + +func WithAPI(store *db.Store, targets *target.Collection, reporter *violations.Reporter) api.ServerOption { + return func(s *api.Server) error { + return s.Register("v1", NewAPIHandler(store, targets, reporter)) + } +} diff --git a/pkg/api/v1/api_test.go b/pkg/api/v1/api_test.go new file mode 100644 index 00000000..c9bb8897 --- /dev/null +++ b/pkg/api/v1/api_test.go @@ -0,0 +1,301 @@ +package v1_test + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/api" + v1 "github.com/kyverno/policy-reporter/pkg/api/v1" + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/email/violations" + "github.com/kyverno/policy-reporter/pkg/fixtures" + "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/report/result" + "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/webhook" +) + +var reconditioner = result.NewReconditioner(nil) + +func TestV1(t *testing.T) { + db, err := database.NewSQLiteDB("db_v2.db") + if err != nil { + assert.Fail(t, "failed to init SQLite DB") + } + + store, err := database.NewStore(db, "1.0") + if err != nil { + assert.Fail(t, "failed to init Store") + } + + if err := store.PrepareDatabase(context.Background()); err != nil { + assert.Fail(t, "failed to prepare Store") + } + + store.Add(context.Background(), reconditioner.Prepare(fixtures.DefaultPolicyReport)) + store.Add(context.Background(), reconditioner.Prepare(fixtures.KyvernoPolicyReport)) + store.Add(context.Background(), reconditioner.Prepare(fixtures.KyvernoClusterPolicyReport)) + + gin.SetMode(gin.ReleaseMode) + + server := api.NewServer(gin.New(), v1.WithAPI(store, target.NewCollection(&target.Target{ + Client: webhook.NewClient(webhook.Options{ + ClientOptions: target.ClientOptions{ + Name: "Webhook", + SkipExistingOnStartup: true, + ResultFilter: &report.ResultFilter{ + MinimumSeverity: "", + Sources: []string{"Kyverno"}, + }, + }, + Host: "http://localhost:8080", + }), + }), violations.NewReporter("../../../templates", "Cluster", "Report"))) + + t.Run("TargetResponse", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/targets", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.Target, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Contains(t, resp, v1.Target{ + Name: "Webhook", + MinimumSeverity: v1alpha2.SeverityInfo, + Sources: []string{"Kyverno"}, + SkipExistingOnStartup: true, + }) + } + }) + + t.Run("ListPolicyReports", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/policy-reports", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := api.Paginated[v1.PolicyReport]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, resp.Count) + } + }) + + t.Run("ListClusterPolicyReports", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/cluster-policy-reports", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := api.Paginated[v1.PolicyReport]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, resp.Count) + } + }) + + t.Run("ListNamespaces", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/namespaces", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, len(resp)) + } + }) + + t.Run("RuleStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/rule-status-count?policy=required-limit&rule=resource-limit-required", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.StatusCount, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 5, len(resp)) + assert.Contains(t, resp, v1.StatusCount{Status: "pass", Count: 1}) + assert.Contains(t, resp, v1.StatusCount{Status: "warn", Count: 1}) + } + }) + + t.Run("ListClusterFilter(Source)", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/cluster-resources/sources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Contains(t, resp, "Kyverno") + } + }) + + t.Run("ListNamespacedFilter(Source)", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/namespaced-resources/sources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, len(resp)) + assert.Contains(t, resp, "Kyverno") + } + }) + + t.Run("ListClusterResources", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/cluster-resources/resources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.Resource, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + } + }) + + t.Run("ListNamespacedResources", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/namespaced-resources/resources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.Resource, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 4, len(resp)) + } + }) + + t.Run("ListClusterStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/cluster-resources/status-counts", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.StatusCount, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 5, len(resp)) + } + }) + + t.Run("ListNamespacedStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/namespaced-resources/status-counts", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v1.NamespaceCount, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 5, len(resp)) + } + }) + + t.Run("ListClusterResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/cluster-resources/results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := api.Paginated[v1.Result]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, resp.Count) + } + }) + + t.Run("ListNamespacedResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/namespaced-resources/results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := api.Paginated[v1.Result]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 5, resp.Count) + } + }) + + t.Run("HTMLViolationsReport", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v1/html-report/violations", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + }) +} diff --git a/pkg/api/v1/finder.go b/pkg/api/v1/finder.go deleted file mode 100644 index 872cc741..00000000 --- a/pkg/api/v1/finder.go +++ /dev/null @@ -1,81 +0,0 @@ -package v1 - -import ( - "context" -) - -type Filter struct { - Kinds []string - Categories []string - Namespaces []string - Sources []string - Policies []string - Rules []string - Severities []string - Status []string - Resources []string - ReportLabel map[string]string - Search string -} - -type Pagination struct { - Page int - Offset int - SortBy []string - Direction string -} - -type PolicyReportFinder interface { - // FetchClusterPolicyReports by filter and pagination - FetchClusterPolicyReports(context.Context, Filter, Pagination) ([]*PolicyReport, error) - // FetchPolicyReports by filter and pagination - FetchPolicyReports(context.Context, Filter, Pagination) ([]*PolicyReport, error) - // CountClusterPolicyReports by filter - CountClusterPolicyReports(context.Context, Filter) (int, error) - // CountPolicyReports by filter - CountPolicyReports(context.Context, Filter) (int, error) - // FetchClusterPolicies from current PolicyReportResults - FetchClusterPolicies(context.Context, Filter) ([]string, error) - // FetchClusterRules from current PolicyReportResults - FetchClusterRules(context.Context, Filter) ([]string, error) - // FetchNamespacedPolicies from current PolicyReportResults with a Namespace - FetchNamespacedPolicies(context.Context, Filter) ([]string, error) - // FetchNamespacedRules from current PolicyReportResults with a Namespace - FetchNamespacedRules(context.Context, Filter) ([]string, error) - // FetchClusterCategories from current PolicyReportResults - FetchClusterCategories(context.Context, Filter) ([]string, error) - // FetchNamespacedCategories from current PolicyReportResults - FetchNamespacedCategories(context.Context, Filter) ([]string, error) - // FetchClusterSources from current PolicyReportResults - FetchClusterSources(context.Context) ([]string, error) - // FetchNamespacedSources from current PolicyReportResults with a Namespace - FetchNamespacedSources(context.Context) ([]string, error) - // FetchNamespacedKinds from current PolicyReportResults with a Namespace - FetchNamespacedKinds(context.Context, Filter) ([]string, error) - // FetchNamespacedResources from current PolicyReportResults with a Namespace - FetchNamespacedResources(context.Context, Filter) ([]*Resource, error) - // FetchClusterResources from current PolicyReportResults - FetchClusterResources(context.Context, Filter) ([]*Resource, error) - // FetchClusterKinds from current PolicyReportResults - FetchClusterKinds(context.Context, Filter) ([]string, error) - // FetchNamespaces from current PolicyReports - FetchNamespaces(context.Context, Filter) ([]string, error) - // FetchNamespacedStatusCounts from current PolicyReportResults with a Namespace - FetchNamespacedStatusCounts(context.Context, Filter) ([]NamespacedStatusCount, error) - // FetchClusterStatusCounts from current PolicyReportResults - FetchClusterStatusCounts(context.Context, Filter) ([]StatusCount, error) - // FetchNamespacedResults from current PolicyReportResults with a Namespace - FetchNamespacedResults(context.Context, Filter, Pagination) ([]*ListResult, error) - // FetchClusterResults from current PolicyReportResults - FetchClusterResults(context.Context, Filter, Pagination) ([]*ListResult, error) - // CountNamespacedResults from current PolicyReportResults with a Namespace - CountNamespacedResults(context.Context, Filter) (int, error) - // CountClusterResults from current PolicyReportResults - CountClusterResults(context.Context, Filter) (int, error) - // FetchRuleStatusCounts from current PolicyReportResults - FetchRuleStatusCounts(context.Context, string, string) ([]StatusCount, error) - // FetchClusterReportLabels from ClusterPolicyReports - FetchClusterReportLabels(context.Context, Filter) (map[string][]string, error) - // FetchNamespacedReportLabels from PolicyReports - FetchNamespacedReportLabels(context.Context, Filter) (map[string][]string, error) -} diff --git a/pkg/api/v1/handler.go b/pkg/api/v1/handler.go deleted file mode 100644 index 93935bbe..00000000 --- a/pkg/api/v1/handler.go +++ /dev/null @@ -1,310 +0,0 @@ -package v1 - -import ( - "net/http" - "strconv" - "strings" - - "go.uber.org/zap" - - "github.com/kyverno/policy-reporter/pkg/helper" - "github.com/kyverno/policy-reporter/pkg/target" -) - -var defaultOrder = []string{"resource_namespace", "resource_name", "resource_uid", "policy", "rule", "message"} - -type Handler struct { - finder PolicyReportFinder -} - -func (h *Handler) logError(err error) { - if err != nil { - zap.L().Error("failed to load data", zap.Error(err)) - } -} - -// TargetsHandler for the Targets REST API -func (h *Handler) TargetsHandler(targets []target.Client) http.HandlerFunc { - apiTargets := make([]Target, 0, len(targets)) - for _, t := range targets { - apiTargets = append(apiTargets, mapTarget(t)) - } - - return func(w http.ResponseWriter, req *http.Request) { - helper.SendJSONResponse(w, apiTargets, nil) - } -} - -// PolicyReportListHandler REST API -func (h *Handler) PolicyReportListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - filter := buildFilter(req) - count, _ := h.finder.CountPolicyReports(req.Context(), filter) - list, err := h.finder.FetchPolicyReports(req.Context(), filter, buildPagination(req, []string{"namespace", "name"})) - h.logError(err) - helper.SendJSONResponse(w, PolicyReportList{Items: list, Count: count}, err) - } -} - -// PolicyReportListHandler REST API -func (h *Handler) ClusterPolicyReportListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - filter := buildFilter(req) - count, _ := h.finder.CountClusterPolicyReports(req.Context(), filter) - list, err := h.finder.FetchClusterPolicyReports(req.Context(), filter, buildPagination(req, []string{"namespace", "name"})) - h.logError(err) - helper.SendJSONResponse(w, PolicyReportList{Items: list, Count: count}, err) - } -} - -// ClusterResourcesPolicyListHandler REST API -func (h *Handler) ClusterResourcesPolicyListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterPolicies(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterResourcesRuleListHandler REST API -func (h *Handler) ClusterResourcesRuleListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterRules(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesPolicyListHandler REST API -func (h *Handler) NamespacedResourcesPolicyListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedPolicies(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesRuleListHandler REST API -func (h *Handler) NamespacedResourcesRuleListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedRules(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// CategoryListHandler REST API -func (h *Handler) ClusterCategoryListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterCategories(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// CategoryListHandler REST API -func (h *Handler) NamespacedCategoryListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedCategories(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterResourcesKindListHandler REST API -func (h *Handler) ClusterResourcesKindListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterKinds(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesKindListHandler REST API -func (h *Handler) NamespacedResourcesKindListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedKinds(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterResourcesListHandler REST API -func (h *Handler) ClusterResourcesListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterResources(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesListHandler REST API -func (h *Handler) NamespacedResourcesListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedResources(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterResourcesSourceListHandler REST API -func (h *Handler) ClusterResourcesSourceListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterSources(req.Context()) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedSourceListHandler REST API -func (h *Handler) NamespacedSourceListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedSources(req.Context()) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedReportLabelListHandler REST API -func (h *Handler) NamespacedReportLabelListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedReportLabels(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterReportLabelListHandler REST API -func (h *Handler) ClusterReportLabelListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterReportLabels(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// ClusterResourcesStatusCountHandler REST API -func (h *Handler) ClusterResourcesStatusCountHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchClusterStatusCounts(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesStatusCountsHandler REST API -func (h *Handler) NamespacedResourcesStatusCountsHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespacedStatusCounts(req.Context(), buildFilter(req)) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// RuleStatusCountHandler REST API -func (h *Handler) RuleStatusCountHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchRuleStatusCounts( - req.Context(), - req.URL.Query().Get("policy"), - req.URL.Query().Get("rule"), - ) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -// NamespacedResourcesResultHandler REST API -func (h *Handler) NamespacedResourcesResultHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - filter := buildFilter(req) - count, _ := h.finder.CountNamespacedResults(req.Context(), filter) - list, err := h.finder.FetchNamespacedResults(req.Context(), filter, buildPagination(req, defaultOrder)) - h.logError(err) - helper.SendJSONResponse(w, ResultList{Items: list, Count: count}, err) - } -} - -// ClusterResourcesResultHandler REST API -func (h *Handler) ClusterResourcesResultHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - filter := buildFilter(req) - count, _ := h.finder.CountClusterResults(req.Context(), filter) - list, err := h.finder.FetchClusterResults(req.Context(), filter, buildPagination(req, defaultOrder)) - h.logError(err) - helper.SendJSONResponse(w, ResultList{Items: list, Count: count}, err) - } -} - -// NamespaceListHandler REST API -func (h *Handler) NamespaceListHandler() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - list, err := h.finder.FetchNamespaces(req.Context(), Filter{ - Sources: req.URL.Query()["sources"], - Categories: req.URL.Query()["categories"], - Policies: req.URL.Query()["policies"], - Rules: req.URL.Query()["rules"], - }) - h.logError(err) - helper.SendJSONResponse(w, list, err) - } -} - -func buildPagination(req *http.Request, defaultOrder []string) Pagination { - page, err := strconv.Atoi(req.URL.Query().Get("page")) - if err != nil || page < 1 { - page = 0 - } - offset, err := strconv.Atoi(req.URL.Query().Get("offset")) - if err != nil || offset < 1 { - offset = 0 - } - direction := "ASC" - if strings.ToLower(req.URL.Query().Get("direction")) == "desc" { - direction = "DESC" - } - sortBy := req.URL.Query()["sortBy"] - if len(sortBy) == 0 { - sortBy = defaultOrder - } - - return Pagination{ - Page: page, - Offset: offset, - SortBy: sortBy, - Direction: direction, - } -} - -func buildFilter(req *http.Request) Filter { - labels := map[string]string{} - - for _, label := range req.URL.Query()["labels"] { - parts := strings.Split(label, ":") - if len(parts) != 2 { - continue - } - - labels[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - - return Filter{ - Namespaces: req.URL.Query()["namespaces"], - Kinds: req.URL.Query()["kinds"], - Resources: req.URL.Query()["resources"], - Sources: req.URL.Query()["sources"], - Categories: req.URL.Query()["categories"], - Severities: req.URL.Query()["severities"], - Policies: req.URL.Query()["policies"], - Rules: req.URL.Query()["rules"], - Status: req.URL.Query()["status"], - ReportLabel: labels, - Search: req.URL.Query().Get("search"), - } -} - -func NewHandler(finder PolicyReportFinder) *Handler { - return &Handler{ - finder: finder, - } -} diff --git a/pkg/api/v1/handler_test.go b/pkg/api/v1/handler_test.go deleted file mode 100644 index ae286c4f..00000000 --- a/pkg/api/v1/handler_test.go +++ /dev/null @@ -1,667 +0,0 @@ -package v1_test - -import ( - "context" - "net/http" - "net/http/httptest" - "strings" - "testing" - "time" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - v1 "github.com/kyverno/policy-reporter/pkg/api/v1" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/database" - "github.com/kyverno/policy-reporter/pkg/email/violations" - "github.com/kyverno/policy-reporter/pkg/target" - "github.com/kyverno/policy-reporter/pkg/target/loki" -) - -var seconds = time.Date(2022, 9, 6, 0, 0, 0, 0, time.UTC).Unix() - -var result1 = v1alpha2.PolicyReportResult{ - ID: "123", - Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "require-requests-and-limits-required", - Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.ErrorPriority, - Result: v1alpha2.StatusFail, - Category: "Best Practices", - Severity: v1alpha2.SeverityHigh, - Scored: true, - Source: "Kyverno", - Timestamp: metav1.Timestamp{Seconds: seconds}, - Resources: []corev1.ObjectReference{{ - APIVersion: "v1", - Kind: "Deployment", - Name: "nginx", - Namespace: "test", - UID: "536ab69f-1b3c-4bd9-9ba4-274a56188409", - }}, -} - -var result2 = v1alpha2.PolicyReportResult{ - ID: "124", - Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "require-requests-and-limits-required", - Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, - Result: v1alpha2.StatusPass, - Category: "Best Practices", - Scored: true, - Source: "Kyverno", - Timestamp: metav1.Timestamp{Seconds: seconds}, - Resources: []corev1.ObjectReference{{ - APIVersion: "v1", - Kind: "Pod", - Name: "nginx", - Namespace: "test", - UID: "536ab69f-1b3c-4bd9-9ba4-274a56188419", - }}, -} - -var cresult1 = v1alpha2.PolicyReportResult{ - ID: "125", - Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace", - Policy: "require-ns-labels", - Rule: "check-for-labels-on-namespace", - Priority: v1alpha2.ErrorPriority, - Result: v1alpha2.StatusPass, - Category: "Convention", - Severity: v1alpha2.SeverityMedium, - Scored: true, - Source: "Kyverno", - Timestamp: metav1.Timestamp{Seconds: seconds}, - Resources: []corev1.ObjectReference{{ - APIVersion: "v1", - Kind: "Namespace", - Name: "test", - UID: "536ab69f-1b3c-4bd9-9ba4-274a56188411", - }}, -} - -var cresult2 = v1alpha2.PolicyReportResult{ - ID: "126", - Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace", - Policy: "require-ns-labels", - Rule: "check-for-labels-on-namespace", - Priority: v1alpha2.WarningPriority, - Result: v1alpha2.StatusFail, - Category: "Convention", - Severity: v1alpha2.SeverityHigh, - Scored: true, - Source: "Kyverno", - Resources: []corev1.ObjectReference{{ - APIVersion: "v1", - Kind: "Namespace", - Name: "dev", - UID: "536ab69f-1b3c-4bd9-9ba4-274a56188412", - }}, -} - -var preport = &v1alpha2.PolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"app": "policy-reporter", "scope": "namespace"}, - Name: "polr-test", - Namespace: "test", - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{result1, result2}, - Summary: v1alpha2.PolicyReportSummary{Fail: 1}, -} - -var creport = &v1alpha2.ClusterPolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"app": "policy-reporter", "scope": "cluster"}, - Name: "cpolr", - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{cresult1, cresult2}, - Summary: v1alpha2.PolicyReportSummary{}, -} - -var ctx = context.Background() - -func Test_V1_API(t *testing.T) { - db, err := database.NewSQLiteDB("test.db") - if err != nil { - t.Error(err) - } - defer db.Close() - if err != nil { - t.Fatal(err) - } - store, err := database.NewStore(db, "test") - if err != nil { - t.Fatal(err) - } - store.PrepareDatabase(ctx) - defer store.CleanUp(ctx) - - store.Add(ctx, preport) - store.Add(ctx, creport) - - handl := v1.NewHandler(store) - htmlHandl := v1.NewHTMLHandler(store, violations.NewReporter("../../../templates", "Cluster", "Report")) - - t.Run("ClusterPolicyListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-policies", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesPolicyListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["require-ns-labels"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterRuleListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-rules", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesRuleListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["check-for-labels-on-namespace"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedPolicyListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-policies", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesPolicyListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["require-requests-and-limits-required"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedRuleListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-rules", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesRuleListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["autogen-check-for-requests-and-limits"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedCategoryListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/categories", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedCategoryListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Best Practices"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterCategoryListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/categories", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterCategoryListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Convention"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterKindListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-kinds", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesKindListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Namespace"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedKindListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-kinds", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesKindListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Deployment","Pod"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterResourcesListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-resources/resources", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"name":"dev","kind":"Namespace"},{"name":"test","kind":"Namespace"}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedResourcesListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-resources/resources", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"name":"nginx","kind":"Deployment"},{"name":"nginx","kind":"Pod"}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterSourceListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-sources", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesSourceListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Kyverno"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedSourceListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namspaced-sources", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedSourceListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["Kyverno"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterStatusCountHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-status-counts?status=pass", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesStatusCountHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"status":"pass","count":1}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedStatusCountHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-status-counts?status=pass", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesStatusCountsHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"status":"pass","items":[{"namespace":"test","count":1}]}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("RuleStatusCountHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/rule-status-count?policy=require-requests-and-limits-required&rule=autogen-check-for-requests-and-limits", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.RuleStatusCountHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `{"status":"fail","count":1}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - - expected = `{"status":"pass","count":1}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - - expected = `{"status":"warn","count":0}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespacedResultHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-results?direction=desc", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedResourcesResultHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"id":"123","namespace":"test","kind":"Deployment","apiVersion":"v1","name":"nginx","message":"validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/","category":"Best Practices","policy":"require-requests-and-limits-required","rule":"autogen-check-for-requests-and-limits","status":"fail","severity":"high","timestamp":1662422400},{"id":"124","namespace":"test","kind":"Pod","apiVersion":"v1","name":"nginx","message":"validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/","category":"Best Practices","policy":"require-requests-and-limits-required","rule":"autogen-check-for-requests-and-limits","status":"pass","timestamp":1662422400}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterResultHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-results?direction=desc", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterResourcesResultHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := "{\"id\":\"125\",\"kind\":\"Namespace\",\"apiVersion\":\"v1\",\"name\":\"test\",\"message\":\"validation error: The label `test` is required. Rule check-for-labels-on-namespace\",\"category\":\"Convention\",\"policy\":\"require-ns-labels\",\"rule\":\"check-for-labels-on-namespace\",\"status\":\"pass\",\"severity\":\"medium\",\"timestamp\":1662422400}" - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("NamespaceListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaces", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespaceListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `["test"]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterReportLabelListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/cluster-resources/report-labels?sources=Kyverno", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterReportLabelListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `{"app":["policy-reporter"],"scope":["cluster"]}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterReportLabelListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/namespaced-resources/report-labels?sources=Kyverno", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.NamespacedReportLabelListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `{"app":["policy-reporter"],"scope":["namespace"]}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("PolicyReportListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/policy-reports?namespaces=test&labels=app:policy-reporter", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.PolicyReportListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `{"items":[{"id":"7605991845421273693","name":"polr-test","namespace":"test","source":"Kyverno","labels":{"app":"policy-reporter","scope":"namespace"},"pass":0,"skip":0,"warn":0,"error":0,"fail":1}],"count":1}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("ClusterPolicyReportListHandler", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/policy-reports?labels=app:policy-reporter", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.ClusterPolicyReportListHandler() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `{"items":[{"id":"7174304213499286261","name":"cpolr","source":"Kyverno","labels":{"app":"policy-reporter","scope":"cluster"},"pass":0,"skip":0,"warn":0,"error":0,"fail":0}],"count":1}` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - - t.Run("HTMLReport", func(t *testing.T) { - req, err := http.NewRequest("GET", "/v1/html-report/violations", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := htmlHandl.HTMLReport() - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - }) -} - -func Test_TargetsAPI(t *testing.T) { - handl := v1.NewHandler(nil) - - t.Run("Empty Respose", func(t *testing.T) { - req, err := http.NewRequest("GET", "/targets", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.TargetsHandler(make([]target.Client, 0)) - - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := "[]" - - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) - t.Run("Respose", func(t *testing.T) { - req, err := http.NewRequest("GET", "/targets", nil) - if err != nil { - t.Fatal(err) - } - - rr := httptest.NewRecorder() - handler := handl.TargetsHandler([]target.Client{ - loki.NewClient(loki.Options{ - ClientOptions: target.ClientOptions{ - Name: "Loki", - SkipExistingOnStartup: true, - }, - HTTPClient: &http.Client{}, - }), - }) - - handler.ServeHTTP(rr, req) - - if status := rr.Code; status != http.StatusOK { - t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) - } - - expected := `[{"name":"Loki","minimumPriority":"debug","skipExistingOnStartup":true}]` - if !strings.Contains(rr.Body.String(), expected) { - t.Errorf("handler returned unexpected body: got %v want %v", rr.Body.String(), expected) - } - }) -} diff --git a/pkg/api/v1/html_report.go b/pkg/api/v1/html_report.go deleted file mode 100644 index 550fefee..00000000 --- a/pkg/api/v1/html_report.go +++ /dev/null @@ -1,146 +0,0 @@ -package v1 - -import ( - "net/http" - "slices" - - "github.com/kyverno/policy-reporter/pkg/email/violations" - "go.uber.org/zap" -) - -type HTMLHandler struct { - reporter *violations.Reporter - finder PolicyReportFinder -} - -func (h *HTMLHandler) HTMLReport() http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - sources := make([]violations.Source, 0) - - namespaced, err := h.finder.FetchNamespacedSources(req.Context()) - if err != nil { - zap.L().Error("failed to load data", zap.Error(err)) - w.WriteHeader(http.StatusInternalServerError) - return - } - - cluster, err := h.finder.FetchClusterSources(req.Context()) - if err != nil { - zap.L().Error("failed to load data", zap.Error(err)) - w.WriteHeader(http.StatusInternalServerError) - return - } - - list := append(namespaced, cluster...) - slices.Sort(list) - list = slices.Compact(list) - - for _, source := range list { - cPass, err := h.finder.CountClusterResults(req.Context(), Filter{ - Sources: []string{source}, - Status: []string{"pass"}, - }) - if err != nil { - continue - } - - statusCounts, err := h.finder.FetchNamespacedStatusCounts(req.Context(), Filter{ - Sources: []string{source}, - Status: []string{"pass"}, - }) - if err != nil { - continue - } - - nsPass := make(map[string]int, len(statusCounts)) - for _, s := range statusCounts[0].Items { - nsPass[s.Namespace] = s.Count - } - - clusterResults, err := h.finder.FetchClusterResults(req.Context(), Filter{ - Sources: []string{source}, - Status: []string{"warn", "fail", "error"}, - }, Pagination{SortBy: defaultOrder}) - if err != nil { - continue - } - - cResults := make(map[string][]violations.Result) - for _, r := range clusterResults { - if _, ok := cResults[r.Status]; !ok { - cResults[r.Status] = make([]violations.Result, 0) - } - - cResults[r.Status] = append(cResults[r.Status], violations.Result{ - Kind: r.Kind, - Name: r.Name, - Policy: r.Policy, - Rule: r.Rule, - Status: r.Status, - }) - } - - namespaces, err := h.finder.FetchNamespaces(req.Context(), Filter{ - Sources: []string{source}, - }) - if err != nil { - continue - } - - nsResults := make(map[string]map[string][]violations.Result) - for _, ns := range namespaces { - results, err := h.finder.FetchNamespacedResults(req.Context(), Filter{ - Sources: []string{source}, - Status: []string{"warn", "fail", "error"}, - Namespaces: []string{ns}, - }, Pagination{SortBy: defaultOrder}) - if err != nil { - continue - } - - mapping := make(map[string][]violations.Result) - mapping["warn"] = make([]violations.Result, 0) - mapping["fail"] = make([]violations.Result, 0) - mapping["error"] = make([]violations.Result, 0) - - for _, r := range results { - mapping[r.Status] = append(mapping[r.Status], violations.Result{ - Kind: r.Kind, - Name: r.Name, - Policy: r.Policy, - Rule: r.Rule, - Status: r.Status, - }) - } - - nsResults[ns] = mapping - } - - sources = append(sources, violations.Source{ - Name: source, - ClusterReports: len(cluster) > 0, - ClusterPassed: cPass, - ClusterResults: cResults, - NamespacePassed: nsPass, - NamespaceResults: nsResults, - }) - } - - data, err := h.reporter.Report(sources, "HTML") - if err != nil { - zap.L().Error("failed to load data", zap.Error(err)) - w.WriteHeader(http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.Write([]byte(data.Message)) - } -} - -func NewHTMLHandler(finder PolicyReportFinder, reporter *violations.Reporter) *HTMLHandler { - return &HTMLHandler{ - finder: finder, - reporter: reporter, - } -} diff --git a/pkg/api/v1/model.go b/pkg/api/v1/model.go index fc151a78..67280f52 100644 --- a/pkg/api/v1/model.go +++ b/pkg/api/v1/model.go @@ -2,9 +2,33 @@ package v1 import ( "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + db "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" ) +// Target API Model +type Target struct { + Name string `json:"name"` + MinimumSeverity string `json:"minimumSeverity"` + Sources []string `json:"sources,omitempty"` + SkipExistingOnStartup bool `json:"skipExistingOnStartup"` +} + +func mapTarget(t target.Client) Target { + minSev := t.MinimumSeverity() + if minSev == "" { + minSev = v1alpha2.SeverityInfo + } + + return Target{ + Name: t.Name(), + MinimumSeverity: minSev, + Sources: t.Sources(), + SkipExistingOnStartup: t.SkipExistingOnStartup(), + } +} + type PolicyReport struct { ID string `json:"id"` Name string `json:"name"` @@ -16,28 +40,70 @@ type PolicyReport struct { Warn int `json:"warn"` Error int `json:"error"` Fail int `json:"fail"` - Type string `json:"-"` - Created int64 `json:"-"` } -type PolicyReportList struct { - Items []*PolicyReport `json:"items"` - Count int `json:"count"` -} - -type ResultList struct { - Items []*ListResult `json:"items"` - Count int `json:"count"` +func MapPolicyReports(results []db.PolicyReport) []PolicyReport { + return helper.Map(results, func(res db.PolicyReport) PolicyReport { + return PolicyReport{ + ID: res.ID, + Name: res.Name, + Namespace: res.Namespace, + Source: res.Source, + Labels: res.Labels, + Pass: res.Pass, + Fail: res.Fail, + Warn: res.Warn, + Error: res.Error, + Skip: res.Skip, + } + }) } type StatusCount struct { + Source string `json:"source,omitempty"` Status string `json:"status"` Count int `json:"count"` } -type NamespacedStatusCount struct { - Status string `json:"status"` - Items []NamespaceCount `json:"items"` +func MapRuleStatusCounts(results []db.StatusCount) []StatusCount { + mapping := map[string]StatusCount{ + v1alpha2.StatusPass: {Status: v1alpha2.StatusPass}, + v1alpha2.StatusFail: {Status: v1alpha2.StatusFail}, + v1alpha2.StatusWarn: {Status: v1alpha2.StatusWarn}, + v1alpha2.StatusError: {Status: v1alpha2.StatusError}, + v1alpha2.StatusSkip: {Status: v1alpha2.StatusSkip}, + } + + for _, result := range results { + mapping[result.Status] = StatusCount{Status: result.Status, Count: result.Count} + } + + return helper.ToList(mapping) +} + +func MapClusterStatusCounts(results []db.StatusCount, status []string) []StatusCount { + var mapping map[string]StatusCount + + if len(status) == 0 { + mapping = map[string]StatusCount{ + v1alpha2.StatusPass: {Status: v1alpha2.StatusPass}, + v1alpha2.StatusFail: {Status: v1alpha2.StatusFail}, + v1alpha2.StatusWarn: {Status: v1alpha2.StatusWarn}, + v1alpha2.StatusError: {Status: v1alpha2.StatusError}, + v1alpha2.StatusSkip: {Status: v1alpha2.StatusSkip}, + } + } else { + mapping = map[string]StatusCount{} + + for _, status := range status { + mapping[status] = StatusCount{Status: status} + } + } + for _, result := range results { + mapping[result.Status] = StatusCount{Status: result.Status, Count: result.Count} + } + + return helper.ToList(mapping) } type NamespaceCount struct { @@ -46,17 +112,73 @@ type NamespaceCount struct { Status string `json:"-"` } -type Resource struct { - Name string `json:"name"` - Kind string `json:"kind"` +type NamespaceStatusCount struct { + Status string `json:"status"` + Items []NamespaceCount `json:"items"` } -type ListResult struct { +func MapNamespaceStatusCounts(results []db.StatusCount, status []string) []NamespaceStatusCount { + var mapping map[string][]NamespaceCount + + if len(status) == 0 { + mapping = map[string][]NamespaceCount{ + v1alpha2.StatusPass: make([]NamespaceCount, 0), + v1alpha2.StatusFail: make([]NamespaceCount, 0), + v1alpha2.StatusWarn: make([]NamespaceCount, 0), + v1alpha2.StatusError: make([]NamespaceCount, 0), + v1alpha2.StatusSkip: make([]NamespaceCount, 0), + } + } else { + mapping = map[string][]NamespaceCount{} + + for _, status := range status { + mapping[status] = make([]NamespaceCount, 0) + } + } + for _, result := range results { + mapping[result.Status] = append(mapping[result.Status], NamespaceCount{Status: result.Status, Count: result.Count, Namespace: result.Namespace}) + } + + statusCounts := make([]NamespaceStatusCount, 0, 5) + for status, items := range mapping { + statusCounts = append(statusCounts, NamespaceStatusCount{ + Status: status, + Items: items, + }) + } + + return statusCounts +} + +type Resource struct { + ID string `json:"id,omitempty"` + UID string `json:"uid,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Kind string `json:"kind,omitempty"` + APIVersion string `json:"apiVersion,omitempty"` +} + +func MapResource(results []db.ResourceResult) []Resource { + return helper.Map(results, func(res db.ResourceResult) Resource { + return Resource{ + ID: res.ID, + UID: res.Resource.UID, + Name: res.Resource.Name, + Namespace: res.Resource.Namespace, + Kind: res.Resource.Kind, + APIVersion: res.Resource.APIVersion, + } + }) +} + +type Result struct { ID string `json:"id"` Namespace string `json:"namespace,omitempty"` Kind string `json:"kind"` APIVersion string `json:"apiVersion"` Name string `json:"name"` + ResourceID string `json:"resourceId"` Message string `json:"message"` Category string `json:"category,omitempty"` Policy string `json:"policy"` @@ -67,24 +189,23 @@ type ListResult struct { Properties map[string]string `json:"properties,omitempty"` } -// Target API Model -type Target struct { - Name string `json:"name"` - MinimumPriority string `json:"minimumPriority"` - Sources []string `json:"sources,omitempty"` - SkipExistingOnStartup bool `json:"skipExistingOnStartup"` -} - -func mapTarget(t target.Client) Target { - minPrio := t.MinimumPriority() - if minPrio == "" { - minPrio = v1alpha2.DebugPriority.String() - } - - return Target{ - Name: t.Name(), - MinimumPriority: minPrio, - Sources: t.Sources(), - SkipExistingOnStartup: t.SkipExistingOnStartup(), - } +func MapResults(results []db.PolicyReportResult) []Result { + return helper.Map(results, func(res db.PolicyReportResult) Result { + return Result{ + ID: res.ID, + Namespace: res.Resource.Namespace, + Kind: res.Resource.Kind, + APIVersion: res.Resource.APIVersion, + Name: res.Resource.Name, + ResourceID: res.Resource.GetID(), + Message: res.Message, + Category: res.Category, + Policy: res.Policy, + Rule: res.Rule, + Status: res.Result, + Severity: res.Severity, + Timestamp: res.Created, + Properties: res.Properties, + } + }) } diff --git a/pkg/api/v1/model_test.go b/pkg/api/v1/model_test.go new file mode 100644 index 00000000..c68254a3 --- /dev/null +++ b/pkg/api/v1/model_test.go @@ -0,0 +1,44 @@ +package v1_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + v1 "github.com/kyverno/policy-reporter/pkg/api/v1" + "github.com/kyverno/policy-reporter/pkg/database" +) + +func TestMapping(t *testing.T) { + t.Run("MapClusterStatusCounts", func(t *testing.T) { + result := v1.MapClusterStatusCounts([]database.StatusCount{ + {Source: "kyverno", Status: "pass", Count: 3}, + {Source: "kyverno", Status: "fail", Count: 4}, + }, []string{"pass", "fail"}) + + assert.Equal(t, 2, len(result)) + assert.Contains(t, result, v1.StatusCount{Status: "pass", Count: 3}) + assert.Contains(t, result, v1.StatusCount{Status: "fail", Count: 4}) + }) + + t.Run("MapNamespaceStatusCounts", func(t *testing.T) { + result := v1.MapNamespaceStatusCounts([]database.StatusCount{ + {Source: "kyverno", Status: "pass", Count: 3, Namespace: "default"}, + {Source: "kyverno", Status: "fail", Count: 4, Namespace: "default"}, + {Source: "kyverno", Status: "pass", Count: 2, Namespace: "user"}, + {Source: "kyverno", Status: "fail", Count: 2, Namespace: "user"}, + }, []string{"pass", "fail"}) + + assert.Equal(t, 2, len(result)) + + assert.Contains(t, result, v1.NamespaceStatusCount{Status: "pass", Items: []v1.NamespaceCount{ + {Namespace: "default", Count: 3, Status: "pass"}, + {Namespace: "user", Count: 2, Status: "pass"}, + }}) + + assert.Contains(t, result, v1.NamespaceStatusCount{Status: "fail", Items: []v1.NamespaceCount{ + {Namespace: "default", Count: 4, Status: "fail"}, + {Namespace: "user", Count: 2, Status: "fail"}, + }}) + }) +} diff --git a/pkg/api/v2/api.go b/pkg/api/v2/api.go new file mode 100644 index 00000000..c9315fd1 --- /dev/null +++ b/pkg/api/v2/api.go @@ -0,0 +1,286 @@ +package v2 + +import ( + "errors" + "net/http" + + "github.com/gin-gonic/gin" + "go.uber.org/zap" + + "github.com/kyverno/policy-reporter/pkg/api" + db "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" + "github.com/kyverno/policy-reporter/pkg/target" +) + +var defaultOrder = []string{"resource_namespace", "resource_name", "resource_uid", "policy", "rule", "message"} + +type APIHandler struct { + store *db.Store + nsClient namespaces.Client + targets map[string][]*Target +} + +func (h *APIHandler) Register(engine *gin.RouterGroup) error { + engine.GET("resource/:id/status-counts", h.GetResourceStatusCounts) + engine.GET("resource/:id/severity-counts", h.GetResourceSeverityCounts) + engine.GET("resource/:id/resource-results", h.ListResourceResults) + engine.GET("resource/:id/results", h.ListResourcePolilcyResults) + engine.GET("resource/:id", h.GetResource) + engine.GET("resource/:id/source-categories", h.ListResourceCategories) + + engine.POST("namespaces/resolve-selector", h.ResolveNamespaceSelector) + engine.GET("namespaces", h.ListNamespaces) + engine.GET("sources", h.ListSources) + engine.GET("sources/:source/use-resources", h.UseResources) + engine.GET("sources/:source/status-counts", h.GetTotalStatusCounts) + engine.GET("sources/:source/severity-counts", h.GetTotalSeverityCounts) + engine.GET("sources/categories", h.ListSourceWithCategories) + engine.GET("policies", h.ListPolicies) + engine.GET("findings", h.ListFindings) + engine.GET("severity-findings", h.ListSeverityFindings) + engine.GET("results-without-resources", h.ListResultsWithoutResource) + engine.GET("targets", h.ListTargets) + engine.GET("properties/:property", h.ListProperty) + + ns := engine.Group("namespace-scoped") + ns.GET("resource-results", h.ListNamespaceResourceResults) + ns.GET(":source/status-counts", h.GetNamespaceStatusCounts) + ns.GET(":source/severity-counts", h.GetNamespaceSeverityCounts) + ns.GET("kinds", h.ListNamespaceKinds) + ns.GET("results", h.ListPolicyResults(true)) + + cluster := engine.Group("cluster-scoped") + cluster.GET("resource-results", h.ListClusterResourceResults) + cluster.GET(":source/status-counts", h.GetClusterStatusCounts) + cluster.GET(":source/severity-counts", h.GetClusterSeverityCounts) + cluster.GET("kinds", h.ListClusterKinds) + cluster.GET("results", h.ListPolicyResults(false)) + + return nil +} + +func (h *APIHandler) ResolveNamespaceSelector(ctx *gin.Context) { + selector := make(map[string]string) + if err := ctx.BindJSON(&selector); err != nil { + zap.L().Error("resolve namespace selector: failed to convert request body", zap.Error(err)) + ctx.AbortWithError(http.StatusBadRequest, errors.New("invalid selector content")) + } + + list, err := h.nsClient.List(ctx, selector) + + api.SendResponse(ctx, list, "failed to get namespaces for the provided selector", err) +} + +func (h *APIHandler) ListNamespaces(ctx *gin.Context) { + list, err := h.store.FetchNamespaces(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, list, "failed to load namespaces", err) +} + +func (h *APIHandler) ListSources(ctx *gin.Context) { + sources, err := h.store.FetchSources(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, sources, "failed to load sources", err) +} + +func (h *APIHandler) ListPolicies(ctx *gin.Context) { + policies, err := h.store.FetchPolicies(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapPolicies(policies), "failed to load policies", err) +} + +func (h *APIHandler) ListSourceWithCategories(ctx *gin.Context) { + categories, err := h.store.FetchCategories(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapToSourceDetails(categories), "failed to load source details", err) +} + +func (h *APIHandler) ListResourceCategories(ctx *gin.Context) { + categories, err := h.store.FetchResourceCategories(ctx, ctx.Param("id"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapResourceCategoryToSourceDetails(categories), "failed to load source details", err) +} + +func (h *APIHandler) GetResource(ctx *gin.Context) { + resource, err := h.store.FetchResource(ctx, ctx.Param("id")) + + api.SendResponse(ctx, MapResource(resource), "failed to load source details", err) +} + +func (h *APIHandler) ListProperty(ctx *gin.Context) { + list, err := h.store.FetchProperty(ctx, ctx.Param("property"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapResultPropertyList(list), "failed to load property value list", err) +} + +func (h *APIHandler) GetResourceStatusCounts(ctx *gin.Context) { + counts, err := h.store.FetchResourceStatusCounts(ctx, ctx.Param("id"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapResourceStatusCounts(counts), "failed to load resource status counts", err) +} + +func (h *APIHandler) GetResourceSeverityCounts(ctx *gin.Context) { + counts, err := h.store.FetchResourceSeverityCounts(ctx, ctx.Param("id"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapResourceSeverityCounts(counts), "failed to load resource severity counts", err) +} + +func (h *APIHandler) ListNamespaceResourceResults(ctx *gin.Context) { + filter := api.BuildFilter(ctx) + list, err := h.store.FetchNamespaceResourceResults(ctx, filter, api.BuildPagination(ctx, []string{"resource_namespace", "resource_name", "resource_uid"})) + if err != nil { + zap.L().Error("failed to load resource results", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + count, err := h.store.CountNamespaceResourceResults(ctx, filter) + + api.SendResponse(ctx, Paginated[ResourceResult]{Count: count, Items: MapResourceResults(list)}, "failed to load resource result list", err) +} + +func (h *APIHandler) ListClusterResourceResults(ctx *gin.Context) { + filter := api.BuildFilter(ctx) + list, err := h.store.FetchClusterResourceResults(ctx, filter, api.BuildPagination(ctx, []string{"resource_namespace", "resource_name", "resource_uid"})) + if err != nil { + zap.L().Error("failed to load resource results", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + count, err := h.store.CountClusterResourceResults(ctx, filter) + + api.SendResponse(ctx, Paginated[ResourceResult]{Count: count, Items: MapResourceResults(list)}, "failed to load resource result list", err) +} + +func (h *APIHandler) GetClusterStatusCounts(ctx *gin.Context) { + results, err := h.store.FetchClusterStatusCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapClusterStatusCounts(results), "failed to calculate cluster status counts", err) +} + +func (h *APIHandler) GetClusterSeverityCounts(ctx *gin.Context) { + results, err := h.store.FetchClusterSeverityCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapClusterSeverityCounts(results), "failed to calculate cluster status counts", err) +} + +func (h *APIHandler) GetNamespaceStatusCounts(ctx *gin.Context) { + results, err := h.store.FetchNamespaceStatusCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapNamespaceStatusCounts(results), "failed to calculate namespace status counts", err) +} + +func (h *APIHandler) GetNamespaceSeverityCounts(ctx *gin.Context) { + results, err := h.store.FetchNamespaceSeverityCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapNamespaceSeverityCounts(results), "failed to calculate namespace severity counts", err) +} + +func (h *APIHandler) GetTotalStatusCounts(ctx *gin.Context) { + results, err := h.store.FetchTotalStatusCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapClusterStatusCounts(results), "failed to calculate total status counts", err) +} + +func (h *APIHandler) GetTotalSeverityCounts(ctx *gin.Context) { + results, err := h.store.FetchTotalSeverityCounts(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapClusterSeverityCounts(results), "failed to calculate total status counts", err) +} + +func (h *APIHandler) ListClusterKinds(ctx *gin.Context) { + kinds, err := h.store.FetchClusterKinds(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, kinds, "failed to load cluster kinds", err) +} + +func (h *APIHandler) ListNamespaceKinds(ctx *gin.Context) { + kinds, err := h.store.FetchNamespaceKinds(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, kinds, "failed to load namespaced kinds", err) +} + +func (h *APIHandler) ListResourceResults(ctx *gin.Context) { + list, err := h.store.FetchResourceResults(ctx, ctx.Param("id"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapResourceResults(list), "failed to load resource result list", err) +} + +func (h *APIHandler) ListResourcePolilcyResults(ctx *gin.Context) { + filter := api.BuildFilter(ctx) + list, err := h.store.FetchResourcePolicyResults(ctx, ctx.Param("id"), filter, api.BuildPagination(ctx, defaultOrder)) + if err != nil { + zap.L().Error("failed to load resource results", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + count, err := h.store.CountResourcePolicyResults(ctx, ctx.Param("id"), filter) + + api.SendResponse(ctx, Paginated[PolicyResult]{Count: count, Items: MapPolicyResults(list)}, "failed to load resource result list", err) +} + +func (h *APIHandler) ListPolicyResults(namespaced bool) gin.HandlerFunc { + return func(ctx *gin.Context) { + filter := api.BuildFilter(ctx) + + list, err := h.store.FetchResults(ctx, namespaced, filter, api.BuildPagination(ctx, defaultOrder)) + if err != nil { + zap.L().Error("failed to load results", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + count, err := h.store.CountResults(ctx, namespaced, filter) + + api.SendResponse(ctx, Paginated[PolicyResult]{Count: count, Items: MapPolicyResults(list)}, "failed to load resource result list", err) + } +} + +func (h *APIHandler) ListResultsWithoutResource(ctx *gin.Context) { + filter := api.BuildFilter(ctx) + + list, err := h.store.FetchResultsWithoutResource(ctx, filter, api.BuildPagination(ctx, defaultOrder)) + if err != nil { + zap.L().Error("failed to load results without resources", zap.Error(err)) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + count, err := h.store.CountResultsWithoutResource(ctx, filter) + + api.SendResponse(ctx, Paginated[PolicyResult]{Count: count, Items: MapPolicyResults(list)}, "failed to load result list without resources", err) +} + +func (h *APIHandler) UseResources(ctx *gin.Context) { + resources, err := h.store.UseResources(ctx, ctx.Param("source"), api.BuildFilter(ctx)) + + api.SendResponse(ctx, gin.H{"resources": resources}, "failed to check if resources are used", err) +} + +func (h *APIHandler) ListFindings(ctx *gin.Context) { + results, err := h.store.FetchFindingCounts(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapFindings(results), "failed to load findings", err) +} + +func (h *APIHandler) ListSeverityFindings(ctx *gin.Context) { + results, err := h.store.FetchSeverityFindingCounts(ctx, api.BuildFilter(ctx)) + + api.SendResponse(ctx, MapSeverityFindings(results), "failed to load findings", err) +} + +func (h *APIHandler) ListTargets(ctx *gin.Context) { + api.SendResponse(ctx, h.targets, "failed to load findings", nil) +} + +func NewAPIHandler(store *db.Store, client namespaces.Client, targets map[string][]*Target) *APIHandler { + return &APIHandler{ + store: store, + nsClient: client, + targets: targets, + } +} + +func WithAPI(store *db.Store, client namespaces.Client, targets target.Targets) api.ServerOption { + return func(s *api.Server) error { + return s.Register("v2", NewAPIHandler(store, client, MapConfigTagrgets(targets))) + } +} diff --git a/pkg/api/v2/api_test.go b/pkg/api/v2/api_test.go new file mode 100644 index 00000000..3998121f --- /dev/null +++ b/pkg/api/v2/api_test.go @@ -0,0 +1,481 @@ +package v2_test + +import ( + "bytes" + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/gin-gonic/gin" + "github.com/patrickmn/go-cache" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/api" + v2 "github.com/kyverno/policy-reporter/pkg/api/v2" + "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/fixtures" + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" + "github.com/kyverno/policy-reporter/pkg/report/result" + "github.com/kyverno/policy-reporter/pkg/target" +) + +const ( + nsDefault = "default" + nsTest = "test" +) + +func newFakeClient() v1.NamespaceInterface { + return fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: nsDefault, + Labels: map[string]string{ + "team": "team-a", + "group": "all", + }, + }, + }, + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: nsTest, + Labels: map[string]string{ + "team": "team-b", + "group": "all", + }, + }, + }, + ).CoreV1().Namespaces() +} + +var reconditioner = result.NewReconditioner(nil) + +func TestV2(t *testing.T) { + db, err := database.NewSQLiteDB("db_v2.db") + if err != nil { + assert.Fail(t, "failed to init SQLite DB") + } + + store, err := database.NewStore(db, "1.0") + if err != nil { + assert.Fail(t, "failed to init Store") + } + + if err := store.PrepareDatabase(context.Background()); err != nil { + assert.Fail(t, "failed to prepare Store") + } + + store.Add(context.Background(), reconditioner.Prepare(fixtures.DefaultPolicyReport)) + store.Add(context.Background(), reconditioner.Prepare(fixtures.KyvernoPolicyReport)) + store.Add(context.Background(), reconditioner.Prepare(fixtures.KyvernoClusterPolicyReport)) + + client := namespaces.NewClient(newFakeClient(), cache.New(time.Second, time.Second)) + + gin.SetMode(gin.ReleaseMode) + + server := api.NewServer(gin.New(), v2.WithAPI(store, client, target.Targets{ + Webhook: &target.Config[target.WebhookOptions]{ + Name: "Webhook", + MinimumSeverity: "warn", + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8080", + }, + }, + })) + + t.Run("TargetResponse", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/targets", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + }) + + t.Run("ResolveNamespaces", func(t *testing.T) { + body := new(bytes.Buffer) + body.Write([]byte(`{"team":"team-a"}`)) + + req, _ := http.NewRequest("POST", "/v2/namespaces/resolve-selector", body) + w := httptest.NewRecorder() + + server.Serve(w, req) + + assert.Equal(t, http.StatusOK, w.Code) + + resp := make([]string, 0, 1) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + }) + + t.Run("ListNamespaces", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/namespaces", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0, 1) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, len(resp)) + assert.Contains(t, resp, "test") + assert.Contains(t, resp, "kyverno") + } + }) + + t.Run("ListSources", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/sources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0, 1) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, len(resp)) + assert.Contains(t, resp, "test") + assert.Contains(t, resp, "Kyverno") + } + }) + + t.Run("ListPolicies", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/policies", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v2.Policy, 0, 1) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 4, len(resp)) + assert.Contains(t, resp, v2.Policy{Source: "test", Category: "Other", Name: "priority-test", Severity: "", Results: map[string]int{"fail": 1}}) + assert.Contains(t, resp, v2.Policy{Source: "Kyverno", Category: "test", Name: "cluster-required-quota", Severity: "high", Results: map[string]int{"fail": 1}}) + assert.Contains(t, resp, v2.Policy{Source: "Kyverno", Category: "test", Name: "required-limit", Severity: "high", Results: map[string]int{"pass": 1, "warn": 1}}) + assert.Contains(t, resp, v2.Policy{Source: "test", Category: "test", Name: "required-label", Severity: "high", Results: map[string]int{"fail": 2}}) + } + }) + + t.Run("UseResources", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/sources/Kyverno/use-resources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make(map[string]bool) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.True(t, resp["resources"]) + } + }) + + t.Run("ListSourceWithCategories", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/sources/categories", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v2.SourceDetails, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Contains(t, resp, v2.SourceDetails{Name: "Kyverno", Categories: []*v2.Category{{Name: "test", Status: &v2.StatusList{Pass: 1, Warn: 1, Fail: 1}, Severities: &v2.SeverityList{High: 3}}}}) + assert.Contains(t, resp, v2.SourceDetails{Name: "test", Categories: []*v2.Category{{Name: "Other", Status: &v2.StatusList{Fail: 1}, Severities: &v2.SeverityList{Unknown: 1}}, {Name: "test", Status: &v2.StatusList{Fail: 2}, Severities: &v2.SeverityList{High: 2}}}}) + } + }) + + t.Run("ListResourceCategories", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/resource/17962226559046503697/source-categories", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v2.SourceDetails, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, resp[0], v2.SourceDetails{Name: "test", Categories: []*v2.Category{{Name: "test", Status: &v2.StatusList{Fail: 1}}}}) + } + }) + + t.Run("GetResource", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/resource/17962226559046503697", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Resource{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, resp, v2.Resource{ID: "17962226559046503697", UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1", Namespace: "test", Name: "nginx", Kind: "Deployment", APIVersion: "v1"}) + } + }) + + t.Run("GetResourceStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/resource/17962226559046503697/status-counts", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v2.ResourceStatusCount, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Contains(t, resp, v2.ResourceStatusCount{Source: "test", Fail: 1}) + } + }) + + t.Run("ListNamespaceResourceResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/namespace-scoped/resource-results?namespaces=kyverno", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.ResourceResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, resp.Count, 2) + assert.Contains(t, resp.Items, v2.ResourceResult{ID: "6274512523942114905", UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1", Name: "nginx", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Status: v2.Status{Pass: 1}, Severities: v2.Severities{High: 1}}) + assert.Contains(t, resp.Items, v2.ResourceResult{ID: "8277600851619588241", UID: "dfd57c50-f30c-4729-b63f-b1954d8988d2", Name: "nginx2", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Status: v2.Status{Warn: 1}, Severities: v2.Severities{High: 1}}) + } + }) + + t.Run("ListClusterResourceResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/cluster-scoped/resource-results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.ResourceResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, resp.Count, 1) + assert.Equal(t, resp.Items[0], v2.ResourceResult{ID: "11786270724827677857", UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1", Name: "kyverno", Kind: "Namespace", APIVersion: "v1", Source: "", Status: v2.Status{Fail: 1}, Severities: v2.Severities{High: 1}}) + } + }) + + t.Run("GetClusterStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/cluster-scoped/Kyverno/status-counts", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make(map[string]int, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 5, len(resp)) + assert.Equal(t, 1, resp["fail"]) + } + }) + + t.Run("GetNamespaceStatusCounts", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/namespace-scoped/Kyverno/status-counts", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make(map[string]map[string]int, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Equal(t, 5, len(resp["kyverno"])) + assert.Equal(t, 1, resp["kyverno"]["pass"]) + assert.Equal(t, 1, resp["kyverno"]["warn"]) + assert.Equal(t, 0, resp["kyverno"]["fail"]) + assert.Equal(t, 0, resp["kyverno"]["error"]) + assert.Equal(t, 0, resp["kyverno"]["skip"]) + } + }) + + t.Run("ListClusterKinds", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/cluster-scoped/kinds", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Equal(t, "Namespace", resp[0]) + } + }) + + t.Run("ListNamespaceKinds", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/namespace-scoped/kinds", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Equal(t, "Deployment", resp[0]) + } + }) + + t.Run("ListResourceResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/resource/6274512523942114905/resource-results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make([]v2.ResourceResult, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.Equal(t, resp[0], v2.ResourceResult{ID: "6274512523942114905", UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1", Name: "nginx", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Source: "Kyverno", Status: v2.Status{Pass: 1}}) + } + }) + + t.Run("ListResourcePolilcyResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/resource/6274512523942114905/results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.PolicyResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, resp.Count) + assert.Equal(t, resp.Items[0], v2.PolicyResult{ID: "14158407137220160684", ResourceID: "6274512523942114905", Severity: "high", Name: "nginx", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Message: "message", Category: "test", Policy: "required-limit", Rule: "resource-limit-required", Status: "pass", Timestamp: 1614093003}) + } + }) + + t.Run("ListPolicyResults Namespaced", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/namespace-scoped/results?namespaces=kyverno", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.PolicyResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 2, resp.Count) + assert.Equal(t, resp.Items[0], v2.PolicyResult{ID: "14158407137220160684", ResourceID: "6274512523942114905", Severity: "high", Name: "nginx", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Message: "message", Category: "test", Policy: "required-limit", Rule: "resource-limit-required", Status: "pass", Timestamp: 1614093003}) + assert.Equal(t, resp.Items[1], v2.PolicyResult{ID: "2079631062832497014", ResourceID: "8277600851619588241", Severity: "high", Name: "nginx2", Kind: "Deployment", APIVersion: "v1", Namespace: "kyverno", Message: "message", Category: "test", Policy: "required-limit", Rule: "resource-limit-required", Status: "warn", Timestamp: 1614093003}) + } + }) + + t.Run("ListPolicyResults", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/cluster-scoped/results", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.PolicyResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, resp.Count) + assert.Equal(t, resp.Items[0], v2.PolicyResult{ID: "16800058481201255747", ResourceID: "11786270724827677857", Severity: "high", Name: "kyverno", Kind: "Namespace", APIVersion: "v1", Namespace: "", Message: "message", Category: "test", Policy: "cluster-required-quota", Rule: "ns-quota-required", Status: "fail", Timestamp: 1614093000}) + } + }) + + t.Run("ListResultsWithoutResource", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/results-without-resources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Paginated[v2.PolicyResult]{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, resp.Count) + assert.Equal(t, resp.Items[0], v2.PolicyResult{ID: "8115731892871392633", ResourceID: "18007334074686647077", Severity: "", Name: "", Kind: "", APIVersion: "", Namespace: "test", Message: "message 2", Category: "Other", Policy: "priority-test", Rule: "", Status: "fail", Timestamp: 1614093000}) + } + }) + + t.Run("UseResources", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/sources/Kyverno/use-resources", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := make(map[string]bool, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 1, len(resp)) + assert.True(t, resp["resources"]) + } + }) + + t.Run("ListFindings", func(t *testing.T) { + req, _ := http.NewRequest("GET", "/v2/findings", nil) + w := httptest.NewRecorder() + + server.Serve(w, req) + + if ok := assert.Equal(t, http.StatusOK, w.Code); ok { + resp := v2.Findings{} + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, 6, resp.Total) + assert.Equal(t, 4, resp.PerResult["fail"]) + assert.Equal(t, 1, resp.PerResult["pass"]) + assert.Equal(t, 1, resp.PerResult["warn"]) + assert.Equal(t, 2, len(resp.Counts)) + assert.Contains(t, resp.Counts, &v2.FindingCounts{ + Total: 3, + Source: "Kyverno", + Counts: map[string]int{ + "fail": 1, + "pass": 1, + "warn": 1, + }, + }) + assert.Contains(t, resp.Counts, &v2.FindingCounts{ + Total: 3, + Source: "test", + Counts: map[string]int{ + "fail": 3, + }, + }) + } + }) +} diff --git a/pkg/api/v2/views.go b/pkg/api/v2/views.go new file mode 100644 index 00000000..0cdd9f8c --- /dev/null +++ b/pkg/api/v2/views.go @@ -0,0 +1,754 @@ +package v2 + +import ( + "fmt" + "net/url" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + db "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/target" +) + +type StatusList struct { + Pass int `json:"pass"` + Skip int `json:"skip"` + Warn int `json:"warn"` + Error int `json:"error"` + Fail int `json:"fail"` +} + +type SeverityList struct { + Unknown int `json:"unknown"` + Low int `json:"low"` + Info int `json:"info"` + Medium int `json:"medium"` + High int `json:"high"` + Critical int `json:"critical"` +} + +type Category struct { + Name string `json:"name"` + Status *StatusList `json:"status"` + Severities *SeverityList `json:"severities"` +} + +type SourceDetails struct { + Name string `json:"name"` + Categories []*Category `json:"categories"` +} + +func MapToSourceDetails(categories []db.Category) []*SourceDetails { + list := make(map[string]*SourceDetails, 0) + + for _, r := range categories { + if s, ok := list[r.Source]; ok { + UpdateCategory(r, s) + continue + } + + list[r.Source] = &SourceDetails{ + Name: r.Source, + Categories: []*Category{{ + Name: helper.Defaults(r.Name, "Other"), + Status: &StatusList{}, + Severities: &SeverityList{}, + }}, + } + + UpdateCategory(r, list[r.Source]) + } + + return helper.ToList(list) +} + +func UpdateCategory(result db.Category, source *SourceDetails) { + for _, c := range source.Categories { + if c.Name == helper.Defaults(result.Name, "Other") { + MapResultToCategory(result, c) + MapSeverityToCategory(result, c) + return + } + } + + category := &Category{ + Name: helper.Defaults(result.Name, "Other"), + Status: &StatusList{}, + Severities: &SeverityList{}, + } + + category = MapResultToCategory(result, category) + category = MapSeverityToCategory(result, category) + + source.Categories = append(source.Categories, category) +} + +func MapResultToCategory(result db.Category, category *Category) *Category { + switch result.Result { + case v1alpha2.StatusPass: + category.Status.Pass += result.Count + case v1alpha2.StatusWarn: + category.Status.Warn += result.Count + case v1alpha2.StatusFail: + category.Status.Fail += result.Count + case v1alpha2.StatusError: + category.Status.Error += result.Count + case v1alpha2.StatusSkip: + category.Status.Skip += result.Count + } + + return category +} + +func MapSeverityToCategory(result db.Category, category *Category) *Category { + switch result.Severity { + case v1alpha2.SeverityLow: + category.Severities.Low += result.Count + case v1alpha2.SeverityInfo: + category.Severities.Info += result.Count + case v1alpha2.SeverityMedium: + category.Severities.Medium += result.Count + case v1alpha2.SeverityHigh: + category.Severities.High += result.Count + case v1alpha2.SeverityCritical: + category.Severities.Critical += result.Count + default: + category.Severities.Unknown += result.Count + } + + return category +} + +type Resource struct { + ID string `json:"id,omitempty"` + UID string `json:"uid,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Kind string `json:"kind,omitempty"` + APIVersion string `json:"apiVersion,omitempty"` +} + +func MapResource(result db.ResourceResult) Resource { + return Resource{ + ID: result.ID, + UID: result.Resource.UID, + APIVersion: result.Resource.APIVersion, + Kind: result.Resource.Kind, + Name: result.Resource.Name, + Namespace: result.Resource.Namespace, + } +} + +type ResourceStatusCount struct { + Source string `json:"source,omitempty"` + Pass int `json:"pass"` + Warn int `json:"warn"` + Fail int `json:"fail"` + Error int `json:"error"` + Skip int `json:"skip"` +} + +func MapResourceStatusCounts(results []db.ResourceStatusCount) []ResourceStatusCount { + list := make([]ResourceStatusCount, 0, len(results)) + for _, result := range results { + list = append(list, ResourceStatusCount{ + Source: result.Source, + Pass: result.Pass, + Fail: result.Fail, + Warn: result.Warn, + Error: result.Error, + Skip: result.Skip, + }) + } + + return list +} + +type ResourceSeverityCount struct { + Source string `json:"source,omitempty"` + Info int `json:"info"` + Low int `json:"low"` + Medium int `json:"medium"` + High int `json:"high"` + Critical int `json:"critical"` + Unknown int `json:"unknown"` +} + +func MapResourceSeverityCounts(results []db.ResourceSeverityCount) []ResourceSeverityCount { + list := make([]ResourceSeverityCount, 0, len(results)) + for _, result := range results { + list = append(list, ResourceSeverityCount{ + Source: result.Source, + Info: result.Info, + Low: result.Low, + Medium: result.Medium, + High: result.High, + Critical: result.Critical, + Unknown: result.Unknown, + }) + } + + return list +} + +type Status struct { + Pass int `json:"pass"` + Skip int `json:"skip"` + Warn int `json:"warn"` + Fail int `json:"fail"` + Error int `json:"error"` +} + +type Severities struct { + Info int `json:"info"` + Low int `json:"low"` + Medium int `json:"medium"` + High int `json:"high"` + Critical int `json:"critical"` + Unknown int `json:"unknown"` +} + +type ResourceResult struct { + ID string `json:"id"` + UID string `json:"uid"` + Name string `json:"name"` + Kind string `json:"kind"` + APIVersion string `json:"apiVersion"` + Namespace string `json:"namespace,omitempty"` + Source string `json:"source,omitempty"` + Status Status `json:"status"` + Severities Severities `json:"severities"` +} + +func MapResourceResults(results []db.ResourceResult) []ResourceResult { + return helper.Map(results, func(res db.ResourceResult) ResourceResult { + return ResourceResult{ + ID: res.ID, + UID: res.Resource.UID, + Namespace: res.Resource.Namespace, + Kind: res.Resource.Kind, + APIVersion: res.Resource.APIVersion, + Name: res.Resource.Name, + Source: res.Source, + Status: Status{ + Pass: res.Pass, + Skip: res.Skip, + Warn: res.Warn, + Fail: res.Fail, + Error: res.Error, + }, + Severities: Severities{ + Unknown: res.Unknown, + Info: res.Info, + Low: res.Low, + Medium: res.Medium, + High: res.High, + Critical: res.Critical, + }, + } + }) +} + +type Paginated[T any] struct { + Items []T `json:"items"` + Count int `json:"count"` +} + +type StatusCount struct { + Namespace string `json:"namespace,omitempty"` + Source string `json:"source,omitempty"` + Status string `json:"status"` + Count int `json:"count"` +} + +func MapClusterSeverityCounts(results []db.SeverityCount) map[string]int { + mapping := map[string]int{ + "unknown": 0, + v1alpha2.SeverityLow: 0, + v1alpha2.SeverityInfo: 0, + v1alpha2.SeverityMedium: 0, + v1alpha2.SeverityHigh: 0, + v1alpha2.SeverityCritical: 0, + } + + for _, result := range results { + mapping[result.Severity] = result.Count + } + + return mapping +} + +func MapClusterStatusCounts(results []db.StatusCount) map[string]int { + mapping := map[string]int{ + v1alpha2.StatusPass: 0, + v1alpha2.StatusFail: 0, + v1alpha2.StatusWarn: 0, + v1alpha2.StatusError: 0, + v1alpha2.StatusSkip: 0, + } + + for _, result := range results { + mapping[result.Status] = result.Count + } + + return mapping +} + +func MapNamespaceStatusCounts(results []db.StatusCount) map[string]map[string]int { + mapping := map[string]map[string]int{} + + for _, result := range results { + if _, ok := mapping[result.Namespace]; !ok { + mapping[result.Namespace] = map[string]int{ + v1alpha2.StatusPass: 0, + v1alpha2.StatusFail: 0, + v1alpha2.StatusWarn: 0, + v1alpha2.StatusError: 0, + v1alpha2.StatusSkip: 0, + } + } + + mapping[result.Namespace][result.Status] = result.Count + } + + return mapping +} + +func MapNamespaceSeverityCounts(results []db.SeverityCount) map[string]map[string]int { + mapping := map[string]map[string]int{} + + for _, result := range results { + if _, ok := mapping[result.Namespace]; !ok { + mapping[result.Namespace] = map[string]int{ + "unknown": 0, + v1alpha2.SeverityInfo: 0, + v1alpha2.SeverityLow: 0, + v1alpha2.SeverityMedium: 0, + v1alpha2.SeverityHigh: 0, + v1alpha2.SeverityCritical: 0, + } + } + + mapping[result.Namespace][result.Severity] = result.Count + } + + return mapping +} + +type Policy struct { + Source string `json:"source,omitempty"` + Category string `json:"category,omitempty"` + Name string `json:"policy"` + Severity string `json:"severity,omitempty"` + Results map[string]int `json:"results"` +} + +func MapPolicies(results []db.PolicyReportFilter) []*Policy { + list := make(map[string]*Policy) + + for _, r := range results { + category := r.Category + if category == "" { + category = "Other" + } + + if _, ok := list[r.Policy]; ok { + list[r.Policy].Results[r.Result] = r.Count + continue + } + + list[r.Policy] = &Policy{ + Source: r.Source, + Category: category, + Name: r.Policy, + Severity: r.Severity, + Results: map[string]int{ + r.Result: r.Count, + }, + } + } + + return helper.ToList(list) +} + +type PolicyResult struct { + ID string `json:"id"` + Namespace string `json:"namespace,omitempty"` + Kind string `json:"kind"` + APIVersion string `json:"apiVersion"` + Name string `json:"name"` + ResourceID string `json:"resourceId"` + Message string `json:"message"` + Category string `json:"category,omitempty"` + Policy string `json:"policy"` + Rule string `json:"rule"` + Status string `json:"status"` + Severity string `json:"severity,omitempty"` + Timestamp int64 `json:"timestamp,omitempty"` + Properties map[string]string `json:"properties,omitempty"` +} + +func MapPolicyResults(results []db.PolicyReportResult) []PolicyResult { + return helper.Map(results, func(res db.PolicyReportResult) PolicyResult { + return PolicyResult{ + ID: res.ID, + Namespace: res.Resource.Namespace, + Kind: res.Resource.Kind, + APIVersion: res.Resource.APIVersion, + Name: res.Resource.Name, + ResourceID: res.Resource.GetID(), + Message: res.Message, + Category: res.Category, + Policy: res.Policy, + Rule: res.Rule, + Status: res.Result, + Severity: res.Severity, + Timestamp: res.Created, + Properties: res.Properties, + } + }) +} + +type FindingCounts struct { + Total int `json:"total"` + Source string `json:"source"` + Counts map[string]int `json:"counts"` +} + +type Findings struct { + Total int `json:"total"` + PerResult map[string]int `json:"perResult"` + Counts []*FindingCounts `json:"counts"` +} + +func MapFindings(results []db.StatusCount) Findings { + findings := make(map[string]*FindingCounts, 0) + totals := make(map[string]int, 5) + total := 0 + + for _, count := range results { + if finding, ok := findings[count.Source]; ok { + finding.Counts[count.Status] = count.Count + finding.Total = finding.Total + count.Count + } else { + findings[count.Source] = &FindingCounts{ + Source: count.Source, + Total: count.Count, + Counts: map[string]int{ + count.Status: count.Count, + }, + } + } + + totals[count.Status] += count.Count + total += count.Count + } + + return Findings{Counts: helper.ToList(findings), Total: total, PerResult: totals} +} + +func MapSeverityFindings(results []db.SeverityCount) Findings { + findings := make(map[string]*FindingCounts, 0) + totals := make(map[string]int, 5) + total := 0 + + for _, count := range results { + if finding, ok := findings[count.Source]; ok { + finding.Counts[count.Severity] = count.Count + finding.Total = finding.Total + count.Count + } else { + findings[count.Source] = &FindingCounts{ + Source: count.Source, + Total: count.Count, + Counts: map[string]int{ + count.Severity: count.Count, + }, + } + } + + totals[count.Severity] += count.Count + total += count.Count + } + + return Findings{Counts: helper.ToList(findings), Total: total, PerResult: totals} +} + +func MapResourceCategoryToSourceDetails(categories []db.ResourceCategory) []*SourceDetails { + list := make(map[string]*SourceDetails, 0) + + for _, r := range categories { + if s, ok := list[r.Source]; ok { + s.Categories = append(s.Categories, &Category{ + Name: r.Name, + Status: &StatusList{ + Pass: r.Pass, + Fail: r.Fail, + Warn: r.Warn, + Error: r.Error, + Skip: r.Skip, + }, + }) + continue + } + + list[r.Source] = &SourceDetails{ + Name: r.Source, + Categories: []*Category{{ + Name: r.Name, + Status: &StatusList{ + Pass: r.Pass, + Fail: r.Fail, + Warn: r.Warn, + Error: r.Error, + Skip: r.Skip, + }, + }}, + } + } + + return helper.ToList(list) +} + +type ValueFilter struct { + Include []string `json:"include,omitempty"` + Exclude []string `json:"exclude,omitempty"` + Selector map[string]any `json:"selector,omitempty"` +} + +type TargetFilter struct { + Namespaces *ValueFilter `json:"namespaces,omitempty"` + Severities *ValueFilter `json:"severities,omitempty"` + Status *ValueFilter `json:"status,omitempty"` + Policies *ValueFilter `json:"policies,omitempty"` + ReportLabels *ValueFilter `json:"reportLabels,omitempty"` + Sources *ValueFilter `json:"sources,omitempty"` +} + +type Target struct { + Name string `json:"name"` + Type string `json:"type"` + SecretRef string `json:"secretRef,omitempty"` + MountedSecret string `json:"mountedSecret,omitempty"` + MinimumSeverity string `json:"minimumSeverity"` + Filter TargetFilter `json:"filter"` + CustomFields map[string]string `json:"customFields"` + Properties map[string]any `json:"properties"` + Host string `json:"host,omitempty"` + SkipTLS bool `json:"skipTLS,omitempty"` + UseTLS bool `json:"useTLS,omitempty"` + Auth bool `json:"auth"` +} + +func MapValueFilter(f target.ValueFilter) *ValueFilter { + if len(f.Exclude)+len(f.Include) == 0+len(f.Selector) { + return nil + } + + return &ValueFilter{ + Include: f.Include, + Exclude: f.Exclude, + Selector: f.Selector, + } +} + +func MapBaseToTarget[T any](t *target.Config[T]) *Target { + fields := t.CustomFields + if fields == nil { + fields = make(map[string]string, 0) + } + + return &Target{ + Name: t.Name, + MinimumSeverity: t.MinimumSeverity, + SecretRef: t.SecretRef, + MountedSecret: t.MountedSecret, + CustomFields: fields, + Properties: make(map[string]any), + Filter: TargetFilter{ + Namespaces: MapValueFilter(t.Filter.Namespaces), + Severities: MapValueFilter(t.Filter.Severities), + Status: MapValueFilter(t.Filter.Status), + Policies: MapValueFilter(t.Filter.Policies), + ReportLabels: MapValueFilter(t.Filter.ReportLabels), + Sources: MapValueFilter(target.ValueFilter{ + Include: t.Sources, + }), + }, + } +} + +func MapSlackToTarget(ta *target.Config[target.SlackOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "Slack" + t.Properties["channel"] = ta.Config.Channel + + return t +} + +func MapLokiToTarget(ta *target.Config[target.LokiOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "Loki" + t.Host = ta.Config.Host + t.SkipTLS = ta.Config.SkipTLS + t.UseTLS = ta.Config.Certificate != "" + t.Properties["api"] = ta.Config.Path + + if v, ok := ta.Config.Headers["Authorization"]; ok && v != "" { + t.Auth = true + } else if ta.Config.Username != "" && ta.Config.Password != "" { + t.Auth = true + } + + return t +} + +func MapElasticsearchToTarget(ta *target.Config[target.ElasticsearchOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "Elasticsearch" + t.Host = ta.Config.Host + t.SkipTLS = ta.Config.SkipTLS + t.UseTLS = ta.Config.Certificate != "" + t.Auth = (ta.Config.Username != "" && ta.Config.Password != "") || ta.Config.APIKey != "" + t.Properties["rotation"] = ta.Config.Rotation + t.Properties["index"] = ta.Config.Index + + if v, ok := ta.Config.Headers["Authorization"]; ok && v != "" { + t.Auth = true + } + + return t +} + +func MapWebhhokToTarget(typeName string) func(ta *target.Config[target.WebhookOptions]) *Target { + return func(ta *target.Config[target.WebhookOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = typeName + t.SkipTLS = ta.Config.SkipTLS + t.UseTLS = ta.Config.Certificate != "" + + if u, err := url.Parse(ta.Config.Webhook); err == nil { + t.Host = fmt.Sprintf("%s://%s", u.Scheme, u.Host) + t.Auth = u.User != nil + } + + if v, ok := ta.Config.Headers["Authorization"]; ok && v != "" { + t.Auth = true + } + + return t + } +} + +func MapTelegramToTarget(ta *target.Config[target.TelegramOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "Telegram" + t.Host = ta.Config.Webhook + t.SkipTLS = ta.Config.SkipTLS + t.UseTLS = ta.Config.Certificate != "" + t.Properties["chatId"] = ta.Config.ChatID + + return t +} + +func MapS3ToTarget(ta *target.Config[target.S3Options]) *Target { + t := MapBaseToTarget(ta) + t.Type = "S3" + t.Host = ta.Config.Endpoint + t.Properties["prefix"] = ta.Config.Prefix + t.Properties["bucket"] = ta.Config.Bucket + t.Properties["region"] = ta.Config.Region + t.Auth = true + + return t +} + +func MapKinesisToTarget(ta *target.Config[target.KinesisOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "Kinesis" + t.Host = ta.Config.Endpoint + t.Properties["stream"] = ta.Config.StreamName + t.Properties["region"] = ta.Config.Region + t.Auth = true + + return t +} + +func MapSecurityHubToTarget(ta *target.Config[target.SecurityHubOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "SecurityHub" + t.Host = ta.Config.Endpoint + t.Properties["region"] = ta.Config.Region + t.Properties["synchronize"] = ta.Config.Synchronize + t.Auth = true + + return t +} + +func MapGCSToTarget(ta *target.Config[target.GCSOptions]) *Target { + t := MapBaseToTarget(ta) + t.Type = "GoogleCloudStore" + t.Properties["prefix"] = ta.Config.Prefix + t.Properties["bucket"] = ta.Config.Bucket + t.Auth = true + + return t +} + +func MapTargets[T any](c *target.Config[T], mapper func(*target.Config[T]) *Target) []*Target { + targets := make([]*Target, 0) + + if c == nil { + return targets + } + + if c.Valid { + targets = append(targets, mapper(c)) + } + + for _, channel := range c.Channels { + if channel.Valid { + targets = append(targets, mapper(channel)) + } + } + + return targets +} + +func MapConfigTagrgets(c target.Targets) map[string][]*Target { + targets := make(map[string][]*Target) + + targets["loki"] = MapTargets(c.Loki, MapLokiToTarget) + targets["elasticsearch"] = MapTargets(c.Elasticsearch, MapElasticsearchToTarget) + targets["slack"] = MapTargets(c.Slack, MapSlackToTarget) + targets["discord"] = MapTargets(c.Discord, MapWebhhokToTarget("Discord")) + targets["teams"] = MapTargets(c.Teams, MapWebhhokToTarget("MS Teams")) + targets["googleChat"] = MapTargets(c.GoogleChat, MapWebhhokToTarget("GoogleChat")) + targets["webhook"] = MapTargets(c.Webhook, MapWebhhokToTarget("Webhook")) + targets["telegram"] = MapTargets(c.Telegram, MapTelegramToTarget) + targets["s3"] = MapTargets(c.S3, MapS3ToTarget) + targets["kinesis"] = MapTargets(c.Kinesis, MapKinesisToTarget) + targets["securityHub"] = MapTargets(c.SecurityHub, MapSecurityHubToTarget) + targets["gcs"] = MapTargets(c.GCS, MapGCSToTarget) + + for k, v := range targets { + if len(v) == 0 { + delete(targets, k) + } + } + + return targets +} + +type ResultProperty struct { + Namespace string `json:"namespace"` + Property string `json:"property"` +} + +func MapResultPropertyList(results []db.ResultProperty) []ResultProperty { + return helper.Map(results, func(res db.ResultProperty) ResultProperty { + return ResultProperty{ + Namespace: res.Namespace, + Property: res.Property, + } + }) +} diff --git a/pkg/api/v2/views_test.go b/pkg/api/v2/views_test.go new file mode 100644 index 00000000..0730ab6a --- /dev/null +++ b/pkg/api/v2/views_test.go @@ -0,0 +1,362 @@ +package v2_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + v2 "github.com/kyverno/policy-reporter/pkg/api/v2" + "github.com/kyverno/policy-reporter/pkg/database" + "github.com/kyverno/policy-reporter/pkg/target" +) + +func TestV2Views(t *testing.T) { + t.Run("MapValueFilter", func(t *testing.T) { + empty := v2.MapValueFilter(target.ValueFilter{}) + + assert.Nil(t, empty) + + original := target.ValueFilter{ + Include: []string{"default"}, + Exclude: []string{"kube-system"}, + Selector: map[string]any{"team": "marketing"}, + } + + filter := v2.MapValueFilter(original) + + assert.Equal(t, original.Include, filter.Include) + assert.Equal(t, original.Exclude, filter.Exclude) + assert.Equal(t, original.Selector, filter.Selector) + }) + + t.Run("MapResourceCategoryToSourceDetails", func(t *testing.T) { + result := v2.MapResourceCategoryToSourceDetails([]database.ResourceCategory{ + { + Source: "Kyverno", + Name: "PSS Baseline", + Pass: 8, + Fail: 3, + }, + { + Source: "Kyverno", + Name: "PSS Restricted", + Pass: 4, + Fail: 1, + }, + { + Source: "Trivy", + Name: "Vulnr", + Pass: 0, + Fail: 2, + Warn: 4, + }, + }) + + assert.Equal(t, 2, len(result)) + assert.Contains(t, result, &v2.SourceDetails{Name: "Kyverno", Categories: []*v2.Category{ + { + Name: "PSS Baseline", + Status: &v2.StatusList{ + Pass: 8, + Fail: 3, + }, + }, + { + Name: "PSS Restricted", + Status: &v2.StatusList{ + Pass: 4, + Fail: 1, + }, + }, + }}) + assert.Contains(t, result, &v2.SourceDetails{Name: "Trivy", Categories: []*v2.Category{ + { + Name: "Vulnr", + Status: &v2.StatusList{ + Pass: 0, + Fail: 2, + Warn: 4, + }, + }, + }}) + }) + + t.Run("MapBaseToTarget", func(t *testing.T) { + target := v2.MapBaseToTarget(&target.Config[target.WebhookOptions]{ + Name: "Webhook", + MinimumSeverity: "medium", + SecretRef: "ref", + MountedSecret: "mounted", + Sources: []string{"Kyverno"}, + SkipExisting: true, + Valid: true, + }) + + assert.Equal(t, "Webhook", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + assert.Equal(t, "ref", target.SecretRef) + assert.Equal(t, "mounted", target.MountedSecret) + assert.NotNil(t, target.CustomFields) + assert.NotNil(t, target.Properties) + assert.Equal(t, []string{"Kyverno"}, target.Filter.Sources.Include) + }) + + t.Run("MapSlackToTarget", func(t *testing.T) { + target := v2.MapSlackToTarget(&target.Config[target.SlackOptions]{ + Name: "Slack", + MinimumSeverity: "medium", + Config: &target.SlackOptions{ + Channel: "general", + WebhookOptions: target.WebhookOptions{ + Webhook: "http://slack.com/xxxx", + }, + }, + Valid: true, + }) + + assert.Equal(t, "Slack", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + assert.Equal(t, "Slack", target.Type) + assert.Equal(t, "general", target.Properties["channel"]) + }) + + t.Run("MapLokiToTarget", func(t *testing.T) { + target := v2.MapLokiToTarget(&target.Config[target.LokiOptions]{ + Name: "Loki 1", + MinimumSeverity: "medium", + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://loki.monitoring:3000", + Certificate: "cert", + SkipTLS: true, + }, + Username: "user", + Password: "password", + Path: "v1/push", + }, + Valid: true, + }) + + assert.Equal(t, "Loki 1", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "Loki", target.Type) + assert.Equal(t, "v1/push", target.Properties["api"]) + assert.Equal(t, "http://loki.monitoring:3000", target.Host) + assert.True(t, target.SkipTLS) + assert.True(t, target.UseTLS) + assert.True(t, target.Auth) + }) + + t.Run("MapElasticsearchToTarget", func(t *testing.T) { + target := v2.MapElasticsearchToTarget(&target.Config[target.ElasticsearchOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.ElasticsearchOptions{ + HostOptions: target.HostOptions{ + Host: "http://elasticsearch.monitoring:3000", + Certificate: "cert", + SkipTLS: true, + Headers: map[string]string{ + "Authorization": "Bearer 123456", + }, + }, + Index: "policy-reporter", + Rotation: "daily", + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "Elasticsearch", target.Type) + assert.Equal(t, "policy-reporter", target.Properties["index"]) + assert.Equal(t, "daily", target.Properties["rotation"]) + assert.Equal(t, "http://elasticsearch.monitoring:3000", target.Host) + assert.True(t, target.SkipTLS) + assert.True(t, target.UseTLS) + assert.True(t, target.Auth) + }) + + t.Run("MapWebhhokToTarget", func(t *testing.T) { + target := v2.MapWebhhokToTarget("Discord")(&target.Config[target.WebhookOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.WebhookOptions{ + Webhook: "http://discord.com/12345/888XABC", + Certificate: "cert", + SkipTLS: true, + Headers: map[string]string{ + "Authorization": "Bearer 123456", + }, + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "Discord", target.Type) + assert.Equal(t, "http://discord.com", target.Host) + assert.True(t, target.SkipTLS) + assert.True(t, target.UseTLS) + assert.True(t, target.Auth) + }) + + t.Run("MapTelegramToTarget", func(t *testing.T) { + target := v2.MapTelegramToTarget(&target.Config[target.TelegramOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.TelegramOptions{ + Token: "ABCDE", + ChatID: "1234567", + WebhookOptions: target.WebhookOptions{ + Webhook: "http://telegram.com", + Certificate: "cert", + SkipTLS: true, + }, + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "Telegram", target.Type) + assert.Equal(t, "http://telegram.com", target.Host) + assert.Equal(t, "1234567", target.Properties["chatId"]) + assert.True(t, target.SkipTLS) + assert.True(t, target.UseTLS) + assert.False(t, target.Auth) + }) + + t.Run("MapS3ToTarget", func(t *testing.T) { + target := v2.MapS3ToTarget(&target.Config[target.S3Options]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.S3Options{ + Prefix: "policy-reporter", + Bucket: "kyverno", + AWSConfig: target.AWSConfig{ + Region: "eu-central-1", + Endpoint: "https://s3.aws.com", + }, + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "S3", target.Type) + assert.Equal(t, "https://s3.aws.com", target.Host) + assert.Equal(t, "kyverno", target.Properties["bucket"]) + assert.Equal(t, "policy-reporter", target.Properties["prefix"]) + assert.Equal(t, "eu-central-1", target.Properties["region"]) + assert.True(t, target.Auth) + }) + + t.Run("MapKinesisToTarget", func(t *testing.T) { + target := v2.MapKinesisToTarget(&target.Config[target.KinesisOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.KinesisOptions{ + StreamName: "policy-reporter", + AWSConfig: target.AWSConfig{ + Region: "eu-central-1", + Endpoint: "https://kinesis.aws.com", + }, + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "Kinesis", target.Type) + assert.Equal(t, "https://kinesis.aws.com", target.Host) + assert.Equal(t, "policy-reporter", target.Properties["stream"]) + assert.Equal(t, "eu-central-1", target.Properties["region"]) + assert.True(t, target.Auth) + }) + + t.Run("MapSecurityHubToTarget", func(t *testing.T) { + target := v2.MapSecurityHubToTarget(&target.Config[target.SecurityHubOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.SecurityHubOptions{ + AccountID: "policy-reporter", + Synchronize: true, + AWSConfig: target.AWSConfig{ + Region: "eu-central-1", + Endpoint: "https://securityhub.aws.com", + }, + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "SecurityHub", target.Type) + assert.Equal(t, "https://securityhub.aws.com", target.Host) + assert.Equal(t, "eu-central-1", target.Properties["region"]) + assert.Equal(t, true, target.Properties["synchronize"]) + assert.True(t, target.Auth) + }) + + t.Run("MapGCSToTarget", func(t *testing.T) { + target := v2.MapGCSToTarget(&target.Config[target.GCSOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.GCSOptions{ + Prefix: "policy-reporter", + Bucket: "kyverno", + }, + Valid: true, + }) + + assert.Equal(t, "Target", target.Name) + assert.Equal(t, "medium", target.MinimumSeverity) + + assert.Equal(t, "GoogleCloudStore", target.Type) + assert.Equal(t, "kyverno", target.Properties["bucket"]) + assert.Equal(t, "policy-reporter", target.Properties["prefix"]) + assert.True(t, target.Auth) + }) + + t.Run("MapTargets", func(t *testing.T) { + targets := v2.MapTargets(&target.Config[target.GCSOptions]{ + Name: "Target", + MinimumSeverity: "medium", + Config: &target.GCSOptions{ + Prefix: "policy-reporter", + Bucket: "kyverno", + }, + Valid: true, + Channels: []*target.Config[target.GCSOptions]{ + { + Name: "Target 2", + MinimumSeverity: "medium", + Config: &target.GCSOptions{ + Prefix: "policy-reporter", + Bucket: "trivy", + }, + Valid: true, + }, + { + Name: "Target 2", + MinimumSeverity: "medium", + Config: &target.GCSOptions{ + Prefix: "policy-reporter", + Bucket: "trivy", + }, + Valid: false, + }, + }, + }, v2.MapGCSToTarget) + + assert.Equal(t, 2, len(targets)) + }) +} diff --git a/pkg/cache/redis_test.go b/pkg/cache/redis_test.go index 11565fa2..bf91391c 100644 --- a/pkg/cache/redis_test.go +++ b/pkg/cache/redis_test.go @@ -7,6 +7,7 @@ import ( "time" goredis "github.com/go-redis/redis/v8" + "github.com/kyverno/policy-reporter/pkg/cache" "github.com/kyverno/policy-reporter/pkg/fixtures" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index 0b59c404..7324d9f6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -3,278 +3,84 @@ package config import "github.com/kyverno/policy-reporter/pkg/target" type ValueFilter struct { - Include []string `mapstructure:"include" json:"include,omitempty"` - Exclude []string `mapstructure:"exclude" json:"exclude,omitempty"` + Include []string `mapstructure:"include"` + Exclude []string `mapstructure:"exclude"` + Selector map[string]any `mapstructure:"selector"` } type EmailReportFilter struct { - DisableClusterReports bool `mapstructure:"disableClusterReports" json:"disableClusterReports,omitempty"` - Namespaces ValueFilter `mapstructure:"namespaces" json:"namespaces,omitempty"` - Sources ValueFilter `mapstructure:"sources" json:"sources,omitempty"` + DisableClusterReports bool `mapstructure:"disableClusterReports"` + Namespaces ValueFilter `mapstructure:"namespaces"` + Sources ValueFilter `mapstructure:"sources"` } type TargetFilter struct { - Namespaces ValueFilter `mapstructure:"namespaces" json:"namespaces,omitempty"` - Priorities ValueFilter `mapstructure:"priorities" json:"priorities,omitempty"` - Policies ValueFilter `mapstructure:"policies" json:"policies,omitempty"` - ReportLabels ValueFilter `mapstructure:"reportLabels" json:"reportLabels,omitempty"` + Namespaces ValueFilter `mapstructure:"namespaces"` + Priorities ValueFilter `mapstructure:"priorities"` + Policies ValueFilter `mapstructure:"policies"` + ReportLabels ValueFilter `mapstructure:"reportLabels"` } type MetricsFilter struct { - Namespaces ValueFilter `mapstructure:"namespaces" json:"namespaces,omitempty"` - Policies ValueFilter `mapstructure:"policies" json:"policies,omitempty"` - Severities ValueFilter `mapstructure:"severities" json:"severities,omitempty"` - Status ValueFilter `mapstructure:"status" json:"status,omitempty"` - Sources ValueFilter `mapstructure:"sources" json:"sources,omitempty"` - Kinds ValueFilter `mapstructure:"kinds" json:"kinds,omitempty"` -} - -type TargetBaseOptions struct { - Name string `mapstructure:"name" json:"name,omitempty"` - MinimumPriority string `mapstructure:"minimumPriority" json:"minimumPriority,omitempty"` - Filter TargetFilter `mapstructure:"filter" json:"filter,omitempty"` - SecretRef string `mapstructure:"secretRef" json:"secretRef,omitempty"` - MountedSecret string `mapstructure:"mountedSecret" json:"mountedSecret,omitempty"` - Sources []string `mapstructure:"sources" json:"sources,omitempty"` - CustomFields map[string]string `mapstructure:"customFields" json:"customFields,omitempty"` - SkipExisting bool `mapstructure:"skipExistingOnStartup" json:"skipExistingOnStartup,omitempty"` -} - -func (config *TargetBaseOptions) MapBaseParent(parent TargetBaseOptions) { - if config.MinimumPriority == "" { - config.MinimumPriority = parent.MinimumPriority - } - - if !config.SkipExisting { - config.SkipExisting = parent.SkipExisting - } -} - -func (config *TargetBaseOptions) ClientOptions() target.ClientOptions { - return target.ClientOptions{ - Name: config.Name, - SkipExistingOnStartup: config.SkipExisting, - ResultFilter: createResultFilter(config.Filter, config.MinimumPriority, config.Sources), - ReportFilter: createReportFilter(config.Filter), - } -} - -type AWSConfig struct { - AccessKeyID string `mapstructure:"accessKeyID" json:"accessKeyID,omitempty"` - SecretAccessKey string `mapstructure:"secretAccessKey" json:"secretAccessKey,omitempty"` - Region string `mapstructure:"region" json:"region,omitempty"` - Endpoint string `mapstructure:"endpoint" json:"endpoint,omitempty"` -} - -func (config *AWSConfig) MapAWSParent(parent AWSConfig) { - if config.Endpoint == "" { - config.Endpoint = parent.Endpoint - } - - if config.AccessKeyID == "" { - config.AccessKeyID = parent.AccessKeyID - } - - if config.SecretAccessKey == "" { - config.SecretAccessKey = parent.SecretAccessKey - } - - if config.Region == "" { - config.Region = parent.Region - } -} - -type TargetOption interface { - BaseOptions() *TargetBaseOptions -} - -// Loki configuration -type Loki struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - CustomLabels map[string]string `mapstructure:"customLabels" json:"customLabels,omitempty"` - Headers map[string]string `mapstructure:"headers" json:"headers,omitempty"` - Host string `mapstructure:"host" json:"host,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` - Path string `mapstructure:"path" json:"path,omitempty"` - Channels []*Loki `mapstructure:"channels" json:"channels,omitempty"` - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` -} - -// Elasticsearch configuration -type Elasticsearch struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Host string `mapstructure:"host" json:"host,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` - Index string `mapstructure:"index" json:"index,omitempty"` - Rotation string `mapstructure:"rotation" json:"rotation,omitempty"` - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` - APIKey string `mapstructure:"apiKey" json:"apiKey,omitempty"` - Channels []*Elasticsearch `mapstructure:"channels" json:"channels,omitempty"` - TypelessAPI bool `mapstructure:"typelessApi" json:"typelessApi,omitempty"` -} - -// Slack configuration -type Slack struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Webhook string `mapstructure:"webhook" json:"webhook,omitempty"` - Channel string `mapstructure:"channel" json:"channel,omitempty"` - Channels []*Slack `mapstructure:"channels" json:"channels,omitempty"` -} - -// Discord configuration -type Discord struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Webhook string `mapstructure:"webhook" json:"webhook,omitempty"` - Channels []*Discord `mapstructure:"channels" json:"channels,omitempty"` -} - -// Teams configuration -type Teams struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Webhook string `mapstructure:"webhook" json:"webhook,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` - Channels []*Teams `mapstructure:"channels" json:"channels,omitempty"` -} - -// UI configuration -type UI struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Host string `mapstructure:"host" json:"host,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` -} - -// Webhook configuration -type Webhook struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Host string `mapstructure:"host" json:"host,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` - Headers map[string]string `mapstructure:"headers" json:"headers,omitempty"` - Channels []*Webhook `mapstructure:"channels" json:"channels,omitempty"` -} - -// Telegram configuration -type Telegram struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Host string `mapstructure:"host"` - Token string `mapstructure:"token"` - ChatID string `mapstructure:"chatID"` - SkipTLS bool `mapstructure:"skipTLS"` - Certificate string `mapstructure:"certificate"` - Headers map[string]string `mapstructure:"headers"` - Channels []*Telegram `mapstructure:"channels"` -} - -// GoogleChat configuration -type GoogleChat struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Webhook string `mapstructure:"webhook" json:"webhook,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` - Headers map[string]string `mapstructure:"headers" json:"headers,omitempty"` - Channels []*GoogleChat `mapstructure:"channels" json:"channels,omitempty"` -} - -// S3 configuration -type S3 struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - AWSConfig `mapstructure:",squash" json:",inline"` - Prefix string `mapstructure:"prefix" json:"prefix,omitempty"` - Bucket string `mapstructure:"bucket" json:"bucket,omitempty"` - BucketKeyEnabled bool `mapstructure:"bucketKeyEnabled" json:"bucketKeyEnabled,omitempty"` - KmsKeyID string `mapstructure:"kmsKeyId" json:"kmsKeyId,omitempty"` - ServerSideEncryption string `mapstructure:"serverSideEncryption" json:"serverSideEncryption,omitempty"` - PathStyle bool `mapstructure:"pathStyle" json:"pathStyle,omitempty"` - Channels []*S3 `mapstructure:"channels" json:"channels,omitempty"` -} - -// Kinesis configuration -type Kinesis struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - AWSConfig `mapstructure:",squash" json:",inline"` - StreamName string `mapstructure:"streamName" json:"streamName,omitempty"` - Channels []*Kinesis `mapstructure:"channels" json:"channels,omitempty"` -} - -// SecurityHub configuration -type SecurityHub struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - AWSConfig `mapstructure:",squash" json:",inline"` - AccountID string `mapstructure:"accountId" json:"accountId,omitempty"` - ProductName string `mapstructure:"productName" json:"productName,omitempty"` - CompanyName string `mapstructure:"companyName" json:"companyName,omitempty"` - DelayInSeconds int `mapstructure:"delayInSeconds" json:"delayInSeconds,omitempty"` - Cleanup bool `mapstructure:"cleanup" json:"cleanup,omitempty"` - Channels []*SecurityHub `mapstructure:"channels" json:"channels,omitempty"` -} - -// GCS configuration -type GCS struct { - TargetBaseOptions `mapstructure:",squash" json:",inline"` - Credentials string `mapstructure:"credentials" json:"customLabels,omitempty"` - Prefix string `mapstructure:"prefix" json:"credentials,omitempty"` - Bucket string `mapstructure:"bucket" json:"bucket,omitempty"` - Sources []string `mapstructure:"sources" json:"sources,omitempty"` - Channels []*GCS `mapstructure:"channels" json:"channels,omitempty"` + Namespaces ValueFilter `mapstructure:"namespaces"` + Policies ValueFilter `mapstructure:"policies"` + Severities ValueFilter `mapstructure:"severities"` + Status ValueFilter `mapstructure:"status"` + Sources ValueFilter `mapstructure:"sources"` + Kinds ValueFilter `mapstructure:"kinds"` } // SMTP configuration type SMTP struct { - Host string `mapstructure:"host" json:"host,omitempty"` - Port int `mapstructure:"port" json:"port,omitempty"` - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` - From string `mapstructure:"from" json:"from,omitempty"` - Encryption string `mapstructure:"encryption" json:"encryption,omitempty"` - SkipTLS bool `mapstructure:"skipTLS" json:"skipTLS,omitempty"` - Certificate string `mapstructure:"certificate" json:"certificate,omitempty"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + From string `mapstructure:"from"` + Encryption string `mapstructure:"encryption"` + SkipTLS bool `mapstructure:"skipTLS"` + Certificate string `mapstructure:"certificate"` } // EmailReport configuration type EmailReport struct { - To []string `mapstructure:"to" json:"to,omitempty"` - Format string `mapstructure:"format" json:"format,omitempty"` - Filter EmailReportFilter `mapstructure:"filter" json:"filter,omitempty"` - Channels []EmailReport `mapstructure:"channels" json:"channels,omitempty"` + To []string `mapstructure:"to"` + Format string `mapstructure:"format"` + Filter EmailReportFilter `mapstructure:"filter"` + Channels []EmailReport `mapstructure:"channels"` } // EmailReport configuration type Templates struct { - Dir string `mapstructure:"dir" json:"dir,omitempty"` + Dir string `mapstructure:"dir"` } // EmailReports configuration type EmailReports struct { - SMTP SMTP `mapstructure:"smtp" json:"smtp,omitempty"` - Summary EmailReport `mapstructure:"summary" json:"summary,omitempty"` - Violations EmailReport `mapstructure:"violations" json:"violations,omitempty"` - ClusterName string `mapstructure:"clusterName" json:"clusterName,omitempty"` - TitlePrefix string `mapstructure:"titlePrefix" json:"titlePrefix,omitempty"` + SMTP SMTP `mapstructure:"smtp"` + Summary EmailReport `mapstructure:"summary"` + Violations EmailReport `mapstructure:"violations"` + ClusterName string `mapstructure:"clusterName"` + TitlePrefix string `mapstructure:"titlePrefix"` } // BasicAuth configuration type BasicAuth struct { - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` - SecretRef string `mapstructure:"secretRef" json:"secretRef,omitempty"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + SecretRef string `mapstructure:"secretRef"` } // API configuration type API struct { - Port int `mapstructure:"port" json:"port,omitempty"` - Logging bool `mapstructure:"logging" json:"logging,omitempty"` - BasicAuth BasicAuth `mapstructure:"basicAuth" json:"basicAuth,omitempty"` + Port int `mapstructure:"port"` + BasicAuth BasicAuth `mapstructure:"basicAuth"` + DebugMode bool `mapstructure:"debug"` } // REST configuration type REST struct { - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + Enabled bool `mapstructure:"enabled"` } // Metrics configuration @@ -287,106 +93,107 @@ type Metrics struct { // Profiling configuration type Profiling struct { - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` -} - -// ClusterReportFilter configuration -type ClusterReportFilter struct { - Disabled bool `mapstructure:"disabled" json:"disabled,omitempty"` + Enabled bool `mapstructure:"enabled"` } // ReportFilter configuration type ReportFilter struct { - Namespaces ValueFilter `mapstructure:"namespaces" json:"namespaces,omitempty"` - ClusterReports ClusterReportFilter `mapstructure:"clusterReports" json:"clusterReports,omitempty"` + Namespaces ValueFilter `mapstructure:"namespaces"` + Sources ValueFilter `mapstructure:"sources"` + Kinds ValueFilter `mapstructure:"kinds"` + DisableClusterReports bool `mapstructure:"disableClusterReports"` } // Redis configuration type Redis struct { - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` - Address string `mapstructure:"address" json:"address,omitempty"` - Prefix string `mapstructure:"prefix" json:"prefix,omitempty"` - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` - Database int `mapstructure:"database" json:"database,omitempty"` + Enabled bool `mapstructure:"enabled"` + Address string `mapstructure:"address"` + Prefix string `mapstructure:"prefix"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + Database int `mapstructure:"database"` } // LeaderElection configuration type LeaderElection struct { - LockName string `mapstructure:"lockName" json:"lockName,omitempty"` - PodName string `mapstructure:"podName" json:"podName,omitempty"` - Namespace string `mapstructure:"namespace" json:"namespace,omitempty"` - LeaseDuration int `mapstructure:"leaseDuration" json:"leaseDuration,omitempty"` - RenewDeadline int `mapstructure:"renewDeadline" json:"renewDeadline,omitempty"` - RetryPeriod int `mapstructure:"retryPeriod" json:"retryPeriod,omitempty"` - ReleaseOnCancel bool `mapstructure:"releaseOnCancel" json:"releaseOnCancel,omitempty"` - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + LockName string `mapstructure:"lockName"` + PodName string `mapstructure:"podName"` + Namespace string `mapstructure:"namespace"` + LeaseDuration int `mapstructure:"leaseDuration"` + RenewDeadline int `mapstructure:"renewDeadline"` + RetryPeriod int `mapstructure:"retryPeriod"` + ReleaseOnCancel bool `mapstructure:"releaseOnCancel"` + Enabled bool `mapstructure:"enabled"` } // K8sClient config struct type K8sClient struct { - QPS float32 `mapstructure:"qps" json:"qps,omitempty"` - Burst int `mapstructure:"burst" json:"burst,omitempty"` - Kubeconfig string `mapstructure:"kubeconfig" json:"kubeconfig,omitempty"` + QPS float32 `mapstructure:"qps"` + Burst int `mapstructure:"burst"` + Kubeconfig string `mapstructure:"kubeconfig"` } type Logging struct { - LogLevel int8 `mapstructure:"logLevel" json:"logLevel,omitempty"` - Encoding string `mapstructure:"encoding" json:"encoding,omitempty"` - Development bool `mapstructure:"development" json:"development,omitempty"` + Server bool `mapstructure:"server"` + LogLevel int8 `mapstructure:"logLevel"` + Encoding string `mapstructure:"encoding"` + Development bool `mapstructure:"development"` } type Database struct { - Type string `mapstructure:"type" json:"type,omitempty"` - DSN string `mapstructure:"dsn" json:"dsn,omitempty"` - Username string `mapstructure:"username" json:"username,omitempty"` - Password string `mapstructure:"password" json:"password,omitempty"` - Database string `mapstructure:"database" json:"database,omitempty"` - Host string `mapstructure:"host" json:"host,omitempty"` - EnableSSL bool `mapstructure:"enableSSL" json:"enableSSL,omitempty"` - SecretRef string `mapstructure:"secretRef" json:"secretRef,omitempty"` - MountedSecret string `mapstructure:"mountedSecret" json:"mountedSecret,omitempty"` + Type string `mapstructure:"type"` + DSN string `mapstructure:"dsn"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + Database string `mapstructure:"database"` + Host string `mapstructure:"host"` + EnableSSL bool `mapstructure:"enableSSL"` + SecretRef string `mapstructure:"secretRef"` + MountedSecret string `mapstructure:"mountedSecret"` +} + +type SourceSelector struct { + Source string `mapstructure:"source"` +} + +type SourceFilter struct { + Selector SourceSelector `mapstructure:"selector"` + Kinds ValueFilter `mapstructure:"kinds"` + Sources ValueFilter `mapstructure:"sources"` + Namespaces ValueFilter `mapstructure:"namespaces"` + UncontrolledOnly bool `mapstructure:"uncontrolledOnly"` + DisableClusterReports bool `mapstructure:"disableClusterReports"` } type CustomID struct { - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` - Fields []string `mapstructure:"fields" json:"fields,omitempty"` + Enabled bool `mapstructure:"enabled"` + Fields []string `mapstructure:"fields"` } type SourceConfig struct { - CustomID `mapstructure:"customID" json:"customID,omitempty"` + Selector SourceSelector `mapstructure:"selector"` + CustomID `mapstructure:"customId"` } // Config of the PolicyReporter type Config struct { - Version string `json:"version,omitempty"` - Namespace string `mapstructure:"namespace" json:"namespace,omitempty"` - Loki *Loki `mapstructure:"loki" json:"loki,omitempty"` - Elasticsearch *Elasticsearch `mapstructure:"elasticsearch" json:"elasticsearch,omitempty"` - Slack *Slack `mapstructure:"slack" json:"slack,omitempty"` - Discord *Discord `mapstructure:"discord" json:"discord,omitempty"` - Teams *Teams `mapstructure:"teams" json:"teams,omitempty"` - S3 *S3 `mapstructure:"s3" json:"s3,omitempty"` - Kinesis *Kinesis `mapstructure:"kinesis" json:"kinesis,omitempty"` - SecurityHub *SecurityHub `mapstructure:"securityHub" json:"securityHub,omitempty"` - GCS *GCS `mapstructure:"gcs" json:"gcs,omitempty"` - UI *UI `mapstructure:"ui" json:"ui,omitempty"` - Webhook *Webhook `mapstructure:"webhook" json:"webhook,omitempty"` - Telegram *Telegram `mapstructure:"telegram" json:"telegram,omitempty"` - GoogleChat *GoogleChat `mapstructure:"googleChat" json:"googleChat,omitempty"` - API API `mapstructure:"api" json:"api,omitempty"` - WorkerCount int `mapstructure:"worker" json:"worker,omitempty"` - DBFile string `mapstructure:"dbfile" json:"dbfile,omitempty"` - Metrics Metrics `mapstructure:"metrics" json:"metrics,omitempty"` - REST REST `mapstructure:"rest" json:"rest,omitempty"` - ReportFilter ReportFilter `mapstructure:"reportFilter" json:"reportFilter,omitempty"` - Redis Redis `mapstructure:"redis" json:"redis,omitempty"` - Profiling Profiling `mapstructure:"profiling" json:"profiling,omitempty"` - EmailReports EmailReports `mapstructure:"emailReports" json:"emailReports,omitempty"` - LeaderElection LeaderElection `mapstructure:"leaderElection" json:"leaderElection,omitempty"` - K8sClient K8sClient `mapstructure:"k8sClient" json:"k8sClient,omitempty"` - Logging Logging `mapstructure:"logging" json:"logging,omitempty"` - Database Database `mapstructure:"database" json:"database,omitempty"` - SourceConfig map[string]SourceConfig `mapstructure:"sourceConfig" json:"sourceConfig,omitempty"` - Templates Templates `mapstructure:"templates" json:"templates,omitempty"` + Version string + Namespace string `mapstructure:"namespace"` + API API `mapstructure:"api"` + WorkerCount int `mapstructure:"worker"` + DBFile string `mapstructure:"dbfile"` + Metrics Metrics `mapstructure:"metrics"` + REST REST `mapstructure:"rest"` + ReportFilter ReportFilter `mapstructure:"reportFilter"` + SourceFilters []SourceFilter `mapstructure:"sourceFilters"` + Redis Redis `mapstructure:"redis"` + Profiling Profiling `mapstructure:"profiling"` + EmailReports EmailReports `mapstructure:"emailReports"` + LeaderElection LeaderElection `mapstructure:"leaderElection"` + K8sClient K8sClient `mapstructure:"k8sClient"` + Logging Logging `mapstructure:"logging"` + Database Database `mapstructure:"database"` + Targets target.Targets `mapstructure:"target"` + SourceConfig []SourceConfig `mapstructure:"sourceConfig"` + Templates Templates `mapstructure:"templates"` } diff --git a/pkg/config/database_factory.go b/pkg/config/database_factory.go index 03383b1e..85ead861 100644 --- a/pkg/config/database_factory.go +++ b/pkg/config/database_factory.go @@ -14,6 +14,7 @@ import ( "github.com/uptrace/bun/dialect/mysqldialect" "github.com/uptrace/bun/dialect/pgdialect" "github.com/uptrace/bun/driver/pgdriver" + "github.com/uptrace/bun/extra/bundebug" "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/database" @@ -88,6 +89,8 @@ func (f *DatabaseFactory) NewSQLite(file string) *bun.DB { return nil } + sqldb.AddQueryHook(bundebug.NewQueryHook()) + return sqldb } diff --git a/pkg/config/database_factory_test.go b/pkg/config/database_factory_test.go index 89468905..543bbdc0 100644 --- a/pkg/config/database_factory_test.go +++ b/pkg/config/database_factory_test.go @@ -1,14 +1,54 @@ package config_test import ( + "encoding/json" + "os" "testing" "github.com/uptrace/bun/dialect" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sfake "k8s.io/client-go/kubernetes/fake" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" "github.com/kyverno/policy-reporter/pkg/config" "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" ) +const ( + secretName = "secret-values" + mountedSecret = "/tmp/secrets-9999" +) + +func newFakeClient() v1.SecretInterface { + return k8sfake.NewSimpleClientset(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: "default", + }, + Data: map[string][]byte{ + "host": []byte("http://localhost:9200"), + "username": []byte("username"), + "password": []byte("password"), + "apiKey": []byte("apiKey"), + "database": []byte("database"), + "dsn": []byte(""), + }, + }).CoreV1().Secrets("default") +} + +func mountSecret() { + secretValues := secrets.Values{ + Host: "http://localhost:9200", + Username: "username", + Password: "password", + Database: "database", + DSN: "", + } + file, _ := json.MarshalIndent(secretValues, "", " ") + _ = os.WriteFile(mountedSecret, file, 0o644) +} + func Test_ResolveDatabase(t *testing.T) { factory := config.NewDatabaseFactory(nil) diff --git a/pkg/config/readinessprobe.go b/pkg/config/readinessprobe.go index 2f613fac..949502f3 100644 --- a/pkg/config/readinessprobe.go +++ b/pkg/config/readinessprobe.go @@ -31,12 +31,15 @@ func (r *ReadinessProbe) Ready() { func (r *ReadinessProbe) Wait() { if r.required() && !r.running { r.running = <-r.ready - close(r.ready) zap.L().Debug("readiness probe finished") return } } +func (r *ReadinessProbe) Close() { + close(r.ready) +} + func (r *ReadinessProbe) Running() bool { return r.running } diff --git a/pkg/config/resolver.go b/pkg/config/resolver.go index 2c0413ef..954eb412 100644 --- a/pkg/config/resolver.go +++ b/pkg/config/resolver.go @@ -8,8 +8,10 @@ import ( "strings" "time" + "github.com/gin-gonic/gin" goredis "github.com/go-redis/redis/v8" _ "github.com/mattn/go-sqlite3" + gocache "github.com/patrickmn/go-cache" "github.com/uptrace/bun" "github.com/uptrace/bun/dialect" mail "github.com/xhit/go-simple-mail/v2" @@ -30,6 +32,9 @@ import ( "github.com/kyverno/policy-reporter/pkg/email/violations" "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/kubernetes" + "github.com/kyverno/policy-reporter/pkg/kubernetes/jobs" + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" + "github.com/kyverno/policy-reporter/pkg/kubernetes/pods" "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" "github.com/kyverno/policy-reporter/pkg/leaderelection" "github.com/kyverno/policy-reporter/pkg/listener" @@ -37,6 +42,7 @@ import ( "github.com/kyverno/policy-reporter/pkg/report" "github.com/kyverno/policy-reporter/pkg/report/result" "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/factory" "github.com/kyverno/policy-reporter/pkg/validate" ) @@ -44,25 +50,22 @@ import ( type Resolver struct { config *Config k8sConfig *rest.Config + clientset *k8s.Clientset publisher report.EventPublisher policyStore *database.Store database *bun.DB policyReportClient report.PolicyReportClient leaderElector *leaderelection.Client resultCache cache.Cache - targetClients []target.Client + targetClients *target.Collection targetsCreated bool + targetFactory target.Factory logger *zap.Logger resultListener *listener.ResultListener } // APIServer resolver method -func (r *Resolver) APIServer(ctx context.Context, synced func() bool) api.Server { - var logger *zap.Logger - if r.config.API.Logging { - logger, _ = r.Logger() - } - +func (r *Resolver) Server(ctx context.Context, options []api.ServerOption) (*api.Server, error) { if r.config.API.BasicAuth.SecretRef != "" { values, err := r.SecretClient().Get(ctx, r.config.API.BasicAuth.SecretRef) if err != nil { @@ -77,23 +80,34 @@ func (r *Resolver) APIServer(ctx context.Context, synced func() bool) api.Server } } - var auth *api.BasicAuth + defaults := []api.ServerOption{ + api.WithGZIP(), + } + + if r.config.Logging.Server || r.config.API.DebugMode { + defaults = append(defaults, api.WithLogging(zap.L())) + } else { + defaults = append(defaults, api.WithRecovery()) + } + if r.config.API.BasicAuth.Username != "" && r.config.API.BasicAuth.Password != "" { - auth = &api.BasicAuth{ + defaults = append(defaults, api.WithBasicAuth(api.BasicAuth{ Username: r.config.API.BasicAuth.Username, Password: r.config.API.BasicAuth.Password, - } + })) zap.L().Info("API BasicAuth enabled") } - return api.NewServer( - r.TargetClients(), - r.config.API.Port, - logger, - auth, - synced, - ) + if r.config.Profiling.Enabled { + defaults = append(defaults, api.WithProfiling()) + } + + if !r.config.API.DebugMode { + gin.SetMode(gin.ReleaseMode) + } + + return api.NewServer(gin.New(), append(defaults, options...)...), nil } // Database resolver method @@ -128,7 +142,7 @@ func (r *Resolver) Database() *bun.DB { } // PolicyReportStore resolver method -func (r *Resolver) PolicyReportStore(db *bun.DB) (*database.Store, error) { +func (r *Resolver) Store(db *bun.DB) (*database.Store, error) { if r.policyStore != nil { return r.policyStore, nil } @@ -178,12 +192,12 @@ func (r *Resolver) EventPublisher() report.EventPublisher { func (r *Resolver) CustomIDGenerators() map[string]result.IDGenerator { generators := make(map[string]result.IDGenerator) - for s, c := range r.config.SourceConfig { + for _, c := range r.config.SourceConfig { if !c.Enabled || len(c.Fields) == 0 { continue } - generators[strings.ToLower(s)] = result.NewIDGenerator(c.Fields) + generators[strings.ToLower(c.Selector.Source)] = result.NewIDGenerator(c.Fields) } return generators @@ -196,10 +210,32 @@ func (r *Resolver) Queue() (*kubernetes.Queue, error) { return nil, err } + podsClient, err := r.PodClient() + if err != nil { + return nil, err + } + + jobsClient, err := r.JobClient() + if err != nil { + return nil, err + } + return kubernetes.NewQueue( kubernetes.NewDebouncer(1*time.Minute, r.EventPublisher()), - workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "report-queue"), + workqueue.NewTypedRateLimitingQueueWithConfig(workqueue.DefaultTypedControllerRateLimiter[string](), workqueue.TypedRateLimitingQueueConfig[string]{ + Name: "report-queue", + }), client, + report.NewSourceFilter(podsClient, jobsClient, helper.Map(r.config.SourceFilters, func(f SourceFilter) report.SourceValidation { + return report.SourceValidation{ + Selector: report.ReportSelector{Source: f.Selector.Source}, + Kinds: ToRuleSet(f.Kinds), + Sources: ToRuleSet(f.Sources), + Namespaces: ToRuleSet(f.Namespaces), + UncontrolledOnly: f.UncontrolledOnly, + DisableClusterReports: f.DisableClusterReports, + } + })), result.NewReconditioner(r.CustomIDGenerators()), ), nil } @@ -207,7 +243,7 @@ func (r *Resolver) Queue() (*kubernetes.Queue, error) { // RegisterNewResultsListener resolver method func (r *Resolver) RegisterNewResultsListener() { targets := r.TargetClients() - if len(targets) == 0 { + if targets.Empty() { return } @@ -222,7 +258,7 @@ func (r *Resolver) RegisterNewResultsListener() { func (r *Resolver) RegisterSendResultListener() { targets := r.TargetClients() - if len(targets) == 0 { + if targets.Empty() { return } @@ -231,9 +267,11 @@ func (r *Resolver) RegisterSendResultListener() { } r.resultListener.RegisterListener(listener.NewSendResultListener(targets)) + r.resultListener.RegisterScopeListener(listener.NewSendScopeResultsListener(targets)) + r.resultListener.RegisterSyncListener(listener.NewSendSyncResultsListener(targets)) } -// RegisterSendResultListener resolver method +// UnregisterSendResultListener resolver method func (r *Resolver) UnregisterSendResultListener() { if r.ResultCache().Shared() { r.EventPublisher().UnregisterListener(listener.NewResults) @@ -244,9 +282,10 @@ func (r *Resolver) UnregisterSendResultListener() { } r.resultListener.UnregisterListener() + r.resultListener.UnregisterScopeListener() } -// RegisterSendResultListener resolver method +// RegisterStoreListener resolver method func (r *Resolver) RegisterStoreListener(ctx context.Context, store report.PolicyReportStore) { r.EventPublisher().RegisterListener(listener.Store, listener.NewStoreListener(ctx, store)) } @@ -271,9 +310,25 @@ func (r *Resolver) RegisterMetricsListener() { )) } +// Clientset resolver method +func (r *Resolver) Clientset() (*k8s.Clientset, error) { + if r.clientset != nil { + return r.clientset, nil + } + + clientset, err := k8s.NewForConfig(r.k8sConfig) + if err != nil { + return nil, err + } + + r.clientset = clientset + + return r.clientset, nil +} + // SecretClient resolver method func (r *Resolver) SecretClient() secrets.Client { - clientset, err := k8s.NewForConfig(r.k8sConfig) + clientset, err := r.Clientset() if err != nil { return nil } @@ -281,10 +336,61 @@ func (r *Resolver) SecretClient() secrets.Client { return secrets.NewClient(clientset.CoreV1().Secrets(r.config.Namespace)) } -func (r *Resolver) TargetFactory() *TargetFactory { - return &TargetFactory{ - secretClient: r.SecretClient(), +// NamespaceClient resolver method +func (r *Resolver) NamespaceClient() (namespaces.Client, error) { + clientset, err := r.Clientset() + if err != nil { + return nil, err } + + return namespaces.NewClient( + clientset.CoreV1().Namespaces(), + gocache.New(15*time.Second, 5*time.Second), + ), nil +} + +// PodClient resolver method +func (r *Resolver) PodClient() (pods.Client, error) { + clientset, err := r.Clientset() + if err != nil { + return nil, err + } + + return pods.NewClient(clientset.CoreV1()), nil +} + +// JobClient resolver method +func (r *Resolver) JobClient() (jobs.Client, error) { + clientset, err := r.Clientset() + if err != nil { + return nil, err + } + + return jobs.NewClient(clientset.BatchV1()), nil +} + +func (r *Resolver) TargetFactory() target.Factory { + if r.targetFactory != nil { + return r.targetFactory + } + + ns, err := r.NamespaceClient() + if err != nil { + zap.L().Error("failed to create namespace client", zap.Error(err)) + } + + r.targetFactory = factory.NewFactory(r.SecretClient(), target.NewResultFilterFactory(ns)) + + return r.targetFactory +} + +func (r *Resolver) SecretInformer() (secrets.Informer, error) { + client, err := r.CRDMetadataClient() + if err != nil { + return nil, err + } + + return secrets.NewInformer(client, r.TargetFactory(), r.config.Namespace), nil } func (r *Resolver) DatabaseFactory() *DatabaseFactory { @@ -294,40 +400,19 @@ func (r *Resolver) DatabaseFactory() *DatabaseFactory { } // TargetClients resolver method -func (r *Resolver) TargetClients() []target.Client { +func (r *Resolver) TargetClients() *target.Collection { if r.targetsCreated { return r.targetClients } - factory := r.TargetFactory() - - clients := make([]target.Client, 0) - - clients = append(clients, factory.LokiClients(r.config.Loki)...) - clients = append(clients, factory.ElasticsearchClients(r.config.Elasticsearch)...) - clients = append(clients, factory.SlackClients(r.config.Slack)...) - clients = append(clients, factory.DiscordClients(r.config.Discord)...) - clients = append(clients, factory.TeamsClients(r.config.Teams)...) - clients = append(clients, factory.S3Clients(r.config.S3)...) - clients = append(clients, factory.KinesisClients(r.config.Kinesis)...) - clients = append(clients, factory.SecurityHubs(r.config.SecurityHub)...) - clients = append(clients, factory.WebhookClients(r.config.Webhook)...) - clients = append(clients, factory.GCSClients(r.config.GCS)...) - clients = append(clients, factory.TelegramClients(r.config.Telegram)...) - clients = append(clients, factory.GoogleChatClients(r.config.GoogleChat)...) - - if ui := factory.UIClient(r.config.UI); ui != nil { - clients = append(clients, ui) - } - - r.targetClients = clients + r.targetClients = r.TargetFactory().CreateClients(&r.config.Targets) r.targetsCreated = true return r.targetClients } func (r *Resolver) HasTargets() bool { - return len(r.TargetClients()) > 0 + return !r.TargetClients().Empty() } func (r *Resolver) EnableLeaderElection() bool { @@ -344,7 +429,7 @@ func (r *Resolver) EnableLeaderElection() bool { // SkipExistingOnStartup config method func (r *Resolver) SkipExistingOnStartup() bool { - for _, client := range r.TargetClients() { + for _, client := range r.TargetClients().Clients() { if !client.SkipExistingOnStartup() { return false } @@ -377,9 +462,14 @@ func (r *Resolver) SummaryGenerator() (*summary.Generator, error) { return nil, err } + nsclient, err := r.NamespaceClient() + if err != nil { + return nil, err + } + return summary.NewGenerator( client, - EmailReportFilterFromConfig(r.config.EmailReports.Summary.Filter), + EmailReportFilterFromConfig(nsclient, r.config.EmailReports.Summary.Filter), !r.config.EmailReports.Summary.Filter.DisableClusterReports, ), nil } @@ -398,9 +488,14 @@ func (r *Resolver) ViolationsGenerator() (*violations.Generator, error) { return nil, err } + nsclient, err := r.NamespaceClient() + if err != nil { + return nil, err + } + return violations.NewGenerator( client, - EmailReportFilterFromConfig(r.config.EmailReports.Violations.Filter), + EmailReportFilterFromConfig(nsclient, r.config.EmailReports.Violations.Filter), !r.config.EmailReports.Violations.Filter.DisableClusterReports, ), nil } @@ -466,9 +561,9 @@ func (r *Resolver) PolicyReportClient() (report.PolicyReportClient, error) { return r.policyReportClient, nil } -func (r *Resolver) ReportFilter() *report.Filter { - return report.NewFilter( - r.config.ReportFilter.ClusterReports.Disabled, +func (r *Resolver) ReportFilter() *report.MetaFilter { + return report.NewMetaFilter( + r.config.ReportFilter.DisableClusterReports, ToRuleSet(r.config.ReportFilter.Namespaces), ) } @@ -554,13 +649,18 @@ func NewResolver(config *Config, k8sConfig *rest.Config) Resolver { } } -func EmailReportFilterFromConfig(config EmailReportFilter) email.Filter { - return email.NewFilter(ToRuleSet(config.Namespaces), ToRuleSet(config.Sources)) +func EmailReportFilterFromConfig(client namespaces.Client, config EmailReportFilter) email.Filter { + return email.NewFilter( + client, + ToRuleSet(config.Namespaces), + ToRuleSet(config.Sources), + ) } func ToRuleSet(filter ValueFilter) validate.RuleSets { return validate.RuleSets{ - Include: filter.Include, - Exclude: filter.Exclude, + Include: filter.Include, + Exclude: filter.Exclude, + Selector: helper.ConvertMap(filter.Selector), } } diff --git a/pkg/config/resolver_test.go b/pkg/config/resolver_test.go index 0a9be6ee..1b8492cb 100644 --- a/pkg/config/resolver_test.go +++ b/pkg/config/resolver_test.go @@ -4,166 +4,208 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" "k8s.io/client-go/rest" "github.com/kyverno/policy-reporter/pkg/config" "github.com/kyverno/policy-reporter/pkg/database" "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/target" ) -var testConfig = &config.Config{ - Loki: &config.Loki{ - Host: "http://localhost:3100", - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, +var targets = target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + SkipTLS: true, + }, }, - SkipTLS: true, - Channels: []*config.Loki{ + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.LokiOptions]{ { - TargetBaseOptions: config.TargetBaseOptions{ - CustomFields: map[string]string{"label2": "value2"}, + CustomFields: map[string]string{"label2": "value2"}, + }, + }, + }, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{ + Config: &target.ElasticsearchOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:9200", + SkipTLS: true, + }, + Index: "policy-reporter", + Rotation: "daily", + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.ElasticsearchOptions]{{}}, + }, + Slack: &target.Config[target.SlackOptions]{ + Config: &target.SlackOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + SkipTLS: true, + }, + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.SlackOptions]{{ + Config: &target.SlackOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:9200", }, }, - }, - Headers: map[string]string{"X-Forward": "http://loki"}, - }, - Elasticsearch: &config.Elasticsearch{ - Host: "http://localhost:9200", - Index: "policy-reporter", - Rotation: "daily", - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, - }, - SkipTLS: true, - Channels: []*config.Elasticsearch{{}}, - }, - Slack: &config.Slack{ - Webhook: "http://hook.slack:80", - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, - }, - Channels: []*config.Slack{{ - Webhook: "http://localhost:9200", }, { - Channel: "general", - }}, - }, - Discord: &config.Discord{ - Webhook: "http://hook.discord:80", - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, - }, - Channels: []*config.Discord{{ - Webhook: "http://localhost:9200", - }}, - }, - Teams: &config.Teams{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, - }, - Webhook: "http://hook.teams:80", - SkipTLS: true, - Channels: []*config.Teams{{ - Webhook: "http://localhost:9200", - }}, - }, - UI: &config.UI{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - }, - Host: "http://localhost:8080", - }, - Webhook: &config.Webhook{ - Host: "http://localhost:8080", - Headers: map[string]string{ - "X-Custom": "Header", - }, - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, - }, - SkipTLS: true, - Channels: []*config.Webhook{{ - Host: "http://localhost:8081", - Headers: map[string]string{ - "X-Custom-2": "Header", + Config: &target.SlackOptions{ + Channel: "general", }, }}, }, - S3: &config.S3{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, + Discord: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://discord:80", + SkipTLS: true, }, - AWSConfig: config.AWSConfig{ - AccessKeyID: "AccessKey", - SecretAccessKey: "SecretAccessKey", - Endpoint: "https://storage.yandexcloud.net", - Region: "ru-central1", - }, - Bucket: "test", - BucketKeyEnabled: false, - KmsKeyID: "", - ServerSideEncryption: "", - PathStyle: true, - Prefix: "prefix", - Channels: []*config.S3{{}}, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:9200", + }, + }}, }, - Kinesis: &config.Kinesis{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, + Teams: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://hook.teams:80", + SkipTLS: true, }, - AWSConfig: config.AWSConfig{ - AccessKeyID: "AccessKey", - SecretAccessKey: "SecretAccessKey", - Endpoint: "https://yds.serverless.yandexcloud.net", - Region: "ru-central1", - }, - StreamName: "policy-reporter", - Channels: []*config.Kinesis{{}}, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:9200", + }, + }}, }, - SecurityHub: &config.SecurityHub{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, + GoogleChat: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:900/webhook", + SkipTLS: true, }, - AWSConfig: config.AWSConfig{ - AccessKeyID: "AccessKey", - SecretAccessKey: "SecretAccessKey", - Endpoint: "https://yds.serverless.yandexcloud.net", - Region: "ru-central1", - }, - AccountID: "AccountID", - Channels: []*config.SecurityHub{{}}, - DelayInSeconds: 2, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{}}, }, - GCS: &config.GCS{ - TargetBaseOptions: config.TargetBaseOptions{ - SkipExisting: true, - MinimumPriority: "debug", - CustomFields: map[string]string{"field": "value"}, + Telegram: &target.Config[target.TelegramOptions]{ + Config: &target.TelegramOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + SkipTLS: true, + }, + Token: "XXX", + ChatID: "123456", }, - Credentials: `{"token": "token", "type": "authorized_user"}`, - Bucket: "test", - Prefix: "prefix", - Channels: []*config.GCS{{}}, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.TelegramOptions]{{ + Config: &target.TelegramOptions{ + ChatID: "1234567", + }, + }}, }, + Webhook: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8080", + SkipTLS: true, + Headers: map[string]string{ + "X-Custom": "Header", + }, + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8081", + Headers: map[string]string{ + "X-Custom-2": "Header", + }, + }, + }}, + }, + S3: &target.Config[target.S3Options]{ + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + Bucket: "test", + BucketKeyEnabled: false, + KmsKeyID: "", + ServerSideEncryption: "", + PathStyle: true, + Prefix: "prefix", + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.S3Options]{{}}, + }, + Kinesis: &target.Config[target.KinesisOptions]{ + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + StreamName: "policy-reporter", + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.KinesisOptions]{{}}, + }, + SecurityHub: &target.Config[target.SecurityHubOptions]{ + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + AccountID: "AccountId", + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.SecurityHubOptions]{{}}, + }, + GCS: &target.Config[target.GCSOptions]{ + Config: &target.GCSOptions{ + Credentials: `{"token": "token", "type": "authorized_user"}`, + Bucket: "test", + Prefix: "prefix", + }, + SkipExisting: true, + MinimumSeverity: "debug", + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.GCSOptions]{{}}, + }, +} + +var testConfig = &config.Config{ Templates: config.Templates{ Dir: "../../templates", }, @@ -177,82 +219,78 @@ var testConfig = &config.Config{ Encryption: "ssl/tls", }, }, - Telegram: &config.Telegram{ - Token: "XXX", - ChatID: "123456", - Channels: []*config.Telegram{ - { - ChatID: "1234567", + Targets: targets, + Logging: config.Logging{ + Development: true, + }, + SourceConfig: []config.SourceConfig{ + { + Selector: config.SourceSelector{ + Source: "test", }, - }, - }, - GoogleChat: &config.GoogleChat{ - Webhook: "http://localhost:900/webhook", - Channels: []*config.GoogleChat{{}}, - }, - SourceConfig: map[string]config.SourceConfig{ - "test": { CustomID: config.CustomID{ Enabled: true, Fields: []string{"resource"}, }, }, - "default": {}, + { + Selector: config.SourceSelector{ + Source: "default", + }, + }, }, } func Test_ResolveTargets(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - if count := len(resolver.TargetClients()); count != 26 { - t.Errorf("Expected 26 Clients, got %d", count) - } + assert.Equal(t, resolver.TargetClients().Length(), 25) } func Test_ResolveHasTargets(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - if !resolver.HasTargets() { - t.Errorf("Expected 'true'") - } + assert.True(t, resolver.HasTargets()) } func Test_ResolveSkipExistingOnStartup(t *testing.T) { testConfig := &config.Config{ - Loki: &config.Loki{ - Host: "http://localhost:3100", - TargetBaseOptions: config.TargetBaseOptions{ + Targets: target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + }, + }, SkipExisting: true, - MinimumPriority: "debug", + MinimumSeverity: "debug", }, - }, - Elasticsearch: &config.Elasticsearch{ - Host: "http://localhost:9200", - TargetBaseOptions: config.TargetBaseOptions{ + Elasticsearch: &target.Config[target.ElasticsearchOptions]{ + Config: &target.ElasticsearchOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:9200", + }, + }, SkipExisting: true, - MinimumPriority: "debug", + MinimumSeverity: "debug", }, }, } t.Run("Resolve false", func(t *testing.T) { - testConfig.Elasticsearch.SkipExisting = false + testConfig.Targets.Elasticsearch.SkipExisting = false resolver := config.NewResolver(testConfig, &rest.Config{}) - if resolver.SkipExistingOnStartup() == true { - t.Error("Expected SkipExistingOnStartup to be false if one Client has SkipExistingOnStartup false configured") - } + assert.False(t, resolver.SkipExistingOnStartup(), "Expected SkipExistingOnStartup to be false if one Client has SkipExistingOnStartup false configured") }) t.Run("Resolve true", func(t *testing.T) { - testConfig.Elasticsearch.SkipExisting = true + testConfig.Targets.Elasticsearch.SkipExisting = true resolver := config.NewResolver(testConfig, &rest.Config{}) - if resolver.SkipExistingOnStartup() == false { - t.Error("Expected SkipExistingOnStartup to be true if all Client has SkipExistingOnStartup true configured") - } + assert.True(t, resolver.SkipExistingOnStartup(), "Expected SkipExistingOnStartup to be true if all Client has SkipExistingOnStartup true configured") }) } @@ -260,28 +298,40 @@ func Test_ResolvePolicyClient(t *testing.T) { resolver := config.NewResolver(&config.Config{DBFile: "test.db"}, &rest.Config{}) client1, err := resolver.PolicyReportClient() - if err != nil { - t.Errorf("Unexpected Error: %s", err) - } + assert.Nil(t, err) client2, _ := resolver.PolicyReportClient() - if client1 != client2 { - t.Error("A second call resolver.PolicyReportClient() should return the cached first client") - } + + assert.Equal(t, client1, client2, "A second call resolver.PolicyReportClient() should return the cached first client") +} + +func Test_ResolveSecretInformer(t *testing.T) { + resolver := config.NewResolver(&config.Config{DBFile: "test.db"}, &rest.Config{}) + + informer, err := resolver.SecretInformer() + assert.Nil(t, err) + assert.NotNil(t, informer) +} + +func Test_ResolveSecretInformerWithInvalidK8sConfig(t *testing.T) { + k8sConfig := &rest.Config{} + k8sConfig.Host = "invalid/url" + + resolver := config.NewResolver(testConfig, k8sConfig) + + _, err := resolver.SecretInformer() + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") } func Test_ResolveLeaderElectionClient(t *testing.T) { resolver := config.NewResolver(&config.Config{DBFile: "test.db"}, &rest.Config{}) client1, err := resolver.LeaderElectionClient() - if err != nil { - t.Errorf("Unexpected Error: %s", err) - } + assert.Nil(t, err) client2, _ := resolver.LeaderElectionClient() - if client1 != client2 { - t.Error("A second call resolver.LeaderElectionClient() should return the cached first client") - } + + assert.Equal(t, client1, client2, "A second call resolver.LeaderElectionClient() should return the cached first client") } func Test_ResolvePolicyStore(t *testing.T) { @@ -289,24 +339,22 @@ func Test_ResolvePolicyStore(t *testing.T) { db := resolver.Database() defer db.Close() - store1, err := resolver.PolicyReportStore(db) - if err != nil { - t.Errorf("Unexpected Error: %s", err) - } + store1, err := resolver.Store(db) + assert.Nil(t, err) - store2, _ := resolver.PolicyReportStore(db) - if store1 != store2 { - t.Error("A second call resolver.PolicyReportClient() should return the cached first client") - } + store2, _ := resolver.Store(db) + assert.Equal(t, store1, store2, "A second call resolver.Store() should return the cached first client") } func Test_ResolveAPIServer(t *testing.T) { - resolver := config.NewResolver(&config.Config{}, &rest.Config{}) + resolver := config.NewResolver(&config.Config{ + API: config.API{ + BasicAuth: config.BasicAuth{Username: "user", Password: "password"}, + }, + }, &rest.Config{}) - server := resolver.APIServer(context.Background(), func() bool { return true }) - if server == nil { - t.Error("Error: Should return API Server") - } + server, _ := resolver.Server(context.Background(), nil) + assert.NotNil(t, server) } func Test_ResolveCache(t *testing.T) { @@ -314,14 +362,9 @@ func Test_ResolveCache(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) cache1 := resolver.ResultCache() - if cache1 == nil { - t.Error("Error: Should return ResultCache") - } + assert.NotNil(t, cache1) - cache2 := resolver.ResultCache() - if cache1 != cache2 { - t.Error("A second call resolver.ResultCache() should return the cached first cache") - } + assert.Equal(t, cache1, resolver.ResultCache(), "A second call resolver.ResultCache() should return the cached first client") }) t.Run("Redis", func(t *testing.T) { @@ -334,20 +377,14 @@ func Test_ResolveCache(t *testing.T) { resolver := config.NewResolver(redisConfig, &rest.Config{}) - cache1 := resolver.ResultCache() - if cache1 == nil { - t.Error("Error: Should return ResultCache") - } + assert.NotNil(t, resolver.ResultCache()) }) } func Test_ResolveReportFilter(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - filter := resolver.ReportFilter() - if filter == nil { - t.Error("Error: Should return Filter") - } + assert.NotNil(t, resolver.ReportFilter()) } func Test_ResolveClientWithInvalidK8sConfig(t *testing.T) { @@ -357,9 +394,7 @@ func Test_ResolveClientWithInvalidK8sConfig(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) _, err := resolver.PolicyReportClient() - if err == nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") } func Test_ResolveLeaderElectionWithInvalidK8sConfig(t *testing.T) { @@ -369,18 +404,14 @@ func Test_ResolveLeaderElectionWithInvalidK8sConfig(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) _, err := resolver.LeaderElectionClient() - if err == nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") } func Test_ResolveCRDClient(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) _, err := resolver.CRDClient() - if err != nil { - t.Error("unexpected error") - } + assert.Nil(t, err) } func Test_ResolveCRDClientWithInvalidK8sConfig(t *testing.T) { @@ -390,18 +421,13 @@ func Test_ResolveCRDClientWithInvalidK8sConfig(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) _, err := resolver.CRDClient() - if err == nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") } func Test_ResolveSecretClient(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - client := resolver.SecretClient() - if client == nil { - t.Error("unexpected error") - } + assert.NotNil(t, resolver.SecretClient()) } func Test_ResolveSecretCClientWithInvalidK8sConfig(t *testing.T) { @@ -411,9 +437,7 @@ func Test_ResolveSecretCClientWithInvalidK8sConfig(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) client := resolver.SecretClient() - if client != nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.Nil(t, client, "Error: 'host must be a URL or a host:port pair' was expected") } func Test_RegisterStoreListener(t *testing.T) { @@ -421,9 +445,7 @@ func Test_RegisterStoreListener(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) resolver.RegisterStoreListener(context.Background(), report.NewPolicyReportStore()) - if len(resolver.EventPublisher().GetListener()) != 1 { - t.Error("Expected one Listener to be registered") - } + assert.Len(t, resolver.EventPublisher().GetListener(), 1, "Expected one Listener to be registered") }) } @@ -432,9 +454,7 @@ func Test_RegisterMetricsListener(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) resolver.RegisterMetricsListener() - if len(resolver.EventPublisher().GetListener()) != 1 { - t.Error("Expected one Listener to be registered") - } + assert.Len(t, resolver.EventPublisher().GetListener(), 1, "Expected one Listener to be registered") }) } @@ -443,18 +463,14 @@ func Test_RegisterSendResultListener(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) resolver.RegisterSendResultListener() - if len(resolver.EventPublisher().GetListener()) != 1 { - t.Error("Expected one Listener to be registered") - } + assert.Len(t, resolver.EventPublisher().GetListener(), 1, "Expected one Listener to be registered") }) t.Run("Register SendResultListener without Targets", func(t *testing.T) { resolver := config.NewResolver(&config.Config{}, &rest.Config{}) resolver.RegisterSendResultListener() - if len(resolver.EventPublisher().GetListener()) != 0 { - t.Error("Expected no Listener to be registered because no target exists") - } + assert.Len(t, resolver.EventPublisher().GetListener(), 0, "Expected no Listener to be registered because no target exists") }) } @@ -462,12 +478,9 @@ func Test_SummaryReportServices(t *testing.T) { t.Run("Generator", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) generator, err := resolver.SummaryGenerator() - if err != nil { - t.Errorf("Unexpected error: %s", err) - } - if generator == nil { - t.Error("Should return Generator Pointer") - } + + assert.Nil(t, err) + assert.NotNil(t, generator) }) t.Run("Generator.Error", func(t *testing.T) { k8sConfig := &rest.Config{} @@ -476,16 +489,12 @@ func Test_SummaryReportServices(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) _, err := resolver.SummaryGenerator() - if err == nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") }) t.Run("Reporter", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - reporter := resolver.SummaryReporter() - if reporter == nil { - t.Error("Should return Reporter Pointer") - } + + assert.NotNil(t, resolver.SummaryReporter()) }) } @@ -493,12 +502,9 @@ func Test_ViolationReportServices(t *testing.T) { t.Run("Generator", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) generator, err := resolver.ViolationsGenerator() - if err != nil { - t.Errorf("Unexpected error: %s", err) - } - if generator == nil { - t.Error("Should return Generator Pointer") - } + + assert.Nil(t, err) + assert.NotNil(t, generator) }) t.Run("Generator.Error", func(t *testing.T) { k8sConfig := &rest.Config{} @@ -507,33 +513,25 @@ func Test_ViolationReportServices(t *testing.T) { resolver := config.NewResolver(testConfig, k8sConfig) _, err := resolver.ViolationsGenerator() - if err == nil { - t.Error("Error: 'host must be a URL or a host:port pair' was expected") - } + assert.NotNil(t, err, "Error: 'host must be a URL or a host:port pair' was expected") }) t.Run("Reporter", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - reporter := resolver.ViolationsReporter() - if reporter == nil { - t.Error("Should return Reporter Pointer") - } + + assert.NotNil(t, resolver.ViolationsReporter()) }) } func Test_SMTP(t *testing.T) { t.Run("SMTP", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - smtp := resolver.SMTPServer() - if smtp == nil { - t.Error("Should return SMTP Pointer") - } + + assert.NotNil(t, resolver.SMTPServer()) }) t.Run("EmailClient", func(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) - client := resolver.EmailClient() - if client == nil { - t.Error("Should return EmailClient Pointer") - } + + assert.NotNil(t, resolver.EmailClient()) }) } @@ -541,27 +539,31 @@ func Test_ResolveLogger(t *testing.T) { resolver := config.NewResolver(testConfig, &rest.Config{}) logger1, _ := resolver.Logger() - if logger1 == nil { - t.Error("Error: Should return Logger") - } + assert.NotNil(t, logger1) logger2, _ := resolver.Logger() - if logger1 != logger2 { - t.Error("A second call resolver.Mapper() should return the cached first cache") - } + assert.NotNil(t, logger2) + + assert.Equal(t, logger1, logger2, "A second call resolver.Logger() should return the cached first cache") } func Test_ResolveEnableLeaderElection(t *testing.T) { t.Run("general disabled", func(t *testing.T) { resolver := config.NewResolver(&config.Config{ LeaderElection: config.LeaderElection{Enabled: false}, - Loki: &config.Loki{Host: "localhost:3100"}, - Database: config.Database{Type: database.MySQL}, + Targets: target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + }, + }, + }, + }, + Database: config.Database{Type: database.MySQL}, }, &rest.Config{}) - if resolver.EnableLeaderElection() { - t.Error("leaderelection should be not enabled if its general disabled") - } + assert.False(t, resolver.EnableLeaderElection(), "leaderelection should be not enabled if its general disabled") }) t.Run("no pushes and SQLite Database", func(t *testing.T) { @@ -571,22 +573,26 @@ func Test_ResolveEnableLeaderElection(t *testing.T) { DBFile: "test.db", }, &rest.Config{}) - if resolver.EnableLeaderElection() { - t.Error("leaderelection should be not enabled if no pushes configured and SQLite is used") - } + assert.False(t, resolver.EnableLeaderElection(), "leaderelection should be not enabled if no pushes configured and SQLite is used") }) t.Run("enabled if pushes defined", func(t *testing.T) { resolver := config.NewResolver(&config.Config{ LeaderElection: config.LeaderElection{Enabled: true}, Database: config.Database{Type: database.SQLite}, - Loki: &config.Loki{Host: "localhost:3100"}, - DBFile: "test.db", + Targets: target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + }, + }, + }, + }, + DBFile: "test.db", }, &rest.Config{}) - if !resolver.EnableLeaderElection() { - t.Error("leaderelection should be enabled if general enabled and targets configured") - } + assert.True(t, resolver.EnableLeaderElection(), "leaderelection should be enabled if general enabled and targets configured") }) } @@ -594,7 +600,14 @@ func Test_ResolveCustomIDGenerators(t *testing.T) { resolver := config.NewResolver(testConfig, nil) generators := resolver.CustomIDGenerators() - if len(generators) != 1 { - t.Error("only enabled custom id config should be mapped") - } + assert.Len(t, generators, 1, "only enabled custom id config should be mapped") +} + +func Test_ResolveTargetCollection(t *testing.T) { + resolver := config.NewResolver(testConfig, &rest.Config{}) + + collection := resolver.TargetClients() + assert.NotNil(t, collection) + + assert.Equal(t, collection, resolver.TargetClients(), "A second call resolver.TargetClients() should return the cached first cache") } diff --git a/pkg/config/target_factory.go b/pkg/config/target_factory.go deleted file mode 100644 index 7e5701f3..00000000 --- a/pkg/config/target_factory.go +++ /dev/null @@ -1,984 +0,0 @@ -package config - -import ( - "context" - "encoding/json" - "fmt" - "os" - "strings" - "time" - - _ "github.com/mattn/go-sqlite3" - "go.uber.org/zap" - - "github.com/kyverno/policy-reporter/pkg/helper" - "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" - "github.com/kyverno/policy-reporter/pkg/report" - "github.com/kyverno/policy-reporter/pkg/target" - "github.com/kyverno/policy-reporter/pkg/target/discord" - "github.com/kyverno/policy-reporter/pkg/target/elasticsearch" - "github.com/kyverno/policy-reporter/pkg/target/gcs" - "github.com/kyverno/policy-reporter/pkg/target/googlechat" - "github.com/kyverno/policy-reporter/pkg/target/http" - "github.com/kyverno/policy-reporter/pkg/target/kinesis" - "github.com/kyverno/policy-reporter/pkg/target/loki" - "github.com/kyverno/policy-reporter/pkg/target/s3" - "github.com/kyverno/policy-reporter/pkg/target/securityhub" - "github.com/kyverno/policy-reporter/pkg/target/slack" - "github.com/kyverno/policy-reporter/pkg/target/teams" - "github.com/kyverno/policy-reporter/pkg/target/telegram" - "github.com/kyverno/policy-reporter/pkg/target/ui" - "github.com/kyverno/policy-reporter/pkg/target/webhook" -) - -// TargetFactory manages target creation -type TargetFactory struct { - secretClient secrets.Client -} - -// LokiClients resolver method -func (f *TargetFactory) LokiClients(config *Loki) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Loki") - setFallback(&config.Path, "/api/prom/push") - - if loki := f.createLokiClient(config, &Loki{}); loki != nil { - clients = append(clients, loki) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Loki Channel %d", i+1)) - - if loki := f.createLokiClient(channel, config); loki != nil { - clients = append(clients, loki) - } - } - - return clients -} - -// ElasticsearchClients resolver method -func (f *TargetFactory) ElasticsearchClients(config *Elasticsearch) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Elasticsearch") - - if es := f.createElasticsearchClient(config, &Elasticsearch{}); es != nil { - clients = append(clients, es) - } - - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Elasticsearch Channel %d", i+1)) - - if es := f.createElasticsearchClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// SlackClients resolver method -func (f *TargetFactory) SlackClients(config *Slack) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Slack") - - if es := f.createSlackClient(config, &Slack{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Slack Channel %d", i+1)) - - if es := f.createSlackClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// DiscordClients resolver method -func (f *TargetFactory) DiscordClients(config *Discord) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Discord") - - if es := f.createDiscordClient(config, &Discord{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Discord Channel %d", i+1)) - - if es := f.createDiscordClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// TeamsClients resolver method -func (f *TargetFactory) TeamsClients(config *Teams) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Teams") - - if es := f.createTeamsClient(config, &Teams{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Teams Channel %d", i+1)) - - if es := f.createTeamsClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// WebhookClients resolver method -func (f *TargetFactory) WebhookClients(config *Webhook) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Webhook") - - if es := f.createWebhookClient(config, &Webhook{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Webhook Channel %d", i+1)) - - if es := f.createWebhookClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// UIClient resolver method -func (f *TargetFactory) UIClient(config *UI) target.Client { - if config == nil || config.Host == "" { - return nil - } - - setFallback(&config.Name, "UI") - - zap.L().Info("UI configured") - - return ui.NewClient(ui.Options{ - ClientOptions: config.ClientOptions(), - Host: config.Host, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - }) -} - -// S3Clients resolver method -func (f *TargetFactory) S3Clients(config *S3) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "S3") - - if es := f.createS3Client(config, &S3{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("S3 Channel %d", i+1)) - - if es := f.createS3Client(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// KinesisClients resolver method -func (f *TargetFactory) KinesisClients(config *Kinesis) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Kinesis") - - if es := f.createKinesisClient(config, &Kinesis{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Kinesis Channel %d", i+1)) - - if es := f.createKinesisClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// SecurityHub resolver method -func (f *TargetFactory) SecurityHubs(config *SecurityHub) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "SecurityHub") - - if es := f.createSecurityHub(config, &SecurityHub{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("SecurityHub Channel %d", i+1)) - - if es := f.createSecurityHub(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// GCSClients resolver method -func (f *TargetFactory) GCSClients(config *GCS) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "GoogleCloudStorage") - - if es := f.createGCSClient(config, &GCS{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("GCS Channel %d", i+1)) - - if es := f.createGCSClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// TelegramClients resolver method -func (f *TargetFactory) TelegramClients(config *Telegram) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "Telegram") - - if es := f.createTelegramClient(config, &Telegram{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("Telegram Channel %d", i+1)) - - if es := f.createTelegramClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -// GoogleChatClients resolver method -func (f *TargetFactory) GoogleChatClients(config *GoogleChat) []target.Client { - clients := make([]target.Client, 0) - if config == nil { - return clients - } - - setFallback(&config.Name, "GoogleChat") - - if es := f.createGoogleChatClient(config, &GoogleChat{}); es != nil { - clients = append(clients, es) - } - for i, channel := range config.Channels { - setFallback(&config.Name, fmt.Sprintf("GoogleChat Channel %d", i+1)) - - if es := f.createGoogleChatClient(channel, config); es != nil { - clients = append(clients, es) - } - } - - return clients -} - -func (f *TargetFactory) createSlackClient(config, parent *Slack) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Webhook == "" && config.Channel == "" { - return nil - } - - setFallback(&config.Webhook, parent.Webhook) - - if config.Webhook == "" { - return nil - } - - config.MapBaseParent(parent.TargetBaseOptions) - - zap.S().Infof("%s configured", config.Name) - - return slack.NewClient(slack.Options{ - ClientOptions: config.ClientOptions(), - Webhook: config.Webhook, - Channel: config.Channel, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient("", false), - }) -} - -func (f *TargetFactory) createLokiClient(config, parent *Loki) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Host == "" && parent.Host == "" { - return nil - } - - setFallback(&config.Host, parent.Host) - setFallback(&config.Certificate, parent.Certificate) - setFallback(&config.Path, parent.Path) - setBool(&config.SkipTLS, parent.SkipTLS) - setFallback(&config.Username, parent.Username) - setFallback(&config.Password, parent.Password) - - config.MapBaseParent(parent.TargetBaseOptions) - - zap.S().Infof("%s configured", config.Name) - - if config.CustomFields == nil { - config.CustomFields = make(map[string]string) - } - - if config.CustomLabels != nil { - for k, v := range config.CustomLabels { - config.CustomFields[k] = v - } - } - - return loki.NewClient(loki.Options{ - ClientOptions: config.ClientOptions(), - Host: config.Host + config.Path, - CustomLabels: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - Username: config.Username, - Password: config.Password, - Headers: config.Headers, - }) -} - -func (f *TargetFactory) createElasticsearchClient(config, parent *Elasticsearch) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Host == "" && parent.Host == "" { - return nil - } - - setFallback(&config.Host, parent.Host) - setFallback(&config.Certificate, parent.Certificate) - setBool(&config.SkipTLS, parent.SkipTLS) - setFallback(&config.Username, parent.Username) - setFallback(&config.Password, parent.Password) - setFallback(&config.APIKey, parent.APIKey) - setFallback(&config.Index, parent.Index, "policy-reporter") - setFallback(&config.Rotation, parent.Rotation, elasticsearch.Daily) - setBool(&config.TypelessAPI, parent.TypelessAPI) - - config.MapBaseParent(parent.TargetBaseOptions) - - zap.S().Infof("%s configured", config.Name) - - return elasticsearch.NewClient(elasticsearch.Options{ - ClientOptions: config.ClientOptions(), - Host: config.Host, - Username: config.Username, - Password: config.Password, - ApiKey: config.APIKey, - Rotation: config.Rotation, - Index: config.Index, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - TypelessApi: config.TypelessAPI, - }) -} - -func (f *TargetFactory) createDiscordClient(config, parent *Discord) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Webhook == "" { - return nil - } - - config.MapBaseParent(parent.TargetBaseOptions) - - zap.S().Infof("%s configured", config.Name) - - return discord.NewClient(discord.Options{ - ClientOptions: config.ClientOptions(), - Webhook: config.Webhook, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient("", false), - }) -} - -func (f *TargetFactory) createTeamsClient(config, parent *Teams) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Webhook == "" { - return nil - } - - setFallback(&config.Certificate, parent.Certificate) - setBool(&config.SkipTLS, parent.SkipTLS) - - config.MapBaseParent(parent.TargetBaseOptions) - - zap.S().Infof("%s configured", config.Name) - - return teams.NewClient(teams.Options{ - ClientOptions: config.ClientOptions(), - Webhook: config.Webhook, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - }) -} - -func (f *TargetFactory) createWebhookClient(config, parent *Webhook) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - if config.Host == "" { - return nil - } - - setFallback(&config.Certificate, parent.Certificate) - setBool(&config.SkipTLS, parent.SkipTLS) - config.MapBaseParent(parent.TargetBaseOptions) - - if len(parent.Headers) > 0 { - headers := map[string]string{} - for header, value := range parent.Headers { - headers[header] = value - } - for header, value := range config.Headers { - headers[header] = value - } - - config.Headers = headers - } - - zap.S().Infof("%s configured", config.Name) - - return webhook.NewClient(webhook.Options{ - ClientOptions: config.ClientOptions(), - Host: config.Host, - Headers: config.Headers, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - }) -} - -func (f *TargetFactory) createTelegramClient(config, parent *Telegram) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - setFallback(&config.Token, parent.Token) - - if config.ChatID == "" || config.Token == "" { - return nil - } - - setFallback(&config.Host, parent.Host) - setFallback(&config.Certificate, parent.Certificate) - setBool(&config.SkipTLS, parent.SkipTLS) - - config.MapBaseParent(parent.TargetBaseOptions) - - if len(parent.Headers) > 0 { - headers := map[string]string{} - for header, value := range parent.Headers { - headers[header] = value - } - for header, value := range config.Headers { - headers[header] = value - } - - config.Headers = headers - } - - host := "https://api.telegram.org" - if config.Host != "" { - host = strings.TrimSuffix(config.Host, "/") - } - - zap.S().Infof("%s configured", config.Name) - - return telegram.NewClient(telegram.Options{ - ClientOptions: config.ClientOptions(), - Host: fmt.Sprintf("%s/bot%s/sendMessage", host, config.Token), - ChatID: config.ChatID, - Headers: config.Headers, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - }) -} - -func (f *TargetFactory) createGoogleChatClient(config, parent *GoogleChat) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - setFallback(&config.Webhook, parent.Webhook) - - if config.Webhook == "" { - return nil - } - - setFallback(&config.Certificate, parent.Certificate) - setBool(&config.SkipTLS, parent.SkipTLS) - config.MapBaseParent(parent.TargetBaseOptions) - - if len(parent.Headers) > 0 { - headers := map[string]string{} - for header, value := range parent.Headers { - headers[header] = value - } - for header, value := range config.Headers { - headers[header] = value - } - - config.Headers = headers - } - - zap.S().Infof("%s configured", config.Name) - - return googlechat.NewClient(googlechat.Options{ - ClientOptions: config.ClientOptions(), - Webhook: config.Webhook, - Headers: config.Headers, - CustomFields: config.CustomFields, - HTTPClient: http.NewClient(config.Certificate, config.SkipTLS), - }) -} - -func (f *TargetFactory) createS3Client(config, parent *S3) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - config.MapAWSParent(parent.AWSConfig) - if config.Endpoint == "" && !hasAWSIdentity() { - return nil - } - - setFallback(&config.Bucket, parent.Bucket) - if config.Bucket == "" { - return nil - } - - sugar := zap.S() - - if err := checkAWSConfig(config.Name, config.AWSConfig, parent.AWSConfig); err != nil { - sugar.Error(err) - - return nil - } - setFallback(&config.Region, os.Getenv("AWS_REGION")) - setFallback(&config.Prefix, parent.Prefix, "policy-reporter") - setFallback(&config.KmsKeyID, parent.KmsKeyID) - setFallback(&config.ServerSideEncryption, parent.ServerSideEncryption) - setBool(&config.BucketKeyEnabled, parent.BucketKeyEnabled) - - config.MapBaseParent(parent.TargetBaseOptions) - - s3Client := helper.NewS3Client( - config.AccessKeyID, - config.SecretAccessKey, - config.Region, - config.Endpoint, - config.Bucket, - config.PathStyle, - helper.WithKMS(config.BucketKeyEnabled, &config.KmsKeyID, &config.ServerSideEncryption), - ) - - sugar.Infof("%s configured", config.Name) - - return s3.NewClient(s3.Options{ - ClientOptions: config.ClientOptions(), - S3: s3Client, - CustomFields: config.CustomFields, - Prefix: config.Prefix, - }) -} - -func (f *TargetFactory) createKinesisClient(config, parent *Kinesis) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - config.MapAWSParent(parent.AWSConfig) - if config.Endpoint == "" { - return nil - } - - sugar := zap.S() - if err := checkAWSConfig(config.Name, config.AWSConfig, parent.AWSConfig); err != nil { - sugar.Error(err) - - return nil - } - - setFallback(&config.StreamName, parent.StreamName) - if config.StreamName == "" { - sugar.Errorf("%s.StreamName has not been declared", config.Name) - return nil - } - - config.MapBaseParent(parent.TargetBaseOptions) - - kinesisClient := helper.NewKinesisClient( - config.AccessKeyID, - config.SecretAccessKey, - config.Region, - config.Endpoint, - config.StreamName, - ) - - sugar.Infof("%s configured", config.Name) - - return kinesis.NewClient(kinesis.Options{ - ClientOptions: config.ClientOptions(), - CustomFields: config.CustomFields, - Kinesis: kinesisClient, - }) -} - -func (f *TargetFactory) createSecurityHub(config, parent *SecurityHub) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - setFallback(&config.AccountID, parent.AccountID) - if !hasAWSIdentity() && config.AccountID == "" { - return nil - } - - sugar := zap.S() - if err := checkAWSConfig(config.Name, config.AWSConfig, parent.AWSConfig); err != nil { - sugar.Error(err) - - return nil - } - - config.MapAWSParent(parent.AWSConfig) - config.MapBaseParent(parent.TargetBaseOptions) - - client := helper.NewHubClient( - config.AccessKeyID, - config.SecretAccessKey, - config.Region, - config.Endpoint, - ) - - sugar.Infof("%s configured", config.Name) - - setFallback(&config.ProductName, parent.ProductName, "Policy Reporter") - setFallback(&config.CompanyName, parent.CompanyName, "Kyverno") - setInt(&config.DelayInSeconds, parent.DelayInSeconds) - - return securityhub.NewClient(securityhub.Options{ - ClientOptions: config.ClientOptions(), - CustomFields: config.CustomFields, - Client: client, - AccountID: config.AccountID, - Region: config.Region, - ProductName: config.ProductName, - CompanyName: config.CompanyName, - Delay: time.Duration(config.DelayInSeconds) * time.Second, - }) -} - -func (f *TargetFactory) createGCSClient(config, parent *GCS) target.Client { - if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { - f.mapSecretValues(config, config.SecretRef, config.MountedSecret) - } - - setFallback(&config.Bucket, parent.Bucket) - if config.Bucket == "" { - return nil - } - - sugar := zap.S() - - setFallback(&config.Credentials, parent.Credentials) - setFallback(&config.Prefix, parent.Prefix, "policy-reporter") - - config.MapBaseParent(parent.TargetBaseOptions) - - gcsClient := helper.NewGCSClient( - context.Background(), - config.Credentials, - config.Bucket, - ) - if gcsClient == nil { - return nil - } - - sugar.Infof("%s configured", config.Name) - - return gcs.NewClient(gcs.Options{ - ClientOptions: config.ClientOptions(), - Client: gcsClient, - CustomFields: config.CustomFields, - Prefix: config.Prefix, - }) -} - -func (f *TargetFactory) mapSecretValues(config any, ref, mountedSecret string) { - values := secrets.Values{} - - if ref != "" { - secretValues, err := f.secretClient.Get(context.Background(), ref) - values = secretValues - if err != nil { - zap.L().Warn("failed to get secret reference", zap.Error(err)) - return - } - } - - if mountedSecret != "" { - file, err := os.ReadFile(mountedSecret) - if err != nil { - zap.L().Warn("failed to get mounted secret", zap.Error(err)) - return - } - err = json.Unmarshal(file, &values) - if err != nil { - zap.L().Warn("failed to unmarshal mounted secret", zap.Error(err)) - return - } - } - - switch c := config.(type) { - case *Loki: - if values.Host != "" { - c.Host = values.Host - } - if values.Username != "" { - c.Username = values.Username - } - if values.Password != "" { - c.Password = values.Password - } - - case *Slack: - if values.Webhook != "" { - c.Webhook = values.Webhook - } - if values.Channel != "" { - c.Channel = values.Channel - } - - case *Discord: - if values.Webhook != "" { - c.Webhook = values.Webhook - } - - case *Teams: - if values.Webhook != "" { - c.Webhook = values.Webhook - } - - case *Elasticsearch: - if values.Host != "" { - c.Host = values.Host - } - if values.Username != "" { - c.Username = values.Username - } - if values.Password != "" { - c.Password = values.Password - } - if values.APIKey != "" { - c.APIKey = values.APIKey - } - if values.TypelessAPI != false { - c.TypelessAPI = values.TypelessAPI - } - - case *S3: - if values.AccessKeyID != "" { - c.AccessKeyID = values.AccessKeyID - } - if values.SecretAccessKey != "" { - c.SecretAccessKey = values.SecretAccessKey - } - if values.KmsKeyID != "" { - c.KmsKeyID = values.KmsKeyID - } - - case *Kinesis: - if values.AccessKeyID != "" { - c.AccessKeyID = values.AccessKeyID - } - if values.SecretAccessKey != "" { - c.SecretAccessKey = values.SecretAccessKey - } - - case *SecurityHub: - if values.AccessKeyID != "" { - c.AccessKeyID = values.AccessKeyID - } - if values.SecretAccessKey != "" { - c.SecretAccessKey = values.SecretAccessKey - } - if values.AccountID != "" { - c.AccountID = values.AccessKeyID - } - - case *GCS: - if values.Credentials != "" { - c.Credentials = values.Credentials - } - - case *Webhook: - if values.Host != "" { - c.Host = values.Host - } - if values.Token != "" { - if c.Headers == nil { - c.Headers = make(map[string]string) - } - - c.Headers["Authorization"] = values.Token - } - case *Telegram: - if values.Token != "" { - c.Token = values.Token - } - if values.Host != "" { - c.Host = values.Host - } - case *GoogleChat: - if values.Webhook != "" { - c.Webhook = values.Webhook - } - } -} - -func createResultFilter(filter TargetFilter, minimumPriority string, sources []string) *report.ResultFilter { - return target.NewResultFilter( - ToRuleSet(filter.Namespaces), - ToRuleSet(filter.Priorities), - ToRuleSet(filter.Policies), - minimumPriority, - sources, - ) -} - -func createReportFilter(filter TargetFilter) *report.ReportFilter { - return target.NewReportFilter( - ToRuleSet(filter.ReportLabels), - ) -} - -func NewTargetFactory(secretClient secrets.Client) *TargetFactory { - return &TargetFactory{secretClient: secretClient} -} - -func hasAWSIdentity() bool { - irsaARN := os.Getenv("AWS_ROLE_ARN") - irsaFile := os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE") - - podIdentityFile := os.Getenv("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") - podIdentityURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI") - - return (irsaARN != "" && irsaFile != "") || (podIdentityFile != "" && podIdentityURI != "") -} - -func checkAWSConfig(name string, config AWSConfig, parent AWSConfig) error { - noEnvConfig := !hasAWSIdentity() - - if noEnvConfig && (config.AccessKeyID == "" && parent.AccessKeyID == "") { - return fmt.Errorf("%s.AccessKeyID has not been declared", name) - } - - if noEnvConfig && (config.SecretAccessKey == "" && parent.SecretAccessKey == "") { - return fmt.Errorf("%s.SecretAccessKey has not been declared", name) - } - - if config.Region == "" && parent.Region == "" { - return fmt.Errorf("%s.Region has not been declared", name) - } - - return nil -} - -func setFallback(config *string, parents ...string) { - if *config == "" { - for _, p := range parents { - if p != "" { - *config = p - return - } - } - } -} - -func setInt(config *int, parents ...int) { - if *config == 0 { - for _, p := range parents { - if p > 0 { - *config = p - return - } - } - } -} - -func setBool(config *bool, parent bool) { - if *config == false { - *config = parent - } -} diff --git a/pkg/config/target_factory_test.go b/pkg/config/target_factory_test.go deleted file mode 100644 index d1db45ea..00000000 --- a/pkg/config/target_factory_test.go +++ /dev/null @@ -1,816 +0,0 @@ -package config_test - -import ( - "encoding/json" - "os" - "reflect" - "testing" - - "go.uber.org/zap" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/fake" - v1 "k8s.io/client-go/kubernetes/typed/core/v1" - - "github.com/kyverno/policy-reporter/pkg/config" - "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" -) - -const ( - secretName = "secret-values" - mountedSecret = "/tmp/secrets-9999" -) - -func newFakeClient() v1.SecretInterface { - return fake.NewSimpleClientset(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: "default", - }, - Data: map[string][]byte{ - "host": []byte("http://localhost:9200"), - "username": []byte("username"), - "password": []byte("password"), - "apiKey": []byte("apiKey"), - "webhook": []byte("http://localhost:9200/webhook"), - "accessKeyID": []byte("accessKeyID"), - "secretAccessKey": []byte("secretAccessKey"), - "accountID": []byte("accountID"), - "kmsKeyId": []byte("kmsKeyId"), - "token": []byte("token"), - "credentials": []byte(`{"token": "token", "type": "authorized_user"}`), - "database": []byte("database"), - "dsn": []byte(""), - "typelessApi": []byte("true"), - }, - }).CoreV1().Secrets("default") -} - -func mountSecret() { - secretValues := secrets.Values{ - Host: "http://localhost:9200", - Webhook: "http://localhost:9200/webhook", - Username: "username", - Password: "password", - APIKey: "apiKey", - AccessKeyID: "accessKeyId", - SecretAccessKey: "secretAccessKey", - KmsKeyID: "kmsKeyId", - Token: "token", - Credentials: `{"token": "token", "type": "authorized_user"}`, - Database: "database", - DSN: "", - TypelessAPI: false, - } - file, _ := json.MarshalIndent(secretValues, "", " ") - _ = os.WriteFile(mountedSecret, file, 0o644) -} - -var logger = zap.NewNop() - -func Test_ResolveTarget(t *testing.T) { - factory := config.NewTargetFactory(nil) - - t.Run("Loki", func(t *testing.T) { - clients := factory.LokiClients(testConfig.Loki) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("Elasticsearch", func(t *testing.T) { - clients := factory.ElasticsearchClients(testConfig.Elasticsearch) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("Slack", func(t *testing.T) { - clients := factory.SlackClients(testConfig.Slack) - if len(clients) != 3 { - t.Error("Expected Client, got nil") - } - }) - t.Run("Discord", func(t *testing.T) { - clients := factory.DiscordClients(testConfig.Discord) - if len(clients) != 2 { - t.Error("Expected Client, got nil") - } - }) - t.Run("Teams", func(t *testing.T) { - clients := factory.TeamsClients(testConfig.Teams) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("Webhook", func(t *testing.T) { - clients := factory.WebhookClients(testConfig.Webhook) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("Telegram", func(t *testing.T) { - clients := factory.TelegramClients(testConfig.Telegram) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("GoogleChat", func(t *testing.T) { - clients := factory.GoogleChatClients(testConfig.GoogleChat) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("S3", func(t *testing.T) { - clients := factory.S3Clients(testConfig.S3) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("GCS", func(t *testing.T) { - clients := factory.GCSClients(testConfig.GCS) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("Kinesis", func(t *testing.T) { - clients := factory.KinesisClients(testConfig.Kinesis) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) - t.Run("SecurityHub", func(t *testing.T) { - clients := factory.SecurityHubs(testConfig.SecurityHub) - if len(clients) != 2 { - t.Errorf("Expected 2 Client, got %d clients", len(clients)) - } - }) -} - -func Test_ResolveTargetWithoutHost(t *testing.T) { - factory := config.NewTargetFactory(nil) - - t.Run("Loki", func(t *testing.T) { - if len(factory.LokiClients(&config.Loki{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Elasticsearch", func(t *testing.T) { - if len(factory.ElasticsearchClients(&config.Elasticsearch{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Slack", func(t *testing.T) { - if len(factory.SlackClients(&config.Slack{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Discord", func(t *testing.T) { - if len(factory.DiscordClients(&config.Discord{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Teams", func(t *testing.T) { - if len(factory.TeamsClients(&config.Teams{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Webhook", func(t *testing.T) { - if len(factory.WebhookClients(&config.Webhook{})) != 0 { - t.Error("Expected Client to be nil if no host is configured") - } - }) - t.Run("Telegram", func(t *testing.T) { - if len(factory.TelegramClients(&config.Telegram{})) != 0 { - t.Error("Expected Client to be nil if no chatID is configured") - } - }) - t.Run("GoogleChat", func(t *testing.T) { - if len(factory.GoogleChatClients(&config.GoogleChat{})) != 0 { - t.Error("Expected Client to be nil if no webhook is configured") - } - }) - t.Run("S3.Endoint", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{})) != 0 { - t.Error("Expected Client to be nil if no endpoint is configured") - } - }) - t.Run("S3.AccessKey", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}})) != 0 { - t.Error("Expected Client to be nil if no accessKey is configured") - } - }) - t.Run("S3.SecretAccessKey", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access"}})) != 0 { - t.Error("Expected Client to be nil if no secretAccessKey is configured") - } - }) - t.Run("S3.Region", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 { - t.Error("Expected Client to be nil if no region is configured") - } - }) - t.Run("S3.Bucket", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 { - t.Error("Expected Client to be nil if no bucket is configured") - } - }) - t.Run("S3.SSE-S3", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "AES256"})) != 0 { - t.Error("Expected Client to be nil if server side encryption is not configured") - } - }) - t.Run("S3.SSE-KMS", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms"})) != 0 { - t.Error("Expected Client to be nil if server side encryption is not configured") - } - }) - t.Run("S3.SSE-KMS-S3-KEY", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"})) != 0 { - t.Error("Expected Client to be nil if server side encryption is not configured") - } - }) - t.Run("S3.SSE-KMS-KEY-ID", func(t *testing.T) { - if len(factory.S3Clients(&config.S3{AWSConfig: config.AWSConfig{Endpoint: "https://storage.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}, ServerSideEncryption: "aws:kms", KmsKeyID: "kmsKeyId"})) != 0 { - t.Error("Expected Client to be nil if server side encryption is not configured") - } - }) - t.Run("Kinesis.Endpoint", func(t *testing.T) { - if len(factory.KinesisClients(&config.Kinesis{})) != 0 { - t.Error("Expected Client to be nil if no endpoint is configured") - } - }) - t.Run("Kinesis.AccessKey", func(t *testing.T) { - if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net"}})) != 0 { - t.Error("Expected Client to be nil if no accessKey is configured") - } - }) - t.Run("Kinesis.SecretAccessKey", func(t *testing.T) { - if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access"}})) != 0 { - t.Error("Expected Client to be nil if no secretAccessKey is configured") - } - }) - t.Run("Kinesis.Region", func(t *testing.T) { - if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 { - t.Error("Expected Client to be nil if no region is configured") - } - }) - t.Run("Kinesis.StreamName", func(t *testing.T) { - if len(factory.KinesisClients(&config.Kinesis{AWSConfig: config.AWSConfig{Endpoint: "https://yds.serverless.yandexcloud.net", AccessKeyID: "access", SecretAccessKey: "secret", Region: "ru-central1"}})) != 0 { - t.Error("Expected Client to be nil if no stream name is configured") - } - }) - t.Run("SecurityHub.AccountID", func(t *testing.T) { - if len(factory.SecurityHubs(&config.SecurityHub{})) != 0 { - t.Error("Expected Client to be nil if no accountID is configured") - } - }) - t.Run("SecurityHub.AccessKey", func(t *testing.T) { - if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID"})) != 0 { - t.Error("Expected Client to be nil if no accessKey is configured") - } - }) - t.Run("SecurityHub.SecretAccessKey", func(t *testing.T) { - if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access"}})) != 0 { - t.Error("Expected Client to be nil if no secretAccessKey is configured") - } - }) - t.Run("SecurityHub.Region", func(t *testing.T) { - if len(factory.SecurityHubs(&config.SecurityHub{AccountID: "accountID", AWSConfig: config.AWSConfig{AccessKeyID: "access", SecretAccessKey: "secret"}})) != 0 { - t.Error("Expected Client to be nil if no region is configured") - } - }) - t.Run("GCS.Bucket", func(t *testing.T) { - if len(factory.GCSClients(&config.GCS{})) != 0 { - t.Error("Expected Client to be nil if no bucket is configured") - } - }) - t.Run("GCS.Credentials", func(t *testing.T) { - if len(factory.GCSClients(&config.GCS{Bucket: "policy-reporter", Credentials: "{}"})) != 0 { - t.Error("Expected Client to be nil if no accessKey is configured") - } - }) -} - -func Test_GetValuesFromSecret(t *testing.T) { - factory := config.NewTargetFactory(secrets.NewClient(newFakeClient())) - - t.Run("Get Loki values from Secret", func(t *testing.T) { - clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Fatal("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - if v := client.FieldByName("host").String(); v != "http://localhost:9200/api/prom/push" { - t.Errorf("Expected host from secret, got %s", v) - } - - username := client.FieldByName("username").String() - if username != "username" { - t.Errorf("Expected username from secret, got %s", username) - } - - password := client.FieldByName("password").String() - if password != "password" { - t.Errorf("Expected password from secret, got %s", password) - } - }) - - t.Run("Get Elasticsearch values from Secret", func(t *testing.T) { - clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Fatal("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - host := client.FieldByName("host").String() - if host != "http://localhost:9200" { - t.Errorf("Expected host from secret, got %s", host) - } - - username := client.FieldByName("username").String() - if username != "username" { - t.Errorf("Expected username from secret, got %s", username) - } - - rotation := client.FieldByName("rotation").String() - if rotation != "daily" { - t.Errorf("Expected rotation from secret, got %s", rotation) - } - - index := client.FieldByName("index").String() - if index != "policy-reporter" { - t.Errorf("Expected rotation from secret, got %s", index) - } - - password := client.FieldByName("password").String() - if password != "password" { - t.Errorf("Expected password from secret, got %s", password) - } - - apiKey := client.FieldByName("apiKey").String() - if apiKey != "apiKey" { - t.Errorf("Expected apiKey from secret, got %s", apiKey) - } - - typelessApi := client.FieldByName("typelessApi").Bool() - if typelessApi == false { - t.Errorf("Expected typelessApi true value from secret, got %t", typelessApi) - } - }) - - t.Run("Get Discord values from Secret", func(t *testing.T) { - clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from secret, got %s", webhook) - } - }) - - t.Run("Get MS Teams values from Secret", func(t *testing.T) { - clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from secret, got %s", webhook) - } - }) - - t.Run("Get Slack values from Secret", func(t *testing.T) { - clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from secret, got %s", webhook) - } - }) - - t.Run("Get Webhook Authentication Token from Secret", func(t *testing.T) { - clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - token := client.FieldByName("headers").MapIndex(reflect.ValueOf("Authorization")).String() - if token != "token" { - t.Errorf("Expected token from secret, got %s", token) - } - }) - - t.Run("Get Telegram Token from Secret", func(t *testing.T) { - clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, ChatID: "1234"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - host := client.FieldByName("host").String() - if host != "http://localhost:9200/bottoken/sendMessage" { - t.Errorf("Expected host with token from secret, got %s", host) - } - }) - t.Run("Get GoogleChat Webhook from Secret", func(t *testing.T) { - clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - host := client.FieldByName("webhook").String() - if host != "http://localhost:9200/webhook" { - t.Errorf("Expected host with token from secret, got %s", host) - } - }) - - t.Run("Get S3 values from Secret", func(t *testing.T) { - clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get S3 values from Secret with KMS", func(t *testing.T) { - clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get Kinesis values from Secret", func(t *testing.T) { - clients := factory.KinesisClients(&config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get SecurityHub values from Secret", func(t *testing.T) { - clients := factory.SecurityHubs(&config.SecurityHub{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get GCS values from Secret", func(t *testing.T) { - clients := factory.GCSClients(&config.GCS{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, Bucket: "bucket"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get none existing secret skips target", func(t *testing.T) { - clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{SecretRef: "no-exist"}}) - if len(clients) != 0 { - t.Error("Expected client are skipped") - } - }) - - t.Run("Get CustomFields from Slack", func(t *testing.T) { - clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from Discord", func(t *testing.T) { - clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from MS Teams", func(t *testing.T) { - clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http://localhost"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from Elasticsearch", func(t *testing.T) { - clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from Webhook", func(t *testing.T) { - clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Host: "http://localhost"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from Telegram", func(t *testing.T) { - clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Token: "XXX", ChatID: "1234"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from GoogleChat", func(t *testing.T) { - clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Webhook: "http;//googlechat.webhook"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from Kinesis", func(t *testing.T) { - clients := factory.KinesisClients(testConfig.Kinesis) - if len(clients) < 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomFields from S3", func(t *testing.T) { - clients := factory.S3Clients(testConfig.S3) - if len(clients) < 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) - t.Run("Get CustomLabels from Loki", func(t *testing.T) { - clients := factory.LokiClients(&config.Loki{ - CustomLabels: map[string]string{"label": "value"}, - Host: "http://localhost", - }) - if len(clients) < 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customLabels").MapKeys() - if customFields[0].String() != "label" { - t.Errorf("Expected customLabels are added") - } - }) - t.Run("Get CustomFields from GCS", func(t *testing.T) { - clients := factory.GCSClients(testConfig.GCS) - if len(clients) < 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - customFields := client.FieldByName("customFields").MapKeys() - if customFields[0].String() != "field" { - t.Errorf("Expected customFields are added") - } - }) -} - -func Test_GetValuesFromMountedSecret(t *testing.T) { - factory := config.NewTargetFactory(nil) - mountSecret() - defer os.Remove(mountedSecret) - - t.Run("Get Loki values from MountedSecret", func(t *testing.T) { - clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - if v := client.FieldByName("host").String(); v != "http://localhost:9200/api/prom/push" { - t.Errorf("Expected host from mounted secret, got %s", v) - } - - username := client.FieldByName("username").String() - if username != "username" { - t.Errorf("Expected username from mounted secret, got %s", username) - } - - password := client.FieldByName("password").String() - if password != "password" { - t.Errorf("Expected password from mounted secret, got %s", password) - } - - }) - - t.Run("Get Elasticsearch values from MountedSecret", func(t *testing.T) { - clients := factory.ElasticsearchClients(&config.Elasticsearch{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - host := client.FieldByName("host").String() - if host != "http://localhost:9200" { - t.Errorf("Expected host from mounted secret, got %s", host) - } - - username := client.FieldByName("username").String() - if username != "username" { - t.Errorf("Expected username from mounted secret, got %s", username) - } - - password := client.FieldByName("password").String() - if password != "password" { - t.Errorf("Expected password from mounted secret, got %s", password) - } - - apiKey := client.FieldByName("apiKey").String() - if apiKey != "apiKey" { - t.Errorf("Expected apiKey from secret, got %s", apiKey) - } - - typelessApi := client.FieldByName("typelessApi").Bool() - if typelessApi != false { - t.Errorf("Expected typelessApi false value from secret, got %t", typelessApi) - } - }) - - t.Run("Get Discord values from MountedSecret", func(t *testing.T) { - clients := factory.DiscordClients(&config.Discord{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from mounted secret, got %s", webhook) - } - }) - - t.Run("Get MS Teams values from MountedSecret", func(t *testing.T) { - clients := factory.TeamsClients(&config.Teams{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from mounted secret, got %s", webhook) - } - }) - - t.Run("Get Slack values from MountedSecret", func(t *testing.T) { - clients := factory.SlackClients(&config.Slack{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - webhook := client.FieldByName("webhook").String() - if webhook != "http://localhost:9200/webhook" { - t.Errorf("Expected webhook from mounted secret, got %s", webhook) - } - }) - - t.Run("Get Webhook Authentication Token from MountedSecret", func(t *testing.T) { - clients := factory.WebhookClients(&config.Webhook{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - token := client.FieldByName("headers").MapIndex(reflect.ValueOf("Authorization")).String() - if token != "token" { - t.Errorf("Expected token from mounted secret, got %s", token) - } - }) - - t.Run("Get Telegram Token from MountedSecret", func(t *testing.T) { - clients := factory.TelegramClients(&config.Telegram{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, ChatID: "123"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - token := client.FieldByName("host").String() - if token != "http://localhost:9200/bottoken/sendMessage" { - t.Errorf("Expected token from mounted secret, got %s", token) - } - }) - - t.Run("Get GoogleChat Webhook from MountedSecret", func(t *testing.T) { - clients := factory.GoogleChatClients(&config.GoogleChat{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - - client := reflect.ValueOf(clients[0]).Elem() - - token := client.FieldByName("webhook").String() - if token != "http://localhost:9200/webhook" { - t.Errorf("Expected token from mounted secret, got %s", token) - } - }) - - t.Run("Get S3 values from MountedSecret", func(t *testing.T) { - clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get S3 values from MountedSecret with KMS", func(t *testing.T) { - clients := factory.S3Clients(&config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket", BucketKeyEnabled: true, ServerSideEncryption: "aws:kms"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get Kinesis values from MountedSecret", func(t *testing.T) { - clients := factory.KinesisClients(&config.Kinesis{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, StreamName: "stream"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get GCS values from MountedSecret", func(t *testing.T) { - clients := factory.GCSClients(&config.GCS{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, Bucket: "bucket"}) - if len(clients) != 1 { - t.Error("Expected one client created") - } - }) - - t.Run("Get none existing mounted secret skips target", func(t *testing.T) { - clients := factory.LokiClients(&config.Loki{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: "no-exists"}}) - if len(clients) != 0 { - t.Error("Expected client are skipped") - } - }) -} diff --git a/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types.go b/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types.go index 2c4a47e1..e1f12abb 100755 --- a/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types.go +++ b/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types.go @@ -68,6 +68,16 @@ func (r *ClusterPolicyReport) GetResults() []PolicyReportResult { return r.Results } +func (r *ClusterPolicyReport) HasResult(id string) bool { + for _, r := range r.Results { + if r.GetID() == id { + return true + } + } + + return false +} + func (r *ClusterPolicyReport) SetResults(results []PolicyReportResult) { r.Results = results } @@ -91,6 +101,10 @@ func (r *ClusterPolicyReport) GetID() string { return strconv.FormatUint(h1, 10) } +func (r *ClusterPolicyReport) GetKey() string { + return r.Name +} + func (r *ClusterPolicyReport) GetKinds() []string { if r.GetScope() != nil { return []string{r.Scope.Kind} diff --git a/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types_test.go b/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types_test.go index 6fb0d76d..07e748dc 100644 --- a/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types_test.go +++ b/pkg/crd/api/policyreport/v1alpha2/clusterpolicyreport_types_test.go @@ -3,9 +3,10 @@ package v1alpha2_test import ( "testing" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" ) func TestClusterPolicyReport(t *testing.T) { diff --git a/pkg/crd/api/policyreport/v1alpha2/common.go b/pkg/crd/api/policyreport/v1alpha2/common.go index 1cb560e3..f5a4389c 100644 --- a/pkg/crd/api/policyreport/v1alpha2/common.go +++ b/pkg/crd/api/policyreport/v1alpha2/common.go @@ -14,7 +14,6 @@ limitations under the License. package v1alpha2 import ( - "bytes" "fmt" "strings" @@ -42,90 +41,6 @@ const ( SeverityInfo = "info" ) -// Priority Enum for internal Result weighting -type Priority int - -const ( - DefaultPriority Priority = iota - DebugPriority - InfoPriority - WarningPriority - CriticalPriority - ErrorPriority -) - -const ( - defaultString = "" - debugString = "debug" - infoString = "info" - warningString = "warning" - errorString = "error" - criticalString = "critical" -) - -// String maps the internal weighting of Priorities to a String representation -func (p Priority) String() string { - switch p { - case DebugPriority: - return debugString - case InfoPriority: - return infoString - case WarningPriority: - return warningString - case ErrorPriority: - return errorString - case CriticalPriority: - return criticalString - default: - return defaultString - } -} - -// MarshalJSON marshals the enum as a quoted json string -func (p Priority) MarshalJSON() ([]byte, error) { - buffer := bytes.NewBufferString(`"`) - buffer.WriteString(p.String()) - buffer.WriteString(`"`) - - return buffer.Bytes(), nil -} - -// NewPriority creates a new Priority based an its string representation -func NewPriority(p string) Priority { - switch p { - case debugString: - return DebugPriority - case infoString: - return InfoPriority - case warningString: - return WarningPriority - case errorString: - return ErrorPriority - case criticalString: - return CriticalPriority - default: - return DefaultPriority - } -} - -// PriorityFromSeverity creates a Priority based on a Severity -func PriorityFromSeverity(s PolicySeverity) Priority { - switch s { - case SeverityCritical: - return CriticalPriority - case SeverityHigh: - return ErrorPriority - case SeverityMedium: - return WarningPriority - case SeverityInfo: - return InfoPriority - case SeverityLow: - return InfoPriority - default: - return DebugPriority - } -} - // PolicyReportSummary provides a status count summary type PolicyReportSummary struct { // Pass provides the count of policies whose requirements were met @@ -169,6 +84,15 @@ type PolicyResult string // - info type PolicySeverity string +var SeverityLevel = map[PolicySeverity]int{ + "": -1, + SeverityInfo: 0, + SeverityLow: 1, + SeverityMedium: 2, + SeverityHigh: 3, + SeverityCritical: 4, +} + // PolicyReportResult provides the result for an individual policy type PolicyReportResult struct { ID string `json:"-"` @@ -216,8 +140,6 @@ type PolicyReportResult struct { // Severity indicates policy check result criticality // +optional Severity PolicySeverity `json:"severity,omitempty"` - - Priority Priority `json:"-"` } func (r *PolicyReportResult) GetResource() *corev1.ObjectReference { @@ -277,8 +199,10 @@ func ToResourceString(res *corev1.ObjectReference) string { type ReportInterface interface { metav1.Object GetID() string + GetKey() string GetScope() *corev1.ObjectReference GetResults() []PolicyReportResult + HasResult(id string) bool GetSummary() PolicyReportSummary GetSource() string GetKinds() []string diff --git a/pkg/crd/api/policyreport/v1alpha2/common_test.go b/pkg/crd/api/policyreport/v1alpha2/common_test.go deleted file mode 100644 index 37a0be2f..00000000 --- a/pkg/crd/api/policyreport/v1alpha2/common_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package v1alpha2_test - -import ( - "encoding/json" - "testing" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report/result" - corev1 "k8s.io/api/core/v1" -) - -func TestCommon(t *testing.T) { - t.Run("Priority.String", func(t *testing.T) { - if v1alpha2.DefaultPriority.String() != "" { - t.Error("unexpected default priority mapping") - } - - if v1alpha2.DebugPriority.String() != "debug" { - t.Error("unexpected debug priority mapping") - } - - if v1alpha2.InfoPriority.String() != "info" { - t.Error("unexpected info mapping") - } - - if v1alpha2.WarningPriority.String() != "warning" { - t.Error("unexpected warning mapping") - } - - if v1alpha2.ErrorPriority.String() != "error" { - t.Error("unexpected error mapping") - } - - if v1alpha2.CriticalPriority.String() != "critical" { - t.Error("unexpected critical mapping") - } - }) - - t.Run("Priority.MarshalJSON", func(t *testing.T) { - v, err := json.Marshal(v1alpha2.WarningPriority) - if err != nil { - t.Fatalf("unexpected marshal error: %s", err.Error()) - } - - if string(v) != `"warning"` { - t.Fatalf("unexpected marshal value: %s", v) - } - }) - - t.Run("NewPriority", func(t *testing.T) { - if v1alpha2.NewPriority("") != v1alpha2.DefaultPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.NewPriority("debug") != v1alpha2.DebugPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.NewPriority("info") != v1alpha2.InfoPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.NewPriority("warning") != v1alpha2.WarningPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.NewPriority("error") != v1alpha2.ErrorPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.NewPriority("critical") != v1alpha2.CriticalPriority { - t.Error("unexpected prioriry created") - } - }) - - t.Run("PriorityFromSeverity", func(t *testing.T) { - if v1alpha2.PriorityFromSeverity(v1alpha2.SeverityCritical) != v1alpha2.CriticalPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.PriorityFromSeverity(v1alpha2.SeverityHigh) != v1alpha2.ErrorPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.PriorityFromSeverity(v1alpha2.SeverityMedium) != v1alpha2.WarningPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.PriorityFromSeverity(v1alpha2.SeverityInfo) != v1alpha2.InfoPriority { - t.Error("unexpected prioriry created") - } - - if v1alpha2.PriorityFromSeverity(v1alpha2.SeverityLow) != v1alpha2.InfoPriority { - t.Error("unexpected prioriry created") - } - if v1alpha2.PriorityFromSeverity("") != v1alpha2.DebugPriority { - t.Error("unexpected prioriry created") - } - }) -} - -func TestPolicyReportResult(t *testing.T) { - t.Run("GetResource Without Resources", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{} - - if r.GetResource() != nil { - t.Error("expected nil resource for empty result") - } - }) - t.Run("GetResource With Resources", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test"}}} - - if r.GetResource().Name != "test" { - t.Error("expected result resource returned") - } - }) - t.Run("GetKind Without Resource", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{} - - if r.GetKind() != "" { - t.Error("expected result kind to be empty string") - } - }) - t.Run("GetKind", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test", Kind: "Pod"}}} - - if r.GetKind() != "Pod" { - t.Error("expected result kind to be Pod") - } - }) - t.Run("GetID from Result With Resource", func(t *testing.T) { - r := v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test", Kind: "Pod"}}} - r.ID = result.NewIDGenerator(nil).Generate(&v1alpha2.PolicyReport{}, r) - - if r.GetID() != "18007334074686647077" { - t.Errorf("expected result kind to be '18007334074686647077', got :%s", r.GetID()) - } - }) - t.Run("GetID from Result With ID Property", func(t *testing.T) { - r := v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test", Kind: "Pod"}}, Properties: map[string]string{"resultID": "result-id"}} - r.ID = result.NewIDGenerator(nil).Generate(&v1alpha2.PolicyReport{}, r) - - if r.GetID() != "result-id" { - t.Errorf("expected result kind to be 'result-id', got :%s", r.GetID()) - } - }) - t.Run("ToResourceString with Namespace and Kind", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test", Namespace: "default", Kind: "Pod"}}} - - if r.ResourceString() != "default/pod/test" { - t.Errorf("expected result resource string 'default/pod/name', got: %s", r.ResourceString()) - } - }) - t.Run("ToResourceString with Kind", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test", Kind: "Namespace"}}} - - if r.ResourceString() != "namespace/test" { - t.Errorf("expected result resource string 'namespace/test', got: %s", r.ResourceString()) - } - }) - t.Run("ToResourceString with Name", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{Resources: []corev1.ObjectReference{{Name: "test"}}} - - if r.ResourceString() != "test" { - t.Errorf("expected result resource string 'test', got :%s", r.ResourceString()) - } - }) - t.Run("ToResourceString Without Resource", func(t *testing.T) { - r := &v1alpha2.PolicyReportResult{} - - if r.ResourceString() != "" { - t.Errorf("expected result resource string to be empty, got :%s", r.ResourceString()) - } - }) -} diff --git a/pkg/crd/api/policyreport/v1alpha2/policyreport_types.go b/pkg/crd/api/policyreport/v1alpha2/policyreport_types.go index 3bae90d5..eacadd38 100644 --- a/pkg/crd/api/policyreport/v1alpha2/policyreport_types.go +++ b/pkg/crd/api/policyreport/v1alpha2/policyreport_types.go @@ -14,6 +14,7 @@ limitations under the License. package v1alpha2 import ( + "fmt" "strconv" "github.com/segmentio/fasthash/fnv1a" @@ -64,6 +65,16 @@ func (r *PolicyReport) GetResults() []PolicyReportResult { return r.Results } +func (r *PolicyReport) HasResult(id string) bool { + for _, r := range r.Results { + if r.GetID() == id { + return true + } + } + + return false +} + func (r *PolicyReport) SetResults(results []PolicyReportResult) { r.Results = results } @@ -125,6 +136,10 @@ func (r *PolicyReport) GetID() string { return strconv.FormatUint(h1, 10) } +func (r *PolicyReport) GetKey() string { + return fmt.Sprintf("%s/%s", r.Namespace, r.Name) +} + func (r *PolicyReport) GetScope() *corev1.ObjectReference { return r.Scope } diff --git a/pkg/crd/api/policyreport/v1alpha2/policyreport_types_test.go b/pkg/crd/api/policyreport/v1alpha2/policyreport_types_test.go index ea3aa735..8a362924 100644 --- a/pkg/crd/api/policyreport/v1alpha2/policyreport_types_test.go +++ b/pkg/crd/api/policyreport/v1alpha2/policyreport_types_test.go @@ -3,9 +3,10 @@ package v1alpha2_test import ( "testing" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" ) func TestPolicyReport(t *testing.T) { diff --git a/pkg/database/builder.go b/pkg/database/builder.go new file mode 100644 index 00000000..06ffe482 --- /dev/null +++ b/pkg/database/builder.go @@ -0,0 +1,229 @@ +package database + +import ( + "context" + "fmt" + "strings" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect" +) + +type QueryBuilder struct { + query *bun.SelectQuery +} + +func (q *QueryBuilder) Filter(column string, values []string) *QueryBuilder { + if len(values) > 1 { + q.query.Where(column+" IN (?)", bun.In(values)) + } else if len(values) == 1 { + q.query.Where(column+" = ?", values[0]) + } + + return q +} + +func (q *QueryBuilder) Scoped(scoped bool) *QueryBuilder { + if scoped { + return q.NamespaceScope() + } + + return q.ClusterScope() +} + +func (q *QueryBuilder) FilterValue(column string, value string) *QueryBuilder { + if value != "" { + q.query.Where(column+" = ?", value) + } + + return q +} + +func (q *QueryBuilder) WithEmpty(column string) *QueryBuilder { + q.query.Where(column + " = ''") + + return q +} + +func (q *QueryBuilder) WithNotEmpty(column string) *QueryBuilder { + q.query.Where(column + " != ''") + + return q +} + +func (q *QueryBuilder) Exclude(filter Filter, prefix string) *QueryBuilder { + if filter.ResourceID == "" && len(filter.Kinds) == 0 && len(filter.Exclude) > 0 { + for source, kind := range filter.Exclude { + q.query.Where(fmt.Sprintf("(%s.source != ? OR (%s.source = ? AND %s.resource_kind NOT IN (?)))", prefix, prefix, prefix), source, source, bun.In(kind)) + } + } + + return q +} + +func (q *QueryBuilder) ResourceSearch(value string) *QueryBuilder { + if value != "" { + q.query.Where(`(resource_name LIKE ?0 OR LOWER(resource_kind) = LOWER(?1))`, "%"+value+"%", value) + } + + return q +} + +func (q *QueryBuilder) PolicySearch(value string) *QueryBuilder { + if value != "" { + q.query.Where(`(f.policy LIKE ?0 OR f.severity LIKE ?0 OR LOWER(f.resource_kind) = LOWER(?1))`, "%"+value+"%", value) + } + + return q +} + +func (q *QueryBuilder) ResultSearch(value string) *QueryBuilder { + if value != "" { + q.query.Where(`(resource_namespace LIKE ?0 OR resource_name LIKE ?0 OR policy LIKE ?0 OR rule LIKE ?0 OR severity = ?1 OR result = ?1 OR LOWER(resource_kind) = LOWER(?1))`, "%"+value+"%", value) + } + + return q +} + +func (q *QueryBuilder) FilterMap(columns map[string][]string) *QueryBuilder { + for column, values := range columns { + if len(values) > 1 { + q.query.Where(column+" IN (?)", bun.In(values)) + } else if len(values) == 1 { + q.query.Where(column+" = ?", values[0]) + } + } + + return q +} + +func (q *QueryBuilder) FilterOptionalNamespaces(values []string) *QueryBuilder { + if len(values) > 1 { + q.query.Where("(resource_namespace IN (?) OR resource_namespace = '')", bun.In(values)) + } else if len(values) == 1 { + q.query.Where("(resource_namespace = ? OR resource_namespace = '')", values[0]) + } + + return q +} + +func (q *QueryBuilder) NamespaceScope() *QueryBuilder { + q.query.Where("resource_namespace != ''") + + return q +} + +func (q *QueryBuilder) ClusterScope() *QueryBuilder { + q.query.Where("resource_namespace = ''") + + return q +} + +func (q *QueryBuilder) Scan(ctx context.Context, dest ...any) error { + return q.query.Scan(ctx, dest...) +} + +func (q *QueryBuilder) Columns(columns ...string) *QueryBuilder { + q.query.Column(columns...) + + return q +} + +func (q *QueryBuilder) Group(columns ...string) *QueryBuilder { + q.query.Group(columns...) + + return q +} + +func (q *QueryBuilder) Order(orders ...string) *QueryBuilder { + q.query.Order(orders...) + + return q +} + +func (q *QueryBuilder) SelectStatusSummaries() *QueryBuilder { + q.query.ColumnExpr("SUM(res.pass) as pass, SUM(res.warn) as warn, SUM(res.fail) as fail, SUM(res.error) as error, SUM(res.skip) as skip") + + return q +} + +func (q *QueryBuilder) SelectSeveritySummaries() *QueryBuilder { + q.query.ColumnExpr("SUM(res.info) as info, SUM(res.low) as low, SUM(res.medium) as medium, SUM(res.high) as high, SUM(res.critical) as critical, SUM(res.unknown) as unknown") + + return q +} + +func (q *QueryBuilder) Pagination(pagination Pagination) *QueryBuilder { + q.query.OrderExpr(fmt.Sprintf( + "%s %s", + strings.Join(pagination.SortBy, ","), + pagination.Direction, + )) + + if pagination.Page == 0 || pagination.Offset == 0 { + return q + } + + q.query.Limit(pagination.Offset) + q.query.Offset((pagination.Page - 1) * pagination.Offset) + + return q +} + +func (q *QueryBuilder) FilterReportLabels(labels map[string]string) *QueryBuilder { + if len(labels) > 0 { + q.query.Join("JOIN policy_report AS pr ON pr.id = policy_report_id") + + for key, value := range labels { + q.query.Where(fmt.Sprintf(q.jsonExtractLayout(), key), value) + } + } + + return q +} + +func (q *QueryBuilder) FilterLabels(labels map[string]string) *QueryBuilder { + if len(labels) > 0 { + q.query.Join("JOIN policy_report AS pr ON pr.id = policy_report_id") + + for key, value := range labels { + q.query.Where(fmt.Sprintf(q.jsonExtractLayout(), key), value) + } + } + + return q +} + +func (q *QueryBuilder) jsonExtractLayout() string { + if q.query.Dialect().Name() == dialect.PG { + return "(pr.labels->>'%s') = ?" + } + + return "json_extract(pr.labels, '$.\"%s\"') = ?" +} + +func (q *QueryBuilder) GetQuery() *bun.SelectQuery { + return q.query +} + +func FromQuery(query *bun.SelectQuery) *QueryBuilder { + return &QueryBuilder{query: query} +} + +func NewFilterQuery(db *bun.DB, column string) *QueryBuilder { + return &QueryBuilder{ + query: db. + NewSelect(). + TableExpr("policy_report_filter as f"). + Column(column). + Distinct(). + Order(column + " ASC"). + Where(column + " != ''"), + } +} + +func NewResourceQuery(db *bun.DB) *QueryBuilder { + return &QueryBuilder{ + query: db.NewSelect().TableExpr("policy_report_resource as res").Distinct(), + } +} diff --git a/pkg/database/bun.go b/pkg/database/bun.go index 3c13c63b..0bc03dc5 100644 --- a/pkg/database/bun.go +++ b/pkg/database/bun.go @@ -3,11 +3,9 @@ package database import ( "context" "database/sql" - "encoding/json" "errors" "fmt" "os" - "strings" "time" _ "github.com/mattn/go-sqlite3" @@ -19,7 +17,6 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - api "github.com/kyverno/policy-reporter/pkg/api/v1" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/report" ) @@ -36,10 +33,831 @@ const ( type Store struct { db *bun.DB version string - - jsonExtractLayout string } +/////////////////////////////// +/// V1 API Queries /// +/////////////////////////////// + +func (s *Store) FetchPolicyReports(ctx context.Context, filter Filter, pagination Pagination) ([]PolicyReport, error) { + list := make([]PolicyReport, 0) + + err := FromQuery(s.db.NewSelect().Model(&list)). + FilterMap(map[string][]string{ + "pr.source": filter.Sources, + "pr.namespace": filter.Namespaces, + }). + FilterLabels(filter.ReportLabel). + FilterValue("pr.type", report.PolicyReportType). + Pagination(pagination). + Scan(ctx) + + return list, err +} + +func (s *Store) CountPolicyReports(ctx context.Context, filter Filter) (int, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReport)(nil))). + FilterMap(map[string][]string{ + "pr.source": filter.Sources, + "pr.namespace": filter.Namespaces, + }). + FilterLabels(filter.ReportLabel). + FilterValue("pr.type", report.PolicyReportType). + GetQuery(). + Count(ctx) +} + +func (s *Store) FetchClusterPolicyReports(ctx context.Context, filter Filter, pagination Pagination) ([]PolicyReport, error) { + list := make([]PolicyReport, 0) + + err := FromQuery(s.db.NewSelect().Model(&list)). + FilterMap(map[string][]string{ + "pr.source": filter.Sources, + }). + FilterLabels(filter.ReportLabel). + FilterValue("pr.type", report.ClusterPolicyReportType). + Pagination(pagination). + Scan(ctx) + + return list, err +} + +func (s *Store) CountClusterPolicyReports(ctx context.Context, filter Filter) (int, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReport)(nil))). + FilterMap(map[string][]string{ + "pr.source": filter.Sources, + }). + FilterLabels(filter.ReportLabel). + FilterValue("pr.type", report.ClusterPolicyReportType). + GetQuery(). + Count(ctx) +} + +func (s *Store) FetchRuleStatusCounts(ctx context.Context, policy, rule string) ([]StatusCount, error) { + counts := make([]StatusCount, 0) + + err := s.db.NewSelect(). + Table("policy_report_result"). + ColumnExpr("COUNT(id) as count, result as status"). + Where("rule = ?", rule). + Where("policy = ?", policy). + Group("status"). + Scan(ctx, &counts) + + return counts, err +} + +func (s *Store) FetchNamespaces(ctx context.Context, filter Filter) ([]string, error) { + return s.FetchNamespacedFilter(ctx, "resource_namespace", filter) +} + +func (s *Store) FetchNamespacedFilter(ctx context.Context, column string, filter Filter) ([]string, error) { + list := make([]string, 0) + + err := NewFilterQuery(s.db, "f."+column). + FilterMap(map[string][]string{ + "f.result": filter.Status, + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.policy": filter.Policies, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + }). + FilterReportLabels(filter.ReportLabel). + NamespaceScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchClusterFilter(ctx context.Context, column string, filter Filter) ([]string, error) { + list := make([]string, 0) + + err := NewFilterQuery(s.db, "f."+column). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.policy": filter.Policies, + "f.resource_kind": filter.Kinds, + }). + FilterReportLabels(filter.ReportLabel). + ClusterScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchNamespacedResources(ctx context.Context, filter Filter) ([]ResourceResult, error) { + list := make([]ResourceResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&list).Distinct()). + Columns("resource_name", "resource_kind", "resource_namespace"). + FilterMap(map[string][]string{ + "res.source": filter.Sources, + "res.category": filter.Categories, + "res.policy": filter.Policies, + "res.resource_kind": filter.Kinds, + "res.resource_namespace": filter.Namespaces, + }). + FilterReportLabels(filter.ReportLabel). + NamespaceScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchClusterResources(ctx context.Context, filter Filter) ([]ResourceResult, error) { + list := make([]ResourceResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&list).Distinct()). + Columns("resource_name", "resource_kind"). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.policy": filter.Policies, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + }). + FilterReportLabels(filter.ReportLabel). + ClusterScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchClusterScopedStatusCounts(ctx context.Context, filter Filter) ([]StatusCount, error) { + list := make([]StatusCount, 0) + + err := FromQuery(s.db.NewSelect().Model(&list).ColumnExpr("SUM(f.count) as count, f.result as status")). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.policy": filter.Policies, + "f.resource_kind": filter.Kinds, + "f.result": filter.Status, + "f.severity": filter.Severities, + }). + FilterReportLabels(filter.ReportLabel). + ClusterScope(). + Group("status"). + Scan(ctx) + + return list, err +} + +func (s *Store) FetchNamespaceScopedStatusCounts(ctx context.Context, filter Filter) ([]StatusCount, error) { + list := make([]StatusCount, 0) + + err := FromQuery(s.db.NewSelect().Model(&list).ColumnExpr("SUM(f.count) as count, f.result as status, f.resource_namespace")). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.policy": filter.Policies, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + "f.result": filter.Status, + "f.severity": filter.Severities, + }). + FilterReportLabels(filter.ReportLabel). + NamespaceScope(). + Group("status", "f.resource_namespace"). + Scan(ctx) + + return list, err +} + +/////////////////////////////// +/// V2 API Queries /// +/////////////////////////////// + +func (s *Store) FetchSources(ctx context.Context, filter Filter) ([]string, error) { + list := make([]string, 0) + + err := NewFilterQuery(s.db, "f.source"). + FilterMap(map[string][]string{ + "f.resource_kind": filter.Kinds, + }). + FilterValue("id", filter.ResourceID). + FilterReportLabels(filter.ReportLabel). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchCategories(ctx context.Context, filter Filter) ([]Category, error) { + list := make([]Category, 0) + + err := FromQuery(s.db.NewSelect().Model(&list).ColumnExpr("SUM(f.count) as count")). + Columns("f.source", "f.category", "f.result", "f.severity"). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + }). + Exclude(filter, "f"). + FilterReportLabels(filter.ReportLabel). + Group("f.source", "f.category", "f.result", "f.severity"). + Order("f.source ASC", "f.category ASC"). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchResource(ctx context.Context, id string) (ResourceResult, error) { + result := ResourceResult{} + + err := FromQuery(s.db.NewSelect().Model(&result)). + Columns("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name", "res.source", "res.category"). + SelectStatusSummaries(). + FilterValue("res.id", id). + GetQuery(). + Limit(1). + Scan(ctx) + + return result, err +} + +func (s *Store) FetchResourceCategories(ctx context.Context, resource string, filter Filter) ([]ResourceCategory, error) { + list := make([]ResourceCategory, 0) + + err := FromQuery(s.db.NewSelect().Model(&list)). + Columns("res.source", "res.category"). + SelectStatusSummaries(). + FilterMap(map[string][]string{ + "res.source": filter.Sources, + "res.category": filter.Categories, + }). + Exclude(filter, "res"). + FilterValue("id", resource). + FilterReportLabels(filter.ReportLabel). + Group("res.source", "res.category"). + Order("res.source ASC", "res.category ASC"). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchProperty(ctx context.Context, property string, filter Filter) ([]ResultProperty, error) { + result := make([]ResultProperty, 0) + + err := FromQuery( + s.db.NewSelect(). + Model(&result). + Distinct(). + ColumnExpr(fmt.Sprintf("resource_namespace, properties->>'%s' as property", property))). + FilterMap(map[string][]string{ + "category": filter.Categories, + "source": filter.Sources, + "policy": filter.Policies, + "rules": filter.Rules, + "status": filter.Status, + "resource_namespace": filter.Namespaces, + }). + GetQuery(). + Where(fmt.Sprintf("properties->'%s' IS NOT NULL", property)). + Scan(ctx) + + return result, err +} + +func (s *Store) FetchResourceStatusCounts(ctx context.Context, id string, filter Filter) ([]ResourceStatusCount, error) { + result := []ResourceStatusCount{} + + err := FromQuery(s.db.NewSelect().Model(&result)). + Columns("res.source"). + SelectStatusSummaries(). + FilterMap(map[string][]string{ + "res.category": filter.Categories, + "res.source": filter.Sources, + "policy": filter.Policies, + }). + FilterValue("res.id", id). + FilterReportLabels(filter.ReportLabel). + Group("res.source"). + Scan(ctx) + + return result, err +} + +func (s *Store) FetchResourceSeverityCounts(ctx context.Context, id string, filter Filter) ([]ResourceSeverityCount, error) { + result := []ResourceSeverityCount{} + + err := FromQuery(s.db.NewSelect().Model(&result)). + Columns("res.source"). + SelectSeveritySummaries(). + FilterMap(map[string][]string{ + "res.category": filter.Categories, + "res.source": filter.Sources, + "policy": filter.Policies, + }). + FilterValue("res.id", id). + FilterReportLabels(filter.ReportLabel). + Group("res.source"). + Scan(ctx) + + return result, err +} + +func (s *Store) FetchNamespaceResourceResults(ctx context.Context, filter Filter, pagination Pagination) ([]ResourceResult, error) { + results := make([]ResourceResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + Columns("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name"). + SelectStatusSummaries(). + SelectSeveritySummaries(). + Group("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name"). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_namespace": filter.Namespaces, + "resource_kind": filter.Kinds, + }). + FilterValue("res.id", filter.ResourceID). + ResourceSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "res"). + NamespaceScope(). + Pagination(pagination). + Scan(ctx) + + return results, err +} + +func (s *Store) CountNamespaceResourceResults(ctx context.Context, filter Filter) (int, error) { + query := FromQuery(s.db.NewSelect().Model((*ResourceResult)(nil))). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_namespace": filter.Namespaces, + "resource_kind": filter.Kinds, + }). + FilterValue("res.id", filter.ResourceID). + ResourceSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "res"). + NamespaceScope(). + Group("res.id"). + GetQuery() + + return query.Count(ctx) +} + +func (s *Store) FetchClusterResourceResults(ctx context.Context, filter Filter, pagination Pagination) ([]ResourceResult, error) { + results := make([]ResourceResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + Columns("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name"). + SelectStatusSummaries(). + SelectSeveritySummaries(). + Group("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name"). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_kind": filter.Kinds, + }). + FilterValue("res.id", filter.ResourceID). + ResourceSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "res"). + ClusterScope(). + Pagination(pagination). + Scan(ctx) + + return results, err +} + +func (s *Store) CountClusterResourceResults(ctx context.Context, filter Filter) (int, error) { + query := FromQuery(s.db.NewSelect().Model((*ResourceResult)(nil))). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_kind": filter.Kinds, + }). + FilterValue("res.id", filter.ResourceID). + ResourceSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "res"). + ClusterScope(). + Group("res.id"). + GetQuery() + + return query.Count(ctx) +} + +func (s *Store) FetchResourceResults(ctx context.Context, id string, filter Filter) ([]ResourceResult, error) { + results := make([]ResourceResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + Columns("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name", "res.source"). + SelectStatusSummaries(). + FilterValue(`res.id`, id). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_kind": filter.Kinds, + }). + FilterReportLabels(filter.ReportLabel). + ResourceSearch(filter.Search). + Order("res.source ASC"). + Group("res.id", "resource_uid", "resource_kind", "resource_api_version", "resource_namespace", "resource_name", "res.source"). + Scan(ctx) + + return results, err +} + +func (s *Store) FetchResourcePolicyResults(ctx context.Context, id string, filter Filter, pagination Pagination) ([]PolicyReportResult, error) { + results := make([]PolicyReportResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + FilterValue(`r.resource_id`, id). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + }). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Pagination(pagination). + Scan(ctx) + + return results, err +} + +func (s *Store) CountResourcePolicyResults(ctx context.Context, id string, filter Filter) (int, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReportResult)(nil))). + FilterValue(`r.resource_id`, id). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + }). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + GetQuery(). + Count(ctx) +} + +func (s *Store) FetchResults(ctx context.Context, namespaced bool, filter Filter, pagination Pagination) ([]PolicyReportResult, error) { + results := make([]PolicyReportResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "policy": filter.Policies, + "rule": filter.Rules, + "resource_namespace": filter.Namespaces, + "resource_kind": filter.Kinds, + "resource_name": filter.Resources, + "result": filter.Status, + "severity": filter.Severities, + }). + Scoped(namespaced). + FilterValue(`r.resource_id`, filter.ResourceID). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "r"). + Pagination(pagination). + Scan(ctx) + + return results, err +} + +func (s *Store) CountResults(ctx context.Context, namespaced bool, filter Filter) (int, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReportResult)(nil))). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "policy": filter.Policies, + "rule": filter.Rules, + "resource_namespace": filter.Namespaces, + "resource_kind": filter.Kinds, + "resource_name": filter.Resources, + "result": filter.Status, + "severity": filter.Severities, + }). + Scoped(namespaced). + FilterValue(`r.resource_id`, filter.ResourceID). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "r"). + GetQuery(). + Count(ctx) +} + +func (s *Store) FetchResultsWithoutResource(ctx context.Context, filter Filter, pagination Pagination) ([]PolicyReportResult, error) { + results := make([]PolicyReportResult, 0) + + err := FromQuery(s.db.NewSelect().Model(&results)). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "policy": filter.Policies, + "rule": filter.Rules, + "result": filter.Status, + "severity": filter.Severities, + }). + WithEmpty("resource_name"). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "r"). + Pagination(pagination). + Scan(ctx) + + return results, err +} + +func (s *Store) CountResultsWithoutResource(ctx context.Context, filter Filter) (int, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReportResult)(nil))). + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "policy": filter.Policies, + "rule": filter.Rules, + "result": filter.Status, + "severity": filter.Severities, + }). + WithEmpty("resource_name"). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "r"). + GetQuery(). + Count(ctx) +} + +func (s *Store) UseResources(ctx context.Context, source string, filter Filter) (bool, error) { + return FromQuery(s.db.NewSelect().Model((*PolicyReportResult)(nil))). + FilterValue("source", source). + FilterMap(map[string][]string{ + "category": filter.Categories, + "policy": filter.Policies, + "rule": filter.Rules, + }). + WithNotEmpty("resource_name"). + ResultSearch(filter.Search). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "r"). + GetQuery(). + Exists(ctx) +} + +func (s *Store) FetchClusterStatusCounts(ctx context.Context, source string, filter Filter) ([]StatusCount, error) { + results := make([]StatusCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.result as status")). + FilterMap(map[string][]string{ + "category": filter.Categories, + "policy": filter.Policies, + "resource_kind": filter.Kinds, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + ClusterScope(). + Group("status"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchClusterSeverityCounts(ctx context.Context, source string, filter Filter) ([]SeverityCount, error) { + results := make([]SeverityCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.severity")). + FilterMap(map[string][]string{ + "category": filter.Categories, + "policy": filter.Policies, + "resource_kind": filter.Kinds, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + ClusterScope(). + Group("f.severity"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchNamespaceStatusCounts(ctx context.Context, source string, filter Filter) ([]StatusCount, error) { + results := make([]StatusCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("f.resource_namespace, SUM(f.count) as count, f.result as status")). + FilterMap(map[string][]string{ + "f.category": filter.Categories, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + "f.policy": filter.Policies, + "status": filter.Status, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + NamespaceScope(). + Group("f.resource_namespace", "status"). + Order("f.resource_namespace ASC", "status ASC"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchNamespaceSeverityCounts(ctx context.Context, source string, filter Filter) ([]SeverityCount, error) { + results := make([]SeverityCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("f.resource_namespace, SUM(f.count) as count, f.severity")). + FilterMap(map[string][]string{ + "f.category": filter.Categories, + "f.resource_kind": filter.Kinds, + "f.resource_namespace": filter.Namespaces, + "f.policy": filter.Policies, + "f.severity": filter.Severities, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + NamespaceScope(). + Group("f.resource_namespace", "f.severity"). + Order("f.resource_namespace ASC", "f.severity ASC"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchTotalStatusCounts(ctx context.Context, source string, filter Filter) ([]StatusCount, error) { + results := make([]StatusCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.result as status")). + FilterMap(map[string][]string{ + "category": filter.Categories, + "policy": filter.Policies, + "resource_kind": filter.Kinds, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + Group("status"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchTotalSeverityCounts(ctx context.Context, source string, filter Filter) ([]SeverityCount, error) { + results := make([]SeverityCount, 0) + + err := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.severity")). + FilterMap(map[string][]string{ + "category": filter.Categories, + "policy": filter.Policies, + "resource_kind": filter.Kinds, + }). + FilterValue("f.source", source). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + Group("severity"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchNamespaceKinds(ctx context.Context, filter Filter) ([]string, error) { + list := make([]string, 0) + + err := NewFilterQuery(s.db, "resource_kind"). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.resource_namespace": filter.Namespaces, + }). + Exclude(filter, "f"). + FilterReportLabels(filter.ReportLabel). + NamespaceScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchClusterKinds(ctx context.Context, filter Filter) ([]string, error) { + list := make([]string, 0) + + err := NewFilterQuery(s.db, "resource_kind"). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + }). + Exclude(filter, "f"). + FilterReportLabels(filter.ReportLabel). + ClusterScope(). + Scan(ctx, &list) + + return list, err +} + +func (s *Store) FetchPolicies(ctx context.Context, filter Filter) ([]PolicyReportFilter, error) { + results := make([]PolicyReportFilter, 0) + + err := FromQuery(s.db.NewSelect().Model(&results).ColumnExpr("f.severity, f.category, f.policy, f.source, f.result, SUM(f.count) as count")). + FilterMap(map[string][]string{ + "f.source": filter.Sources, + "f.category": filter.Categories, + "f.resource_kind": filter.Kinds, + }). + PolicySearch(filter.Search). + Exclude(filter, "f"). + FilterReportLabels(filter.ReportLabel). + Order("f.source ASC", "f.category ASC"). + Group("f.category", "f.policy", "f.source", "f.result", "f.severity"). + Scan(ctx) + + return results, err +} + +func (s *Store) FetchFindingCounts(ctx context.Context, filter Filter) ([]StatusCount, error) { + results := make([]StatusCount, 0) + + query := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.result as status, f.source")) + + if filter.Namespaced { + query. + NamespaceScope(). + Filter("resource_namespace", filter.Namespaces) + } else { + query.FilterOptionalNamespaces(filter.Namespaces) + } + + err := query. + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_kind": filter.Kinds, + "policy": filter.Policies, + "status": filter.Status, + }). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + Group("f.source", "status"). + Order("f.source"). + Scan(ctx, &results) + + return results, err +} + +func (s *Store) FetchSeverityFindingCounts(ctx context.Context, filter Filter) ([]SeverityCount, error) { + results := make([]SeverityCount, 0) + + query := FromQuery(s.db. + NewSelect(). + TableExpr("policy_report_filter as f"). + ColumnExpr("SUM(f.count) as count, f.severity, f.source")) + + if filter.Namespaced { + query. + NamespaceScope(). + Filter("resource_namespace", filter.Namespaces) + } else { + query.FilterOptionalNamespaces(filter.Namespaces) + } + + err := query. + FilterMap(map[string][]string{ + "source": filter.Sources, + "category": filter.Categories, + "resource_kind": filter.Kinds, + "policy": filter.Policies, + "severity": filter.Severities, + }). + FilterReportLabels(filter.ReportLabel). + Exclude(filter, "f"). + Group("f.source", "f.severity"). + Order("f.source"). + Scan(ctx, &results) + + return results, err +} + +///////////////////////// +/// Lifecycle Methods /// +///////////////////////// + func (s *Store) CreateSchemas(ctx context.Context) error { if s.db.Dialect().Name() == dialect.SQLite { if _, err := s.db.Exec("PRAGMA foreign_keys = ON"); err != nil { @@ -77,6 +895,14 @@ func (s *Store) CreateSchemas(ctx context.Context) error { Exec(ctx) logOnError("create policy_report_filter table", err) + _, err = s.db. + NewCreateTable(). + IfNotExists(). + Model((*ResourceResult)(nil)). + ForeignKey(`(policy_report_id) REFERENCES policy_report(id) ON DELETE CASCADE`). + Exec(ctx) + logOnError("create policy_report_resource table", err) + return err } @@ -105,6 +931,12 @@ func (s *Store) DropSchema(ctx context.Context) error { Exec(ctx) logOnError("drop policy_report table", err) + _, err = s.db.NewDropTable(). + IfExists(). + Model((*ResourceResult)(nil)). + Exec(ctx) + logOnError("drop policy_report_resource table", err) + return err } @@ -123,6 +955,15 @@ func (s *Store) Add(ctx context.Context, report v1alpha2.ReportInterface) error } } + resources := chunkSlice(MapPolicyReportResource(report), 50) + for _, list := range resources { + _, err = s.db.NewInsert().Model(&list).Exec(ctx) + if err != nil { + zap.L().Error("failed to bulk import policy report resources", zap.Error(err)) + return err + } + } + results := chunkSlice(MapPolicyReportResults(report), 50) for _, list := range results { _, err = s.db.NewInsert().Ignore().Model(&list).Exec(ctx) @@ -164,506 +1005,6 @@ func (s *Store) CleanUp(ctx context.Context) error { return err } -func (s *Store) FetchPolicyReports(ctx context.Context, filter api.Filter, pagination api.Pagination) ([]*api.PolicyReport, error) { - list := []*api.PolicyReport{} - query := s.db.NewSelect().Model((*PolicyReport)(nil)) - - s.addFilter(query, filter) - addPolicyReportFilter(query, filter) - query.Where(`pr.type = ?`, report.PolicyReportType) - - addPagination(query, pagination) - - err := query.Scan(ctx, &list) - if err != nil { - zap.L().Error("failed to select policy report results", zap.Error(err), zap.Any("filter", filter), zap.Any("pagination", pagination)) - } - - return list, err -} - -func (s *Store) CountPolicyReports(ctx context.Context, filter api.Filter) (int, error) { - query := s.db.NewSelect().Model((*PolicyReport)(nil)) - - s.addFilter(query, filter) - addPolicyReportFilter(query, filter) - query.Where(`pr.type = ?`, report.PolicyReportType) - - count, err := query.Count(ctx) - if err != nil { - zap.L().Error("failed to select policy report results", zap.Error(err), zap.Any("filter", filter)) - } - - return count, err -} - -func (s *Store) FetchNamespacedReportLabels(ctx context.Context, filter api.Filter) (map[string][]string, error) { - results := []string{} - list := make(map[string][]string) - - query := s.db.NewSelect(). - TableExpr("policy_report as pr"). - Distinct(). - Where(`pr.type = ?`, report.PolicyReportType) - - if s.db.Dialect().Name() == dialect.PG { - query.ColumnExpr("labels::text") - } else { - query.Column("labels") - } - - addPolicyReportFilter(query, filter) - - err := query.Scan(ctx, &results) - if err != nil { - return list, err - } - - for _, labels := range results { - for key, value := range convertJSONToMap(labels) { - _, ok := list[key] - contained := contains(value, list[key]) - - if ok && !contained { - list[key] = append(list[key], value) - continue - } else if ok && contained { - continue - } - - list[key] = []string{value} - } - } - - return list, nil -} - -func (s *Store) FetchClusterPolicyReports(ctx context.Context, filter api.Filter, pagination api.Pagination) ([]*api.PolicyReport, error) { - list := []*api.PolicyReport{} - query := s.db.NewSelect().Model((*PolicyReport)(nil)) - - s.addFilter(query, filter) - addPolicyReportFilter(query, filter) - query.Where(`pr.type = ?`, report.ClusterPolicyReportType) - - addPagination(query, pagination) - - err := query.Scan(ctx, &list) - if err != nil { - zap.L().Error("failed to select policy report results", zap.Error(err), zap.Any("filter", filter), zap.Any("pagination", pagination)) - } - - return list, err -} - -func (s *Store) CountClusterPolicyReports(ctx context.Context, filter api.Filter) (int, error) { - query := s.db.NewSelect().Model((*PolicyReport)(nil)) - - s.addFilter(query, filter) - addPolicyReportFilter(query, filter) - query.Where(`pr.type = ?`, report.ClusterPolicyReportType) - - count, err := query.Count(ctx) - if err != nil { - zap.L().Error("failed to select policy report results", zap.Error(err), zap.Any("filter", filter)) - } - - return count, err -} - -func (s *Store) FetchClusterReportLabels(ctx context.Context, filter api.Filter) (map[string][]string, error) { - results := []string{} - list := make(map[string][]string) - - query := s.db.NewSelect(). - TableExpr("policy_report as pr"). - Distinct(). - Where(`pr.type = ?`, report.ClusterPolicyReportType) - - if s.db.Dialect().Name() == dialect.PG { - query.ColumnExpr("labels::text") - } else { - query.Column("labels") - } - - addPolicyReportFilter(query, filter) - - err := query.Scan(ctx, &results) - if err != nil { - return list, err - } - - for _, labels := range results { - for key, value := range convertJSONToMap(labels) { - _, ok := list[key] - contained := contains(value, list[key]) - - if ok && !contained { - list[key] = append(list[key], value) - continue - } else if ok && contained { - continue - } - - list[key] = []string{value} - } - } - - return list, nil -} - -func (s *Store) FetchClusterRules(ctx context.Context, filter api.Filter) ([]string, error) { - list := make([]string, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_result as r"). - Column("rule"). - Distinct(). - Order("rule ASC"). - Where(`r.resource_namespace = ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - query.Scan(ctx, &list) - - return list, nil -} - -func (s *Store) FetchClusterResources(ctx context.Context, filter api.Filter) ([]*api.Resource, error) { - list := make([]*api.Resource, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_result as r"). - ColumnExpr("resource_name as name, resource_kind as kind"). - Distinct(). - Order("kind ASC", "name ASC"). - Where(`r.resource_namespace = ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - query.Scan(ctx, &list) - - return list, nil -} - -func (s *Store) FetchClusterPolicies(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "policy", filter, false) -} - -func (s *Store) FetchClusterKinds(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "kind", filter, false) -} - -func (s *Store) FetchClusterCategories(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "category", filter, false) -} - -func (s *Store) FetchClusterSources(ctx context.Context) ([]string, error) { - return s.fetchFilterOptions(ctx, "source", api.Filter{}, false) -} - -func (s *Store) FetchClusterStatusCounts(ctx context.Context, filter api.Filter) ([]api.StatusCount, error) { - var list map[string]api.StatusCount - - if len(filter.Status) == 0 { - list = map[string]api.StatusCount{ - v1alpha2.StatusPass: {Status: v1alpha2.StatusPass}, - v1alpha2.StatusFail: {Status: v1alpha2.StatusFail}, - v1alpha2.StatusWarn: {Status: v1alpha2.StatusWarn}, - v1alpha2.StatusError: {Status: v1alpha2.StatusError}, - v1alpha2.StatusSkip: {Status: v1alpha2.StatusSkip}, - } - } else { - list = map[string]api.StatusCount{} - - for _, status := range filter.Status { - list[status] = api.StatusCount{Status: status} - } - } - - counts := make([]api.StatusCount, 0, len(list)) - results := make([]api.StatusCount, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_filter as f"). - ColumnExpr("SUM(f.count) as count, f.result as status"). - Where(`f.namespace = ''`). - Group("status") - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = f.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportFilterFilter(query, filter) - - err := query.Scan(ctx, &results) - if err != nil { - zap.L().Error("failed to load cluster status counts", zap.Error(err)) - return nil, err - } - - for _, count := range results { - list[count.Status] = count - } - - for _, count := range list { - counts = append(counts, count) - } - - return counts, nil -} - -func (s *Store) FetchClusterResults(ctx context.Context, filter api.Filter, pagination api.Pagination) ([]*api.ListResult, error) { - results := make([]*PolicyReportResult, 0) - - query := s.db. - NewSelect(). - Model(&results). - Where(`r.resource_namespace = ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - addPagination(query, pagination) - - err := query.Scan(ctx) - if err != nil { - return nil, err - } - - return MapListResult(results), nil -} - -func (s *Store) CountClusterResults(ctx context.Context, filter api.Filter) (int, error) { - query := s.db. - NewSelect(). - Model((*PolicyReportResult)(nil)). - Where(`r.resource_namespace = ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - return query.Count(ctx) -} - -func (s *Store) FetchNamespacedRules(ctx context.Context, filter api.Filter) ([]string, error) { - list := make([]string, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_result as r"). - Column("rule"). - Distinct(). - Order("rule ASC"). - Where(`r.resource_namespace != ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - query.Scan(ctx, &list) - - return list, nil -} - -func (s *Store) FetchNamespacedResources(ctx context.Context, filter api.Filter) ([]*api.Resource, error) { - list := make([]*api.Resource, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_result as r"). - ColumnExpr("resource_name as name, resource_kind as kind"). - Distinct(). - Order("kind ASC", "name ASC"). - Where(`r.resource_namespace != ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - query.Scan(ctx, &list) - - return list, nil -} - -func (s *Store) FetchNamespacedPolicies(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "policy", filter, true) -} - -func (s *Store) FetchNamespacedKinds(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "kind", filter, true) -} - -func (s *Store) FetchNamespacedCategories(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "category", filter, true) -} - -func (s *Store) FetchNamespacedSources(ctx context.Context) ([]string, error) { - return s.fetchFilterOptions(ctx, "source", api.Filter{}, true) -} - -func (s *Store) FetchNamespaces(ctx context.Context, filter api.Filter) ([]string, error) { - return s.fetchFilterOptions(ctx, "f.namespace", filter, true) -} - -func (s *Store) FetchNamespacedStatusCounts(ctx context.Context, filter api.Filter) ([]api.NamespacedStatusCount, error) { - var list map[string][]api.NamespaceCount - - if len(filter.Status) == 0 { - list = map[string][]api.NamespaceCount{ - v1alpha2.StatusPass: make([]api.NamespaceCount, 0), - v1alpha2.StatusFail: make([]api.NamespaceCount, 0), - v1alpha2.StatusWarn: make([]api.NamespaceCount, 0), - v1alpha2.StatusError: make([]api.NamespaceCount, 0), - v1alpha2.StatusSkip: make([]api.NamespaceCount, 0), - } - } else { - list = map[string][]api.NamespaceCount{} - - for _, status := range filter.Status { - list[status] = make([]api.NamespaceCount, 0) - } - } - - statusCounts := make([]api.NamespacedStatusCount, 0, 5) - counts := make([]api.NamespaceCount, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_filter as f"). - ColumnExpr("SUM(f.count) as count, f.namespace, f.result as status"). - Where(`f.namespace != ''`). - Group("f.namespace", "status"). - Order("f.namespace ASC") - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = f.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportFilterFilter(query, filter) - - err := query.Scan(ctx, &counts) - if err != nil { - zap.L().Error("failed to load namespaced status counts", zap.Error(err)) - return nil, err - } - - for _, count := range counts { - list[count.Status] = append(list[count.Status], count) - } - - for status, items := range list { - statusCounts = append(statusCounts, api.NamespacedStatusCount{ - Status: status, - Items: items, - }) - } - - return statusCounts, nil -} - -func (s *Store) FetchRuleStatusCounts(ctx context.Context, policy, rule string) ([]api.StatusCount, error) { - list := map[string]api.StatusCount{ - v1alpha2.StatusPass: {Status: v1alpha2.StatusPass}, - v1alpha2.StatusFail: {Status: v1alpha2.StatusFail}, - v1alpha2.StatusWarn: {Status: v1alpha2.StatusWarn}, - v1alpha2.StatusError: {Status: v1alpha2.StatusError}, - v1alpha2.StatusSkip: {Status: v1alpha2.StatusSkip}, - } - - statusCounts := make([]api.StatusCount, 0, len(list)) - counts := make([]api.StatusCount, 0) - - err := s.db.NewSelect(). - Table("policy_report_result"). - ColumnExpr("COUNT(id) as count, result as status"). - Where("rule = ?", rule). - Where("policy = ?", policy). - Group("status"). - Scan(ctx, &counts) - if err != nil { - return statusCounts, err - } - - for _, count := range counts { - list[count.Status] = count - } - - for _, count := range list { - statusCounts = append(statusCounts, count) - } - - return statusCounts, nil -} - -func (s *Store) FetchNamespacedResults(ctx context.Context, filter api.Filter, pagination api.Pagination) ([]*api.ListResult, error) { - results := make([]*PolicyReportResult, 0) - - query := s.db. - NewSelect(). - Model(&results). - Where(`r.resource_namespace != ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - addPagination(query, pagination) - - err := query.Scan(ctx) - if err != nil { - return nil, err - } - - return MapListResult(results), nil -} - -func (s *Store) CountNamespacedResults(ctx context.Context, filter api.Filter) (int, error) { - query := s.db. - NewSelect(). - Model((*PolicyReportResult)(nil)). - Where(`r.resource_namespace != ''`) - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = r.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportResultFilter(query, filter) - - return query.Count(ctx) -} - func (s *Store) Get(ctx context.Context, id string) (v1alpha2.ReportInterface, error) { polr := &PolicyReport{} @@ -747,45 +1088,11 @@ func (s *Store) fetchResults(ctx context.Context, id string) ([]v1alpha2.PolicyR return list, nil } -func (s *Store) fetchFilterOptions(ctx context.Context, option string, filter api.Filter, namespaced bool) ([]string, error) { - list := make([]string, 0) - - query := s.db. - NewSelect(). - TableExpr("policy_report_filter as f"). - Column(option). - Distinct(). - Order(option+" ASC"). - Where(`? != ''`, bun.Ident(option)) - - if namespaced { - query.Where(`f.namespace != ''`) - } else { - query.Where(`f.namespace = ''`) - } - - if len(filter.ReportLabel) > 0 { - query.Join("JOIN policy_report AS pr ON pr.id = f.policy_report_id") - } - - s.addFilter(query, filter) - addPolicyReportFilterFilter(query, filter) - - err := query.Scan(ctx, &list) - - return list, err -} - -func (s *Store) Configure() { - if s.db.Dialect().Name() == dialect.PG { - s.jsonExtractLayout = "(pr.labels->>'%s') = ?" - return - } - - s.jsonExtractLayout = "json_extract(pr.labels, '$.\"%s\"') = ?" -} - func (s *Store) RequireSchemaUpgrade(ctx context.Context) bool { + if s.IsSQLite() { + return true + } + config := Config{} err := s.db.NewSelect().Model(&config).Where("id = ?", 1).Scan(ctx) @@ -841,8 +1148,6 @@ func NewStore(db *bun.DB, version string) (*Store, error) { version: version, } - s.Configure() - return s, nil } @@ -872,106 +1177,6 @@ func createSQLiteDB(dbFile string) (*sql.DB, error) { return db, nil } -func addPolicyReportFilterFilter(query *bun.SelectQuery, filter api.Filter) { - if len(filter.Namespaces) > 0 { - query.Where("f.namespace IN (?)", bun.In(filter.Namespaces)) - } - if len(filter.Kinds) > 0 { - query.Where("f.kind IN (?)", bun.In(filter.Kinds)) - } - if len(filter.Sources) > 0 { - query.Where("f.source IN (?)", bun.In(filter.Sources)) - } -} - -func addPolicyReportResultFilter(query *bun.SelectQuery, filter api.Filter) { - if len(filter.Namespaces) > 0 { - query.Where("r.resource_namespace IN (?)", bun.In(filter.Namespaces)) - } - if len(filter.Rules) > 0 { - query.Where("r.rule IN (?)", bun.In(filter.Rules)) - } - if len(filter.Kinds) > 0 { - query.Where("r.resource_kind IN (?)", bun.In(filter.Kinds)) - } - if len(filter.Resources) > 0 { - query.Where("r.resource_name IN (?)", bun.In(filter.Resources)) - } - if len(filter.Sources) > 0 { - query.Where("r.source IN (?)", bun.In(filter.Sources)) - } - - if filter.Search != "" { - query.Where(`(resource_namespace LIKE ?0 OR resource_name LIKE ?0 OR policy LIKE ?0 OR rule LIKE ?0 OR severity = ?1 OR result = ?1 OR LOWER(resource_kind) = LOWER(?1))`, "%"+filter.Search+"%", filter.Search) - } -} - -func addPolicyReportFilter(query *bun.SelectQuery, filter api.Filter) { - if len(filter.Namespaces) > 0 { - query.Where("pr.namespace IN (?)", bun.In(filter.Namespaces)) - } - if len(filter.Sources) > 0 { - query.Where("pr.source IN (?)", bun.In(filter.Sources)) - } -} - -func (s *Store) addFilter(query *bun.SelectQuery, filter api.Filter) { - if len(filter.Policies) > 0 { - query.Where("policy IN (?)", bun.In(filter.Policies)) - } - if len(filter.Categories) > 0 { - query.Where("category IN (?)", bun.In(filter.Categories)) - } - if len(filter.Severities) > 0 { - query.Where("severity IN (?)", bun.In(filter.Severities)) - } - if len(filter.Status) > 0 { - query.Where("result IN (?)", bun.In(filter.Status)) - } - - if len(filter.ReportLabel) > 0 { - for key, value := range filter.ReportLabel { - query.Where(fmt.Sprintf(s.jsonExtractLayout, key), value) - } - } -} - -func addPagination(query *bun.SelectQuery, pagination api.Pagination) { - query.OrderExpr(fmt.Sprintf( - "%s %s", - strings.Join(pagination.SortBy, ","), - pagination.Direction, - )) - - if pagination.Page == 0 || pagination.Offset == 0 { - return - } - - query.Limit(pagination.Offset) - query.Offset((pagination.Page - 1) * pagination.Offset) -} - -func convertJSONToMap(s string) map[string]string { - m := make(map[string]string) - if s == "" { - return m - } - - _ = json.Unmarshal([]byte(s), &m) - - return m -} - -func contains(source string, sources []string) bool { - for _, s := range sources { - if strings.EqualFold(s, source) { - return true - } - } - - return false -} - func chunkSlice[K interface{}](slice []K, chunkSize int) [][]K { var chunks [][]K for i := 0; i < len(slice); i += chunkSize { diff --git a/pkg/database/bun_test.go b/pkg/database/bun_test.go deleted file mode 100644 index af6bcff4..00000000 --- a/pkg/database/bun_test.go +++ /dev/null @@ -1,678 +0,0 @@ -package database_test - -import ( - "context" - "database/sql" - "testing" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - v1 "github.com/kyverno/policy-reporter/pkg/api/v1" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/database" - "github.com/kyverno/policy-reporter/pkg/fixtures" -) - -var pagination = v1.Pagination{Page: 1, Offset: 20, Direction: "ASC", SortBy: []string{"resource_name"}} - -var polrPagination = v1.Pagination{Page: 1, Offset: 20, Direction: "ASC", SortBy: []string{"namespace"}} - -var preport = &v1alpha2.PolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Name: "polr-test", - Namespace: "test", - Labels: map[string]string{"app": "policy-reporter", "scope": "namespaced"}, - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{fixtures.FailResult}, - Summary: v1alpha2.PolicyReportSummary{Fail: 1}, -} - -var dreport = &v1alpha2.PolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Name: "polr-test", - Namespace: "test", - Labels: map[string]string{"app": "policy-reporter", "scope": "namespaced"}, - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{fixtures.FailResult, fixtures.FailResult, fixtures.FailPodResult}, - Summary: v1alpha2.PolicyReportSummary{Fail: 1}, -} - -var ureport = &v1alpha2.PolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Name: "polr-test", - Namespace: "test", - Labels: map[string]string{"app": "policy-reporter", "owner": "team-a", "scope": "namespaced"}, - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{fixtures.FailResult, fixtures.PassPodResult}, - Summary: v1alpha2.PolicyReportSummary{Fail: 1, Pass: 1}, -} - -var creport = &v1alpha2.ClusterPolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cpolr", - Labels: map[string]string{"app": "policy-reporter", "scope": "cluster"}, - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{fixtures.PassNamespaceResult, fixtures.FailNamespaceResult}, - Summary: v1alpha2.PolicyReportSummary{}, -} - -var scopeReport = &v1alpha2.PolicyReport{ - ObjectMeta: metav1.ObjectMeta{ - Name: "polr-scope-test", - Namespace: "test", - CreationTimestamp: metav1.Now(), - }, - Results: []v1alpha2.PolicyReportResult{fixtures.ScopeResult}, - Summary: v1alpha2.PolicyReportSummary{Fail: 1, Pass: 0}, - Scope: &corev1.ObjectReference{ - APIVersion: "v1", - Kind: "Deployment", - Name: "nginx", - Namespace: "test", - UID: "536ab69f-1b3c-4bd9-9ba4-274a56188409", - }, -} - -func Test_PolicyReportStore(t *testing.T) { - db, err := database.NewSQLiteDB("test.db") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - ctx := context.Background() - - store, _ := database.NewStore(db, "develop") - store.PrepareDatabase(ctx) - - t.Run("Add/Get/Update PolicyReport", func(t *testing.T) { - _, err := store.Get(ctx, preport.GetID()) - if err != sql.ErrNoRows { - t.Fatalf("Should not be found in empty Store") - } - - err = store.Add(ctx, preport) - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - polr, err := store.Get(ctx, preport.GetID()) - if err != nil { - t.Fatalf("Should found policy reporter after adding: %v", err) - } - - if len(polr.GetResults()) == 0 { - t.Fatalf("Failed to load PolicyReportResults: %v", err) - } - - err = store.Update(ctx, ureport) - if err != nil { - t.Fatalf("Failed to update policy report: %v", err) - } - - r2, _ := store.Get(ctx, ureport.GetID()) - if r2.GetSummary().Pass != 1 { - t.Errorf("Expected 1 Passed Results in GetSummary() after Update") - } - - if r2.GetLabels()["owner"] != "team-a" { - t.Errorf("Expected Labels are updated") - } - }) - - t.Run("Add/Get PolicyReport with ScopeResource", func(t *testing.T) { - _, err := store.Get(ctx, scopeReport.GetID()) - if err != sql.ErrNoRows { - t.Fatalf("Should not be found in empty Store") - } - - err = store.Add(ctx, scopeReport) - if err != nil { - t.Fatalf("Unexpected add error: %s", err) - } - - rep, err := store.Get(ctx, scopeReport.GetID()) - if err != nil { - t.Error("Should be found in Store after adding report to the store") - } - if len(rep.GetResults()) == 0 { - t.Fatal("Exptected at least one result on the report") - } - res := rep.GetResults()[0] - if !res.HasResource() { - t.Error("Expected scope resource set as result resource") - } - - store.Remove(ctx, rep.GetID()) - }) - - t.Run("Add/Get ClusterPolicyReport", func(t *testing.T) { - _, err := store.Get(ctx, creport.GetID()) - if err != sql.ErrNoRows { - t.Fatalf("Should not be found in empty Store") - } - - err = store.Add(ctx, creport) - if err != nil { - t.Fatalf("Failed to persist ClusterPolicyReport: %v", err) - } - - _, err = store.Get(ctx, creport.GetID()) - if err != nil { - t.Fatalf("Should be found in Store after adding report to the store") - } - }) - - t.Run("FetchPolicyReports", func(t *testing.T) { - items, err := store.FetchPolicyReports(ctx, v1.Filter{Namespaces: []string{"test"}, ReportLabel: map[string]string{"scope": "namespaced"}}, polrPagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return one policy report, got %d", len(items)) - } - }) - - t.Run("CountPolicyReports", func(t *testing.T) { - count, err := store.CountPolicyReports(ctx, v1.Filter{Namespaces: []string{"test"}, ReportLabel: map[string]string{"scope": "namespaced"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if count != 1 { - t.Fatalf("Should return one policy report, got %d", count) - } - }) - - t.Run("NamespacedGetLabels()", func(t *testing.T) { - items, err := store.FetchNamespacedReportLabels(ctx, v1.Filter{Sources: []string{"Kyverno"}, Namespaces: []string{"test"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 3 { - t.Fatalf("Should return 3 GetLabels() results") - } - - if len(items["scope"]) != 1 && items["scope"][0] != "namespaced" { - t.Fatalf("Should return cluster as scope value") - } - - if len(items["app"]) != 1 && items["app"][0] != "policy-reporter" { - t.Fatalf("Should return policy-reporter as app value") - } - - if len(items["owner"]) != 1 && items["owner"][0] != "team-a" { - t.Fatalf("Should return policy-reporter as app value") - } - }) - t.Run("FetchClusterReports", func(t *testing.T) { - items, err := store.FetchClusterPolicyReports(ctx, v1.Filter{ReportLabel: map[string]string{"scope": "cluster"}}, polrPagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return one policy report, got %d", len(items)) - } - }) - - t.Run("CountClusterReports", func(t *testing.T) { - items, err := store.CountClusterPolicyReports(ctx, v1.Filter{ReportLabel: map[string]string{"scope": "cluster"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if items != 1 { - t.Fatalf("Should return one policy report, got %d", items) - } - }) - - t.Run("ClusterGetLabels()", func(t *testing.T) { - items, err := store.FetchClusterReportLabels(ctx, v1.Filter{Sources: []string{"Kyverno"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 2 { - t.Fatalf("Should return 2 GetLabels() results") - } - - if len(items["scope"]) != 1 && items["scope"][0] != "cluster" { - t.Fatalf("Should return cluster as scope value") - } - - if len(items["app"]) != 1 && items["app"][0] != "policy-reporter" { - t.Fatalf("Should return policy-reporter as app value") - } - }) - - t.Run("FetchClusterPolicies", func(t *testing.T) { - items, err := store.FetchClusterPolicies(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should Find 1 cluster scoped policy, found %d", len(items)) - } - if items[0] != "require-ns-GetLabels()" { - t.Fatalf("Should return 'require-ns-GetLabels()' policy") - } - }) - - t.Run("FetchClusterRules", func(t *testing.T) { - items, err := store.FetchClusterRules(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should Find 1 cluster scoped rule, found %d", len(items)) - } - if items[0] != "check-for-GetLabels()-on-namespace" { - t.Fatalf("Should return 'check-for-GetLabels()-on-namespace' rule") - } - }) - - t.Run("FetchNamespacedPolicies", func(t *testing.T) { - items, err := store.FetchNamespacedPolicies(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Errorf("Should find 1 namespace scoped policy") - } - if items[0] != "require-requests-and-limits-required" { - t.Errorf("Should return 'require-requests-and-limits-required' policy") - } - }) - - t.Run("FetchNamespacedRules", func(t *testing.T) { - items, err := store.FetchNamespacedRules(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should find 1 namespace scoped policy, found %d", len(items)) - } - if items[0] != "autogen-check-for-requests-and-limits" { - t.Fatalf("Should return 'require-requests-and-limits-required' policy") - } - }) - - t.Run("FetchNamespacedResources", func(t *testing.T) { - items, err := store.FetchNamespacedResources(ctx, v1.Filter{Sources: []string{"Kyverno"}, Kinds: []string{"Pod"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should find 1 distinct resource with namespace Scope, got %d", len(items)) - } - if items[0].Name != "nginx" { - t.Errorf("Should return 'nginx' as first result, got %s", items[0].Name) - } - }) - - t.Run("FetchClusterResources", func(t *testing.T) { - items, err := store.FetchClusterResources(ctx, v1.Filter{Sources: []string{"Kyverno"}, Kinds: []string{"Namespace"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 2 { - t.Fatalf("Should find 2 resources with cluster scope") - } - if items[0].Name != "dev" { - t.Errorf("Should return 'test' as first result") - } - if items[1].Name != "test" { - t.Errorf("Should return 'test' as second result") - } - }) - - t.Run("FetchClusterSources", func(t *testing.T) { - items, err := store.FetchClusterSources(ctx) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Errorf("Should find 1 Source") - } - if items[0] != "Kyverno" { - t.Errorf("Should return Kyverno") - } - }) - - t.Run("FetchNamespacedSources", func(t *testing.T) { - items, err := store.FetchNamespacedSources(ctx) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Errorf("Should find 1 Source") - } - if items[0] != "Kyverno" { - t.Errorf("Should return Kyverno") - } - }) - - t.Run("FetchNamespaces", func(t *testing.T) { - items, err := store.FetchNamespaces(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatal("Should find 1 Namespace") - } - if items[0] != "test" { - t.Errorf("Should return test namespace") - } - }) - - t.Run("FetchNamespacedStatusCounts", func(t *testing.T) { - items, err := store.FetchNamespacedStatusCounts(ctx, v1.Filter{ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 5 { - t.Fatalf("Should include 1 item per possible status") - } - - var passed v1.NamespacedStatusCount - var failed v1.NamespacedStatusCount - for _, item := range items { - if item.Status == v1alpha2.StatusPass { - passed = item - } - if item.Status == v1alpha2.StatusFail { - failed = item - } - } - - if passed.Status != v1alpha2.StatusPass { - t.Errorf("Expected Pass Counts as first item") - } - if passed.Items[0].Count != 1 { - t.Errorf("Expected count to be one for pass") - } - - if failed.Status != v1alpha2.StatusFail { - t.Errorf("Expected Pass Counts as first item") - } - if failed.Items[0].Count != 1 { - t.Errorf("Expected count to be one for fail") - } - }) - - t.Run("FetchNamespacedStatusCounts with StatusFilter", func(t *testing.T) { - items, err := store.FetchNamespacedStatusCounts(ctx, v1.Filter{Status: []string{v1alpha2.StatusPass}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should have only 1 item for pass counts") - } - if items[0].Status != v1alpha2.StatusPass { - t.Errorf("Expected Pass Counts") - } - if items[0].Items[0].Count != 1 { - t.Errorf("Expected count to be one for pass") - } - }) - - t.Run("FetchClusterStatusCounts", func(t *testing.T) { - items, err := store.FetchClusterStatusCounts(ctx, v1.Filter{ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - var passed v1.StatusCount - var failed v1.StatusCount - for _, item := range items { - if item.Status == v1alpha2.StatusPass { - passed = item - } - if item.Status == v1alpha2.StatusFail { - failed = item - } - } - if len(items) != 5 { - t.Fatalf("Should include 1 item per possible status") - } - if passed.Count != 1 { - t.Errorf("Expected count to be one for pass") - } - if failed.Count != 1 { - t.Errorf("Expected count to be one for fail") - } - }) - - t.Run("FetchClusterStatusCounts with StatusFilter", func(t *testing.T) { - items, err := store.FetchClusterStatusCounts(ctx, v1.Filter{Status: []string{v1alpha2.StatusPass}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should have only 1 item for pass counts") - } - if items[0].Status != v1alpha2.StatusPass { - t.Errorf("Expected Pass Counts") - } - if items[0].Count != 1 { - t.Errorf("Expected count to be one for pass") - } - }) - - t.Run("FetchRuleStatusCounts", func(t *testing.T) { - items, err := store.FetchRuleStatusCounts(ctx, "require-requests-and-limits-required", "autogen-check-for-requests-and-limits") - var passed v1.StatusCount - var failed v1.StatusCount - for _, item := range items { - if item.Status == v1alpha2.StatusPass { - passed = item - } - if item.Status == v1alpha2.StatusFail { - failed = item - } - } - - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if passed.Count != 1 { - t.Errorf("Expected count to be one for pass") - } - - if failed.Count != 1 { - t.Errorf("Expected count to be one for fail") - } - }) - - t.Run("FetchNamespacedResults", func(t *testing.T) { - items, err := store.FetchNamespacedResults(ctx, v1.Filter{Namespaces: []string{"test"}}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 2 { - t.Fatalf("Should return 2 namespaced results") - } - }) - - t.Run("FetchNamespacedResults with SeverityFilter", func(t *testing.T) { - items, err := store.FetchNamespacedResults(ctx, v1.Filter{Severities: []string{v1alpha2.SeverityHigh}}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return 1 namespaced result") - } - if items[0].Severity != v1alpha2.SeverityHigh { - t.Fatalf("result with severity high") - } - }) - - t.Run("CountNamespacedResults", func(t *testing.T) { - count, err := store.CountNamespacedResults(ctx, v1.Filter{ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if count != 2 { - t.Fatalf("Should return 2 namespaced result") - } - }) - - t.Run("CountNamespacedResults with SeverityFilter", func(t *testing.T) { - count, err := store.CountNamespacedResults(ctx, v1.Filter{Severities: []string{v1alpha2.SeverityHigh}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if count != 1 { - t.Fatalf("Should return 1 namespaced result") - } - }) - - t.Run("FetchNamespacedResults with SearchFilter::Severity", func(t *testing.T) { - items, err := store.FetchNamespacedResults(ctx, v1.Filter{Search: v1alpha2.SeverityHigh}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return 1 namespaced result") - } - if items[0].Severity != v1alpha2.SeverityHigh { - t.Fatalf("result with severity high expected") - } - }) - - t.Run("FetchNamespacedResults with SearchFilter::Kind", func(t *testing.T) { - items, err := store.FetchNamespacedResults(ctx, v1.Filter{Search: "deployment"}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return 1 namespaced result, got %d", len(items)) - } - if items[0].Kind != "Deployment" { - t.Fatalf("result with kind Deployment expected") - } - }) - - t.Run("FetchClusterResults", func(t *testing.T) { - items, err := store.FetchClusterResults(ctx, v1.Filter{Status: []string{v1alpha2.StatusPass, v1alpha2.StatusFail}, ReportLabel: map[string]string{"app": "policy-reporter"}}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 2 { - t.Fatalf("Should return 2 cluster results") - } - }) - - t.Run("CountClusterResults", func(t *testing.T) { - count, err := store.CountClusterResults(ctx, v1.Filter{Status: []string{v1alpha2.StatusPass, v1alpha2.StatusFail}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if count != 2 { - t.Fatalf("Should return 2 cluster results") - } - }) - - t.Run("FetchClusterResults with SeverityFilter", func(t *testing.T) { - items, err := store.FetchClusterResults(ctx, v1.Filter{Severities: []string{v1alpha2.SeverityHigh}}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return 1 namespaced result") - } - if items[0].Severity != v1alpha2.SeverityHigh { - t.Fatalf("result with severity high") - } - }) - - t.Run("FetchClusterResults with SearchFilter", func(t *testing.T) { - items, err := store.FetchClusterResults(ctx, v1.Filter{Search: v1alpha2.SeverityHigh}, pagination) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - - if len(items) != 1 { - t.Fatalf("Should return 1 namespaced result") - } - if items[0].Severity != v1alpha2.SeverityHigh { - t.Fatalf("result with severity high") - } - }) - - t.Run("FetchNamespacedKinds", func(t *testing.T) { - items, err := store.FetchNamespacedKinds(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 2 { - t.Fatalf("Should Find 2 Kinds with Namespace Scope") - } - if items[0] != "Deployment" { - t.Errorf("Should return 'Deployment' as first result") - } - if items[1] != "Pod" { - t.Errorf("Should return 'Pod' as second result") - } - }) - - t.Run("FetchClusterKinds", func(t *testing.T) { - items, err := store.FetchClusterKinds(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Fatalf("Should find 1 kind with cluster scope") - } - if items[0] != "Namespace" { - t.Errorf("Should return 'Namespace' as first result") - } - }) - - t.Run("FetchNamespacedCategories", func(t *testing.T) { - items, err := store.FetchNamespacedCategories(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 2 { - t.Errorf("Should find 2 categories, got %d", len(items)) - } - if items[0] != "Best Practices" { - t.Errorf("Should return 'Best Practices' as first category") - } - }) - - t.Run("FetchClusterCategories", func(t *testing.T) { - items, err := store.FetchClusterCategories(ctx, v1.Filter{Sources: []string{"Kyverno"}, ReportLabel: map[string]string{"app": "policy-reporter"}}) - if err != nil { - t.Fatalf("Unexpected Error: %s", err) - } - if len(items) != 1 { - t.Errorf("Should find 1 category, got %d", len(items)) - } - if items[0] != "namespaces" { - t.Errorf("Should return 'Best Practices' as first category, get '%s'", items[0]) - } - }) - - err = store.CleanUp(ctx) - if err != nil { - t.Fatalf("Failed to cleanup policy reports: %v", err) - } -} diff --git a/pkg/database/model.go b/pkg/database/model.go index 4e195721..000e8a1b 100644 --- a/pkg/database/model.go +++ b/pkg/database/model.go @@ -6,8 +6,8 @@ import ( "github.com/segmentio/fasthash/fnv1a" "github.com/uptrace/bun" - api "github.com/kyverno/policy-reporter/pkg/api/v1" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/report" "github.com/kyverno/policy-reporter/pkg/report/result" ) @@ -44,11 +44,22 @@ type Resource struct { UID string } +func (r Resource) GetID() string { + h1 := fnv1a.Init64 + h1 = fnv1a.AddString64(h1, r.Namespace) + h1 = fnv1a.AddString64(h1, r.Name) + h1 = fnv1a.AddString64(h1, r.Kind) + h1 = fnv1a.AddString64(h1, r.APIVersion) + + return strconv.FormatUint(h1, 10) +} + type PolicyReportResult struct { bun.BaseModel `bun:"table:policy_report_result,alias:r" json:"-"` ID string `bun:",pk" json:"id"` - PolicyReportID string `bund:"policy_report_id" json:"-"` + PolicyReportID string `bun:"policy_report_id" json:"-"` + ResourceID string `bun:"resource_id"` Resource Resource `bun:"embed:resource_"` Policy string Rule string @@ -62,13 +73,34 @@ type PolicyReportResult struct { Created int64 } +type ResourceResult struct { + bun.BaseModel `bun:"table:policy_report_resource,alias:res" json:"-"` + + ID string `bun:",pk"` + PolicyReportID string `bun:"policy_report_id,pk"` + Resource Resource `bun:"embed:resource_"` + Source string `bun:",pk"` + Category string `bun:"category,pk"` + Pass int + Warn int + Fail int + Error int + Skip int + Info int + Low int + Medium int + High int + Critical int + Unknown int +} + type PolicyReportFilter struct { bun.BaseModel `bun:"table:policy_report_filter,alias:f"` - PolicyReportID string `bund:"policy_report_id"` - Namespace string + PolicyReportID string `bun:"policy_report_id"` + Namespace string `bun:"resource_namespace"` + Kind string `bun:"resource_kind"` Policy string - Kind string Result string Severity string Category string @@ -117,26 +149,29 @@ func MapPolicyReportResults(polr v1alpha2.ReportInterface) []*PolicyReportResult ns = polr.GetNamespace() } + resource := Resource{ + APIVersion: res.APIVersion, + Kind: res.Kind, + Name: res.Name, + Namespace: ns, + UID: string(res.UID), + } + list = append(list, &PolicyReportResult{ ID: r.GetID(), PolicyReportID: polr.GetID(), - Resource: Resource{ - APIVersion: res.APIVersion, - Kind: res.Kind, - Name: res.Name, - Namespace: ns, - UID: string(res.UID), - }, - Policy: r.Policy, - Rule: r.Rule, - Source: r.Source, - Scored: r.Scored, - Message: r.Message, - Result: string(r.Result), - Severity: string(r.Severity), - Category: r.Category, - Properties: r.Properties, - Created: r.Timestamp.Seconds, + ResourceID: resource.GetID(), + Resource: resource, + Policy: r.Policy, + Rule: r.Rule, + Source: r.Source, + Scored: r.Scored, + Message: r.Message, + Result: string(r.Result), + Severity: string(r.Severity), + Category: r.Category, + Properties: r.Properties, + Created: r.Timestamp.Seconds, }) } @@ -177,25 +212,93 @@ func MapPolicyReportFilter(polr v1alpha2.ReportInterface) []*PolicyReportFilter return list } -func MapListResult(results []*PolicyReportResult) []*api.ListResult { - list := make([]*api.ListResult, 0, len(results)) - for _, res := range results { - list = append(list, &api.ListResult{ - ID: res.ID, - Namespace: res.Resource.Namespace, - Kind: res.Resource.Kind, - APIVersion: res.Resource.APIVersion, - Name: res.Resource.Name, - Message: res.Message, - Category: res.Category, - Policy: res.Policy, - Rule: res.Rule, - Status: res.Result, - Severity: res.Severity, - Timestamp: res.Created, - Properties: res.Properties, - }) +func MapPolicyReportResource(polr v1alpha2.ReportInterface) []*ResourceResult { + mapping := make(map[string]*ResourceResult) + for _, res := range polr.GetResults() { + resource := polr.GetScope() + if res.HasResource() { + resource = res.GetResource() + } + + if resource == nil { + continue + } + + r := Resource{ + APIVersion: resource.APIVersion, + Kind: resource.Kind, + UID: string(resource.UID), + Namespace: resource.Namespace, + Name: resource.Name, + } + + id := r.GetID() + res.Category + polr.GetID() + + value, ok := mapping[id] + if !ok { + value = &ResourceResult{ + ID: r.GetID(), + PolicyReportID: polr.GetID(), + Resource: r, + Source: res.Source, + Category: res.Category, + } + + mapping[id] = value + } + + switch res.Result { + case v1alpha2.StatusPass: + value.Pass = value.Pass + 1 + case v1alpha2.StatusSkip: + value.Skip = value.Skip + 1 + case v1alpha2.StatusWarn: + value.Warn = value.Warn + 1 + case v1alpha2.StatusFail: + value.Fail = value.Fail + 1 + case v1alpha2.StatusError: + value.Error = value.Error + 1 + } + + switch res.Severity { + case v1alpha2.SeverityInfo: + value.Info = value.Info + 1 + case v1alpha2.SeverityLow: + value.Low = value.Low + 1 + case v1alpha2.SeverityMedium: + value.Medium = value.Medium + 1 + case v1alpha2.SeverityHigh: + value.High = value.High + 1 + case v1alpha2.SeverityCritical: + value.Critical = value.Critical + 1 + default: + value.Unknown = value.Unknown + 1 + } } - return list + return helper.ToList(mapping) +} + +type Filter struct { + Kinds []string + Categories []string + Namespaces []string + Sources []string + Policies []string + Rules []string + Severities []string + Status []string + Resources []string + ResourceID string + ReportLabel map[string]string + Exclude map[string][]string + Namespaced bool + Search string +} + +type Pagination struct { + Page int + Offset int + SortBy []string + Direction string } diff --git a/pkg/database/views.go b/pkg/database/views.go new file mode 100644 index 00000000..d05dc535 --- /dev/null +++ b/pkg/database/views.go @@ -0,0 +1,71 @@ +package database + +import "github.com/uptrace/bun" + +type Category struct { + bun.BaseModel `bun:"table:policy_report_filter,alias:f"` + + Source string + Name string `bun:"category"` + Result string + Severity string + Count int +} + +type ResourceCategory struct { + bun.BaseModel `bun:"table:policy_report_resource,alias:res"` + + Source string + Name string `bun:"category"` + Pass int + Warn int + Fail int + Error int + Skip int +} + +type ResourceStatusCount struct { + bun.BaseModel `bun:"table:policy_report_resource,alias:res"` + Source string + Pass int + Warn int + Fail int + Error int + Skip int +} + +type ResourceSeverityCount struct { + bun.BaseModel `bun:"table:policy_report_resource,alias:res"` + Source string + Info int + Low int + Medium int + High int + Critical int + Unknown int +} + +type StatusCount struct { + bun.BaseModel `bun:"table:policy_report_filter,alias:f"` + + Source string + Namespace string `bun:"resource_namespace"` + Status string + Count int +} + +type SeverityCount struct { + bun.BaseModel `bun:"table:policy_report_filter,alias:f"` + + Source string + Namespace string `bun:"resource_namespace"` + Severity string + Count int +} + +type ResultProperty struct { + bun.BaseModel `bun:"table:policy_report_result,alias:pr"` + + Namespace string `bun:"resource_namespace"` + Property string `bun:"property"` +} diff --git a/pkg/email/filter.go b/pkg/email/filter.go index 9f679fe3..bbfd9e40 100644 --- a/pkg/email/filter.go +++ b/pkg/email/filter.go @@ -1,22 +1,41 @@ package email import ( + "context" + + "go.uber.org/zap" + + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" "github.com/kyverno/policy-reporter/pkg/validate" ) type Filter struct { + client namespaces.Client namespace validate.RuleSets sources validate.RuleSets } func (f Filter) ValidateSource(source string) bool { - return validate.ContainsRuleSet(source, f.sources) + return validate.MatchRuleSet(source, f.sources) } func (f Filter) ValidateNamespace(namespace string) bool { - return validate.Namespace(namespace, f.namespace) + ruleset := f.namespace + + if len(f.namespace.Selector) > 0 { + list, err := f.client.List(context.Background(), f.namespace.Selector) + if err != nil { + zap.L().Error("failed to resolve namespace selector", zap.Error(err)) + } + + ruleset = validate.RuleSets{ + Include: list, + } + } + + return validate.Namespace(namespace, ruleset) } -func NewFilter(namespaces, sources validate.RuleSets) Filter { - return Filter{namespaces, sources} +func NewFilter(client namespaces.Client, namespaces, sources validate.RuleSets) Filter { + return Filter{client, namespaces, sources} } diff --git a/pkg/email/filter_test.go b/pkg/email/filter_test.go index 356f90d7..f1fc03a3 100644 --- a/pkg/email/filter_test.go +++ b/pkg/email/filter_test.go @@ -9,7 +9,7 @@ import ( func Test_Filters(t *testing.T) { t.Run("Validate Default", func(t *testing.T) { - filter := email.NewFilter(validate.RuleSets{}, validate.RuleSets{}) + filter := email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{}) if !filter.ValidateNamespace("test") { t.Errorf("Unexpected Validation Result without configured rules") diff --git a/pkg/email/summary/fixtures_test.go b/pkg/email/summary/fixtures_test.go index dbd17099..462854c0 100644 --- a/pkg/email/summary/fixtures_test.go +++ b/pkg/email/summary/fixtures_test.go @@ -10,7 +10,7 @@ import ( ) var ( - filter = email.NewFilter(validate.RuleSets{}, validate.RuleSets{}) + filter = email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{}) logger = zap.NewNop() ) diff --git a/pkg/email/summary/generator_test.go b/pkg/email/summary/generator_test.go index e473b42f..ce447412 100644 --- a/pkg/email/summary/generator_test.go +++ b/pkg/email/summary/generator_test.go @@ -81,7 +81,7 @@ func Test_GenerateDataWithSourceFilter(t *testing.T) { _, _ = cClient.Create(ctx, fixtures.EmptyClusterPolicyReport, v1.CreateOptions{}) _, _ = cClient.Create(ctx, fixtures.KyvernoClusterPolicyReport, v1.CreateOptions{}) - generator := summary.NewGenerator(client, email.NewFilter(validate.RuleSets{}, validate.RuleSets{Include: []string{"test"}}), true) + generator := summary.NewGenerator(client, email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{Include: []string{"test"}}), true) data, err := generator.GenerateData(ctx) if err != nil { @@ -113,7 +113,7 @@ func Test_FilterSourcesBySource(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = summary.FilterSources(data, email.NewFilter(validate.RuleSets{}, validate.RuleSets{Include: []string{"Kyverno"}}), true) + data = summary.FilterSources(data, email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{Include: []string{"Kyverno"}}), true) if len(data) != 1 { t.Fatalf("expected one source left, got: %d", len(data)) } @@ -139,7 +139,7 @@ func Test_FilterSourcesByNamespace(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = summary.FilterSources(data, email.NewFilter(validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), true) + data = summary.FilterSources(data, email.NewFilter(nil, validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), true) source := data[0] if source.Name != "Kyverno" { source = data[1] @@ -170,7 +170,7 @@ func Test_RemoveEmptySource(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = summary.FilterSources(data, email.NewFilter(validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), false) + data = summary.FilterSources(data, email.NewFilter(nil, validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), false) if len(data) != 1 { t.Fatalf("expected one source left, got: %d", len(data)) } diff --git a/pkg/email/violations/fixtures_test.go b/pkg/email/violations/fixtures_test.go index 77bc2c11..dc38ce7e 100644 --- a/pkg/email/violations/fixtures_test.go +++ b/pkg/email/violations/fixtures_test.go @@ -10,7 +10,7 @@ import ( ) var ( - filter = email.NewFilter(validate.RuleSets{}, validate.RuleSets{}) + filter = email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{}) logger = zap.NewNop() ) diff --git a/pkg/email/violations/generator_test.go b/pkg/email/violations/generator_test.go index 519b92a7..f9adbc88 100644 --- a/pkg/email/violations/generator_test.go +++ b/pkg/email/violations/generator_test.go @@ -105,7 +105,7 @@ func Test_GenerateDataWithSourceFilter(t *testing.T) { _, _ = cClient.Create(ctx, fixtures.EmptyClusterPolicyReport, v1.CreateOptions{}) _, _ = cClient.Create(ctx, fixtures.KyvernoClusterPolicyReport, v1.CreateOptions{}) - generator := violations.NewGenerator(client, email.NewFilter(validate.RuleSets{}, validate.RuleSets{Include: []string{"test"}}), true) + generator := violations.NewGenerator(client, email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{Include: []string{"test"}}), true) data, err := generator.GenerateData(ctx) if err != nil { @@ -137,7 +137,7 @@ func Test_FilterSourcesBySource(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = violations.FilterSources(data, email.NewFilter(validate.RuleSets{}, validate.RuleSets{Include: []string{"Kyverno"}}), true) + data = violations.FilterSources(data, email.NewFilter(nil, validate.RuleSets{}, validate.RuleSets{Include: []string{"Kyverno"}}), true) if len(data) != 1 { t.Fatalf("expected one source left, got: %d", len(data)) } @@ -163,7 +163,7 @@ func Test_FilterSourcesByNamespace(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = violations.FilterSources(data, email.NewFilter(validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), true) + data = violations.FilterSources(data, email.NewFilter(nil, validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), true) source := data[0] if source.Name != "Kyverno" { source = data[1] @@ -194,7 +194,7 @@ func Test_RemoveEmptySource(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - data = violations.FilterSources(data, email.NewFilter(validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), false) + data = violations.FilterSources(data, email.NewFilter(nil, validate.RuleSets{Exclude: []string{"kyverno"}}, validate.RuleSets{}), false) if len(data) != 1 { t.Fatalf("expected one source left, got: %d", len(data)) } diff --git a/pkg/fixtures/policy_reports.go b/pkg/fixtures/policy_reports.go index 398747bc..cde8a261 100644 --- a/pkg/fixtures/policy_reports.go +++ b/pkg/fixtures/policy_reports.go @@ -60,6 +60,7 @@ var DefaultPolicyReport = &v1alpha2.PolicyReport{ Scored: true, Policy: "priority-test", Timestamp: v1.Timestamp{Seconds: 1614093000}, + Source: "test", }, { ID: "12347", @@ -86,6 +87,42 @@ var DefaultPolicyReport = &v1alpha2.PolicyReport{ }, } +var ScopePolicyReport = &v1alpha2.PolicyReport{ + ObjectMeta: v1.ObjectMeta{ + Name: "policy-report", + Namespace: "test", + }, + Summary: v1alpha2.PolicyReportSummary{ + Pass: 0, + Skip: 0, + Warn: 0, + Fail: 3, + Error: 0, + }, + Scope: &corev1.ObjectReference{ + APIVersion: "v1", + Kind: "Deployment", + Name: "nginx", + Namespace: "test", + UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1", + }, + Results: []v1alpha2.PolicyReportResult{ + { + ID: "12348", + Message: "message", + Result: v1alpha2.StatusFail, + Scored: true, + Policy: "required-label", + Rule: "app-label-required", + Timestamp: v1.Timestamp{Seconds: 1614093000}, + Source: "test", + Category: "test", + Severity: v1alpha2.SeverityHigh, + Properties: map[string]string{"version": "1.2.0"}, + }, + }, +} + var MultiResourcePolicyReport = &v1alpha2.PolicyReport{ ObjectMeta: v1.ObjectMeta{ Name: "policy-report", diff --git a/pkg/fixtures/policy_results.go b/pkg/fixtures/policy_results.go index 83e5c231..b0b1f68d 100644 --- a/pkg/fixtures/policy_results.go +++ b/pkg/fixtures/policy_results.go @@ -11,7 +11,6 @@ var PassResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusPass, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -32,7 +31,6 @@ var PassPodResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusPass, Category: "Best Practices", Scored: true, @@ -52,7 +50,6 @@ var TrivyResult = v1alpha2.PolicyReportResult{ Message: "validation error", Policy: "policy", Rule: "rule", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Category: "Best Practices", Scored: true, @@ -64,7 +61,6 @@ var FailResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -84,7 +80,6 @@ var FailDisallowRuleResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "disallow-policy", Rule: "disallow-policy", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -104,7 +99,6 @@ var FailPodResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Category: "Best Practices", Scored: true, @@ -122,7 +116,6 @@ var FailResultWithoutResource = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -135,7 +128,6 @@ var PassNamespaceResult = v1alpha2.PolicyReportResult{ Message: "validation error: The label `test` is required. Rule check-for-GetLabels()-on-namespace", Policy: "require-ns-GetLabels()", Rule: "check-for-GetLabels()-on-namespace", - Priority: v1alpha2.ErrorPriority, Result: v1alpha2.StatusPass, Category: "namespaces", Severity: v1alpha2.SeverityMedium, @@ -154,7 +146,6 @@ var FailNamespaceResult = v1alpha2.PolicyReportResult{ Message: "validation error: The label `test` is required. Rule check-for-GetLabels()-on-namespace", Policy: "require-ns-GetLabels()", Rule: "check-for-GetLabels()-on-namespace", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Category: "namespaces", Severity: v1alpha2.SeverityHigh, @@ -172,7 +163,6 @@ var ScopeResult = v1alpha2.PolicyReportResult{ Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/", Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", diff --git a/pkg/fixtures/target_results.go b/pkg/fixtures/target_results.go index 06fbaefc..65399c06 100644 --- a/pkg/fixtures/target_results.go +++ b/pkg/fixtures/target_results.go @@ -16,7 +16,6 @@ var CompleteTargetSendResult = v1alpha2.PolicyReportResult{ Policy: "require-requests-and-limits-required", Rule: "autogen-check-for-requests-and-limits", Timestamp: v1.Timestamp{Seconds: seconds}, - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -33,11 +32,10 @@ var CompleteTargetSendResult = v1alpha2.PolicyReportResult{ } var MinimalTargetSendResult = v1alpha2.PolicyReportResult{ - Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "app-label-requirement", - Priority: v1alpha2.CriticalPriority, - Result: v1alpha2.StatusFail, - Scored: true, + Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", + Policy: "app-label-requirement", + Result: v1alpha2.StatusFail, + Scored: true, } var EnforceTargetSendResult = v1alpha2.PolicyReportResult{ @@ -45,7 +43,6 @@ var EnforceTargetSendResult = v1alpha2.PolicyReportResult{ Policy: "require-requests-and-limits-required", Rule: "check-for-requests-and-limits", Timestamp: v1.Timestamp{Seconds: seconds}, - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -66,7 +63,6 @@ var MissingUIDSendResult = v1alpha2.PolicyReportResult{ Policy: "require-requests-and-limits-required", Rule: "check-for-requests-and-limits", Timestamp: v1.Timestamp{Seconds: seconds}, - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -87,7 +83,6 @@ var MissingAPIVersionSendResult = v1alpha2.PolicyReportResult{ Policy: "require-requests-and-limits-required", Rule: "check-for-requests-and-limits", Timestamp: v1.Timestamp{Seconds: seconds}, - Priority: v1alpha2.WarningPriority, Result: v1alpha2.StatusFail, Severity: v1alpha2.SeverityHigh, Category: "resources", @@ -104,33 +99,29 @@ var MissingAPIVersionSendResult = v1alpha2.PolicyReportResult{ } var ErrorSendResult = v1alpha2.PolicyReportResult{ - Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "app-label-requirement", - Priority: v1alpha2.ErrorPriority, - Result: v1alpha2.StatusFail, - Scored: true, + Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", + Policy: "app-label-requirement", + Result: v1alpha2.StatusFail, + Scored: true, } var CritcalSendResult = v1alpha2.PolicyReportResult{ - Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "app-label-requirement", - Priority: v1alpha2.CriticalPriority, - Result: v1alpha2.StatusFail, - Scored: true, + Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", + Policy: "app-label-requirement", + Result: v1alpha2.StatusFail, + Scored: true, } var InfoSendResult = v1alpha2.PolicyReportResult{ - Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "app-label-requirement", - Priority: v1alpha2.InfoPriority, - Result: v1alpha2.StatusFail, - Scored: true, + Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", + Policy: "app-label-requirement", + Result: v1alpha2.StatusFail, + Scored: true, } var DebugSendResult = v1alpha2.PolicyReportResult{ - Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", - Policy: "app-label-requirement", - Priority: v1alpha2.DebugPriority, - Result: v1alpha2.StatusFail, - Scored: true, + Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/", + Policy: "app-label-requirement", + Result: v1alpha2.StatusFail, + Scored: true, } diff --git a/pkg/helper/chunk_slice.go b/pkg/helper/chunk_slice.go new file mode 100644 index 00000000..61d9f36a --- /dev/null +++ b/pkg/helper/chunk_slice.go @@ -0,0 +1,16 @@ +package helper + +func ChunkSlice[K interface{}](slice []K, chunkSize int) [][]K { + var chunks [][]K + for i := 0; i < len(slice); i += chunkSize { + end := i + chunkSize + + if end > len(slice) { + end = len(slice) + } + + chunks = append(chunks, slice[i:end]) + } + + return chunks +} diff --git a/pkg/helper/http_test.go b/pkg/helper/http_test.go new file mode 100644 index 00000000..169e3053 --- /dev/null +++ b/pkg/helper/http_test.go @@ -0,0 +1,43 @@ +package helper_test + +import ( + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/helper" +) + +func TestSendJSONResponse(t *testing.T) { + t.Run("success response", func(t *testing.T) { + w := httptest.NewRecorder() + + helper.SendJSONResponse(w, []string{"default", "user"}, nil) + + assert.Equal(t, http.StatusOK, w.Code) + + resp := make([]string, 0, 2) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, []string{"default", "user"}, resp) + }) + + t.Run("error response", func(t *testing.T) { + w := httptest.NewRecorder() + + helper.SendJSONResponse(w, nil, errors.New("error")) + + assert.Equal(t, http.StatusInternalServerError, w.Code) + + resp := make(map[string]string, 0) + + json.NewDecoder(w.Body).Decode(&resp) + + assert.Equal(t, map[string]string{"message": "error"}, resp) + }) +} diff --git a/pkg/helper/title.go b/pkg/helper/title.go new file mode 100644 index 00000000..471876f5 --- /dev/null +++ b/pkg/helper/title.go @@ -0,0 +1,12 @@ +package helper + +import ( + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +var caser = cases.Title(language.English, cases.NoLower) + +func Title(s string) string { + return caser.String(s) +} diff --git a/pkg/helper/utils.go b/pkg/helper/utils.go index d8ade1f5..a4af84ce 100644 --- a/pkg/helper/utils.go +++ b/pkg/helper/utils.go @@ -1,6 +1,8 @@ package helper -import "strings" +import ( + "strings" +) func Contains(source string, sources []string) bool { for _, s := range sources { @@ -12,6 +14,44 @@ func Contains(source string, sources []string) bool { return false } +func ToList[T any, R comparable](mapping map[R]T) []T { + list := make([]T, 0, len(mapping)) + for _, i := range mapping { + list = append(list, i) + } + + return list +} + +func Map[T any, R any](source []T, cb func(T) R) []R { + list := make([]R, 0, len(source)) + for _, i := range source { + list = append(list, cb(i)) + } + + return list +} + +func MapSlice[T any, R any, Z comparable](source map[Z]T, cb func(T) R) []R { + list := make([]R, 0, len(source)) + for _, i := range source { + list = append(list, cb(i)) + } + + return list +} + +func ConvertMap(m map[string]any) map[string]string { + n := make(map[string]string, len(m)) + for k, v := range m { + if l, ok := v.(string); ok { + n[k] = l + } + } + + return n +} + func Defaults(s, f string) string { if s != "" { return s @@ -19,3 +59,26 @@ func Defaults(s, f string) string { return f } + +func ToPointer[T any](s T) *T { + return &s +} + +func Filter[T any](s []T, keep func(T) bool) []T { + d := make([]T, 0, len(s)) + for _, n := range s { + if keep(n) { + d = append(d, n) + } + } + return d +} + +func Find[T any](s []T, keep func(T) bool, fallback T) T { + for _, n := range s { + if keep(n) { + return n + } + } + return fallback +} diff --git a/pkg/helper/utils_test.go b/pkg/helper/utils_test.go new file mode 100644 index 00000000..d11aa639 --- /dev/null +++ b/pkg/helper/utils_test.go @@ -0,0 +1,75 @@ +package helper_test + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/helper" +) + +func TestContains(t *testing.T) { + assert.True(t, helper.Contains("kyverno", []string{"test", "kyverno", "trivy"})) + assert.False(t, helper.Contains("kube-bench", []string{"test", "kyverno", "trivy"})) +} + +func TestToList(t *testing.T) { + result := helper.ToList(map[string]string{ + "first": "kyverno", + "second": "trivy", + }) + + assert.Equal(t, 2, len(result)) + assert.Contains(t, result, "kyverno") + assert.Contains(t, result, "trivy") +} + +func TestMap(t *testing.T) { + assert.Equal(t, []string{"kyverno", "trivy"}, helper.Map([]string{"source_kyverno", "source_trivy"}, func(value string) string { + return strings.TrimPrefix(value, "source_") + })) +} + +func TestConvertMap(t *testing.T) { + assert.Equal(t, map[string]string{"first": "kyverno", "second": "trivy"}, helper.ConvertMap(map[string]any{ + "first": "kyverno", + "second": "trivy", + "third": 3, + })) +} + +func TestDetauls(t *testing.T) { + assert.Equal(t, "fallback", helper.Defaults("", "fallback")) + assert.Equal(t, "value", helper.Defaults("value", "fallback")) +} + +func TestToPointer(t *testing.T) { + value := "test" + number := 5 + + assert.Equal(t, &value, helper.ToPointer(value)) + assert.Equal(t, &number, helper.ToPointer(number)) +} + +func TestFind(t *testing.T) { + list := []string{"test", "find", "item"} + + assert.Equal(t, "find", helper.Find(list, func(t string) bool { return t == "find" }, "")) + assert.Equal(t, "fallback", helper.Find(list, func(t string) bool { return t == "invalid" }, "fallback")) +} + +func TestMapSlice(t *testing.T) { + mapped := helper.MapSlice(map[int]string{2: "source_kyverno", 3: "source_trivy"}, func(value string) string { + return strings.TrimPrefix(value, "source_") + }) + + assert.Contains(t, mapped, "kyverno") + assert.Contains(t, mapped, "trivy") +} + +func TestFilter(t *testing.T) { + list := []string{"test", "find", "item", "", ""} + + assert.Equal(t, []string{"test", "find", "item"}, helper.Filter(list, func(t string) bool { return t != "" })) +} diff --git a/pkg/kubernetes/jobs/client.go b/pkg/kubernetes/jobs/client.go new file mode 100644 index 00000000..1de8709a --- /dev/null +++ b/pkg/kubernetes/jobs/client.go @@ -0,0 +1,32 @@ +package jobs + +import ( + "context" + + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/kubernetes/typed/batch/v1" + + "github.com/kyverno/policy-reporter/pkg/kubernetes" +) + +type Client interface { + Get(scope *corev1.ObjectReference) (*batchv1.Job, error) +} + +type k8sClient struct { + client v1.BatchV1Interface +} + +func (c *k8sClient) Get(scope *corev1.ObjectReference) (*batchv1.Job, error) { + return kubernetes.Retry(func() (*batchv1.Job, error) { + return c.client.Jobs(scope.Namespace).Get(context.Background(), scope.Name, metav1.GetOptions{}) + }) +} + +func NewClient(client v1.BatchV1Interface) Client { + return &k8sClient{ + client: client, + } +} diff --git a/pkg/kubernetes/namespaces/client.go b/pkg/kubernetes/namespaces/client.go new file mode 100644 index 00000000..c07b9dca --- /dev/null +++ b/pkg/kubernetes/namespaces/client.go @@ -0,0 +1,54 @@ +package namespaces + +import ( + "context" + + gocache "github.com/patrickmn/go-cache" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/kubernetes" +) + +type Client interface { + List(context.Context, map[string]string) ([]string, error) +} + +type k8sClient struct { + client v1.NamespaceInterface + cache *gocache.Cache +} + +func (c *k8sClient) List(ctx context.Context, selector map[string]string) ([]string, error) { + labelSelector := metav1.FormatLabelSelector(&metav1.LabelSelector{MatchLabels: selector}) + if cached, ok := c.cache.Get(labelSelector); ok { + return cached.([]string), nil + } + + list, err := kubernetes.Retry(func() ([]string, error) { + namespaces, err := c.client.List(ctx, metav1.ListOptions{LabelSelector: labelSelector}) + if err != nil { + return nil, err + } + + return helper.Map(namespaces.Items, func(ns corev1.Namespace) string { + return ns.Name + }), nil + }) + if err != nil { + return nil, err + } + + c.cache.Set(labelSelector, list, 0) + + return list, nil +} + +func NewClient(secretClient v1.NamespaceInterface, cache *gocache.Cache) Client { + return &k8sClient{ + client: secretClient, + cache: cache, + } +} diff --git a/pkg/kubernetes/namespaces/client_test.go b/pkg/kubernetes/namespaces/client_test.go new file mode 100644 index 00000000..310c2db7 --- /dev/null +++ b/pkg/kubernetes/namespaces/client_test.go @@ -0,0 +1,100 @@ +package namespaces_test + +import ( + "context" + "errors" + "testing" + + gocache "github.com/patrickmn/go-cache" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" +) + +func newFakeClient() v1.NamespaceInterface { + return fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + Labels: map[string]string{ + "team": "team-a", + "name": "default", + }, + }, + }, + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user", + Labels: map[string]string{ + "team": "team-a", + "name": "user", + }, + }, + }, + ).CoreV1().Namespaces() +} + +type nsErrorClient struct { + v1.NamespaceInterface +} + +func (s *nsErrorClient) List(ctx context.Context, opts metav1.ListOptions) (*corev1.NamespaceList, error) { + return nil, errors.New("error") +} + +func TestClient(t *testing.T) { + t.Run("read from api", func(t *testing.T) { + client := namespaces.NewClient(newFakeClient(), gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration)) + + list, err := client.List(context.Background(), map[string]string{"name": "default"}) + + assert.Nil(t, err) + assert.Equal(t, 1, len(list)) + }) + + t.Run("read from cache", func(t *testing.T) { + fake := newFakeClient() + cache := gocache.New(gocache.NoExpiration, gocache.NoExpiration) + + client := namespaces.NewClient(fake, cache) + + list, err := client.List(context.Background(), map[string]string{"team": "team-a"}) + + assert.Nil(t, err) + assert.Equal(t, 2, len(list)) + + fake.Create(context.Background(), &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "finance", + Labels: map[string]string{ + "team": "team-a", + "name": "finance", + }, + }, + }, metav1.CreateOptions{}) + + list, err = client.List(context.Background(), map[string]string{"team": "team-a"}) + + assert.Nil(t, err) + assert.Equal(t, 2, len(list)) + + cache.Flush() + + list, err = client.List(context.Background(), map[string]string{"team": "team-a"}) + + assert.Nil(t, err) + assert.Equal(t, 3, len(list)) + }) + t.Run("return error", func(t *testing.T) { + client := namespaces.NewClient(&nsErrorClient{NamespaceInterface: newFakeClient()}, gocache.New(gocache.DefaultExpiration, gocache.DefaultExpiration)) + + _, err := client.List(context.Background(), map[string]string{"team": "team-a"}) + + assert.NotNil(t, err) + assert.Equal(t, "error", err.Error()) + }) +} diff --git a/pkg/kubernetes/pods/client.go b/pkg/kubernetes/pods/client.go new file mode 100644 index 00000000..36bc101a --- /dev/null +++ b/pkg/kubernetes/pods/client.go @@ -0,0 +1,31 @@ +package pods + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/kubernetes" +) + +type Client interface { + Get(scope *corev1.ObjectReference) (*corev1.Pod, error) +} + +type k8sClient struct { + client v1.CoreV1Interface +} + +func (c *k8sClient) Get(scope *corev1.ObjectReference) (*corev1.Pod, error) { + return kubernetes.Retry(func() (*corev1.Pod, error) { + return c.client.Pods(scope.Namespace).Get(context.Background(), scope.Name, metav1.GetOptions{}) + }) +} + +func NewClient(client v1.CoreV1Interface) Client { + return &k8sClient{ + client: client, + } +} diff --git a/pkg/kubernetes/policy_report_client.go b/pkg/kubernetes/policy_report_client.go index 44435ec2..e4a65f03 100644 --- a/pkg/kubernetes/policy_report_client.go +++ b/pkg/kubernetes/policy_report_client.go @@ -25,7 +25,7 @@ type k8sPolicyReportClient struct { metaClient metadata.Interface synced bool mx *sync.Mutex - reportFilter *report.Filter + reportFilter *report.MetaFilter stopChan chan struct{} } @@ -110,7 +110,7 @@ func (k *k8sPolicyReportClient) configureInformer(informer cache.SharedIndexInfo } // NewPolicyReportClient new Client for Policy Report Kubernetes API -func NewPolicyReportClient(metaClient metadata.Interface, reportFilter *report.Filter, queue *Queue) report.PolicyReportClient { +func NewPolicyReportClient(metaClient metadata.Interface, reportFilter *report.MetaFilter, queue *Queue) report.PolicyReportClient { return &k8sPolicyReportClient{ metaClient: metaClient, mx: &sync.Mutex{}, diff --git a/pkg/kubernetes/policy_report_client_test.go b/pkg/kubernetes/policy_report_client_test.go index 72e3d281..4bde24eb 100644 --- a/pkg/kubernetes/policy_report_client_test.go +++ b/pkg/kubernetes/policy_report_client_test.go @@ -16,7 +16,7 @@ import ( "github.com/kyverno/policy-reporter/pkg/validate" ) -var filter = report.NewFilter(false, validate.RuleSets{}) +var filter = report.NewMetaFilter(false, validate.RuleSets{}) func Test_PolicyReportWatcher(t *testing.T) { ctx := context.Background() @@ -37,8 +37,9 @@ func Test_PolicyReportWatcher(t *testing.T) { queue := kubernetes.NewQueue( kubernetes.NewDebouncer(0, publisher), - workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "test-queue"), + workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[string]()), restClient.Wgpolicyk8sV1alpha2(), + report.NewSourceFilter(nil, nil, []report.SourceValidation{}), result.NewReconditioner(nil), ) @@ -88,8 +89,9 @@ func Test_ClusterPolicyReportWatcher(t *testing.T) { queue := kubernetes.NewQueue( kubernetes.NewDebouncer(0, publisher), - workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "test-queue"), + workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[string]()), restClient.Wgpolicyk8sV1alpha2(), + report.NewSourceFilter(nil, nil, []report.SourceValidation{}), result.NewReconditioner(nil), ) @@ -129,8 +131,9 @@ func Test_HasSynced(t *testing.T) { queue := kubernetes.NewQueue( kubernetes.NewDebouncer(0, report.NewEventPublisher()), - workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "test-queue"), + workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[string]()), restClient.Wgpolicyk8sV1alpha2(), + report.NewSourceFilter(nil, nil, []report.SourceValidation{}), result.NewReconditioner(nil), ) diff --git a/pkg/kubernetes/queue.go b/pkg/kubernetes/queue.go index e1b81aa9..fdd62235 100644 --- a/pkg/kubernetes/queue.go +++ b/pkg/kubernetes/queue.go @@ -21,12 +21,13 @@ import ( ) type Queue struct { - queue workqueue.RateLimitingInterface + queue workqueue.TypedRateLimitingInterface[string] client v1alpha2.Wgpolicyk8sV1alpha2Interface reconditioner *result.Reconditioner debouncer Debouncer lock *sync.Mutex cache sets.Set[string] + filter *report.SourceFilter } func (q *Queue) Add(obj *v1.PartialObjectMetadata) error { @@ -56,11 +57,10 @@ func (q *Queue) runWorker() { } func (q *Queue) processNextItem() bool { - obj, quit := q.queue.Get() + key, quit := q.queue.Get() if quit { return false } - key := obj.(string) defer q.queue.Done(key) namespace, name, err := cache.SplitMetaNamespaceKey(key) @@ -103,6 +103,10 @@ func (q *Queue) processNextItem() bool { return true } + if ok := q.filter.Validate(polr); !ok { + return true + } + event := func() report.Event { q.lock.Lock() defer q.lock.Unlock() @@ -122,7 +126,7 @@ func (q *Queue) processNextItem() bool { return true } -func (q *Queue) handleErr(err error, key interface{}) { +func (q *Queue) handleErr(err error, key string) { if err == nil { q.queue.Forget(key) return @@ -143,8 +147,9 @@ func (q *Queue) handleErr(err error, key interface{}) { func NewQueue( debouncer Debouncer, - queue workqueue.RateLimitingInterface, + queue workqueue.TypedRateLimitingInterface[string], client v1alpha2.Wgpolicyk8sV1alpha2Interface, + filter *report.SourceFilter, reconditioner *result.Reconditioner, ) *Queue { return &Queue{ @@ -153,6 +158,7 @@ func NewQueue( client: client, cache: sets.New[string](), lock: &sync.Mutex{}, + filter: filter, reconditioner: reconditioner, } } diff --git a/pkg/kubernetes/retry.go b/pkg/kubernetes/retry.go new file mode 100644 index 00000000..33488e82 --- /dev/null +++ b/pkg/kubernetes/retry.go @@ -0,0 +1,41 @@ +package kubernetes + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/util/retry" +) + +func Retry[T any](cb func() (T, error)) (T, error) { + var value T + + err := retry.OnError(retry.DefaultRetry, func(err error) bool { + if _, ok := err.(errors.APIStatus); !ok { + return true + } + + if ok := errors.IsTimeout(err); ok { + return true + } + + if ok := errors.IsServerTimeout(err); ok { + return true + } + + if ok := errors.IsServiceUnavailable(err); ok { + return true + } + + return false + }, func() error { + v, err := cb() + if err != nil { + return err + } + + value = v + + return nil + }) + + return value, err +} diff --git a/pkg/kubernetes/retry_test.go b/pkg/kubernetes/retry_test.go new file mode 100644 index 00000000..ce7fb936 --- /dev/null +++ b/pkg/kubernetes/retry_test.go @@ -0,0 +1,152 @@ +package kubernetes_test + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + kerr "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/kubernetes" +) + +func newFakeClient() v1.NamespaceInterface { + return fake.NewSimpleClientset( + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + Labels: map[string]string{ + "team": "team-a", + "name": "default", + }, + }, + }, + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "user", + Labels: map[string]string{ + "team": "team-a", + "name": "user", + }, + }, + }, + ).CoreV1().Namespaces() +} + +type ns struct { + maxRetry int + try int + err bool + v1.NamespaceInterface +} + +func (s *ns) List(ctx context.Context, opts metav1.ListOptions) (*corev1.NamespaceList, error) { + if !s.err { + if s.try >= s.maxRetry { + return s.NamespaceInterface.List(ctx, opts) + } + + s.try++ + } + + return nil, errors.New("error") +} + +func TestRetry(t *testing.T) { + t.Run("direct success", func(t *testing.T) { + client := &ns{NamespaceInterface: newFakeClient()} + + list, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { + return client.List(context.Background(), metav1.ListOptions{}) + }) + + assert.Nil(t, err) + assert.Equal(t, 2, len(list.Items)) + }) + + t.Run("retry success", func(t *testing.T) { + client := &ns{maxRetry: 1, NamespaceInterface: newFakeClient()} + + list, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { + return client.List(context.Background(), metav1.ListOptions{}) + }) + + assert.Nil(t, err) + assert.Equal(t, 2, len(list.Items)) + }) + + t.Run("retry error", func(t *testing.T) { + client := &ns{NamespaceInterface: newFakeClient(), err: true} + + _, err := kubernetes.Retry(func() (*corev1.NamespaceList, error) { + return client.List(context.Background(), metav1.ListOptions{}) + }) + + assert.NotNil(t, err) + }) + + t.Run("retry timeout", func(t *testing.T) { + try := 0 + + _, err := kubernetes.Retry(func() (any, error) { + try++ + + return nil, &kerr.StatusError{ + ErrStatus: metav1.Status{Reason: metav1.StatusReasonTimeout}, + } + }) + + assert.Equal(t, 5, try) + assert.NotNil(t, err) + }) + + t.Run("retry server timeout", func(t *testing.T) { + try := 0 + + _, err := kubernetes.Retry(func() (any, error) { + try++ + + return nil, &kerr.StatusError{ + ErrStatus: metav1.Status{Reason: metav1.StatusReasonServerTimeout}, + } + }) + + assert.Equal(t, 5, try) + assert.NotNil(t, err) + }) + + t.Run("retry service unavailable", func(t *testing.T) { + try := 0 + + _, err := kubernetes.Retry(func() (any, error) { + try++ + + return nil, &kerr.StatusError{ + ErrStatus: metav1.Status{Reason: metav1.StatusReasonServiceUnavailable}, + } + }) + + assert.Equal(t, 5, try) + assert.NotNil(t, err) + }) + + t.Run("retry ignore other status", func(t *testing.T) { + try := 0 + + _, err := kubernetes.Retry(func() (any, error) { + try++ + + return nil, &kerr.StatusError{ + ErrStatus: metav1.Status{Reason: metav1.StatusReasonForbidden}, + } + }) + + assert.Equal(t, 1, try) + assert.NotNil(t, err) + }) +} diff --git a/pkg/kubernetes/secrets/client.go b/pkg/kubernetes/secrets/client.go index f9a75497..21e0f9ca 100644 --- a/pkg/kubernetes/secrets/client.go +++ b/pkg/kubernetes/secrets/client.go @@ -2,14 +2,13 @@ package secrets import ( "context" - "strconv" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/client-go/util/retry" + + "github.com/kyverno/policy-reporter/pkg/kubernetes" ) type Values struct { @@ -19,9 +18,9 @@ type Values struct { Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` APIKey string `json:"apiKey,omitempty"` - AccessKeyID string `json:"accessKeyID,omitempty"` + AccessKeyID string `json:"accessKeyId,omitempty"` SecretAccessKey string `json:"secretAccessKey,omitempty"` - AccountID string `json:"accountID,omitempty"` + AccountID string `json:"accountId,omitempty"` KmsKeyID string `json:"kmsKeyId,omitempty"` Token string `json:"token,omitempty"` Credentials string `json:"credentials,omitempty"` @@ -39,31 +38,8 @@ type k8sClient struct { } func (c *k8sClient) Get(ctx context.Context, name string) (Values, error) { - var secret *corev1.Secret - - err := retry.OnError(retry.DefaultRetry, func(err error) bool { - if _, ok := err.(errors.APIStatus); !ok { - return true - } - - if ok := errors.IsTimeout(err); ok { - return true - } - - if ok := errors.IsServerTimeout(err); ok { - return true - } - - if ok := errors.IsServiceUnavailable(err); ok { - return true - } - - return false - }, func() error { - var err error - secret, err = c.client.Get(ctx, name, metav1.GetOptions{}) - - return err + secret, err := kubernetes.Retry(func() (*corev1.Secret, error) { + return c.client.Get(ctx, name, metav1.GetOptions{}) }) values := Values{} @@ -103,7 +79,7 @@ func (c *k8sClient) Get(ctx context.Context, name string) (Values, error) { values.DSN = string(dsn) } - if accessKeyID, ok := secret.Data["accessKeyID"]; ok { + if accessKeyID, ok := secret.Data["accessKeyId"]; ok { values.AccessKeyID = string(accessKeyID) } @@ -115,7 +91,7 @@ func (c *k8sClient) Get(ctx context.Context, name string) (Values, error) { values.KmsKeyID = string(kmsKeyID) } - if accountID, ok := secret.Data["accountID"]; ok { + if accountID, ok := secret.Data["accountId"]; ok { values.AccountID = string(accountID) } diff --git a/pkg/kubernetes/secrets/client_test.go b/pkg/kubernetes/secrets/client_test.go index 8d2864c8..2aa61dd8 100644 --- a/pkg/kubernetes/secrets/client_test.go +++ b/pkg/kubernetes/secrets/client_test.go @@ -27,11 +27,11 @@ func newFakeClient() v1.SecretInterface { "password": []byte("password"), "apiKey": []byte("apiKey"), "webhook": []byte("http://localhost:9200/webhook"), - "accessKeyID": []byte("accessKeyID"), + "accessKeyId": []byte("accessKeyId"), "secretAccessKey": []byte("secretAccessKey"), "kmsKeyId": []byte("kmsKeyId"), "token": []byte("token"), - "accountID": []byte("accountID"), + "accountId": []byte("accountId"), "database": []byte("database"), "dsn": []byte("dsn"), "typelessApi": []byte("false"), @@ -68,7 +68,7 @@ func Test_Client(t *testing.T) { t.Errorf("Unexpected ApiKey: %s", values.APIKey) } - if values.AccessKeyID != "accessKeyID" { + if values.AccessKeyID != "accessKeyId" { t.Errorf("Unexpected AccessKeyID: %s", values.AccessKeyID) } @@ -84,8 +84,8 @@ func Test_Client(t *testing.T) { t.Errorf("Unexpected KmsKeyId: %s", values.KmsKeyID) } - if values.AccountID != "accountID" { - t.Errorf("Unexpected AccountID: %s", values.AccountID) + if values.AccountID != "accountId" { + t.Errorf("Unexpected accountId: %s", values.AccountID) } if values.Database != "database" { @@ -97,7 +97,7 @@ func Test_Client(t *testing.T) { } if values.TypelessAPI { - t.Errorf("Unexpected TypelessApi: %t", values.TypelessAPI) + t.Errorf("Unexpected TypelessAPI: %t", values.TypelessAPI) } }) diff --git a/pkg/kubernetes/secrets/informer.go b/pkg/kubernetes/secrets/informer.go new file mode 100644 index 00000000..dacda08e --- /dev/null +++ b/pkg/kubernetes/secrets/informer.go @@ -0,0 +1,122 @@ +package secrets + +import ( + "fmt" + "sync" + "time" + + "go.uber.org/zap" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/metadata" + "k8s.io/client-go/metadata/metadatainformer" + "k8s.io/client-go/tools/cache" + + "github.com/kyverno/policy-reporter/pkg/target" +) + +type Informer interface { + Sync(targets *target.Collection, stopper chan struct{}) error + HasSynced() bool +} + +type informer struct { + metaClient metadata.Interface + synced bool + mx *sync.Mutex + stopChan chan struct{} + factory target.Factory + namespace string +} + +func (k *informer) HasSynced() bool { + return k.synced +} + +func (k *informer) Sync(targets *target.Collection, stopper chan struct{}) error { + k.stopChan = stopper + + factory := metadatainformer.NewFilteredSharedInformerFactory(k.metaClient, 15*time.Minute, k.namespace, nil) + + informer := k.configureInformer(targets, factory.ForResource(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}).Informer()) + + factory.Start(stopper) + + if informer != nil && !cache.WaitForCacheSync(stopper, informer.HasSynced) { + return fmt.Errorf("failed to sync secrets") + } + + k.synced = true + + zap.L().Info("secret informer sync completed") + + return nil +} + +func (k *informer) configureInformer(targets *target.Collection, informer cache.SharedIndexInformer) cache.SharedIndexInformer { + informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + UpdateFunc: func(_, newObj interface{}) { + if s, ok := newObj.(*v1.PartialObjectMetadata); ok { + for _, t := range targets.Targets() { + if t.Secret() == s.Name { + targets.Update(k.UpdateTarget(t, s.Name)) + } + } + } + }, + }) + + informer.SetWatchErrorHandler(func(_ *cache.Reflector, _ error) { + k.synced = false + }) + + return informer +} + +func (k *informer) UpdateTarget(t *target.Target, secret string) *target.Target { + updatedTarget := t + switch t.Type { + case target.Loki: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateLokiTarget) + case target.Elasticsearch: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateLokiTarget) + case target.Slack: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateSlackTarget) + case target.Discord: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateDiscordTarget) + case target.Teams: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateTeamsTarget) + case target.Webhook: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateWebhookTarget) + case target.Telegram: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateTelegramTarget) + case target.GoogleChat: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateGoogleChatTarget) + case target.S3: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateS3Target) + case target.Kinesis: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateKinesisTarget) + case target.SecurityHub: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateSecurityHubTarget) + case target.GCS: + updatedTarget = createClients(t.Config, t.ParentConfig, k.factory.CreateGCSTarget) + } + + updatedTarget.ID = t.ID + + return updatedTarget +} + +// NewPolicyReportClient new Client for Policy Report Kubernetes API +func NewInformer(metaClient metadata.Interface, factory target.Factory, namespace string) Informer { + return &informer{ + metaClient: metaClient, + mx: new(sync.Mutex), + factory: factory, + namespace: namespace, + } +} + +func createClients[T any](config, parent any, mapper func(*target.Config[T], *target.Config[T]) *target.Target) *target.Target { + return mapper(config.(*target.Config[T]), parent.(*target.Config[T])) +} diff --git a/pkg/kubernetes/secrets/informer_test.go b/pkg/kubernetes/secrets/informer_test.go new file mode 100644 index 00000000..c7fd4bc8 --- /dev/null +++ b/pkg/kubernetes/secrets/informer_test.go @@ -0,0 +1,67 @@ +package secrets_test + +import ( + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + metafake "k8s.io/client-go/metadata/fake" + + "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" + "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/factory" + "github.com/kyverno/policy-reporter/pkg/target/webhook" +) + +func NewFakeMetaClient() (*metafake.FakeMetadataClient, metafake.MetadataClient) { + s := metafake.NewTestScheme() + metav1.AddMetaToScheme(s) + + client := metafake.NewSimpleMetadataClient(s) + return client, client.Resource(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}).Namespace("default").(metafake.MetadataClient) +} + +func Test_SecretInformer(t *testing.T) { + stop := make(chan struct{}) + defer close(stop) + + t.Run("update secretRef", func(t *testing.T) { + collection := target.NewCollection( + &target.Target{ + ID: uuid.NewString(), + Type: target.Webhook, + Client: webhook.NewClient(webhook.Options{ + ClientOptions: target.ClientOptions{ + Name: "Webhook", + }, + }), + Config: &target.Config[target.WebhookOptions]{ + Name: "Webhook", + SecretRef: secretName, + Config: &target.WebhookOptions{}, + }, + ParentConfig: &target.Config[target.WebhookOptions]{Config: &target.WebhookOptions{}}, + }, + ) + + client, secret := NewFakeMetaClient() + + informer := secrets.NewInformer(client, factory.NewFactory(secrets.NewClient(newFakeClient()), target.NewResultFilterFactory(nil)), "default") + + err := informer.Sync(collection, stop) + assert.Nil(t, err) + + assert.True(t, informer.HasSynced()) + + secret.CreateFake(&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: "default"}}, metav1.CreateOptions{}) + time.Sleep(1 * time.Second) + + secret.UpdateFake(&metav1.PartialObjectMetadata{ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: "default"}}, metav1.UpdateOptions{}) + time.Sleep(1 * time.Second) + + assert.Equal(t, collection.Targets()[0].Config.(*target.Config[target.WebhookOptions]).Config.Webhook, "http://localhost:9200/webhook") + }) +} diff --git a/pkg/leaderelection/client.go b/pkg/leaderelection/client.go index 6444a9cd..76b02d80 100644 --- a/pkg/leaderelection/client.go +++ b/pkg/leaderelection/client.go @@ -45,7 +45,13 @@ func (c *Client) RegisterOnNew(callback func(currentID string, lockID string)) * } func (c *Client) Run(ctx context.Context) error { - k8sleaderelection.RunOrDie(ctx, k8sleaderelection.LeaderElectionConfig{ + k8sleaderelection.RunOrDie(ctx, c.CreateConfig()) + + return errors.New("leaderelection stopped") +} + +func (c *Client) CreateConfig() k8sleaderelection.LeaderElectionConfig { + return k8sleaderelection.LeaderElectionConfig{ Lock: c.CreateLock(), ReleaseOnCancel: c.releaseOnCancel, LeaseDuration: c.leaseDuration, @@ -58,9 +64,7 @@ func (c *Client) Run(ctx context.Context) error { c.onNewLeader(identity, c.identity) }, }, - }) - - return errors.New("leaderelection stopped") + } } func (c *Client) CreateLock() *resourcelock.LeaseLock { diff --git a/pkg/leaderelection/client_test.go b/pkg/leaderelection/client_test.go index 76fd8b84..4228a79e 100644 --- a/pkg/leaderelection/client_test.go +++ b/pkg/leaderelection/client_test.go @@ -5,30 +5,42 @@ import ( "testing" "time" - "github.com/kyverno/policy-reporter/pkg/leaderelection" + "github.com/stretchr/testify/assert" "k8s.io/client-go/kubernetes/typed/coordination/v1/fake" + + "github.com/kyverno/policy-reporter/pkg/leaderelection" ) func TestClient(t *testing.T) { - client := leaderelection.New(&fake.FakeCoordinationV1{}, "policy-reporter", "namespace", "pod-123", time.Second, time.Second, time.Second, false) + client := leaderelection.New(&fake.FakeCoordinationV1{}, "policy-reporter", "namespace", "pod-123", time.Second, time.Second, time.Second, true) if client == nil { t.Fatal("failed to create leaderelection client") } - client.RegisterOnNew(func(currentID, lockID string) {}) + var isLeader bool + client.RegisterOnNew(func(currentID, lockID string) { + isLeader = currentID == lockID + }) + client.RegisterOnStart(func(c context.Context) {}) client.RegisterOnStop(func() {}) lock := client.CreateLock() - if lock.LeaseMeta.Name != "policy-reporter" { - t.Error("unexpected lease name") - } - if lock.LeaseMeta.Namespace != "namespace" { - t.Error("unexpected lease namespace") - } - if lock.LockConfig.Identity != "pod-123" { - t.Error("unexpected lease identity") - } + assert.Equal(t, "policy-reporter", lock.LeaseMeta.Name) + assert.Equal(t, "namespace", lock.LeaseMeta.Namespace) + assert.Equal(t, "pod-123", lock.LockConfig.Identity) + + assert.False(t, isLeader) + + config := client.CreateConfig() + + config.Callbacks.OnNewLeader("pod-123") + + assert.True(t, isLeader) + assert.Equal(t, time.Second, config.LeaseDuration) + assert.Equal(t, time.Second, config.RenewDeadline) + assert.Equal(t, time.Second, config.RetryPeriod) + assert.True(t, config.ReleaseOnCancel) } diff --git a/pkg/listener/cleanup.go b/pkg/listener/cleanup.go index 2dfbd6ee..5206b627 100644 --- a/pkg/listener/cleanup.go +++ b/pkg/listener/cleanup.go @@ -9,9 +9,13 @@ import ( const CleanUpListener = "cleanup_listener" -func NewCleanupListener(ctx context.Context, handlers []target.Client) report.PolicyReportListener { +func NewCleanupListener(ctx context.Context, targets *target.Collection) report.PolicyReportListener { return func(event report.LifecycleEvent) { - for _, handler := range handlers { + if event.Type == report.Added { + return + } + + for _, handler := range targets.SyncClients() { handler.CleanUp(ctx, event.PolicyReport) } } diff --git a/pkg/listener/cleanup_test.go b/pkg/listener/cleanup_test.go index bc7fa7d3..d2b7656c 100644 --- a/pkg/listener/cleanup_test.go +++ b/pkg/listener/cleanup_test.go @@ -3,6 +3,8 @@ package listener_test import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/kyverno/policy-reporter/pkg/listener" "github.com/kyverno/policy-reporter/pkg/report" "github.com/kyverno/policy-reporter/pkg/target" @@ -10,13 +12,11 @@ import ( func Test_CleanupListener(t *testing.T) { t.Run("Execute Cleanup Handler", func(t *testing.T) { - c := &client{} + c := &client{cleanup: true} - slistener := listener.NewCleanupListener(ctx, []target.Client{c}) - slistener(report.LifecycleEvent{Type: report.Added, PolicyReport: preport1}) + slistener := listener.NewCleanupListener(ctx, target.NewCollection(&target.Target{Client: c})) + slistener(report.LifecycleEvent{Type: report.Deleted, PolicyReport: preport1}) - if !c.cleanupCalled { - t.Error("expected cleanup method was called") - } + assert.True(t, c.cleanupCalled, "expected cleanup method was called") }) } diff --git a/pkg/listener/metrics.go b/pkg/listener/metrics.go index fa870ab9..c67f3a51 100644 --- a/pkg/listener/metrics.go +++ b/pkg/listener/metrics.go @@ -36,7 +36,7 @@ func NewMetricsListener( func ResultListeners( filter *report.ResultFilter, - reportFilter *report.ReportFilter, + _ *report.ReportFilter, mode metrics.Mode, labels []string, ) []report.PolicyReportListener { @@ -96,20 +96,8 @@ func ResultListeners( } } - prCallback := metrics.CreateDetailedResultMetricListener(filter, metrics.RegisterDetailedResultGauge(ResultGaugeName)) - pCallback := metrics.CreatePolicyReportMetricsListener(reportFilter) - - crCallback := metrics.CreateDetailedClusterResultMetricListener(filter, metrics.RegisterDetailedClusterResultGauge(ClusterResultGaugeName)) - cCallback := metrics.CreateClusterPolicyReportMetricsListener(reportFilter) - return []report.PolicyReportListener{ - func(event report.LifecycleEvent) { - pCallback(event) - prCallback(event) - }, - func(event report.LifecycleEvent) { - cCallback(event) - crCallback(event) - }, + metrics.CreateDetailedResultMetricListener(filter, metrics.RegisterDetailedResultGauge(ResultGaugeName)), + metrics.CreateDetailedClusterResultMetricListener(filter, metrics.RegisterDetailedClusterResultGauge(ClusterResultGaugeName)), } } diff --git a/pkg/listener/metrics/cluster_policy_report.go b/pkg/listener/metrics/cluster_policy_report.go deleted file mode 100644 index e80daf9c..00000000 --- a/pkg/listener/metrics/cluster_policy_report.go +++ /dev/null @@ -1,50 +0,0 @@ -package metrics - -import ( - "strings" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report" -) - -var clusterPolicyGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "cluster_policy_report_summary", - Help: "Summary of all ClusterPolicyReports", -}, []string{"name", "status"}) - -func CreateClusterPolicyReportMetricsListener(filter *report.ReportFilter) report.PolicyReportListener { - prometheus.Register(clusterPolicyGauge) - - var newReport v1alpha2.ReportInterface - - return func(event report.LifecycleEvent) { - newReport = event.PolicyReport - if !filter.Validate(newReport) { - return - } - - switch event.Type { - case report.Added: - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusSkip)).Set(float64(newReport.GetSummary().Skip)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusPass)).Set(float64(newReport.GetSummary().Pass)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusWarn)).Set(float64(newReport.GetSummary().Warn)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusFail)).Set(float64(newReport.GetSummary().Fail)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusError)).Set(float64(newReport.GetSummary().Error)) - case report.Updated: - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusSkip)).Set(float64(newReport.GetSummary().Skip)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusPass)).Set(float64(newReport.GetSummary().Pass)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusWarn)).Set(float64(newReport.GetSummary().Warn)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusFail)).Set(float64(newReport.GetSummary().Fail)) - clusterPolicyGauge.WithLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusError)).Set(float64(newReport.GetSummary().Error)) - case report.Deleted: - clusterPolicyGauge.DeleteLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusSkip)) - clusterPolicyGauge.DeleteLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusPass)) - clusterPolicyGauge.DeleteLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusWarn)) - clusterPolicyGauge.DeleteLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusFail)) - clusterPolicyGauge.DeleteLabelValues(newReport.GetName(), strings.Title(v1alpha2.StatusError)) - } - } -} diff --git a/pkg/listener/metrics/cluster_policy_report_test.go b/pkg/listener/metrics/cluster_policy_report_test.go deleted file mode 100644 index c10e29e1..00000000 --- a/pkg/listener/metrics/cluster_policy_report_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package metrics_test - -import ( - "fmt" - "testing" - - "github.com/prometheus/client_golang/prometheus" - ioprometheusclient "github.com/prometheus/client_model/go" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/listener/metrics" - "github.com/kyverno/policy-reporter/pkg/report" - "github.com/kyverno/policy-reporter/pkg/validate" -) - -func Test_ClusterPolicyReportMetricGeneration(t *testing.T) { - report1 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "cpolr-test", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 1, Fail: 1}, - } - - report2 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "cpolr-test", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 0, Fail: 1}, - } - - report3 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "cpolr-test", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 0, Fail: 1}, - Results: []v1alpha2.PolicyReportResult{{Source: "Kube Bench"}}, - } - - filter := metrics.NewReportFilter(validate.RuleSets{}, validate.RuleSets{Exclude: []string{"Kube Bench"}}) - handler := metrics.CreateClusterPolicyReportMetricsListener(filter) - - t.Run("Added Metric", func(t *testing.T) { - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: cluster_policy_report_summary") - } - - metrics := summary.GetMetric() - - if err = testClusterSummaryMetricLabels(metrics[0], report1, "Error", 0); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[1], report1, "Fail", 1); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[2], report1, "Pass", 1); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[3], report1, "Skip", 0); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[4], report1, "Warn", 0); err != nil { - t.Error(err) - } - }) - - t.Run("Modified Metric", func(t *testing.T) { - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - handler(report.LifecycleEvent{Type: report.Updated, PolicyReport: report2}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: cluster_policy_report_summary") - } - - metrics := summary.GetMetric() - - if err = testClusterSummaryMetricLabels(metrics[0], report2, "Error", 0); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[1], report2, "Fail", 1); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[2], report2, "Pass", 0); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[3], report2, "Skip", 0); err != nil { - t.Error(err) - } - if err = testClusterSummaryMetricLabels(metrics[4], report2, "Warn", 0); err != nil { - t.Error(err) - } - }) - - t.Run("Deleted Metric", func(t *testing.T) { - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - handler(report.LifecycleEvent{Type: report.Updated, PolicyReport: report2}) - handler(report.LifecycleEvent{Type: report.Deleted, PolicyReport: report2}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary != nil { - t.Error("cluster_policy_report_summary should no longer exist", *summary.Name) - } - - results := metricFam[0] - - if *results.Name == "cluster_policy_report_result" { - t.Error("cluster_policy_report_result should no longer exist", *results.Name) - } - }) - - t.Run("Filtered Report", func(t *testing.T) { - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report3}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary != nil { - t.Error("cluster_policy_report_summary should not be created", *summary.Name) - } - }) -} - -func testClusterSummaryMetricLabels( - metric *ioprometheusclient.Metric, - preport v1alpha2.ReportInterface, - status string, - gauge float64, -) error { - if name := *metric.Label[0].Name; name != "name" { - return fmt.Errorf("unexpected Name Label: %s", name) - } - if value := *metric.Label[0].Value; value != preport.GetName() { - return fmt.Errorf("unexpected Name Label Value: %s", value) - } - - if name := *metric.Label[1].Name; name != "status" { - return fmt.Errorf("unexpected Name Label: %s", name) - } - if value := *metric.Label[1].Value; value != status { - return fmt.Errorf("unexpected Status Label Value: %s", value) - } - - if value := metric.Gauge.GetValue(); value != gauge { - return fmt.Errorf("unexpected Metric Value: %v", value) - } - - return nil -} diff --git a/pkg/listener/metrics/policy_report.go b/pkg/listener/metrics/policy_report.go deleted file mode 100644 index 7960ab45..00000000 --- a/pkg/listener/metrics/policy_report.go +++ /dev/null @@ -1,50 +0,0 @@ -package metrics - -import ( - "strings" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report" -) - -var policyGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "policy_report_summary", - Help: "Summary of all PolicyReports", -}, []string{"namespace", "name", "status"}) - -func CreatePolicyReportMetricsListener(filter *report.ReportFilter) report.PolicyReportListener { - prometheus.Register(policyGauge) - - var newReport v1alpha2.ReportInterface - - return func(event report.LifecycleEvent) { - newReport = event.PolicyReport - if !filter.Validate(newReport) { - return - } - - switch event.Type { - case report.Added: - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusSkip)).Set(float64(newReport.GetSummary().Skip)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusPass)).Set(float64(newReport.GetSummary().Pass)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusWarn)).Set(float64(newReport.GetSummary().Warn)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusFail)).Set(float64(newReport.GetSummary().Fail)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusError)).Set(float64(newReport.GetSummary().Error)) - case report.Updated: - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusSkip)).Set(float64(newReport.GetSummary().Skip)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusPass)).Set(float64(newReport.GetSummary().Pass)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusWarn)).Set(float64(newReport.GetSummary().Warn)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusFail)).Set(float64(newReport.GetSummary().Fail)) - policyGauge.WithLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusError)).Set(float64(newReport.GetSummary().Error)) - case report.Deleted: - policyGauge.DeleteLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusSkip)) - policyGauge.DeleteLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusPass)) - policyGauge.DeleteLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusWarn)) - policyGauge.DeleteLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusFail)) - policyGauge.DeleteLabelValues(newReport.GetNamespace(), newReport.GetName(), strings.Title(v1alpha2.StatusError)) - } - } -} diff --git a/pkg/listener/metrics/policy_report_test.go b/pkg/listener/metrics/policy_report_test.go deleted file mode 100644 index ccacfe11..00000000 --- a/pkg/listener/metrics/policy_report_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package metrics_test - -import ( - "testing" - - "github.com/prometheus/client_golang/prometheus" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/listener/metrics" - "github.com/kyverno/policy-reporter/pkg/report" - "github.com/kyverno/policy-reporter/pkg/validate" -) - -func Test_PolicyReportMetricGeneration(t *testing.T) { - report1 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "polr-test", - Namespace: "test", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 2, Fail: 1}, - } - - report2 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "polr-test", - Namespace: "test", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 3, Fail: 4}, - } - - report3 := &v1alpha2.PolicyReport{ - ObjectMeta: v1.ObjectMeta{ - Name: "polr-dev", - Namespace: "dev", - CreationTimestamp: v1.Now(), - }, - Summary: v1alpha2.PolicyReportSummary{Pass: 0, Fail: 1, Warn: 3}, - } - - filter := metrics.NewReportFilter(validate.RuleSets{Exclude: []string{"dev"}}, validate.RuleSets{Exclude: []string{"Test"}}) - - t.Run("Added Metric", func(t *testing.T) { - handler := metrics.CreatePolicyReportMetricsListener(filter) - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: policy_report_summary") - } - - metrics := summary.GetMetric() - - if err = testSummaryMetricLabels(metrics[0], report1, "Error", 0); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[1], report1, "Fail", 1); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[2], report1, "Pass", 2); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[3], report1, "Skip", 0); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[4], report1, "Warn", 0); err != nil { - t.Error(err) - } - }) - - t.Run("Modified Metric", func(t *testing.T) { - handler := metrics.CreatePolicyReportMetricsListener(filter) - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - handler(report.LifecycleEvent{Type: report.Updated, PolicyReport: report2}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: policy_report_summary") - } - - metrics := summary.GetMetric() - - if err = testSummaryMetricLabels(metrics[0], preport, "Error", 0); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[1], preport, "Fail", 4); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[2], preport, "Pass", 3); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[3], preport, "Skip", 0); err != nil { - t.Error(err) - } - if err = testSummaryMetricLabels(metrics[4], preport, "Warn", 0); err != nil { - t.Error(err) - } - }) - - t.Run("Deleted Metric", func(t *testing.T) { - handler := metrics.CreatePolicyReportMetricsListener(filter) - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report1}) - handler(report.LifecycleEvent{Type: report.Updated, PolicyReport: report2}) - handler(report.LifecycleEvent{Type: report.Deleted, PolicyReport: report2}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "policy_report_summary") - if summary != nil { - t.Error("policy_report_summary should no longer exist", *summary.Name) - } - }) - - t.Run("Validate Metric Filter", func(t *testing.T) { - handler := metrics.CreatePolicyReportMetricsListener(filter) - handler(report.LifecycleEvent{Type: report.Added, PolicyReport: report3}) - - metricFam, err := prometheus.DefaultGatherer.Gather() - if err != nil { - t.Errorf("unexpected Error: %s", err) - } - - summary := findMetric(metricFam, "policy_report_summary") - if summary != nil { - t.Error("policy_report_summary should not created", *summary.Name) - } - }) -} diff --git a/pkg/listener/metrics_test.go b/pkg/listener/metrics_test.go index 9a74f3c4..5d0e2ce1 100644 --- a/pkg/listener/metrics_test.go +++ b/pkg/listener/metrics_test.go @@ -5,6 +5,7 @@ import ( "github.com/prometheus/client_golang/prometheus" ioprometheusclient "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/assert" "github.com/kyverno/policy-reporter/pkg/listener" "github.com/kyverno/policy-reporter/pkg/listener/metrics" @@ -26,13 +27,10 @@ func Test_SimpleMetricsListener(t *testing.T) { } summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary != nil { - t.Fatalf("Metric should not be created: cluster_policy_report_summary") - } + assert.Nil(t, summary, "Metric should not be created: cluster_policy_report_summary") + result := findMetric(metricFam, "cluster_policy_report_simple_result") - if result == nil { - t.Fatalf("Metric not found: cluster_policy_report_simple_result") - } + assert.NotNil(t, result, "Metric not found: cluster_policy_report_simple_result") }) t.Run("Add PolicyReport Metric", func(t *testing.T) { slistener(report.LifecycleEvent{Type: report.Added, PolicyReport: preport1}) @@ -43,13 +41,10 @@ func Test_SimpleMetricsListener(t *testing.T) { } summary := findMetric(metricFam, "policy_report_summary") - if summary != nil { - t.Fatalf("Metric should not be created: policy_report_summary") - } + assert.Nil(t, summary, "Metric should not be created: policy_report_summary") + result := findMetric(metricFam, "policy_report_simple_result") - if result == nil { - t.Fatalf("Metric not found: policy_report_simple_result") - } + assert.NotNil(t, result, "Metric not found: policy_report_simple_result") }) } @@ -69,13 +64,10 @@ func Test_CustomMetricsListener(t *testing.T) { } summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary != nil { - t.Fatalf("Metric should not be created: cluster_policy_report_summary") - } + assert.Nil(t, summary, "Metric should not be created: cluster_policy_report_summary") + result := findMetric(metricFam, "cluster_policy_report_custom_result") - if result == nil { - t.Fatalf("Metric not found: cluster_policy_report_custom_result") - } + assert.NotNil(t, result, "Metric not found: cluster_policy_report_custom_result") }) t.Run("Add PolicyReport Metric", func(t *testing.T) { slistener(report.LifecycleEvent{Type: report.Added, PolicyReport: preport1}) @@ -86,13 +78,10 @@ func Test_CustomMetricsListener(t *testing.T) { } summary := findMetric(metricFam, "policy_report_summary") - if summary != nil { - t.Fatalf("Metric should not be created: policy_report_summary") - } + assert.Nil(t, summary, "Metric should not be created: policy_report_summary") + result := findMetric(metricFam, "policy_report_custom_result") - if result == nil { - t.Fatalf("Metric not found: policy_report_custom_result") - } + assert.NotNil(t, result, "Metric not found: policy_report_custom_result") }) } @@ -110,14 +99,8 @@ func Test_MetricsListener(t *testing.T) { t.Errorf("unexpected Error: %s", err) } - summary := findMetric(metricFam, "cluster_policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: cluster_policy_report_summary") - } result := findMetric(metricFam, "cluster_policy_report_result") - if result == nil { - t.Fatalf("Metric not found: cluster_policy_report_result") - } + assert.NotNil(t, result, "Metric not found: cluster_policy_report_result") }) t.Run("Add PolicyReport Metric", func(t *testing.T) { slistener(report.LifecycleEvent{Type: report.Added, PolicyReport: preport1}) @@ -127,14 +110,8 @@ func Test_MetricsListener(t *testing.T) { t.Errorf("unexpected Error: %s", err) } - summary := findMetric(metricFam, "policy_report_summary") - if summary == nil { - t.Fatalf("Metric not found: policy_report_summary") - } result := findMetric(metricFam, "policy_report_result") - if result == nil { - t.Fatalf("Metric not found: policy_report_result") - } + assert.NotNil(t, result, "Metric not found: policy_report_result") }) } diff --git a/pkg/listener/new_result.go b/pkg/listener/new_result.go index 0a72cd00..ba2a77dd 100644 --- a/pkg/listener/new_result.go +++ b/pkg/listener/new_result.go @@ -13,10 +13,12 @@ import ( const NewResults = "new_results_listener" type ResultListener struct { - skipExisting bool - listener []report.PolicyReportResultListener - cache cache.Cache - startUp time.Time + skipExisting bool + listener []report.PolicyReportResultListener + scopeListener []report.ScopeResultsListener + syncListener []report.SyncResultsListener + cache cache.Cache + startUp time.Time } func (l *ResultListener) RegisterListener(listener report.PolicyReportResultListener) { @@ -27,6 +29,30 @@ func (l *ResultListener) UnregisterListener() { l.listener = make([]report.PolicyReportResultListener, 0) } +func (l *ResultListener) RegisterScopeListener(listener report.ScopeResultsListener) { + l.scopeListener = append(l.scopeListener, listener) +} + +func (l *ResultListener) UnregisterScopeListener() { + l.scopeListener = make([]report.ScopeResultsListener, 0) +} + +func (l *ResultListener) RegisterSyncListener(listener report.SyncResultsListener) { + l.syncListener = append(l.syncListener, listener) +} + +func (l *ResultListener) UnregisterSyncListener() { + l.syncListener = make([]report.SyncResultsListener, 0) +} + +func (l *ResultListener) Validate(r v1alpha2.PolicyReportResult) bool { + if r.Result == v1alpha2.StatusSkip || r.Result == v1alpha2.StatusPass { + return false + } + + return true +} + func (l *ResultListener) Listen(event report.LifecycleEvent) { if event.Type != report.Added && event.Type != report.Updated { l.cache.RemoveReport(event.PolicyReport.GetID()) @@ -39,7 +65,25 @@ func (l *ResultListener) Listen(event report.LifecycleEvent) { } listenerCount := len(l.listener) - if listenerCount == 0 { + scopeListenerCount := len(l.scopeListener) + syncListenerCount := len(l.syncListener) + + if syncListenerCount > 0 { + wg := sync.WaitGroup{} + wg.Add(syncListenerCount) + + for _, cb := range l.syncListener { + go func(callback report.SyncResultsListener) { + defer wg.Done() + + callback(event.PolicyReport) + }(cb) + } + + wg.Wait() + } + + if listenerCount == 0 && scopeListenerCount == 0 { l.cache.AddReport(event.PolicyReport) return } @@ -56,31 +100,59 @@ func (l *ResultListener) Listen(event report.LifecycleEvent) { } existing := l.cache.GetResults(event.PolicyReport.GetID()) + newResults := make([]v1alpha2.PolicyReportResult, 0) + + for _, r := range event.PolicyReport.GetResults() { + if helper.Contains(r.GetID(), existing) || !l.Validate(r) { + continue + } + + if r.Timestamp.Seconds > 0 { + created := time.Unix(r.Timestamp.Seconds, int64(r.Timestamp.Nanos)) + if l.skipExisting && created.Local().Before(l.startUp) { + continue + } + } + + newResults = append(newResults, r) + } + + l.cache.AddReport(event.PolicyReport) + if len(newResults) == 0 { + return + } + + if scopeListenerCount > 0 { + wg := sync.WaitGroup{} + wg.Add(scopeListenerCount) + + for _, cb := range l.scopeListener { + go func(callback report.ScopeResultsListener, results []v1alpha2.PolicyReportResult) { + defer wg.Done() + + callback(event.PolicyReport, results, preExisted) + }(cb, newResults) + } + } + + if len(l.listener) == 0 { + return + } grp := sync.WaitGroup{} - grp.Add(resultCount) - for _, res := range event.PolicyReport.GetResults() { + grp.Add(len(newResults)) + for _, res := range newResults { go func(r v1alpha2.PolicyReportResult) { defer grp.Done() - if helper.Contains(r.GetID(), existing) { - return - } - - if r.Timestamp.Seconds > 0 { - created := time.Unix(r.Timestamp.Seconds, int64(r.Timestamp.Nanos)) - if l.skipExisting && created.Local().Before(l.startUp) { - return - } - } - wg := sync.WaitGroup{} wg.Add(listenerCount) for _, cb := range l.listener { go func(callback report.PolicyReportResultListener, result v1alpha2.PolicyReportResult) { + defer wg.Done() + callback(event.PolicyReport, result, preExisted) - wg.Done() }(cb, r) } @@ -89,15 +161,15 @@ func (l *ResultListener) Listen(event report.LifecycleEvent) { } grp.Wait() - - l.cache.AddReport(event.PolicyReport) } func NewResultListener(skipExisting bool, rcache cache.Cache, startUp time.Time) *ResultListener { return &ResultListener{ - skipExisting: skipExisting, - cache: rcache, - startUp: startUp, - listener: make([]report.PolicyReportResultListener, 0), + skipExisting: skipExisting, + cache: rcache, + startUp: startUp, + listener: make([]report.PolicyReportResultListener, 0), + scopeListener: make([]report.ScopeResultsListener, 0), + syncListener: make([]report.SyncResultsListener, 0), } } diff --git a/pkg/listener/new_result_test.go b/pkg/listener/new_result_test.go index 3be27c73..73f8dee9 100644 --- a/pkg/listener/new_result_test.go +++ b/pkg/listener/new_result_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kyverno/policy-reporter/pkg/cache" @@ -25,9 +26,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Added, PolicyReport: preport1}) slistener.Listen(report.LifecycleEvent{Type: report.Updated, PolicyReport: preport2}) - if called.GetID() != fixtures.FailPodResult.GetID() { - t.Error("Expected Listener to be called with FailPodResult") - } + assert.Equal(t, called.GetID(), fixtures.FailPodResult.GetID(), "Expected Listener to be called with FailPodResult") }) t.Run("Ignore Delete Event", func(t *testing.T) { @@ -40,9 +39,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Deleted, PolicyReport: preport2}) - if called { - t.Error("Expected Listener not be called on Deleted event") - } + assert.False(t, called, "Expected Listener not be called on Deleted event") }) t.Run("Ignore Added Results created before startup", func(t *testing.T) { @@ -55,9 +52,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Added, PolicyReport: preport2}) - if called { - t.Error("Expected Listener not be called on Deleted event") - } + assert.False(t, called, "Expected Listener not be called on Deleted event") }) t.Run("Ignore CacheResults", func(t *testing.T) { @@ -71,9 +66,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Added, PolicyReport: preport2}) slistener.Listen(report.LifecycleEvent{Type: report.Updated, PolicyReport: preport2}) - if called { - t.Error("Expected Listener not be called on cached results") - } + assert.False(t, called, "Expected Listener not be called on cached results") }) t.Run("Early Return if Results are empty", func(t *testing.T) { @@ -86,9 +79,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Updated, PolicyReport: preport3}) - if called { - t.Error("Expected Listener not be called with empty results") - } + assert.False(t, called, "Expected Listener not be called with empty results") }) t.Run("Skip process events when no listeners registered", func(t *testing.T) { @@ -97,9 +88,7 @@ func Test_ResultListener(t *testing.T) { slistener := listener.NewResultListener(true, c, time.Now()) slistener.Listen(report.LifecycleEvent{Type: report.Added, PolicyReport: preport2}) - if res := c.GetResults(preport2.GetID()); len(res) == 0 { - t.Error("Expected cached report was found") - } + assert.Greater(t, len(c.GetResults(preport2.GetID())), 0, "Expected cached report was found") }) t.Run("UnregisterListener removes all listeners", func(t *testing.T) { @@ -114,9 +103,7 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Updated, PolicyReport: preport2}) - if called { - t.Error("Expected Listener not called because it was unregistered") - } + assert.False(t, called, "Expected Listener not called because it was unregistered") }) t.Run("ignore results with past timestamps", func(t *testing.T) { var called bool @@ -136,8 +123,6 @@ func Test_ResultListener(t *testing.T) { slistener.Listen(report.LifecycleEvent{Type: report.Updated, PolicyReport: rep}) - if called { - t.Error("Expected Listener not called because it was unregistered") - } + assert.False(t, called, "Expected Listener not called because it was unregistered") }) } diff --git a/pkg/listener/scope_results.go b/pkg/listener/scope_results.go new file mode 100644 index 00000000..5bf92a9f --- /dev/null +++ b/pkg/listener/scope_results.go @@ -0,0 +1,39 @@ +package listener + +import ( + "sync" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/target" +) + +const SendScopeResults = "send_scope_results_listener" + +func NewSendScopeResultsListener(targets *target.Collection) report.ScopeResultsListener { + return func(rep v1alpha2.ReportInterface, r []v1alpha2.PolicyReportResult, e bool) { + clients := targets.BatchSendClients() + + wg := &sync.WaitGroup{} + wg.Add(len(clients)) + + for _, t := range clients { + go func(target target.Client, re v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult, preExisted bool) { + defer wg.Done() + + filtered := helper.Filter(results, func(result v1alpha2.PolicyReportResult) bool { + return target.Validate(re, result) + }) + + if len(filtered) == 0 || preExisted && target.SkipExistingOnStartup() { + return + } + + target.BatchSend(re, filtered) + }(t, rep, r, e) + } + + wg.Wait() + } +} diff --git a/pkg/listener/scope_results_test.go b/pkg/listener/scope_results_test.go new file mode 100644 index 00000000..64bc2064 --- /dev/null +++ b/pkg/listener/scope_results_test.go @@ -0,0 +1,38 @@ +package listener_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/fixtures" + "github.com/kyverno/policy-reporter/pkg/listener" + "github.com/kyverno/policy-reporter/pkg/target" +) + +func Test_ScopeResultsListener(t *testing.T) { + t.Run("Send Results", func(t *testing.T) { + c := &client{validated: true, batchSend: true} + slistener := listener.NewSendScopeResultsListener(target.NewCollection(&target.Target{Client: c})) + slistener(preport1, []v1alpha2.PolicyReportResult{fixtures.FailResult}, false) + + assert.True(t, c.Called, "Expected Send to be called") + }) + t.Run("Don't Send Result when validation fails", func(t *testing.T) { + c := &client{validated: false, batchSend: true} + slistener := listener.NewSendScopeResultsListener(target.NewCollection(&target.Target{Client: c})) + slistener(preport1, []v1alpha2.PolicyReportResult{fixtures.FailResult}, false) + + assert.False(t, c.Called, "Expected Send not to be called") + }) + t.Run("Don't Send pre existing Result when skipExistingOnStartup is true", func(t *testing.T) { + c := &client{skipExistingOnStartup: true, batchSend: true} + slistener := listener.NewSendScopeResultsListener(target.NewCollection(&target.Target{Client: c})) + slistener(preport1, []v1alpha2.PolicyReportResult{fixtures.FailResult}, true) + + if c.Called { + t.Error("Expected Send not to be called") + } + }) +} diff --git a/pkg/listener/send_result.go b/pkg/listener/send_result.go index 37420d9f..367e9158 100644 --- a/pkg/listener/send_result.go +++ b/pkg/listener/send_result.go @@ -12,8 +12,10 @@ import ( const SendResults = "send_results_listener" -func NewSendResultListener(clients []target.Client) report.PolicyReportResultListener { +func NewSendResultListener(targets *target.Collection) report.PolicyReportResultListener { return func(rep v1alpha2.ReportInterface, r v1alpha2.PolicyReportResult, e bool) { + clients := targets.SingleSendClients() + wg := &sync.WaitGroup{} wg.Add(len(clients)) diff --git a/pkg/listener/send_result_test.go b/pkg/listener/send_result_test.go index e0b50028..8fe4ddb1 100644 --- a/pkg/listener/send_result_test.go +++ b/pkg/listener/send_result_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/fixtures" "github.com/kyverno/policy-reporter/pkg/listener" @@ -15,14 +17,16 @@ type client struct { skipExistingOnStartup bool validated bool cleanupCalled bool + batchSend bool + cleanup bool } func (c *client) Send(result v1alpha2.PolicyReportResult) { c.Called = true } -func (c *client) MinimumPriority() string { - return v1alpha2.InfoPriority.String() +func (c *client) MinimumSeverity() string { + return v1alpha2.SeverityInfo } func (c *client) Name() string { @@ -41,36 +45,49 @@ func (c client) Validate(rep v1alpha2.ReportInterface, result v1alpha2.PolicyRep return c.validated } +func (c *client) Reset(_ context.Context) error { + return nil +} + func (c *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) { c.cleanupCalled = true } +func (c *client) BatchSend(_ v1alpha2.ReportInterface, _ []v1alpha2.PolicyReportResult) { + c.Called = true +} + +func (c *client) Type() target.ClientType { + if c.cleanup { + return target.SyncSend + } + if c.batchSend { + return target.BatchSend + } + + return target.SingleSend +} + func Test_SendResultListener(t *testing.T) { t.Run("Send Result", func(t *testing.T) { c := &client{validated: true} - slistener := listener.NewSendResultListener([]target.Client{c}) + slistener := listener.NewSendResultListener(target.NewCollection(&target.Target{Client: c})) slistener(preport1, fixtures.FailResult, false) - if !c.Called { - t.Error("Expected Send to be called") - } + assert.True(t, c.Called, "Expected Send to be called") }) t.Run("Don't Send Result when validation fails", func(t *testing.T) { c := &client{validated: false} - slistener := listener.NewSendResultListener([]target.Client{c}) + slistener := listener.NewSendResultListener(target.NewCollection(&target.Target{Client: c})) slistener(preport1, fixtures.FailResult, false) - if c.Called { - t.Error("Expected Send not to be called") - } + assert.False(t, c.Called, "Expected Send not to be called") }) t.Run("Don't Send pre existing Result when skipExistingOnStartup is true", func(t *testing.T) { c := &client{skipExistingOnStartup: true} - slistener := listener.NewSendResultListener([]target.Client{c}) + slistener := listener.NewSendResultListener(target.NewCollection(&target.Target{Client: c})) slistener(preport1, fixtures.FailResult, true) - if c.Called { - t.Error("Expected Send not to be called") - } + assert.False(t, c.Called, "Expected Send not to be called") }) } diff --git a/pkg/listener/sync_results.go b/pkg/listener/sync_results.go new file mode 100644 index 00000000..44d435d7 --- /dev/null +++ b/pkg/listener/sync_results.go @@ -0,0 +1,52 @@ +package listener + +import ( + "context" + "sync" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/target" +) + +const SendSyncResults = "send_sync_results_listener" + +func NewSendSyncResultsListener(targets *target.Collection) report.SyncResultsListener { + ready := make(chan bool) + ok := false + go func() { + ok = targets.Reset(context.Background()) + if ok { + close(ready) + } + }() + + return func(rep v1alpha2.ReportInterface) { + clients := targets.SyncClients() + if len(clients) == 0 { + return + } + + if !ok { + <-ready + } + + wg := &sync.WaitGroup{} + wg.Add(len(clients)) + + for _, t := range clients { + go func(target target.Client, re v1alpha2.ReportInterface) { + defer wg.Done() + + filtered := helper.Filter(re.GetResults(), func(result v1alpha2.PolicyReportResult) bool { + return target.Validate(re, result) + }) + + target.BatchSend(re, filtered) + }(t, rep) + } + + wg.Wait() + } +} diff --git a/pkg/report/client.go b/pkg/report/client.go index f05f5657..babd440f 100644 --- a/pkg/report/client.go +++ b/pkg/report/client.go @@ -10,6 +10,12 @@ type PolicyReportListener = func(LifecycleEvent) // PolicyReportResultListener is called whenever a new PolicyResult comes in type PolicyReportResultListener = func(v1alpha2.ReportInterface, v1alpha2.PolicyReportResult, bool) +// ScopeResultsListener is called whenever a new PolicyReport with a single resource scope and new results comes in +type ScopeResultsListener = func(v1alpha2.ReportInterface, []v1alpha2.PolicyReportResult, bool) + +// SyncResultsListener is called whenever a PolicyReport event comes in +type SyncResultsListener = func(v1alpha2.ReportInterface) + // PolicyReportClient watches for PolicyReport Events and executes registered callback type PolicyReportClient interface { // Run starts the informer and workerqueue diff --git a/pkg/report/filter.go b/pkg/report/filter.go deleted file mode 100644 index 56c3c3de..00000000 --- a/pkg/report/filter.go +++ /dev/null @@ -1,77 +0,0 @@ -package report - -import ( - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/validate" -) - -type Namespaced interface { - GetNamespace() string -} - -type Filter struct { - disbaleClusterReports bool - namespace validate.RuleSets -} - -func (f *Filter) DisableClusterReports() bool { - return f.disbaleClusterReports -} - -func (f *Filter) AllowReport(report Namespaced) bool { - return validate.Namespace(report.GetNamespace(), f.namespace) -} - -func NewFilter(disableClusterReports bool, namespace validate.RuleSets) *Filter { - return &Filter{disableClusterReports, namespace} -} - -type ResultValidation = func(v1alpha2.PolicyReportResult) bool - -type ResultFilter struct { - validations []ResultValidation - Sources []string - MinimumPriority string -} - -func (rf *ResultFilter) AddValidation(v ResultValidation) { - rf.validations = append(rf.validations, v) -} - -func (rf *ResultFilter) Validate(result v1alpha2.PolicyReportResult) bool { - for _, validation := range rf.validations { - if !validation(result) { - return false - } - } - - return true -} - -func NewResultFilter() *ResultFilter { - return &ResultFilter{} -} - -type ReportValidation = func(v1alpha2.ReportInterface) bool - -type ReportFilter struct { - validations []ReportValidation -} - -func (rf *ReportFilter) AddValidation(v ReportValidation) { - rf.validations = append(rf.validations, v) -} - -func (rf *ReportFilter) Validate(report v1alpha2.ReportInterface) bool { - for _, validation := range rf.validations { - if !validation(report) { - return false - } - } - - return true -} - -func NewReportFilter() *ReportFilter { - return &ReportFilter{} -} diff --git a/pkg/report/filter_test.go b/pkg/report/filter_test.go deleted file mode 100644 index dbdfb250..00000000 --- a/pkg/report/filter_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package report_test - -import ( - "testing" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/fixtures" - "github.com/kyverno/policy-reporter/pkg/report" - "github.com/kyverno/policy-reporter/pkg/validate" -) - -func Test_DisableClusterReports(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{}) - - if !filter.DisableClusterReports() { - t.Error("Expected EnableClusterReports to return true as configured") - } -} - -func Test_AllowReport(t *testing.T) { - t.Run("Allow ClusterReport", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{Exclude: []string{"*"}}) - if !filter.AllowReport(creport) { - t.Error("Expected AllowReport returns true if Report is a ClusterPolicyReport without namespace") - } - }) - - t.Run("Allow Report with matching include Namespace", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{Include: []string{"patch", "te*"}}) - if !filter.AllowReport(preport) { - t.Error("Expected AllowReport returns true if Report namespace matches include pattern") - } - }) - - t.Run("Disallow Report with matching exclude Namespace", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{Exclude: []string{"patch", "te*"}}) - if filter.AllowReport(preport) { - t.Error("Expected AllowReport returns false if Report namespace matches exclude pattern") - } - }) - - t.Run("Ignores exclude pattern if include namespaces provided", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{Include: []string{"*"}, Exclude: []string{"te*"}}) - if !filter.AllowReport(preport) { - t.Error("Expected AllowReport returns true because exclude patterns ignored if include patterns provided") - } - }) - - t.Run("Allow Report when no configuration exists", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{}) - if !filter.AllowReport(preport) { - t.Error("Expected AllowReport returns true if no namespace patterns configured") - } - }) - - t.Run("Disallow Report if no include namespace matches", func(t *testing.T) { - filter := report.NewFilter(true, validate.RuleSets{Include: []string{"patch", "dev"}}) - if filter.AllowReport(preport) { - t.Error("Expected AllowReport returns false if no namespace pattern matches") - } - }) -} - -func Test_ResultFilter(t *testing.T) { - t.Run("don't filter any result without validations", func(t *testing.T) { - filter := report.NewResultFilter() - if !filter.Validate(fixtures.FailResult) { - t.Error("Expected result validates to true") - } - }) - t.Run("filter result with a false validation", func(t *testing.T) { - filter := report.NewResultFilter() - filter.AddValidation(func(r v1alpha2.PolicyReportResult) bool { return false }) - if filter.Validate(fixtures.FailResult) { - t.Error("Expected result validates to false") - } - }) -} - -func Test_ReportFilter(t *testing.T) { - t.Run("don't filter any result without validations", func(t *testing.T) { - filter := report.NewReportFilter() - if !filter.Validate(preport) { - t.Error("Expected result validates to true") - } - }) - t.Run("filter result with a false validation", func(t *testing.T) { - filter := report.NewReportFilter() - filter.AddValidation(func(r v1alpha2.ReportInterface) bool { return false }) - if filter.Validate(preport) { - t.Error("Expected result validates to false") - } - }) -} diff --git a/pkg/report/meta_filter.go b/pkg/report/meta_filter.go new file mode 100644 index 00000000..445b03d1 --- /dev/null +++ b/pkg/report/meta_filter.go @@ -0,0 +1,26 @@ +package report + +import ( + "github.com/kyverno/policy-reporter/pkg/validate" +) + +type Namespaced interface { + GetNamespace() string +} + +type MetaFilter struct { + disbaleClusterReports bool + namespace validate.RuleSets +} + +func (f *MetaFilter) DisableClusterReports() bool { + return f.disbaleClusterReports +} + +func (f *MetaFilter) AllowReport(report Namespaced) bool { + return validate.Namespace(report.GetNamespace(), f.namespace) +} + +func NewMetaFilter(disableClusterReports bool, namespace validate.RuleSets) *MetaFilter { + return &MetaFilter{disableClusterReports, namespace} +} diff --git a/pkg/report/meta_filter_test.go b/pkg/report/meta_filter_test.go new file mode 100644 index 00000000..5d35ce60 --- /dev/null +++ b/pkg/report/meta_filter_test.go @@ -0,0 +1,60 @@ +package report_test + +import ( + "testing" + + "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/validate" +) + +func TestMetaFilter(t *testing.T) { + t.Run("disable cluster reports", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{}) + + if !filter.DisableClusterReports() { + t.Error("Expected EnableClusterReports to return true as configured") + } + }) + + t.Run("Allow ClusterReport", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{Exclude: []string{"*"}}) + if !filter.AllowReport(creport) { + t.Error("Expected AllowReport returns true if Report is a ClusterPolicyReport without namespace") + } + }) + + t.Run("Allow Report with matching include Namespace", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{Include: []string{"patch", "te*"}}) + if !filter.AllowReport(preport) { + t.Error("Expected AllowReport returns true if Report namespace matches include pattern") + } + }) + + t.Run("Disallow Report with matching exclude Namespace", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{Exclude: []string{"patch", "te*"}}) + if filter.AllowReport(preport) { + t.Error("Expected AllowReport returns false if Report namespace matches exclude pattern") + } + }) + + t.Run("Ignores exclude pattern if include namespaces provided", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{Include: []string{"*"}, Exclude: []string{"te*"}}) + if !filter.AllowReport(preport) { + t.Error("Expected AllowReport returns true because exclude patterns ignored if include patterns provided") + } + }) + + t.Run("Allow Report when no configuration exists", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{}) + if !filter.AllowReport(preport) { + t.Error("Expected AllowReport returns true if no namespace patterns configured") + } + }) + + t.Run("Disallow Report if no include namespace matches", func(t *testing.T) { + filter := report.NewMetaFilter(true, validate.RuleSets{Include: []string{"patch", "dev"}}) + if filter.AllowReport(preport) { + t.Error("Expected AllowReport returns false if no namespace pattern matches") + } + }) +} diff --git a/pkg/report/report_filter.go b/pkg/report/report_filter.go new file mode 100644 index 00000000..671ebbe9 --- /dev/null +++ b/pkg/report/report_filter.go @@ -0,0 +1,29 @@ +package report + +import ( + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" +) + +type ReportValidation = func(v1alpha2.ReportInterface) bool + +type ReportFilter struct { + validations []ReportValidation +} + +func (rf *ReportFilter) AddValidation(v ReportValidation) { + rf.validations = append(rf.validations, v) +} + +func (rf *ReportFilter) Validate(report v1alpha2.ReportInterface) bool { + for _, validation := range rf.validations { + if !validation(report) { + return false + } + } + + return true +} + +func NewReportFilter() *ReportFilter { + return &ReportFilter{} +} diff --git a/pkg/report/report_filter_test.go b/pkg/report/report_filter_test.go new file mode 100644 index 00000000..0a2e40f7 --- /dev/null +++ b/pkg/report/report_filter_test.go @@ -0,0 +1,24 @@ +package report_test + +import ( + "testing" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/report" +) + +func Test_ReportFilter(t *testing.T) { + t.Run("don't filter any result without validations", func(t *testing.T) { + filter := report.NewReportFilter() + if !filter.Validate(preport) { + t.Error("Expected result validates to true") + } + }) + t.Run("filter result with a false validation", func(t *testing.T) { + filter := report.NewReportFilter() + filter.AddValidation(func(r v1alpha2.ReportInterface) bool { return false }) + if filter.Validate(preport) { + t.Error("Expected result validates to false") + } + }) +} diff --git a/pkg/report/result/id_generator.go b/pkg/report/result/id_generator.go index 77d91f0a..8157adc9 100644 --- a/pkg/report/result/id_generator.go +++ b/pkg/report/result/id_generator.go @@ -4,9 +4,10 @@ import ( "strconv" "strings" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/segmentio/fasthash/fnv1a" corev1 "k8s.io/api/core/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" ) type FieldMapperFunc = func(h1 uint64, polr v1alpha2.ReportInterface, res v1alpha2.PolicyReportResult) uint64 diff --git a/pkg/report/result/id_generator_test.go b/pkg/report/result/id_generator_test.go index 0bb8bbad..b0d4a307 100644 --- a/pkg/report/result/id_generator_test.go +++ b/pkg/report/result/id_generator_test.go @@ -3,10 +3,11 @@ package result_test import ( "testing" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report/result" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/report/result" ) func TestDefaultGenerator(t *testing.T) { diff --git a/pkg/report/result/mapper.go b/pkg/report/result/mapper.go deleted file mode 100644 index b2290788..00000000 --- a/pkg/report/result/mapper.go +++ /dev/null @@ -1,29 +0,0 @@ -package result - -import ( - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" -) - -func ResolvePriority(result v1alpha2.PolicyReportResult) v1alpha2.Priority { - if result.Result == v1alpha2.StatusSkip { - return v1alpha2.DebugPriority - } - - if result.Result == v1alpha2.StatusPass { - return v1alpha2.InfoPriority - } - - if result.Result == v1alpha2.StatusError { - return v1alpha2.ErrorPriority - } - - if result.Result == v1alpha2.StatusWarn { - return v1alpha2.WarningPriority - } - - if result.Severity != "" { - return v1alpha2.PriorityFromSeverity(result.Severity) - } - - return v1alpha2.WarningPriority -} diff --git a/pkg/report/result/mapper_test.go b/pkg/report/result/mapper_test.go deleted file mode 100644 index 143acfb0..00000000 --- a/pkg/report/result/mapper_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package result_test - -import ( - "testing" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report/result" -) - -func Test_ResolvePriority(t *testing.T) { - t.Run("Status Skip", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusSkip, - Severity: v1alpha2.SeverityHigh, - }) - - if priority != v1alpha2.DebugPriority { - t.Errorf("expected priority debug, got %s", priority.String()) - } - }) - - t.Run("Status Pass", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusPass, - Severity: v1alpha2.SeverityHigh, - }) - - if priority != v1alpha2.InfoPriority { - t.Errorf("expected priority info, got %s", priority.String()) - } - }) - - t.Run("Status Warning", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusWarn, - Severity: v1alpha2.SeverityHigh, - }) - - if priority != v1alpha2.WarningPriority { - t.Errorf("expected priority warning, got %s", priority.String()) - } - }) - - t.Run("Status Error", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusError, - Severity: v1alpha2.SeverityHigh, - }) - - if priority != v1alpha2.ErrorPriority { - t.Errorf("expected priority warning, got %s", priority.String()) - } - }) - - t.Run("Status Fail Fallback", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusFail, - }) - - if priority != v1alpha2.WarningPriority { - t.Errorf("expected priority warning as fail fallback, got %s", priority.String()) - } - }) - - t.Run("Status Severity", func(t *testing.T) { - priority := result.ResolvePriority(v1alpha2.PolicyReportResult{ - Result: v1alpha2.StatusFail, - Severity: v1alpha2.SeverityCritical, - }) - - if priority != v1alpha2.CriticalPriority { - t.Errorf("expected priority critical, got %s", priority.String()) - } - }) -} diff --git a/pkg/report/result/reconditioner.go b/pkg/report/result/reconditioner.go index cb1c3ec2..be9bb307 100644 --- a/pkg/report/result/reconditioner.go +++ b/pkg/report/result/reconditioner.go @@ -21,7 +21,6 @@ func (r *Reconditioner) Prepare(polr v1alpha2.ReportInterface) v1alpha2.ReportIn results := polr.GetResults() for i, r := range results { r.ID = generator.Generate(polr, r) - r.Priority = ResolvePriority(r) r.Category = helper.Defaults(r.Category, "Other") scope := polr.GetScope() diff --git a/pkg/report/result/reconditioner_test.go b/pkg/report/result/reconditioner_test.go index 9ad52ff9..97287db6 100644 --- a/pkg/report/result/reconditioner_test.go +++ b/pkg/report/result/reconditioner_test.go @@ -3,10 +3,11 @@ package result_test import ( "testing" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/report/result" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/report/result" ) func TestReconditioner(t *testing.T) { @@ -58,9 +59,6 @@ func TestReconditioner(t *testing.T) { if res.Category != "Other" { t.Error("result category should default to Other") } - if res.Priority != v1alpha2.ErrorPriority { - t.Error("result prioriry should be mapped") - } if len(res.Resources) == 0 || res.Resources[0] != *report.GetScope() { t.Error("result resource should be mapped to scope") } @@ -116,9 +114,6 @@ func TestReconditioner(t *testing.T) { if res.Category != "Other" { t.Error("result category should default to Other") } - if res.Priority != v1alpha2.ErrorPriority { - t.Error("result prioriry should be mapped") - } if len(res.Resources) == 0 || res.Resources[0] != *report.GetScope() { t.Error("result resource should be mapped to scope") } diff --git a/pkg/report/result/resource.go b/pkg/report/result/resource.go index cfa40b2a..c04cc095 100644 --- a/pkg/report/result/resource.go +++ b/pkg/report/result/resource.go @@ -1,8 +1,9 @@ package result import ( - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" corev1 "k8s.io/api/core/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" ) func Resource(p v1alpha2.ReportInterface, r v1alpha2.PolicyReportResult) *corev1.ObjectReference { diff --git a/pkg/report/result/resource_test.go b/pkg/report/result/resource_test.go index b1d9c2b0..1cd3c619 100644 --- a/pkg/report/result/resource_test.go +++ b/pkg/report/result/resource_test.go @@ -3,9 +3,10 @@ package result_test import ( "testing" + corev1 "k8s.io/api/core/v1" + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/report/result" - corev1 "k8s.io/api/core/v1" ) func TestResource(t *testing.T) { diff --git a/pkg/report/result_filter.go b/pkg/report/result_filter.go new file mode 100644 index 00000000..70fe9178 --- /dev/null +++ b/pkg/report/result_filter.go @@ -0,0 +1,31 @@ +package report + +import ( + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" +) + +type ResultValidation = func(v1alpha2.PolicyReportResult) bool + +type ResultFilter struct { + validations []ResultValidation + Sources []string + MinimumSeverity string +} + +func (rf *ResultFilter) AddValidation(v ResultValidation) { + rf.validations = append(rf.validations, v) +} + +func (rf *ResultFilter) Validate(result v1alpha2.PolicyReportResult) bool { + for _, validation := range rf.validations { + if !validation(result) { + return false + } + } + + return true +} + +func NewResultFilter() *ResultFilter { + return &ResultFilter{} +} diff --git a/pkg/report/result_filter_test.go b/pkg/report/result_filter_test.go new file mode 100644 index 00000000..bfcc0b8a --- /dev/null +++ b/pkg/report/result_filter_test.go @@ -0,0 +1,25 @@ +package report_test + +import ( + "testing" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/fixtures" + "github.com/kyverno/policy-reporter/pkg/report" +) + +func Test_ResultFilter(t *testing.T) { + t.Run("don't filter any result without validations", func(t *testing.T) { + filter := report.NewResultFilter() + if !filter.Validate(fixtures.FailResult) { + t.Error("Expected result validates to true") + } + }) + t.Run("filter result with a false validation", func(t *testing.T) { + filter := report.NewResultFilter() + filter.AddValidation(func(r v1alpha2.PolicyReportResult) bool { return false }) + if filter.Validate(fixtures.FailResult) { + t.Error("Expected result validates to false") + } + }) +} diff --git a/pkg/report/source_filter.go b/pkg/report/source_filter.go new file mode 100644 index 00000000..2d40515c --- /dev/null +++ b/pkg/report/source_filter.go @@ -0,0 +1,154 @@ +package report + +import ( + "strings" + + "go.uber.org/zap" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/validate" +) + +type PodClient interface { + Get(res *corev1.ObjectReference) (*corev1.Pod, error) +} + +type JobClient interface { + Get(res *corev1.ObjectReference) (*batchv1.Job, error) +} + +type ReportSelector struct { + Source string +} + +type SourceValidation struct { + Selector ReportSelector + Kinds validate.RuleSets + Sources validate.RuleSets + Namespaces validate.RuleSets + UncontrolledOnly bool + DisableClusterReports bool +} + +type SourceFilter struct { + pods PodClient + jobs JobClient + validations []SourceValidation +} + +func (s *SourceFilter) Validate(polr v1alpha2.ReportInterface) bool { + for _, validation := range s.validations { + if ok := s.run(polr, validation); !ok { + return false + } + } + + return true +} + +func (s *SourceFilter) run(polr v1alpha2.ReportInterface, options SourceValidation) bool { + logger := zap.L().With( + zap.String("namespace", polr.GetNamespace()), + zap.String("report", polr.GetName()), + ) + + if !Match(polr, options.Selector) { + return true + } + + if options.DisableClusterReports && polr.GetNamespace() == "" { + logger.Debug("filter cluster report") + return false + } + + if options.Sources.Enabled() && !validate.MatchRuleSet(polr.GetSource(), options.Sources) { + logger.Debug("filter report source") + return false + } + + scope := polr.GetScope() + if scope == nil { + return true + } + + logger = logger.With( + zap.String("kind", scope.Kind), + zap.String("name", scope.Name), + zap.String("namespace", scope.Namespace), + ) + + if options.Kinds.Enabled() && !validate.MatchRuleSet(scope.Kind, options.Kinds) { + logger.Debug("filter scope resource kind") + return false + } + + if options.Namespaces.Enabled() && !validate.MatchRuleSet(scope.Namespace, options.Namespaces) { + logger.Debug("filter scope resource namespace") + return false + } + + if options.UncontrolledOnly && s.pods != nil && scope.Kind == "Pod" { + pod, err := s.pods.Get(scope) + if err != nil { + logger.Error("failed to get pod", zap.Error(err), zap.String("name", scope.Name), zap.String("namespace", scope.Namespace)) + return true + } + + if ok := Uncontrolled(pod.OwnerReferences); ok { + return true + } + + logger.Debug("filter controlled pod resource") + return false + } + + if options.UncontrolledOnly && s.jobs != nil && scope.Kind == "Job" { + job, err := s.jobs.Get(scope) + if err != nil { + logger.Error("failed to get job", zap.Error(err)) + return true + } + + if ok := Uncontrolled(job.OwnerReferences); ok { + return true + } + + logger.Debug("filter controlled job resource") + return false + } + + return true +} + +func NewSourceFilter(pods PodClient, jobs JobClient, validations []SourceValidation) *SourceFilter { + return &SourceFilter{pods: pods, jobs: jobs, validations: validations} +} + +var controller = []string{"ReplicaSet", "DaemonSet", "CronJob", "Job", "Job", "StatefulSet"} + +func Uncontrolled(owner []metav1.OwnerReference) bool { + if len(owner) == 0 { + return true + } + + for _, o := range owner { + isController := o.Controller + if isController == nil { + continue + } + + if *isController == true && helper.Contains(o.Kind, controller) { + return false + } + } + + return true +} + +func Match(polr v1alpha2.ReportInterface, selector ReportSelector) bool { + return selector.Source == "" || strings.ToLower(selector.Source) == strings.ToLower(polr.GetSource()) +} diff --git a/pkg/target/client.go b/pkg/target/client.go index 7e96a97f..25d849ce 100644 --- a/pkg/target/client.go +++ b/pkg/target/client.go @@ -5,41 +5,54 @@ import ( "strings" "github.com/kyverno/go-wildcard" + "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/kubernetes/namespaces" "github.com/kyverno/policy-reporter/pkg/report" "github.com/kyverno/policy-reporter/pkg/validate" ) +type ClientType = string + +const ( + SingleSend ClientType = "single" + BatchSend ClientType = "batch" + SyncSend ClientType = "sync" +) + // Client for a provided Target type Client interface { // Send the given Result to the configured Target Send(result v1alpha2.PolicyReportResult) + // BatchSend the given Results of a single PolicyReport to the configured Target + BatchSend(report v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) // SkipExistingOnStartup skips already existing PolicyReportResults on startup SkipExistingOnStartup() bool // Name is a unique identifier for each Target Name() string // Validate if a result should send Validate(rep v1alpha2.ReportInterface, result v1alpha2.PolicyReportResult) bool - // MinimumPriority for a triggered Result to send to this target - MinimumPriority() string + // MinimumSeverity for a triggered Result to send to this target + MinimumSeverity() string // Sources of the Results which should send to this target, empty means all sources Sources() []string - // Cleanup old results if supported by the target + // Type for the given target + Type() ClientType + // CleanUp old results if supported by the target CleanUp(context.Context, v1alpha2.ReportInterface) + // Reset the current state in the related target + Reset(context.Context) error } -func NewResultFilter(namespace, priority, policy validate.RuleSets, minimumPriority string, sources []string) *report.ResultFilter { - f := report.NewResultFilter() - f.Sources = sources - f.MinimumPriority = minimumPriority +type ResultFilterFactory struct { + client namespaces.Client +} - if len(sources) > 0 { - f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { - return helper.Contains(r.Source, sources) - }) - } +func (rf *ResultFilterFactory) CreateFilter(namespace, severity, status, policy, sources validate.RuleSets, minimumSeverity string) *report.ResultFilter { + f := report.NewResultFilter() + f.Sources = sources.Include + f.MinimumSeverity = minimumSeverity if namespace.Count() > 0 { f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { @@ -51,9 +64,31 @@ func NewResultFilter(namespace, priority, policy validate.RuleSets, minimumPrior }) } - if minimumPriority != "" { + if len(namespace.Selector) > 0 { f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { - return r.Priority >= v1alpha2.NewPriority(f.MinimumPriority) + if r.GetResource() == nil || r.GetResource().Namespace == "" { + return true + } + + namespaces, err := rf.client.List(context.Background(), namespace.Selector) + if err != nil { + zap.L().Error("failed to resolve namespace selector", zap.Error(err)) + return false + } + + return validate.Namespace(r.GetResource().Namespace, validate.RuleSets{Include: namespaces}) + }) + } + + if minimumSeverity != "" { + f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { + return v1alpha2.SeverityLevel[r.Severity] >= v1alpha2.SeverityLevel[v1alpha2.PolicySeverity(f.MinimumSeverity)] + }) + } + + if sources.Count() > 0 { + f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { + return validate.MatchRuleSet(r.Source, sources) }) } @@ -63,17 +98,24 @@ func NewResultFilter(namespace, priority, policy validate.RuleSets, minimumPrior }) } - if priority.Count() > 0 { + if severity.Count() > 0 { f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { - return validate.ContainsRuleSet(r.Priority.String(), priority) + return validate.ContainsRuleSet(string(r.Severity), severity) + }) + } + + if status.Count() > 0 { + f.AddValidation(func(r v1alpha2.PolicyReportResult) bool { + return validate.ContainsRuleSet(string(r.Result), status) }) } return f } -func NewReportFilter(labels validate.RuleSets) *report.ReportFilter { +func NewReportFilter(labels, sources validate.RuleSets) *report.ReportFilter { f := report.NewReportFilter() + if labels.Count() > 0 { f.AddValidation(func(r v1alpha2.ReportInterface) bool { if len(labels.Include) > 0 { @@ -116,9 +158,24 @@ func NewReportFilter(labels validate.RuleSets) *report.ReportFilter { }) } + if sources.Count() > 0 { + f.AddValidation(func(r v1alpha2.ReportInterface) bool { + source := r.GetSource() + if source == "" { + return true + } + + return validate.MatchRuleSet(source, sources) + }) + } + return f } +func NewResultFilterFactory(client namespaces.Client) *ResultFilterFactory { + return &ResultFilterFactory{client: client} +} + type BaseClient struct { name string skipExistingOnStartup bool @@ -137,12 +194,12 @@ func (c *BaseClient) Name() string { return c.name } -func (c *BaseClient) MinimumPriority() string { +func (c *BaseClient) MinimumSeverity() string { if c.resultFilter == nil { - return v1alpha2.DefaultPriority.String() + return v1alpha2.SeverityInfo } - return c.resultFilter.MinimumPriority + return c.resultFilter.MinimumSeverity } func (c *BaseClient) Sources() []string { @@ -154,11 +211,7 @@ func (c *BaseClient) Sources() []string { } func (c *BaseClient) Validate(rep v1alpha2.ReportInterface, result v1alpha2.PolicyReportResult) bool { - if rep == nil { - return false - } - - if c.reportFilter != nil && !c.reportFilter.Validate(rep) { + if !c.ValidateReport(rep) { return false } @@ -169,10 +222,30 @@ func (c *BaseClient) Validate(rep v1alpha2.ReportInterface, result v1alpha2.Poli return true } +func (c *BaseClient) ValidateReport(rep v1alpha2.ReportInterface) bool { + if rep == nil { + return false + } + + if c.reportFilter != nil && !c.reportFilter.Validate(rep) { + return false + } + + return true +} + func (c *BaseClient) SkipExistingOnStartup() bool { return c.skipExistingOnStartup } +func (c *BaseClient) Reset(_ context.Context) error { + return nil +} + +func (c *BaseClient) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} + +func (c *BaseClient) BatchSend(_ v1alpha2.ReportInterface, _ []v1alpha2.PolicyReportResult) {} + func NewBaseClient(options ClientOptions) BaseClient { return BaseClient{options.Name, options.SkipExistingOnStartup, options.ResultFilter, options.ReportFilter} } diff --git a/pkg/target/client_test.go b/pkg/target/client_test.go index 90f64be7..8f90e5fe 100644 --- a/pkg/target/client_test.go +++ b/pkg/target/client_test.go @@ -3,6 +3,7 @@ package target_test import ( "testing" + "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" @@ -18,187 +19,226 @@ var preport = &v1alpha2.PolicyReport{ }, } +var factory = target.NewResultFilterFactory(nil) + func Test_BaseClient(t *testing.T) { - t.Run("Validate MinimumPriority", func(t *testing.T) { - filter := target.NewResultFilter( + t.Run("Validate MinimumSeverity", func(t *testing.T) { + filter := factory.CreateFilter( validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, - "error", - make([]string, 0), + validate.RuleSets{}, + validate.RuleSets{}, + v1alpha2.SeverityCritical, ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Source", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{Include: []string{"jsPolicy"}}, "", - []string{"jsPolicy"}, ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate ClusterResult", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{Include: []string{"default"}}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResultWithoutResource) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResultWithoutResource), "Unexpected Validation Result") }) t.Run("Validate Exclude Namespace match", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{Exclude: []string{"test"}}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Exclude Namespace mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{Exclude: []string{"team-a"}}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Include Namespace match", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{Include: []string{"test"}}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Exclude Namespace mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( validate.RuleSets{Include: []string{"team-a"}}, validate.RuleSets{}, validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) - t.Run("Validate Exclude Priority match", func(t *testing.T) { - filter := target.NewResultFilter( + t.Run("Validate Exclude Status match", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{Exclude: []string{v1alpha2.StatusFail}}, validate.RuleSets{}, - validate.RuleSets{Exclude: []string{v1alpha2.WarningPriority.String()}}, validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) - t.Run("Validate Exclude Priority mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + t.Run("Validate Exclude Status mismatch", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{Exclude: []string{v1alpha2.StatusSkip}}, validate.RuleSets{}, - validate.RuleSets{Exclude: []string{v1alpha2.ErrorPriority.String()}}, validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) - t.Run("Validate Include Priority match", func(t *testing.T) { - filter := target.NewResultFilter( + t.Run("Validate Include Status match", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{Include: []string{v1alpha2.StatusFail}}, validate.RuleSets{}, - validate.RuleSets{Include: []string{v1alpha2.WarningPriority.String()}}, validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) - t.Run("Validate Exclude Priority mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + t.Run("Validate Exclude Status mismatch", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{Exclude: []string{v1alpha2.StatusFail}}, validate.RuleSets{}, - validate.RuleSets{Include: []string{v1alpha2.ErrorPriority.String()}}, validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") + }) + + t.Run("Validate Exclude Severity match", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{Exclude: []string{v1alpha2.SeverityHigh}}, + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, + "", + ) + + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") + }) + t.Run("Validate Exclude Severity mismatch", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{Exclude: []string{v1alpha2.SeverityCritical}}, + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, + "", + ) + + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") + }) + t.Run("Validate Include Severity match", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{Include: []string{v1alpha2.SeverityHigh}}, + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, + "", + ) + + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") + }) + t.Run("Validate Exclude Severity mismatch", func(t *testing.T) { + filter := factory.CreateFilter( + validate.RuleSets{}, + validate.RuleSets{Include: []string{v1alpha2.SeverityCritical}}, + validate.RuleSets{}, + validate.RuleSets{}, + validate.RuleSets{}, + "", + ) + + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Exclude Policy match", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( + validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{Exclude: []string{"require-requests-and-limits-required"}}, + validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Exclude Policy mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( + validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{Exclude: []string{"policy-test"}}, + validate.RuleSets{}, "", - make([]string, 0), ) - if !filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Include Policy match", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( + validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{Include: []string{"require-requests-and-limits-required"}}, + validate.RuleSets{}, "", - make([]string, 0), ) if !filter.Validate(fixtures.FailResult) { @@ -206,31 +246,30 @@ func Test_BaseClient(t *testing.T) { } }) t.Run("Validate Exclude Policy mismatch", func(t *testing.T) { - filter := target.NewResultFilter( + filter := factory.CreateFilter( + validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{Include: []string{"policy-test"}}, + validate.RuleSets{}, "", - make([]string, 0), ) - if filter.Validate(fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Validate Include Label match", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Include: []string{"app:policy-reporter"}}, + validate.RuleSets{}, ) - if !filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Validate Exclude Label match", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Exclude: []string{"app:policy-reporter"}}, + validate.RuleSets{}, ) if filter.Validate(preport) { @@ -240,97 +279,92 @@ func Test_BaseClient(t *testing.T) { t.Run("Validate Exclude Label mismatch", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Exclude: []string{"app:monitoring"}}, + validate.RuleSets{}, ) - if !filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Validate Include Label mismatch", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Include: []string{"app:monitoring"}}, + validate.RuleSets{}, ) - if filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Validate label as wildcard filter", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Exclude: []string{"app"}}, + validate.RuleSets{}, ) - if filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(preport), "Unexpected Validation Result") filter = target.NewReportFilter( validate.RuleSets{Include: []string{"app"}}, + validate.RuleSets{}, ) - if !filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Validate Include Label wildcard", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Include: []string{"app:*"}}, + validate.RuleSets{}, ) - if !filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.True(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Validate Exclude Label wildcard", func(t *testing.T) { filter := target.NewReportFilter( validate.RuleSets{Exclude: []string{"app:*"}}, + validate.RuleSets{}, ) - if filter.Validate(preport) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, filter.Validate(preport), "Unexpected Validation Result") }) t.Run("Client Result Validation", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ Name: "Client", - ResultFilter: target.NewResultFilter( + ResultFilter: factory.CreateFilter( validate.RuleSets{}, validate.RuleSets{}, validate.RuleSets{Include: []string{"policy-test"}}, + validate.RuleSets{}, + validate.RuleSets{Include: []string{"jsPolicy"}}, "", - []string{"jsPolicy"}, ), SkipExistingOnStartup: true, }) - if client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Client Report Validation", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ - Name: "Client", - ReportFilter: target.NewReportFilter(validate.RuleSets{Include: []string{"app"}}), + Name: "Client", + ReportFilter: target.NewReportFilter( + validate.RuleSets{Include: []string{"app"}}, + validate.RuleSets{}, + ), SkipExistingOnStartup: true, }) - if client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Client nil Validation", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ - Name: "Client", - ReportFilter: target.NewReportFilter(validate.RuleSets{Include: []string{"app"}}), + Name: "Client", + ReportFilter: target.NewReportFilter( + validate.RuleSets{Include: []string{"app"}}, + validate.RuleSets{}, + ), SkipExistingOnStartup: true, }) - if client.Validate(nil, fixtures.FailResult) { - t.Errorf("Unexpected Validation Result") - } + assert.False(t, client.Validate(nil, fixtures.FailResult), "Unexpected Validation Result") }) t.Run("Client Validation Fallbacks", func(t *testing.T) { @@ -339,15 +373,9 @@ func Test_BaseClient(t *testing.T) { SkipExistingOnStartup: true, }) - if !client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult) { - t.Errorf("Should fallback to true") - } - if client.MinimumPriority() != v1alpha2.DefaultPriority.String() { - t.Errorf("Should fallback to default priority") - } - if len(client.Sources()) != 0 || client.Sources() == nil { - t.Errorf("Should fallback to empty list") - } + assert.True(t, client.Validate(&v1alpha2.PolicyReport{}, fixtures.FailResult), "Should fallback to true") + assert.Equal(t, client.MinimumSeverity(), v1alpha2.SeverityInfo, "Should fallback to severity info") + assert.NotNil(t, client.Sources(), "Should fallback to empty list") }) t.Run("SkipExistingOnStartup", func(t *testing.T) { @@ -357,31 +385,25 @@ func Test_BaseClient(t *testing.T) { SkipExistingOnStartup: true, }) - if !client.SkipExistingOnStartup() { - t.Error("Should return configured SkipExistingOnStartup") - } + assert.True(t, client.SkipExistingOnStartup(), "Should return configured SkipExistingOnStartup") }) - t.Run("MinimumPriority", func(t *testing.T) { + t.Run("MinimumSeverity", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ Name: "Client", - ResultFilter: &report.ResultFilter{MinimumPriority: "error"}, + ResultFilter: &report.ResultFilter{MinimumSeverity: v1alpha2.SeverityHigh}, SkipExistingOnStartup: true, }) - if client.MinimumPriority() != "error" { - t.Error("Should return configured MinimumPriority") - } + assert.Equal(t, client.MinimumSeverity(), v1alpha2.SeverityHigh, "Should return configured MinimumSeverity") }) t.Run("Name", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ Name: "Client", - ResultFilter: &report.ResultFilter{MinimumPriority: "error"}, + ResultFilter: &report.ResultFilter{MinimumSeverity: "error"}, SkipExistingOnStartup: true, }) - if client.Name() != "Client" { - t.Error("Should return configured Name") - } + assert.Equal(t, client.Name(), "Client", "Should return configured Name") }) t.Run("Sources", func(t *testing.T) { client := target.NewBaseClient(target.ClientOptions{ @@ -390,11 +412,7 @@ func Test_BaseClient(t *testing.T) { SkipExistingOnStartup: true, }) - if len(client.Sources()) != 1 { - t.Fatal("Unexpected length of Sources") - } - if client.Sources()[0] != "Kyverno" { - t.Error("Unexptected Source returned") - } + assert.Len(t, client.Sources(), 1) + assert.Equal(t, client.Sources()[0], "Kyverno") }) } diff --git a/pkg/target/collection.go b/pkg/target/collection.go new file mode 100644 index 00000000..090ba33a --- /dev/null +++ b/pkg/target/collection.go @@ -0,0 +1,144 @@ +package target + +import ( + "context" + "sync" + + "go.uber.org/zap" + + "github.com/kyverno/policy-reporter/pkg/helper" +) + +type TargetType = string + +const ( + Loki TargetType = "Loki" + Elasticsearch TargetType = "Elasticsearch" + Slack TargetType = "Slack" + Discord TargetType = "Discord" + Teams TargetType = "Teams" + GoogleChat TargetType = "GoogleChat" + Telegram TargetType = "Telegram" + Webhook TargetType = "Webhook" + S3 TargetType = "S3" + Kinesis TargetType = "Kinesis" + SecurityHub TargetType = "SecurityHub" + GCS TargetType = "GCS" +) + +type TargetConfig interface { + Secret() string +} + +type Target struct { + ID string + Type TargetType + Client Client + ParentConfig TargetConfig + Config TargetConfig +} + +func (t *Target) Secret() string { + if t.Config.Secret() != "" { + return t.Config.Secret() + } + + return t.ParentConfig.Secret() +} + +type Collection struct { + mx *sync.Mutex + clients []Client + targets map[string]*Target +} + +func (c *Collection) Update(t *Target) { + c.mx.Lock() + c.targets[t.ID] = t + c.clients = make([]Client, 0) + c.mx.Unlock() +} + +func (c *Collection) Reset(ctx context.Context) bool { + clients := c.SyncClients() + + for _, c := range clients { + if err := c.Reset(ctx); err != nil { + zap.L().Error("failed to reset target", zap.String("type", c.Type()), zap.String("name", c.Name())) + } + } + + return true +} + +func (c *Collection) Targets() []*Target { + return helper.ToList(c.targets) +} + +func (c *Collection) Clients() []Client { + if len(c.clients) != 0 { + return c.clients + } + + c.clients = helper.MapSlice(c.targets, func(t *Target) Client { + return t.Client + }) + + return c.clients +} + +func (c *Collection) Client(name string) Client { + return helper.Find(c.Clients(), func(c Client) bool { + return c.Name() == name + }, nil) +} + +func (c *Collection) SingleSendClients() []Client { + return helper.Filter(c.Clients(), func(c Client) bool { + return c.Type() == SingleSend + }) +} + +func (c *Collection) SyncClients() []Client { + return helper.Filter(c.Clients(), func(c Client) bool { + return c.Type() == SyncSend + }) +} + +func (c *Collection) BatchSendClients() []Client { + return helper.Filter(c.Clients(), func(c Client) bool { + return c.Type() == BatchSend + }) +} + +func (c *Collection) UsesSecrets() bool { + useSecrets := helper.Filter(c.Targets(), func(t *Target) bool { + return t.Secret() != "" + }) + + return len(useSecrets) > 0 +} + +func (c *Collection) Empty() bool { + return c.Length() == 0 +} + +func (c *Collection) Length() int { + return len(c.targets) +} + +func NewCollection(targets ...*Target) *Collection { + collection := &Collection{ + clients: make([]Client, 0), + targets: make(map[string]*Target, 0), + mx: new(sync.Mutex), + } + + for _, t := range targets { + if t != nil { + collection.Update(t) + } + } + + return collection +} diff --git a/pkg/target/collection_test.go b/pkg/target/collection_test.go new file mode 100644 index 00000000..61b2e5e0 --- /dev/null +++ b/pkg/target/collection_test.go @@ -0,0 +1,88 @@ +package target_test + +import ( + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/discord" + "github.com/kyverno/policy-reporter/pkg/target/slack" + "github.com/kyverno/policy-reporter/pkg/target/webhook" +) + +func TestCollection(t *testing.T) { + collection := target.NewCollection( + &target.Target{ + ID: uuid.NewString(), + Type: target.Webhook, + Client: webhook.NewClient(webhook.Options{ + ClientOptions: target.ClientOptions{ + Name: "Webhook", + }, + }), + Config: &target.Config[target.WebhookOptions]{SecretRef: "webhook-secret"}, + ParentConfig: &target.Config[target.WebhookOptions]{}, + }, + &target.Target{ + ID: uuid.NewString(), + Type: target.Slack, + Client: slack.NewClient(slack.Options{ + ClientOptions: target.ClientOptions{ + Name: "Slack", + }, + }), + Config: &target.Config[target.SlackOptions]{}, + ParentConfig: &target.Config[target.SlackOptions]{SecretRef: "slack-secret"}, + }, + &target.Target{ + ID: uuid.NewString(), + Type: target.Discord, + Client: discord.NewClient(discord.Options{ + ClientOptions: target.ClientOptions{ + Name: "Discord", + }, + }), + Config: &target.Config[target.WebhookOptions]{}, + ParentConfig: &target.Config[target.WebhookOptions]{SecretRef: "slack-secret"}, + }, + ) + + t.Run("empty returns if the collection has any target", func(t *testing.T) { + assert.True(t, target.NewCollection().Empty()) + assert.False(t, collection.Empty()) + }) + + t.Run("length returns the amount of targets within a collection", func(t *testing.T) { + assert.Equal(t, collection.Length(), 3) + }) + + t.Run("clients returns all clients of the given targets", func(t *testing.T) { + assert.Equal(t, len(collection.Clients()), 3) + }) + + t.Run("client searches for a configured target with the given name", func(t *testing.T) { + assert.NotNil(t, collection.Client("Webhook")) + assert.NotNil(t, collection.Client("Discord")) + assert.NotNil(t, collection.Client("Slack")) + assert.Nil(t, collection.Client("Invalid")) + }) + + t.Run("usesSecret checks if at least on target has a secretRef configured", func(t *testing.T) { + assert.False(t, target.NewCollection().UsesSecrets()) + assert.True(t, collection.UsesSecrets()) + }) + + t.Run("SingleSendClients only returns clients which do not support batch sending", func(t *testing.T) { + for _, c := range collection.SingleSendClients() { + assert.Equal(t, target.SingleSend, c.Type()) + } + }) + + t.Run("BatchSendClients only returns clients which do support batch sending", func(t *testing.T) { + for _, c := range collection.BatchSendClients() { + assert.Equal(t, target.BatchSend, c.Type()) + } + }) +} diff --git a/pkg/target/discord/discord.go b/pkg/target/discord/discord.go index 05c653fc..58bb7f36 100644 --- a/pkg/target/discord/discord.go +++ b/pkg/target/discord/discord.go @@ -35,16 +35,16 @@ type embedField struct { Inline bool `json:"inline"` } -var colors = map[v1alpha2.Priority]string{ - v1alpha2.DebugPriority: "12370112", - v1alpha2.InfoPriority: "3066993", - v1alpha2.WarningPriority: "15105570", - v1alpha2.CriticalPriority: "15158332", - v1alpha2.ErrorPriority: "15158332", +var colors = map[v1alpha2.PolicySeverity]string{ + v1alpha2.SeverityInfo: "12370112", + v1alpha2.SeverityLow: "3066993", + v1alpha2.StatusWarn: "15105570", + v1alpha2.SeverityHigh: "15158332", + v1alpha2.SeverityCritical: "15158332", } func newPayload(result v1alpha2.PolicyReportResult, customFields map[string]string) payload { - color := colors[result.Priority] + color := colors[result.Severity] embedFields := make([]embedField, 0) @@ -54,8 +54,6 @@ func newPayload(result v1alpha2.PolicyReportResult, customFields map[string]stri embedFields = append(embedFields, embedField{"Rule", result.Rule, true}) } - embedFields = append(embedFields, embedField{"Priority", result.Priority.String(), true}) - if result.Category != "" { embedFields = append(embedFields, embedField{"Category", result.Category, true}) } @@ -106,7 +104,7 @@ type client struct { } func (d *client) Send(result v1alpha2.PolicyReportResult) { - req, err := http.CreateJSONRequest(d.Name(), "POST", d.webhook, newPayload(result, d.customFields)) + req, err := http.CreateJSONRequest("POST", d.webhook, newPayload(result, d.customFields)) if err != nil { return } @@ -117,6 +115,12 @@ func (d *client) Send(result v1alpha2.PolicyReportResult) { func (d *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (d *client) BatchSend(_ v1alpha2.ReportInterface, _ []v1alpha2.PolicyReportResult) {} + +func (d *client) Type() target.ClientType { + return target.SingleSend +} + // NewClient creates a new loki.client to send Results to Discord func NewClient(options Options) target.Client { return &client{ diff --git a/pkg/target/elasticsearch/elasticsearch.go b/pkg/target/elasticsearch/elasticsearch.go index 01760da6..211f6626 100644 --- a/pkg/target/elasticsearch/elasticsearch.go +++ b/pkg/target/elasticsearch/elasticsearch.go @@ -1,7 +1,6 @@ package elasticsearch import ( - "context" "time" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" @@ -83,7 +82,7 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { result.Properties = props } - req, err := http.CreateJSONRequest(e.Name(), "POST", host, http.NewJSONResult(result)) + req, err := http.CreateJSONRequest("POST", host, http.NewJSONResult(result)) if err != nil { return } @@ -98,7 +97,9 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { http.ProcessHTTPResponse(e.Name(), resp, err) } -func (e *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (e *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new elasticsearch.client to send Results to Elasticsearch func NewClient(options Options) target.Client { diff --git a/pkg/target/factory.go b/pkg/target/factory.go new file mode 100644 index 00000000..9f50ab6c --- /dev/null +++ b/pkg/target/factory.go @@ -0,0 +1,172 @@ +package target + +type ValueFilter struct { + Include []string `mapstructure:"include"` + Exclude []string `mapstructure:"exclude"` + Selector map[string]any `mapstructure:"selector"` +} + +type Filter struct { + Namespaces ValueFilter `mapstructure:"namespaces"` + Status ValueFilter `mapstructure:"status"` + Severities ValueFilter `mapstructure:"severities"` + Policies ValueFilter `mapstructure:"policies"` + Sources ValueFilter `mapstructure:"sources"` + ReportLabels ValueFilter `mapstructure:"reportLabels"` +} + +type Config[T any] struct { + Config *T `mapstructure:"config"` + Name string `mapstructure:"name"` + MinimumSeverity string `mapstructure:"minimumSeverity"` + Filter Filter `mapstructure:"filter"` + SecretRef string `mapstructure:"secretRef"` + MountedSecret string `mapstructure:"mountedSecret"` + Sources []string `mapstructure:"sources"` + CustomFields map[string]string `mapstructure:"customFields"` + SkipExisting bool `mapstructure:"skipExistingOnStartup"` + Channels []*Config[T] `mapstructure:"channels"` + Valid bool `mapstructure:"-"` +} + +func (config *Config[T]) MapBaseParent(parent *Config[T]) { + if config.MinimumSeverity == "" { + config.MinimumSeverity = parent.MinimumSeverity + } + + if !config.SkipExisting { + config.SkipExisting = parent.SkipExisting + } +} + +func (config *Config[T]) Secret() string { + return config.SecretRef +} + +type AWSConfig struct { + AccessKeyID string `mapstructure:"accessKeyId"` + SecretAccessKey string `mapstructure:"secretAccessKey"` + Region string `mapstructure:"region"` + Endpoint string `mapstructure:"endpoint"` +} + +func (config *AWSConfig) MapAWSParent(parent AWSConfig) { + if config.Endpoint == "" { + config.Endpoint = parent.Endpoint + } + + if config.AccessKeyID == "" { + config.AccessKeyID = parent.AccessKeyID + } + + if config.SecretAccessKey == "" { + config.SecretAccessKey = parent.SecretAccessKey + } + + if config.Region == "" { + config.Region = parent.Region + } +} + +type WebhookOptions struct { + Webhook string `mapstructure:"webhook"` + SkipTLS bool `mapstructure:"skipTLS"` + Certificate string `mapstructure:"certificate"` + Headers map[string]string `mapstructure:"headers"` +} + +type HostOptions struct { + Host string `mapstructure:"host"` + SkipTLS bool `mapstructure:"skipTLS"` + Certificate string `mapstructure:"certificate"` + Headers map[string]string `mapstructure:"headers"` +} + +type TelegramOptions struct { + WebhookOptions `mapstructure:",squash"` + Token string `mapstructure:"token"` + ChatID string `mapstructure:"chatId"` +} + +type SlackOptions struct { + WebhookOptions `mapstructure:",squash"` + Channel string `mapstructure:"channel"` +} + +type LokiOptions struct { + HostOptions `mapstructure:",squash"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + Path string `mapstructure:"path"` +} + +type ElasticsearchOptions struct { + HostOptions `mapstructure:",squash"` + Index string `mapstructure:"index"` + Rotation string `mapstructure:"rotation"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + APIKey string `mapstructure:"apiKey"` + TypelessAPI bool `mapstructure:"typelessApi"` +} + +type S3Options struct { + AWSConfig `mapstructure:",squash"` + Prefix string `mapstructure:"prefix"` + Bucket string `mapstructure:"bucket"` + BucketKeyEnabled bool `mapstructure:"bucketKeyEnabled"` + KmsKeyID string `mapstructure:"kmsKeyId"` + ServerSideEncryption string `mapstructure:"serverSideEncryption"` + PathStyle bool `mapstructure:"pathStyle"` +} + +type KinesisOptions struct { + AWSConfig `mapstructure:",squash"` + StreamName string `mapstructure:"streamName"` +} + +type SecurityHubOptions struct { + AWSConfig `mapstructure:",squash"` + AccountID string `mapstructure:"accountId"` + ProductName string `mapstructure:"productName"` + CompanyName string `mapstructure:"companyName"` + DelayInSeconds int `mapstructure:"delayInSeconds"` + Synchronize bool `mapstructure:"synchronize"` +} + +type GCSOptions struct { + Credentials string `mapstructure:"credentials"` + Prefix string `mapstructure:"prefix"` + Bucket string `mapstructure:"bucket"` +} + +type Targets struct { + Loki *Config[LokiOptions] `mapstructure:"loki"` + Elasticsearch *Config[ElasticsearchOptions] `mapstructure:"elasticsearch"` + Slack *Config[SlackOptions] `mapstructure:"slack"` + Discord *Config[WebhookOptions] `mapstructure:"discord"` + Teams *Config[WebhookOptions] `mapstructure:"teams"` + Webhook *Config[WebhookOptions] `mapstructure:"webhook"` + GoogleChat *Config[WebhookOptions] `mapstructure:"googleChat"` + Telegram *Config[TelegramOptions] `mapstructure:"telegram"` + S3 *Config[S3Options] `mapstructure:"s3"` + Kinesis *Config[KinesisOptions] `mapstructure:"kinesis"` + SecurityHub *Config[SecurityHubOptions] `mapstructure:"securityHub"` + GCS *Config[GCSOptions] `mapstructure:"gcs"` +} + +type Factory interface { + CreateClients(config *Targets) *Collection + CreateLokiTarget(config, parent *Config[LokiOptions]) *Target + CreateElasticsearchTarget(config, parent *Config[ElasticsearchOptions]) *Target + CreateSlackTarget(config, parent *Config[SlackOptions]) *Target + CreateDiscordTarget(config, parent *Config[WebhookOptions]) *Target + CreateTeamsTarget(config, parent *Config[WebhookOptions]) *Target + CreateWebhookTarget(config, parent *Config[WebhookOptions]) *Target + CreateTelegramTarget(config, parent *Config[TelegramOptions]) *Target + CreateGoogleChatTarget(config, parent *Config[WebhookOptions]) *Target + CreateS3Target(config, parent *Config[S3Options]) *Target + CreateKinesisTarget(config, parent *Config[KinesisOptions]) *Target + CreateSecurityHubTarget(config, parent *Config[SecurityHubOptions]) *Target + CreateGCSTarget(config, parent *Config[GCSOptions]) *Target +} diff --git a/pkg/target/factory/factory.go b/pkg/target/factory/factory.go new file mode 100644 index 00000000..bb27bc4e --- /dev/null +++ b/pkg/target/factory/factory.go @@ -0,0 +1,960 @@ +package factory + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strings" + "time" + + "github.com/google/uuid" + _ "github.com/mattn/go-sqlite3" + "go.uber.org/zap" + + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" + "github.com/kyverno/policy-reporter/pkg/report" + "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/discord" + "github.com/kyverno/policy-reporter/pkg/target/elasticsearch" + "github.com/kyverno/policy-reporter/pkg/target/gcs" + "github.com/kyverno/policy-reporter/pkg/target/googlechat" + "github.com/kyverno/policy-reporter/pkg/target/http" + "github.com/kyverno/policy-reporter/pkg/target/kinesis" + "github.com/kyverno/policy-reporter/pkg/target/loki" + "github.com/kyverno/policy-reporter/pkg/target/provider/aws" + gs "github.com/kyverno/policy-reporter/pkg/target/provider/gcs" + "github.com/kyverno/policy-reporter/pkg/target/s3" + "github.com/kyverno/policy-reporter/pkg/target/securityhub" + "github.com/kyverno/policy-reporter/pkg/target/slack" + "github.com/kyverno/policy-reporter/pkg/target/teams" + "github.com/kyverno/policy-reporter/pkg/target/telegram" + "github.com/kyverno/policy-reporter/pkg/target/webhook" + "github.com/kyverno/policy-reporter/pkg/validate" +) + +// TargetFactory manages target creation +type TargetFactory struct { + secretClient secrets.Client + filterFactory *target.ResultFilterFactory +} + +// LokiClients resolver method +func createClients[T any](name string, config *target.Config[T], mapper func(*target.Config[T], *target.Config[T]) *target.Target) []*target.Target { + clients := make([]*target.Target, 0) + if config == nil { + return clients + } + + if config.Config == nil { + config.Config = new(T) + } + + setFallback(&config.Name, name) + + if client := mapper(config, &target.Config[T]{Config: new(T)}); client != nil { + clients = append(clients, client) + config.Valid = true + } + + for i, channel := range config.Channels { + setFallback(&config.Name, fmt.Sprintf("%s Channel %d", name, i+1)) + + if channel.Config == nil { + channel.Config = new(T) + } + + if client := mapper(channel, config); client != nil { + clients = append(clients, client) + channel.Valid = true + } + } + + return clients +} + +// LokiClients resolver method +func (f *TargetFactory) CreateClients(config *target.Targets) *target.Collection { + targets := make([]*target.Target, 0) + if config == nil { + return target.NewCollection() + } + + targets = append(targets, createClients("Loki", config.Loki, f.CreateLokiTarget)...) + targets = append(targets, createClients("Elasticsearch", config.Elasticsearch, f.CreateElasticsearchTarget)...) + targets = append(targets, createClients("Slack", config.Slack, f.CreateSlackTarget)...) + targets = append(targets, createClients("Discord", config.Discord, f.CreateDiscordTarget)...) + targets = append(targets, createClients("Teams", config.Teams, f.CreateTeamsTarget)...) + targets = append(targets, createClients("GoogleChat", config.GoogleChat, f.CreateGoogleChatTarget)...) + targets = append(targets, createClients("Telegram", config.Telegram, f.CreateTelegramTarget)...) + targets = append(targets, createClients("Webhook", config.Webhook, f.CreateWebhookTarget)...) + targets = append(targets, createClients("S3", config.S3, f.CreateS3Target)...) + targets = append(targets, createClients("Kinesis", config.Kinesis, f.CreateKinesisTarget)...) + targets = append(targets, createClients("SecurityHub", config.SecurityHub, f.CreateSecurityHubTarget)...) + targets = append(targets, createClients("GoogleCloudStorage", config.GCS, f.CreateGCSTarget)...) + + return target.NewCollection(targets...) +} + +func (f *TargetFactory) CreateSlackTarget(config, parent *target.Config[target.SlackOptions]) *target.Target { + if config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + if config.Config.Webhook == "" && config.Config.Channel == "" { + return nil + } + + setFallback(&config.Config.Webhook, parent.Config.Webhook) + + if config.Config.Webhook == "" { + return nil + } + + config.MapBaseParent(parent) + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Slack, + Config: config, + ParentConfig: parent, + Client: slack.NewClient(slack.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Channel: config.Config.Channel, + Webhook: config.Config.Webhook, + CustomFields: config.CustomFields, + Headers: config.Config.Headers, + HTTPClient: http.NewClient("", false), + }), + } +} + +func (f *TargetFactory) CreateLokiTarget(config, parent *target.Config[target.LokiOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + if config.Config.Host == "" && parent.Config.Host == "" { + return nil + } + + setFallback(&config.Config.Path, "/loki/api/v1/push") + setFallback(&config.Config.Host, parent.Config.Host) + setFallback(&config.Config.Certificate, parent.Config.Certificate) + setFallback(&config.Config.Path, parent.Config.Path) + setFallback(&config.Config.Username, parent.Config.Username) + setFallback(&config.Config.Password, parent.Config.Password) + setBool(&config.Config.SkipTLS, parent.Config.SkipTLS) + + config.MapBaseParent(parent) + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Loki, + Config: config, + ParentConfig: parent, + Client: loki.NewClient(loki.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Host: config.Config.Host + config.Config.Path, + CustomFields: config.CustomFields, + Username: config.Config.Username, + Password: config.Config.Password, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + Headers: config.Config.Headers, + }), + } +} + +func (f *TargetFactory) CreateElasticsearchTarget(config, parent *target.Config[target.ElasticsearchOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + if config.Config.Host == "" && parent.Config.Host == "" { + return nil + } + + setFallback(&config.Config.Host, parent.Config.Host) + setFallback(&config.Config.Certificate, parent.Config.Certificate) + setBool(&config.Config.SkipTLS, parent.Config.SkipTLS) + setFallback(&config.Config.Username, parent.Config.Username) + setFallback(&config.Config.Password, parent.Config.Password) + setFallback(&config.Config.APIKey, parent.Config.APIKey) + setFallback(&config.Config.Index, parent.Config.Index, "policy-reporter") + setFallback(&config.Config.Rotation, parent.Config.Rotation, elasticsearch.Daily) + setBool(&config.Config.TypelessAPI, parent.Config.TypelessAPI) + + config.MapBaseParent(parent) + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Elasticsearch, + Config: config, + ParentConfig: parent, + Client: elasticsearch.NewClient(elasticsearch.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Host: config.Config.Host, + Username: config.Config.Username, + Password: config.Config.Password, + ApiKey: config.Config.APIKey, + Rotation: config.Config.Rotation, + Index: config.Config.Index, + TypelessApi: config.Config.TypelessAPI, + CustomFields: config.CustomFields, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateDiscordTarget(config, parent *target.Config[target.WebhookOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + mapWebhookTarget(config, parent) + + if config.Config.Webhook == "" { + return nil + } + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Discord, + Config: config, + ParentConfig: parent, + Client: discord.NewClient(discord.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Webhook: config.Config.Webhook, + CustomFields: config.CustomFields, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateTeamsTarget(config, parent *target.Config[target.WebhookOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + mapWebhookTarget(config, parent) + + if config.Config.Webhook == "" { + return nil + } + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Teams, + Config: config, + ParentConfig: parent, + Client: teams.NewClient(teams.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Webhook: config.Config.Webhook, + CustomFields: config.CustomFields, + Headers: config.Config.Headers, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateWebhookTarget(config, parent *target.Config[target.WebhookOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + mapWebhookTarget(config, parent) + + if config.Config.Webhook == "" { + return nil + } + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Webhook, + Config: config, + ParentConfig: parent, + Client: webhook.NewClient(webhook.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Host: config.Config.Webhook, + Headers: config.Config.Headers, + CustomFields: config.CustomFields, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateTelegramTarget(config, parent *target.Config[target.TelegramOptions]) *target.Target { + if config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + setFallback(&config.Config.Token, parent.Config.Token) + + if config.Config.ChatID == "" || config.Config.Token == "" { + return nil + } + + setFallback(&config.Config.Webhook, parent.Config.Webhook) + setFallback(&config.Config.Certificate, parent.Config.Certificate) + setBool(&config.Config.SkipTLS, parent.Config.SkipTLS) + + config.MapBaseParent(parent) + + if len(parent.Config.Headers) > 0 { + headers := map[string]string{} + for header, value := range parent.Config.Headers { + headers[header] = value + } + for header, value := range config.Config.Headers { + headers[header] = value + } + + config.Config.Headers = headers + } + + host := "https://api.telegram.org" + if config.Config.Webhook != "" { + host = strings.TrimSuffix(config.Config.Webhook, "/") + } + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Telegram, + Config: config, + ParentConfig: parent, + Client: telegram.NewClient(telegram.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Host: fmt.Sprintf("%s/bot%s/sendMessage", host, config.Config.Token), + ChatID: config.Config.ChatID, + Headers: config.Config.Headers, + CustomFields: config.CustomFields, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateGoogleChatTarget(config, parent *target.Config[target.WebhookOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + mapWebhookTarget(config, parent) + + if config.Config.Webhook == "" { + return nil + } + + zap.S().Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.GoogleChat, + Config: config, + ParentConfig: parent, + Client: googlechat.NewClient(googlechat.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Webhook: config.Config.Webhook, + Headers: config.Config.Headers, + CustomFields: config.CustomFields, + HTTPClient: http.NewClient(config.Config.Certificate, config.Config.SkipTLS), + }), + } +} + +func (f *TargetFactory) CreateS3Target(config, parent *target.Config[target.S3Options]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + setFallback(&config.Config.Bucket, parent.Config.Bucket) + if config.Config.Bucket == "" { + return nil + } + + config.Config.MapAWSParent(parent.Config.AWSConfig) + if config.Config.Endpoint == "" && !hasAWSIdentity() { + return nil + } + + sugar := zap.S() + + if err := checkAWSConfig(config.Name, config.Config.AWSConfig, parent.Config.AWSConfig); err != nil { + sugar.Error(err) + + return nil + } + + setFallback(&config.Config.Region, os.Getenv("AWS_REGION")) + setFallback(&config.Config.Prefix, parent.Config.Prefix, "policy-reporter") + setFallback(&config.Config.KmsKeyID, parent.Config.KmsKeyID) + setFallback(&config.Config.ServerSideEncryption, parent.Config.ServerSideEncryption) + setBool(&config.Config.BucketKeyEnabled, parent.Config.BucketKeyEnabled) + + config.MapBaseParent(parent) + + s3Client := aws.NewS3Client( + config.Config.AccessKeyID, + config.Config.SecretAccessKey, + config.Config.Region, + config.Config.Endpoint, + config.Config.Bucket, + config.Config.PathStyle, + aws.WithKMS(config.Config.BucketKeyEnabled, &config.Config.KmsKeyID, &config.Config.ServerSideEncryption), + ) + + sugar.Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.S3, + Config: config, + ParentConfig: parent, + Client: s3.NewClient(s3.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + S3: s3Client, + CustomFields: config.CustomFields, + Prefix: config.Config.Prefix, + }), + } +} + +func (f *TargetFactory) CreateKinesisTarget(config, parent *target.Config[target.KinesisOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + config.Config.MapAWSParent(parent.Config.AWSConfig) + if config.Config.Endpoint == "" { + return nil + } + + sugar := zap.S() + if err := checkAWSConfig(config.Name, config.Config.AWSConfig, parent.Config.AWSConfig); err != nil { + sugar.Error(err) + + return nil + } + + setFallback(&config.Config.StreamName, parent.Config.StreamName) + if config.Config.StreamName == "" { + sugar.Errorf("%s.StreamName has not been declared", config.Name) + return nil + } + + setFallback(&config.Config.Region, os.Getenv("AWS_REGION")) + + config.MapBaseParent(parent) + + kinesisClient := aws.NewKinesisClient( + config.Config.AccessKeyID, + config.Config.SecretAccessKey, + config.Config.Region, + config.Config.Endpoint, + config.Config.StreamName, + ) + + sugar.Infof("%s configured", config.Name) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.Kinesis, + Config: config, + ParentConfig: parent, + Client: kinesis.NewClient(kinesis.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + CustomFields: config.CustomFields, + Kinesis: kinesisClient, + }), + } +} + +func (f *TargetFactory) CreateSecurityHubTarget(config, parent *target.Config[target.SecurityHubOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + setFallback(&config.Config.AccountID, parent.Config.AccountID) + if config.Config.AccountID == "" { + return nil + } + setFallback(&config.Config.Region, os.Getenv("AWS_REGION")) + + sugar := zap.S() + if err := checkAWSConfig(config.Name, config.Config.AWSConfig, parent.Config.AWSConfig); err != nil { + sugar.Error(err) + + return nil + } + + config.Config.MapAWSParent(parent.Config.AWSConfig) + config.MapBaseParent(parent) + + setFallback(&config.Config.ProductName, parent.Config.ProductName, "Policy Reporter") + setFallback(&config.Config.CompanyName, parent.Config.CompanyName, "Kyverno") + setInt(&config.Config.DelayInSeconds, parent.Config.DelayInSeconds) + + client := aws.NewHubClient( + config.Config.AccessKeyID, + config.Config.SecretAccessKey, + config.Config.Region, + config.Config.Endpoint, + ) + + zap.L().Info(config.Name+" configured", zap.Bool("synchronize", config.Config.Synchronize)) + + hub := securityhub.NewClient(securityhub.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + CustomFields: config.CustomFields, + Client: client, + AccountID: config.Config.AccountID, + ProductName: config.Config.ProductName, + CompanyName: config.Config.CompanyName, + Region: config.Config.Region, + Delay: time.Duration(config.Config.DelayInSeconds) * time.Second, + Synchronize: config.Config.Synchronize, + }) + + return &target.Target{ + ID: uuid.NewString(), + Type: target.SecurityHub, + Config: config, + ParentConfig: parent, + Client: hub, + } +} + +func (f *TargetFactory) CreateGCSTarget(config, parent *target.Config[target.GCSOptions]) *target.Target { + if config == nil || config.Config == nil { + return nil + } + + if (parent.SecretRef != "" && f.secretClient != nil) || parent.MountedSecret != "" { + f.mapSecretValues(parent, parent.SecretRef, parent.MountedSecret) + } + + if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" { + f.mapSecretValues(config, config.SecretRef, config.MountedSecret) + } + + setFallback(&config.Config.Bucket, parent.Config.Bucket) + if config.Config.Bucket == "" { + return nil + } + + sugar := zap.S() + + setFallback(&config.Config.Credentials, parent.Config.Credentials) + if config.Config.Credentials == "" { + sugar.Errorf("%s.Credentials has not been declared", config.Name) + return nil + } + + setFallback(&config.Config.Prefix, parent.Config.Prefix, "policy-reporter") + + config.MapBaseParent(parent) + + gcsClient := gs.NewClient( + context.Background(), + config.Config.Credentials, + config.Config.Bucket, + ) + if gcsClient == nil { + return nil + } + + sugar.Infof("%s configured", config.Name) + return &target.Target{ + ID: uuid.NewString(), + Type: target.GCS, + Config: config, + ParentConfig: parent, + Client: gcs.NewClient(gcs.Options{ + ClientOptions: target.ClientOptions{ + Name: config.Name, + SkipExistingOnStartup: config.SkipExisting, + ResultFilter: f.createResultFilter(config.Filter, config.MinimumSeverity, config.Sources), + ReportFilter: createReportFilter(config.Filter), + }, + Client: gcsClient, + CustomFields: config.CustomFields, + Prefix: config.Config.Prefix, + }), + } +} + +func (f *TargetFactory) createResultFilter(filter target.Filter, minimumSeverity string, sources []string) *report.ResultFilter { + sourceFilter := filter.Sources + if len(sources) > 0 { + sourceFilter = target.ValueFilter{Include: sources} + } + + return f.filterFactory.CreateFilter( + validate.RuleSets{ + Include: filter.Namespaces.Include, + Exclude: filter.Namespaces.Exclude, + Selector: helper.ConvertMap(filter.Namespaces.Selector), + }, + ToRuleSet(filter.Severities), + ToRuleSet(filter.Status), + ToRuleSet(filter.Policies), + ToRuleSet(sourceFilter), + minimumSeverity, + ) +} + +func (f *TargetFactory) mapSecretValues(config any, ref, mountedSecret string) { + values := secrets.Values{} + + if ref != "" { + secretValues, err := f.secretClient.Get(context.Background(), ref) + values = secretValues + if err != nil { + zap.L().Warn("failed to get secret reference", zap.Error(err)) + return + } + } + + if mountedSecret != "" { + file, err := os.ReadFile(mountedSecret) + if err != nil { + zap.L().Warn("failed to get mounted secret", zap.Error(err)) + return + } + err = json.Unmarshal(file, &values) + if err != nil { + zap.L().Warn("failed to unmarshal mounted secret", zap.Error(err)) + return + } + } + + switch c := config.(type) { + case *target.Config[target.LokiOptions]: + if values.Host != "" { + c.Config.Host = values.Host + } + + case *target.Config[target.SlackOptions]: + if values.Webhook != "" { + c.Config.Webhook = values.Webhook + } + if values.Channel != "" { + c.Config.Channel = values.Channel + } + + case *target.Config[target.WebhookOptions]: + if values.Webhook != "" { + c.Config.Webhook = values.Webhook + } + if values.Token != "" { + if c.Config.Headers == nil { + c.Config.Headers = make(map[string]string) + } + + c.Config.Headers["Authorization"] = values.Token + } + + case *target.Config[target.ElasticsearchOptions]: + if values.Host != "" { + c.Config.Host = values.Host + } + if values.Username != "" { + c.Config.Username = values.Username + } + if values.Password != "" { + c.Config.Password = values.Password + } + if values.APIKey != "" { + c.Config.APIKey = values.APIKey + } + + case *target.Config[target.S3Options]: + if values.AccessKeyID != "" { + c.Config.AccessKeyID = values.AccessKeyID + } + if values.SecretAccessKey != "" { + c.Config.SecretAccessKey = values.SecretAccessKey + } + if values.KmsKeyID != "" { + c.Config.KmsKeyID = values.KmsKeyID + } + + case *target.Config[target.KinesisOptions]: + if values.AccessKeyID != "" { + c.Config.AccessKeyID = values.AccessKeyID + } + if values.SecretAccessKey != "" { + c.Config.SecretAccessKey = values.SecretAccessKey + } + + case *target.Config[target.SecurityHubOptions]: + if values.AccessKeyID != "" { + c.Config.AccessKeyID = values.AccessKeyID + } + if values.SecretAccessKey != "" { + c.Config.SecretAccessKey = values.SecretAccessKey + } + if values.AccountID != "" { + c.Config.AccountID = values.AccountID + } + + case *target.Config[target.GCSOptions]: + if values.Credentials != "" { + c.Config.Credentials = values.Credentials + } + + case *target.Config[target.TelegramOptions]: + if values.Token != "" { + c.Config.Token = values.Token + } + if values.Host != "" { + c.Config.Webhook = values.Host + } + } +} + +func NewFactory(secretClient secrets.Client, filterFactory *target.ResultFilterFactory) target.Factory { + return &TargetFactory{secretClient: secretClient, filterFactory: filterFactory} +} + +func mapWebhookTarget(config, parent *target.Config[target.WebhookOptions]) { + setFallback(&config.Config.Webhook, parent.Config.Webhook) + setFallback(&config.Config.Certificate, parent.Config.Certificate) + setBool(&config.Config.SkipTLS, parent.Config.SkipTLS) + + config.MapBaseParent(parent) + + if len(parent.Config.Headers) > 0 { + headers := map[string]string{} + for header, value := range parent.Config.Headers { + headers[header] = value + } + for header, value := range config.Config.Headers { + headers[header] = value + } + + config.Config.Headers = headers + } +} + +func hasAWSIdentity() bool { + irsaARN := os.Getenv("AWS_ROLE_ARN") + irsaFile := os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE") + + podIdentityFile := os.Getenv("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE") + podIdentityURI := os.Getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI") + + return (irsaARN != "" && irsaFile != "") || (podIdentityFile != "" && podIdentityURI != "") +} + +func checkAWSConfig(name string, config target.AWSConfig, parent target.AWSConfig) error { + noEnvConfig := !hasAWSIdentity() + + if noEnvConfig && (config.AccessKeyID == "" && parent.AccessKeyID == "") { + return fmt.Errorf("%s.AccessKeyID has not been declared", name) + } + + if noEnvConfig && (config.SecretAccessKey == "" && parent.SecretAccessKey == "") { + return fmt.Errorf("%s.SecretAccessKey has not been declared", name) + } + + if config.Region == "" && parent.Region == "" { + return fmt.Errorf("%s.Region has not been declared", name) + } + + return nil +} + +func setFallback(config *string, parents ...string) { + if *config == "" { + for _, p := range parents { + if p != "" { + *config = p + return + } + } + } +} + +func setBool(config *bool, parent bool) { + if *config == false { + *config = parent + } +} + +func setInt(config *int, parent int) { + if *config == 0 { + *config = parent + } +} + +func createReportFilter(filter target.Filter) *report.ReportFilter { + return target.NewReportFilter( + ToRuleSet(filter.ReportLabels), + ToRuleSet(filter.Sources), + ) +} + +func ToRuleSet(filter target.ValueFilter) validate.RuleSets { + return validate.RuleSets{ + Include: filter.Include, + Exclude: filter.Exclude, + } +} diff --git a/pkg/target/factory/factory_test.go b/pkg/target/factory/factory_test.go new file mode 100644 index 00000000..0af34ddb --- /dev/null +++ b/pkg/target/factory/factory_test.go @@ -0,0 +1,1006 @@ +package factory_test + +import ( + "encoding/json" + "os" + "reflect" + "testing" + + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/kubernetes/secrets" + "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/factory" +) + +const ( + secretName = "secret-values" + mountedSecret = "/tmp/secrets-9999" +) + +func newFakeClient() v1.SecretInterface { + return fake.NewSimpleClientset(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: "default", + }, + Data: map[string][]byte{ + "host": []byte("http://localhost:9200"), + "username": []byte("username"), + "password": []byte("password"), + "channel": []byte("general"), + "apiKey": []byte("apiKey"), + "webhook": []byte("http://localhost:9200/webhook"), + "accountId": []byte("accountId"), + "typelessApi": []byte("true"), + "accessKeyId": []byte("accessKeyId"), + "secretAccessKey": []byte("secretAccessKey"), + "kmsKeyId": []byte("kmsKeyId"), + "token": []byte("token"), + "credentials": []byte(`{"token": "token", "type": "authorized_user"}`), + "database": []byte("database"), + "dsn": []byte(""), + }, + }).CoreV1().Secrets("default") +} + +func mountSecret() { + secretValues := secrets.Values{ + Host: "http://localhost:9200", + Webhook: "http://localhost:9200/webhook", + Channel: "general", + Username: "username", + Password: "password", + APIKey: "apiKey", + AccountID: "accountId", + AccessKeyID: "accessKeyId", + SecretAccessKey: "secretAccessKey", + KmsKeyID: "kmsKeyId", + Token: "token", + Credentials: `{"token": "token", "type": "authorized_user"}`, + Database: "database", + TypelessAPI: true, + DSN: "", + } + file, _ := json.MarshalIndent(secretValues, "", " ") + _ = os.WriteFile(mountedSecret, file, 0o644) +} + +var logger = zap.NewNop() + +var targets = target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + SkipTLS: true, + }, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.LokiOptions]{ + { + CustomFields: map[string]string{"label2": "value2"}, + }, + }, + }, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{ + Config: &target.ElasticsearchOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:9200", + SkipTLS: true, + }, + Index: "policy-reporter", + Rotation: "daily", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.ElasticsearchOptions]{{}}, + }, + Slack: &target.Config[target.SlackOptions]{ + Config: &target.SlackOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + SkipTLS: true, + }, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.SlackOptions]{{ + Config: &target.SlackOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:9200", + }, + }, + }, { + Config: &target.SlackOptions{ + Channel: "general", + }, + }}, + }, + Discord: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://discord:80", + SkipTLS: true, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:9200", + }, + }}, + }, + Teams: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://hook.teams:80", + SkipTLS: true, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:9200", + }, + }}, + }, + GoogleChat: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:900/webhook", + SkipTLS: true, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{}}, + }, + Telegram: &target.Config[target.TelegramOptions]{ + Config: &target.TelegramOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + SkipTLS: true, + }, + Token: "XXX", + ChatID: "123456", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.TelegramOptions]{{ + Config: &target.TelegramOptions{ + ChatID: "1234567", + }, + }}, + }, + Webhook: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8080", + SkipTLS: true, + Headers: map[string]string{ + "X-Custom": "Header", + }, + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.WebhookOptions]{{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8081", + Headers: map[string]string{ + "X-Custom-2": "Header", + }, + }, + }}, + }, + S3: &target.Config[target.S3Options]{ + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + Bucket: "test", + BucketKeyEnabled: false, + KmsKeyID: "", + ServerSideEncryption: "", + PathStyle: true, + Prefix: "prefix", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.S3Options]{{}}, + }, + Kinesis: &target.Config[target.KinesisOptions]{ + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + StreamName: "policy-reporter", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.KinesisOptions]{{}}, + }, + SecurityHub: &target.Config[target.SecurityHubOptions]{ + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + AccountID: "AccountID", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.SecurityHubOptions]{{}}, + }, + GCS: &target.Config[target.GCSOptions]{ + Config: &target.GCSOptions{ + Credentials: `{"token": "token", "type": "authorized_user"}`, + Bucket: "test", + Prefix: "prefix", + }, + SkipExisting: true, + MinimumSeverity: v1alpha2.SeverityInfo, + CustomFields: map[string]string{"field": "value"}, + Channels: []*target.Config[target.GCSOptions]{{}}, + }, +} + +func Test_ResolveTarget(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + clients := factory.CreateClients(&targets) + if len(clients.Clients()) != 25 { + t.Errorf("Expected 25 Client, got %d clients", len(clients.Clients())) + } +} + +func Test_ResolveTargetsWithoutRequiredConfiguration(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := target.Targets{ + Loki: &target.Config[target.LokiOptions]{}, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{}, + Slack: &target.Config[target.SlackOptions]{}, + Discord: &target.Config[target.WebhookOptions]{}, + Teams: &target.Config[target.WebhookOptions]{}, + GoogleChat: &target.Config[target.WebhookOptions]{}, + Webhook: &target.Config[target.WebhookOptions]{}, + Telegram: &target.Config[target.TelegramOptions]{}, + S3: &target.Config[target.S3Options]{}, + Kinesis: &target.Config[target.KinesisOptions]{}, + SecurityHub: &target.Config[target.SecurityHubOptions]{}, + } + + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no required fields are configured") + } + + targets = target.Targets{} + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no target is configured") + } + + targets.S3 = &target.Config[target.S3Options]{ + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}, + }, + } +} + +func Test_S3Validation(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := target.Targets{ + S3: &target.Config[target.S3Options]{ + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}, + }, + }, + } + + t.Run("S3.AccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no accessKey is configured") + } + }) + + targets.S3.Config.AWSConfig.AccessKeyID = "access" + t.Run("S3.SecretAccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no secretAccessKey is configured") + } + }) + + targets.S3.Config.AWSConfig.SecretAccessKey = "secret" + t.Run("S3.Region", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no region is configured") + } + }) + + targets.S3.Config.AWSConfig.Region = "ru-central1" + t.Run("S3.Bucket", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no bucket is configured") + } + }) + + targets.S3.Config.ServerSideEncryption = "AES256" + t.Run("S3.SSE-S3", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if server side encryption is not configured") + } + }) + + targets.S3.Config.ServerSideEncryption = "aws:kms" + t.Run("S3.SSE-KMS", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if server side encryption is not configured") + } + }) + + targets.S3.Config.BucketKeyEnabled = true + t.Run("S3.SSE-KMS-S3-KEY", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if server side encryption is not configured") + } + }) + + targets.S3.Config.KmsKeyID = "kmsKeyId" + t.Run("S3.SSE-KMS-KEY-ID", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if server side encryption is not configured") + } + }) +} + +func Test_KinesisValidation(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := target.Targets{ + Kinesis: &target.Config[target.KinesisOptions]{ + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}, + }, + }, + } + + t.Run("Kinesis.AccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no accessKey is configured") + } + }) + + targets.Kinesis.Config.AWSConfig.AccessKeyID = "access" + t.Run("Kinesis.SecretAccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no secretAccessKey is configured") + } + }) + + targets.Kinesis.Config.AWSConfig.SecretAccessKey = "secret" + + t.Run("Kinesis.Region", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no region is configured") + } + }) + + targets.Kinesis.Config.AWSConfig.Region = "ru-central1" + + t.Run("Kinesis.StreamName", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no stream name is configured") + } + }) +} + +func Test_SecurityHubValidation(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := target.Targets{ + SecurityHub: &target.Config[target.SecurityHubOptions]{ + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{Endpoint: "https://storage.yandexcloud.net"}, + }, + }, + } + + t.Run("SecurityHub.AccountId", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no accountId is configured") + } + }) + + targets.SecurityHub.Config.AccountID = "accountId" + t.Run("SecurityHub.AccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no accessKey is configured") + } + }) + + targets.SecurityHub.Config.AWSConfig.AccessKeyID = "access" + t.Run("SecurityHub.SecretAccessKey", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no secretAccessKey is configured") + } + }) + + targets.SecurityHub.Config.AWSConfig.SecretAccessKey = "secret" + t.Run("SecurityHub.Region", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no region is configured") + } + }) +} + +func Test_GCSValidation(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := target.Targets{ + GCS: &target.Config[target.GCSOptions]{ + Config: &target.GCSOptions{ + Credentials: "{}", + }, + }, + } + + t.Run("GCS.Bucket", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no bucket is configured") + } + }) + + targets.GCS.Config.Bucket = "policy-reporter" + t.Run("GCS.Credentials", func(t *testing.T) { + if len(factory.CreateClients(&targets).Clients()) != 0 { + t.Error("Expected Client to be nil if no accessKey is configured") + } + }) +} + +func Test_GetValuesFromSecret(t *testing.T) { + factory := factory.NewFactory(secrets.NewClient(newFakeClient()), nil) + + targets := target.Targets{ + Loki: &target.Config[target.LokiOptions]{SecretRef: secretName}, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{SecretRef: secretName}, + Slack: &target.Config[target.SlackOptions]{SecretRef: secretName}, + Discord: &target.Config[target.WebhookOptions]{SecretRef: secretName}, + Teams: &target.Config[target.WebhookOptions]{SecretRef: secretName}, + GoogleChat: &target.Config[target.WebhookOptions]{SecretRef: secretName}, + Webhook: &target.Config[target.WebhookOptions]{SecretRef: secretName}, + Telegram: &target.Config[target.TelegramOptions]{ + SecretRef: secretName, + Config: &target.TelegramOptions{ + ChatID: "1234", + }, + }, + S3: &target.Config[target.S3Options]{ + SecretRef: secretName, + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + Bucket: "bucket", + }, + }, + Kinesis: &target.Config[target.KinesisOptions]{ + SecretRef: secretName, + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + StreamName: "stream", + }, + }, + SecurityHub: &target.Config[target.SecurityHubOptions]{ + SecretRef: secretName, + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + AccountID: "accountId", + }, + }, + GCS: &target.Config[target.GCSOptions]{ + SecretRef: secretName, + Config: &target.GCSOptions{ + Bucket: "policy-reporter", + }, + }, + } + + clients := factory.CreateClients(&targets) + if len(clients.Clients()) != 12 { + t.Fatalf("expected 12 clients created, got %d", len(clients.Clients())) + } + + t.Run("Get Loki values from Secret", func(t *testing.T) { + fv := reflect.ValueOf(clients.Client("Loki")).Elem().FieldByName("host") + if v := fv.String(); v != "http://localhost:9200/loki/api/v1/push" { + t.Errorf("Expected host from secret, got %s", v) + } + }) + + t.Run("Get Elasticsearch values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Elasticsearch")).Elem() + + host := client.FieldByName("host").String() + if host != "http://localhost:9200" { + t.Errorf("Expected host from secret, got %s", host) + } + + username := client.FieldByName("username").String() + if username != "username" { + t.Errorf("Expected username from secret, got %s", username) + } + + rotation := client.FieldByName("rotation").String() + if rotation != "daily" { + t.Errorf("Expected rotation from secret, got %s", rotation) + } + + index := client.FieldByName("index").String() + if index != "policy-reporter" { + t.Errorf("Expected rotation from secret, got %s", index) + } + + password := client.FieldByName("password").String() + if password != "password" { + t.Errorf("Expected password from secret, got %s", password) + } + + apiKey := client.FieldByName("apiKey").String() + if apiKey != "apiKey" { + t.Errorf("Expected apiKey from secret, got %s", apiKey) + } + }) + + t.Run("Get Slack values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Slack")).Elem() + + webhook := client.FieldByName("channel").String() + if webhook != "general" { + t.Errorf("Expected channel from secret, got %s", webhook) + } + }) + + t.Run("Get Discord values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Discord")).Elem() + + webhook := client.FieldByName("webhook").String() + if webhook != "http://localhost:9200/webhook" { + t.Errorf("Expected webhook from secret, got %s", webhook) + } + }) + + t.Run("Get MS Teams values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Teams")).Elem() + + webhook := client.FieldByName("webhook").String() + if webhook != "http://localhost:9200/webhook" { + t.Errorf("Expected webhook from secret, got %s", webhook) + } + }) + + t.Run("Get GoogleChat Webhook from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("GoogleChat")).Elem() + + host := client.FieldByName("webhook").String() + if host != "http://localhost:9200/webhook" { + t.Errorf("Expected host with token from secret, got %s", host) + } + }) + + t.Run("Get Telegram Token from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Telegram")).Elem() + + host := client.FieldByName("host").String() + if host != "http://localhost:9200/bottoken/sendMessage" { + t.Errorf("Expected host with token from secret, got %s", host) + } + }) + + t.Run("Get Webhook Authentication Token from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Webhook")).Elem() + + token := client.FieldByName("headers").MapIndex(reflect.ValueOf("Authorization")).String() + if token != "token" { + t.Errorf("Expected token from secret, got %s", token) + } + }) + + t.Run("Get none existing secret skips target", func(t *testing.T) { + clients := factory.CreateClients(&target.Targets{ + Loki: &target.Config[target.LokiOptions]{SecretRef: "not-exist"}, + }) + + if len(clients.Clients()) != 0 { + t.Error("Expected client are skipped") + } + }) +} + +func Test_CustomFields(t *testing.T) { + factory := factory.NewFactory(nil, nil) + + targets := &target.Targets{ + Loki: &target.Config[target.LokiOptions]{ + Config: &target.LokiOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:3100", + }, + }, + CustomFields: map[string]string{"field": "value"}, + }, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{ + Config: &target.ElasticsearchOptions{ + HostOptions: target.HostOptions{ + Host: "http://localhost:9200", + }, + }, + CustomFields: map[string]string{"field": "value"}, + }, + Slack: &target.Config[target.SlackOptions]{ + Config: &target.SlackOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + }, + }, + CustomFields: map[string]string{"field": "value"}, + }, + Discord: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://discord:80", + }, + CustomFields: map[string]string{"field": "value"}, + }, + Teams: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://hook.teams:80", + }, + CustomFields: map[string]string{"field": "value"}, + }, + GoogleChat: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:900/webhook", + }, + CustomFields: map[string]string{"field": "value"}, + }, + Telegram: &target.Config[target.TelegramOptions]{ + Config: &target.TelegramOptions{ + WebhookOptions: target.WebhookOptions{ + Webhook: "http://localhost:80", + }, + Token: "XXX", + ChatID: "123456", + }, + CustomFields: map[string]string{"field": "value"}, + }, + Webhook: &target.Config[target.WebhookOptions]{ + Config: &target.WebhookOptions{ + Webhook: "http://localhost:8080", + }, + CustomFields: map[string]string{"field": "value"}, + }, + S3: &target.Config[target.S3Options]{ + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + Bucket: "test", + }, + CustomFields: map[string]string{"field": "value"}, + }, + Kinesis: &target.Config[target.KinesisOptions]{ + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + StreamName: "policy-reporter", + }, + CustomFields: map[string]string{"field": "value"}, + }, + SecurityHub: &target.Config[target.SecurityHubOptions]{ + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{ + AccessKeyID: "AccessKey", + SecretAccessKey: "SecretAccessKey", + Endpoint: "https://storage.yandexcloud.net", + Region: "ru-central1", + }, + AccountID: "AccountId", + }, + CustomFields: map[string]string{"field": "value"}, + }, + GCS: &target.Config[target.GCSOptions]{ + Config: &target.GCSOptions{ + Credentials: `{"token": "token", "type": "authorized_user"}`, + Bucket: "test", + Prefix: "prefix", + }, + CustomFields: map[string]string{"field": "value"}, + }, + } + + clients := factory.CreateClients(targets) + + if len(clients.Clients()) != 12 { + t.Fatalf("expected 12 client created, got %d", len(clients.Clients())) + } + + t.Run("Get CustomFields from Loki", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Loki")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + + t.Run("Get CustomFields from Elasticsearch", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Elasticsearch")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + + t.Run("Get CustomFields from Slack", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Slack")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + t.Run("Get CustomFields from Discord", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Discord")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + t.Run("Get CustomFields from MS Teams", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Teams")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + + t.Run("Get CustomFields from GoogleChat", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("GoogleChat")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + + t.Run("Get CustomFields from Telegram", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Telegram")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + + t.Run("Get CustomFields from Webhook", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Webhook")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + t.Run("Get CustomFields from S3", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("S3")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + t.Run("Get CustomFields from Kinesis", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Kinesis")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) + t.Run("Get CustomFields from GCS", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("GoogleCloudStorage")).Elem() + + customFields := client.FieldByName("customFields").MapKeys() + if customFields[0].String() != "field" { + t.Errorf("Expected customFields are added") + } + }) +} + +func Test_GetValuesFromMountedSecret(t *testing.T) { + factory := factory.NewFactory(secrets.NewClient(newFakeClient()), nil) + + mountSecret() + defer os.Remove(mountedSecret) + + targets := target.Targets{ + Loki: &target.Config[target.LokiOptions]{MountedSecret: mountedSecret}, + Elasticsearch: &target.Config[target.ElasticsearchOptions]{MountedSecret: mountedSecret}, + Slack: &target.Config[target.SlackOptions]{MountedSecret: mountedSecret}, + Discord: &target.Config[target.WebhookOptions]{MountedSecret: mountedSecret}, + Teams: &target.Config[target.WebhookOptions]{MountedSecret: mountedSecret}, + GoogleChat: &target.Config[target.WebhookOptions]{MountedSecret: mountedSecret}, + Webhook: &target.Config[target.WebhookOptions]{MountedSecret: mountedSecret}, + Telegram: &target.Config[target.TelegramOptions]{ + MountedSecret: mountedSecret, + Config: &target.TelegramOptions{ + ChatID: "1234", + }, + }, + S3: &target.Config[target.S3Options]{ + MountedSecret: mountedSecret, + Config: &target.S3Options{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + Bucket: "bucket", + }, + }, + Kinesis: &target.Config[target.KinesisOptions]{ + MountedSecret: mountedSecret, + Config: &target.KinesisOptions{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + StreamName: "stream", + }, + }, + SecurityHub: &target.Config[target.SecurityHubOptions]{ + MountedSecret: mountedSecret, + Config: &target.SecurityHubOptions{ + AWSConfig: target.AWSConfig{Endpoint: "endoint", Region: "region"}, + AccountID: "accountId", + }, + }, + GCS: &target.Config[target.GCSOptions]{ + MountedSecret: mountedSecret, + Config: &target.GCSOptions{ + Bucket: "policy-reporter", + }, + }, + } + + clients := factory.CreateClients(&targets) + if len(clients.Clients()) != 12 { + t.Fatalf("expected 12 client created, got %d", len(clients.Clients())) + } + + t.Run("Get Loki values from Secret", func(t *testing.T) { + fv := reflect.ValueOf(clients.Client("Loki")).Elem().FieldByName("host") + if v := fv.String(); v != "http://localhost:9200/loki/api/v1/push" { + t.Errorf("Expected host from secret, got %s", v) + } + }) + + t.Run("Get Elasticsearch values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Elasticsearch")).Elem() + + host := client.FieldByName("host").String() + if host != "http://localhost:9200" { + t.Errorf("Expected host from secret, got %s", host) + } + + username := client.FieldByName("username").String() + if username != "username" { + t.Errorf("Expected username from secret, got %s", username) + } + + rotation := client.FieldByName("rotation").String() + if rotation != "daily" { + t.Errorf("Expected rotation from secret, got %s", rotation) + } + + index := client.FieldByName("index").String() + if index != "policy-reporter" { + t.Errorf("Expected rotation from secret, got %s", index) + } + + password := client.FieldByName("password").String() + if password != "password" { + t.Errorf("Expected password from secret, got %s", password) + } + + apiKey := client.FieldByName("apiKey").String() + if apiKey != "apiKey" { + t.Errorf("Expected apiKey from secret, got %s", apiKey) + } + }) + + t.Run("Get Slack values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Slack")).Elem() + + webhook := client.FieldByName("channel").String() + if webhook != "general" { + t.Errorf("Expected channel from secret, got %s", webhook) + } + }) + + t.Run("Get Discord values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Discord")).Elem() + + webhook := client.FieldByName("webhook").String() + if webhook != "http://localhost:9200/webhook" { + t.Errorf("Expected webhook from secret, got %s", webhook) + } + }) + + t.Run("Get MS Teams values from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Teams")).Elem() + + webhook := client.FieldByName("webhook").String() + if webhook != "http://localhost:9200/webhook" { + t.Errorf("Expected webhook from secret, got %s", webhook) + } + }) + + t.Run("Get GoogleChat Webhook from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("GoogleChat")).Elem() + + host := client.FieldByName("webhook").String() + if host != "http://localhost:9200/webhook" { + t.Errorf("Expected host with token from secret, got %s", host) + } + }) + + t.Run("Get Telegram Token from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Telegram")).Elem() + + host := client.FieldByName("host").String() + if host != "http://localhost:9200/bottoken/sendMessage" { + t.Errorf("Expected host with token from secret, got %s", host) + } + }) + + t.Run("Get Webhook Authentication Token from Secret", func(t *testing.T) { + client := reflect.ValueOf(clients.Client("Webhook")).Elem() + + token := client.FieldByName("headers").MapIndex(reflect.ValueOf("Authorization")).String() + if token != "token" { + t.Errorf("Expected token from secret, got %s", token) + } + }) + + t.Run("Get none existing secret skips target", func(t *testing.T) { + clients := factory.CreateClients(&target.Targets{ + Loki: &target.Config[target.LokiOptions]{SecretRef: "not-exist"}, + }) + + if len(clients.Clients()) != 0 { + t.Error("Expected client are skipped") + } + }) +} diff --git a/pkg/target/factory_test.go b/pkg/target/factory_test.go new file mode 100644 index 00000000..9a72e5b2 --- /dev/null +++ b/pkg/target/factory_test.go @@ -0,0 +1,96 @@ +package target_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/target" +) + +func TestConfig(t *testing.T) { + t.Run("return expected secret ref", func(t *testing.T) { + c := &target.Config[target.WebhookOptions]{ + SecretRef: "webhook-secret", + } + + assert.Equal(t, c.Secret(), "webhook-secret") + }) + + t.Run("ignores secret mount", func(t *testing.T) { + c := &target.Config[target.WebhookOptions]{ + MountedSecret: "webhook-secret", + } + + assert.Equal(t, c.Secret(), "") + }) + + t.Run("base mapper set expected fallbacks from parent config", func(t *testing.T) { + p := &target.Config[target.WebhookOptions]{ + MinimumSeverity: v1alpha2.SeverityMedium, + SkipExisting: true, + } + + c := &target.Config[target.WebhookOptions]{} + c.MapBaseParent(p) + + assert.Equal(t, c.MinimumSeverity, p.MinimumSeverity) + assert.Equal(t, c.SkipExisting, p.SkipExisting) + }) + + t.Run("base mapper keeps none empty values", func(t *testing.T) { + p := &target.Config[target.WebhookOptions]{ + MinimumSeverity: v1alpha2.SeverityMedium, + } + + c := &target.Config[target.WebhookOptions]{ + MinimumSeverity: v1alpha2.SeverityInfo, + } + + c.MapBaseParent(p) + + assert.Equal(t, c.MinimumSeverity, v1alpha2.SeverityInfo) + }) +} + +func TestAWSConfig(t *testing.T) { + t.Run("aws mapper set expected fallbacks from parent config", func(t *testing.T) { + p := target.AWSConfig{ + AccessKeyID: "access", + SecretAccessKey: "secret", + Region: "eu", + Endpoint: "http://localhost:8080", + } + + c := target.AWSConfig{} + c.MapAWSParent(p) + + assert.Equal(t, c.AccessKeyID, p.AccessKeyID) + assert.Equal(t, c.SecretAccessKey, p.SecretAccessKey) + assert.Equal(t, c.Region, p.Region) + assert.Equal(t, c.Endpoint, p.Endpoint) + }) + + t.Run("base mapper keeps none empty values", func(t *testing.T) { + p := target.AWSConfig{ + AccessKeyID: "access", + SecretAccessKey: "secret", + Region: "eu", + Endpoint: "http://localhost:8080", + } + + c := target.AWSConfig{ + AccessKeyID: "access_child", + SecretAccessKey: "secret_child", + Region: "de", + Endpoint: "http://localhost:9090", + } + c.MapAWSParent(p) + + assert.Equal(t, c.AccessKeyID, "access_child") + assert.Equal(t, c.SecretAccessKey, "secret_child") + assert.Equal(t, c.Region, "de") + assert.Equal(t, c.Endpoint, "http://localhost:9090") + }) +} diff --git a/pkg/target/formatting/resource.go b/pkg/target/formatting/resource.go new file mode 100644 index 00000000..19d3c05d --- /dev/null +++ b/pkg/target/formatting/resource.go @@ -0,0 +1,19 @@ +package formatting + +import ( + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" +) + +func ResourceString(res *corev1.ObjectReference) string { + var resource string + if res.Namespace == "" { + resource = fmt.Sprintf("%s/%s: %s", res.APIVersion, res.Kind, res.Name) + } else { + resource = fmt.Sprintf("%s/%s: %s/%s", res.APIVersion, res.Kind, res.Namespace, res.Name) + } + + return strings.Trim(resource, "/") +} diff --git a/pkg/target/gcs/gcs.go b/pkg/target/gcs/gcs.go index add51ce1..c6638245 100644 --- a/pkg/target/gcs/gcs.go +++ b/pkg/target/gcs/gcs.go @@ -2,7 +2,6 @@ package gcs import ( "bytes" - "context" "encoding/json" "fmt" "time" @@ -10,23 +9,23 @@ import ( "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/http" + "github.com/kyverno/policy-reporter/pkg/target/provider/gcs" ) // Options to configure the GCS target type Options struct { target.ClientOptions CustomFields map[string]string - Client helper.GCPClient + Client gcs.Client Prefix string } type client struct { target.BaseClient customFields map[string]string - client helper.GCPClient + client gcs.Client prefix string } @@ -63,7 +62,9 @@ func (c *client) Send(result v1alpha2.PolicyReportResult) { zap.L().Info(c.Name() + ": PUSH OK") } -func (c *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (c *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new GCS.client to send Results to Google Cloud Storage. func NewClient(options Options) target.Client { diff --git a/pkg/target/googlechat/googlechat.go b/pkg/target/googlechat/googlechat.go index fa75e7ca..46a67930 100644 --- a/pkg/target/googlechat/googlechat.go +++ b/pkg/target/googlechat/googlechat.go @@ -2,7 +2,6 @@ package googlechat import ( "bytes" - "context" "text/template" "time" @@ -15,7 +14,7 @@ import ( ) const ( - messageTempl string = `[{{ .Priority }}] {{ or .Result.Policy .Result.Rule }}` + messageTempl string = `[{{ .Result.Severity }}] {{ or .Result.Policy .Result.Rule }}` resourceTempl string = `{{ if .Namespace }}[{{ .Namespace }}] {{ end }} {{ .APIVersion }}/{{ .Kind }} {{ .Name }}` ) @@ -98,13 +97,13 @@ func mapPayload(result v1alpha2.PolicyReportResult) (*Payload, error) { return nil, err } - prio := result.Priority.String() + prio := result.Severity if prio == "" { - prio = v1alpha2.DebugPriority.String() + prio = v1alpha2.SeverityInfo } var textBuffer bytes.Buffer - err = ttmpl.Execute(&textBuffer, values{Result: result, Priority: prio, Resource: result.GetResource()}) + err = ttmpl.Execute(&textBuffer, values{Result: result, Resource: result.GetResource()}) if err != nil { return nil, err } @@ -207,7 +206,7 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { return } - req, err := http.CreateJSONRequest(e.Name(), "POST", e.webhook, payload) + req, err := http.CreateJSONRequest("POST", e.webhook, payload) if err != nil { return } @@ -220,7 +219,9 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { http.ProcessHTTPResponse(e.Name(), resp, err) } -func (e *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (e *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new loki.client to send Results to Elasticsearch func NewClient(options Options) target.Client { diff --git a/pkg/target/http/logroundtripper.go b/pkg/target/http/logroundtripper.go index 762c669e..231315ca 100644 --- a/pkg/target/http/logroundtripper.go +++ b/pkg/target/http/logroundtripper.go @@ -16,14 +16,13 @@ type logRoundTripper struct { roundTripper http.RoundTripper } +var _ http.RoundTripper = (*logRoundTripper)(nil) + func (rt *logRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { logger := zap.L() if logger.Core().Enabled(zap.DebugLevel) { if info, err := httputil.DumpRequest(req, true); err == nil { logger.Debug(fmt.Sprintf("Sending request: %s", string(info))) - if err != nil { - return nil, err - } } } resp, err := rt.roundTripper.RoundTrip(req) diff --git a/pkg/target/http/logroundtripper_test.go b/pkg/target/http/logroundtripper_test.go new file mode 100644 index 00000000..3afc24bd --- /dev/null +++ b/pkg/target/http/logroundtripper_test.go @@ -0,0 +1,33 @@ +package http_test + +import ( + net "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" + + "github.com/kyverno/policy-reporter/pkg/target/http" +) + +type mock struct{} + +func (rt mock) RoundTrip(req *net.Request) (*net.Response, error) { + return httptest.NewRecorder().Result(), nil +} + +func TestDebug(t *testing.T) { + obs, logs := observer.New(zap.DebugLevel) + + zap.ReplaceGlobals(zap.New(obs)) + + r := http.NewLoggingRoundTripper(mock{}) + + _, err := r.RoundTrip(httptest.NewRequest("GET", "http://localhost:8080/healthz", nil)) + + assert.Nil(t, err) + + assert.Equal(t, 2, logs.FilterLevelExact(zap.DebugLevel).Len()) +} diff --git a/pkg/target/http/utils.go b/pkg/target/http/utils.go index 1f8b52f7..6ba56bc2 100644 --- a/pkg/target/http/utils.go +++ b/pkg/target/http/utils.go @@ -15,14 +15,14 @@ import ( ) // CreateJSONRequest for the given configuration -func CreateJSONRequest(target, method, host string, payload interface{}) (*http.Request, error) { +func CreateJSONRequest(method, host string, payload interface{}) (*http.Request, error) { body := new(bytes.Buffer) json.NewEncoder(body).Encode(payload) req, err := http.NewRequest(method, host, body) if err != nil { - zap.L().Error(target+": PUSH FAILED", zap.Error(err)) + zap.L().Error("failed to create request", zap.Error(err)) return nil, err } @@ -67,7 +67,6 @@ func NewJSONResult(r v1alpha2.PolicyReportResult) Result { Message: r.Message, Policy: r.Policy, Rule: r.Rule, - Priority: r.Priority.String(), Status: string(r.Result), Severity: string(r.Severity), Category: r.Category, diff --git a/pkg/target/http/utils_test.go b/pkg/target/http/utils_test.go new file mode 100644 index 00000000..18436fda --- /dev/null +++ b/pkg/target/http/utils_test.go @@ -0,0 +1,94 @@ +package http_test + +import ( + "encoding/json" + "errors" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "go.uber.org/zap/zaptest/observer" + + "github.com/kyverno/policy-reporter/pkg/fixtures" + "github.com/kyverno/policy-reporter/pkg/target/http" +) + +func TestResultMapping(t *testing.T) { + result := http.NewJSONResult(fixtures.CompleteTargetSendResult) + + assert.Equal(t, result.Message, fixtures.CompleteTargetSendResult.Message) + assert.Equal(t, result.Policy, fixtures.CompleteTargetSendResult.Policy) + assert.Equal(t, result.Rule, fixtures.CompleteTargetSendResult.Rule) + assert.Equal(t, result.Resource.Name, fixtures.CompleteTargetSendResult.Resources[0].Name) +} + +func TestCreateJSONRequest(t *testing.T) { + t.Run("success", func(t *testing.T) { + req, err := http.CreateJSONRequest("GET", "http://localhost:8080", []string{"test"}) + + assert.Nil(t, err) + + list := make([]string, 0) + + json.NewDecoder(req.Body).Decode(&list) + + assert.Equal(t, []string{"test"}, list) + assert.Equal(t, "GET", req.Method) + assert.Equal(t, "application/json; charset=utf-8", req.Header.Get("Content-Type")) + assert.Equal(t, "Policy-Reporter", req.Header.Get("User-Agent")) + }) + + t.Run("error", func(t *testing.T) { + _, err := http.CreateJSONRequest("GET", "\test", []string{"test"}) + + assert.NotNil(t, err) + }) +} + +func TestClient(t *testing.T) { + assert.NotNil(t, http.NewClient("", true)) +} + +func TestProcessHTTPResponse(t *testing.T) { + t.Run("success", func(t *testing.T) { + obs, logs := observer.New(zap.InfoLevel) + + zap.ReplaceGlobals(zap.New(obs)) + + w := httptest.NewRecorder() + w.Write([]byte(`["test"]`)) + + http.ProcessHTTPResponse("Test", w.Result(), nil) + + assert.Equal(t, 1, logs.Len()) + assert.Equal(t, 1, logs.FilterLevelExact(zap.InfoLevel).Len()) + }) + t.Run("error", func(t *testing.T) { + obs, logs := observer.New(zap.InfoLevel) + + zap.ReplaceGlobals(zap.New(obs)) + + w := httptest.NewRecorder() + w.Write([]byte(`["test"]`)) + + http.ProcessHTTPResponse("Test", w.Result(), errors.New("error")) + + assert.Equal(t, 1, logs.Len()) + assert.Equal(t, 1, logs.FilterMessage("Test: PUSH FAILED").Len()) + }) + t.Run("error status code", func(t *testing.T) { + obs, logs := observer.New(zap.InfoLevel) + + zap.ReplaceGlobals(zap.New(obs)) + + w := httptest.NewRecorder() + resp := w.Result() + resp.StatusCode = 404 + + http.ProcessHTTPResponse("Test", w.Result(), nil) + + assert.Equal(t, 1, logs.Len()) + assert.Equal(t, 1, logs.FilterMessage("Test: PUSH FAILED").Len()) + }) +} diff --git a/pkg/target/kinesis/kinesis.go b/pkg/target/kinesis/kinesis.go index c365a613..04699a26 100644 --- a/pkg/target/kinesis/kinesis.go +++ b/pkg/target/kinesis/kinesis.go @@ -2,7 +2,6 @@ package kinesis import ( "bytes" - "context" "encoding/json" "fmt" "time" @@ -10,22 +9,22 @@ import ( "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/http" + "github.com/kyverno/policy-reporter/pkg/target/provider/aws" ) // Options to configure the Kinesis target type Options struct { target.ClientOptions CustomFields map[string]string - Kinesis helper.AWSClient + Kinesis aws.Client } type client struct { target.BaseClient customFields map[string]string - kinesis helper.AWSClient + kinesis aws.Client } func (c *client) Send(result v1alpha2.PolicyReportResult) { @@ -52,8 +51,7 @@ func (c *client) Send(result v1alpha2.PolicyReportResult) { t := time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) key := fmt.Sprintf("%s-%s-%s", result.Policy, result.ID, t.Format(time.RFC3339Nano)) - err := c.kinesis.Upload(body, key) - if err != nil { + if err := c.kinesis.Upload(body, key); err != nil { zap.L().Error("kinesis upload error", zap.String("name", c.Name()), zap.Error(err)) return } @@ -61,7 +59,9 @@ func (c *client) Send(result v1alpha2.PolicyReportResult) { zap.L().Info("PUSH OK", zap.String("name", c.Name())) } -func (c *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (c *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new Kinesis.client to send Results to AWS Kinesis compatible source func NewClient(options Options) target.Client { diff --git a/pkg/target/loki/loki.go b/pkg/target/loki/loki.go index 5a1f6a2c..c2b8d3b6 100644 --- a/pkg/target/loki/loki.go +++ b/pkg/target/loki/loki.go @@ -1,108 +1,122 @@ package loki import ( - "context" + "fmt" "strings" "time" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/http" ) -// Options to configure the Loko target +var ( + keyReplacer = strings.NewReplacer(".", "_", "]", "", "[", "") + labelReplacer = strings.NewReplacer("/", "") +) + +// Options to configure the Loki target type Options struct { target.ClientOptions Host string - CustomLabels map[string]string + CustomFields map[string]string Headers map[string]string HTTPClient http.Client Username string Password string } -type payload struct { - Streams []stream `json:"streams"` +type Payload struct { + Streams []Stream `json:"streams"` } -type stream struct { - Labels string `json:"labels"` - Entries []entry `json:"entries"` +type Stream struct { + Stream map[string]string `json:"stream"` + Values []Value `json:"values"` } -type entry struct { - Ts string `json:"ts"` - Line string `json:"line"` -} +type Value = []string -func newLokiPayload(result v1alpha2.PolicyReportResult, customLabels map[string]string) payload { +func newLokiStream(result v1alpha2.PolicyReportResult, customFields map[string]string) Stream { timestamp := time.Now() if result.Timestamp.Seconds != 0 { timestamp = time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) } - le := entry{Ts: timestamp.Format(time.RFC3339), Line: "[" + strings.ToUpper(result.Priority.String()) + "] " + result.Message} - ls := stream{Entries: []entry{le}} - - labels := []string{ - "status=\"" + string(result.Result) + "\"", - "policy=\"" + result.Policy + "\"", - "priority=\"" + result.Priority.String() + "\"", - "source=\"policy-reporter\"", + labels := map[string]string{ + "status": string(result.Result), + "policy": result.Policy, + "createdBy": "policy-reporter", } if result.Rule != "" { - labels = append(labels, "rule=\""+result.Rule+"\"") + labels["rule"] = result.Rule } if result.Category != "" { - labels = append(labels, "category=\""+result.Category+"\"") + labels["category"] = result.Category } if result.Severity != "" { - labels = append(labels, "severity=\""+string(result.Severity)+"\"") + labels["severity"] = string(result.Severity) } if result.Source != "" { - labels = append(labels, "producer=\""+result.Source+"\"") + labels["source"] = result.Source } if result.HasResource() { res := result.GetResource() if res.APIVersion != "" { - labels = append(labels, "apiVersion=\""+res.APIVersion+"\"") + labels["apiVersion"] = res.APIVersion + labels["kind"] = res.Kind + labels["name"] = res.Name } - labels = append(labels, "kind=\""+res.Kind+"\"") - labels = append(labels, "name=\""+res.Name+"\"") if res.UID != "" { - labels = append(labels, "uid=\""+string(res.UID)+"\"") + labels["uid"] = string(res.UID) } if res.Namespace != "" { - labels = append(labels, "namespace=\""+res.Namespace+"\"") + labels["namespace"] = res.Namespace } } for property, value := range result.Properties { - labels = append(labels, strings.ReplaceAll(property, ".", "_")+"=\""+strings.ReplaceAll(value, "\"", "")+"\"") + labels[keyReplacer.Replace(property)] = labelReplacer.Replace(value) } - for label, value := range customLabels { - labels = append(labels, strings.ReplaceAll(label, ".", "_")+"=\""+strings.ReplaceAll(value, "\"", "")+"\"") + for label, value := range customFields { + labels[keyReplacer.Replace(label)] = labelReplacer.Replace(value) } - ls.Labels = "{" + strings.Join(labels, ",") + "}" - - return payload{Streams: []stream{ls}} + return Stream{ + Values: []Value{[]string{fmt.Sprintf("%v", timestamp.UnixNano()), "[" + strings.ToUpper(string(result.Severity)) + "] " + result.Message}}, + Stream: labels, + } } type client struct { target.BaseClient host string client http.Client - customLabels map[string]string + customFields map[string]string headers map[string]string username string password string } func (l *client) Send(result v1alpha2.PolicyReportResult) { - req, err := http.CreateJSONRequest(l.Name(), "POST", l.host, newLokiPayload(result, l.customLabels)) + l.send(Payload{ + Streams: []Stream{ + newLokiStream(result, l.customFields), + }, + }) +} + +func (l *client) BatchSend(_ v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) { + l.send(Payload{Streams: helper.Map(results, func(result v1alpha2.PolicyReportResult) Stream { + return newLokiStream(result, l.customFields) + })}) +} + +func (l *client) send(payload Payload) { + req, err := http.CreateJSONRequest("POST", l.host, payload) if err != nil { return } @@ -120,7 +134,9 @@ func (l *client) Send(result v1alpha2.PolicyReportResult) { http.ProcessHTTPResponse(l.Name(), resp, err) } -func (l *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (l *client) Type() target.ClientType { + return target.BatchSend +} // NewClient creates a new loki.client to send Results to Loki func NewClient(options Options) target.Client { @@ -128,7 +144,7 @@ func NewClient(options Options) target.Client { target.NewBaseClient(options.ClientOptions), options.Host, options.HTTPClient, - options.CustomLabels, + options.CustomFields, options.Headers, options.Username, options.Password, diff --git a/pkg/target/loki/loki_test.go b/pkg/target/loki/loki_test.go index 27624d02..96b101ba 100644 --- a/pkg/target/loki/loki_test.go +++ b/pkg/target/loki/loki_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/kyverno/policy-reporter/pkg/fixtures" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/loki" @@ -39,7 +41,7 @@ func Test_LokiTarget(t *testing.T) { t.Errorf("Unexpected Host: %s", agend) } - if url := req.URL.String(); url != "http://localhost:3100/api/prom/push" { + if url := req.URL.String(); url != "http://localhost:3100/loki/api/v1/push" { t.Errorf("Unexpected Host: %s", url) } @@ -47,60 +49,32 @@ func Test_LokiTarget(t *testing.T) { t.Error("Expected Authentication header for BasicAuth is set") } - expectedLine := fmt.Sprintf("[%s] %s", strings.ToUpper(fixtures.CompleteTargetSendResult.Priority.String()), fixtures.CompleteTargetSendResult.Message) - labels, line := convertAndValidateBody(req, t) - if line != expectedLine { - t.Errorf("Unexpected LineContent: %s", line) - } - if !strings.Contains(labels, "policy=\""+fixtures.CompleteTargetSendResult.Policy+"\"") { - t.Error("Missing Content for Label 'policy'") - } - if !strings.Contains(labels, "status=\""+string(fixtures.CompleteTargetSendResult.Result)+"\"") { - t.Error("Missing Content for Label 'status'") - } - if !strings.Contains(labels, "priority=\""+fixtures.CompleteTargetSendResult.Priority.String()+"\"") { - t.Error("Missing Content for Label 'priority'") - } - if !strings.Contains(labels, "source=\"policy-reporter\"") { - t.Error("Missing Content for Label 'policy-reporter'") - } - if !strings.Contains(labels, "rule=\""+fixtures.CompleteTargetSendResult.Rule+"\"") { - t.Error("Missing Content for Label 'rule'") - } - if !strings.Contains(labels, "category=\""+fixtures.CompleteTargetSendResult.Category+"\"") { - t.Error("Missing Content for Label 'category'") - } - if !strings.Contains(labels, "severity=\""+string(fixtures.CompleteTargetSendResult.Severity)+"\"") { - t.Error("Missing Content for Label 'severity'") - } - if !strings.Contains(labels, "custom=\"label\"") { - t.Error("Missing Content for Label 'severity'") - } + expectedLine := fmt.Sprintf("[%s] %s", strings.ToUpper(string(fixtures.CompleteTargetSendResult.Severity)), fixtures.CompleteTargetSendResult.Message) + + stream := convertAndValidateBody(req, t) + + assert.Equal(t, expectedLine, stream.Values[0][1]) + assert.Equal(t, fixtures.CompleteTargetSendResult.Rule, stream.Stream["rule"]) + assert.Equal(t, fixtures.CompleteTargetSendResult.Policy, stream.Stream["policy"]) + assert.Equal(t, fixtures.CompleteTargetSendResult.Category, stream.Stream["category"]) + assert.Equal(t, string(fixtures.CompleteTargetSendResult.Result), stream.Stream["status"]) + assert.Equal(t, string(fixtures.CompleteTargetSendResult.Severity), stream.Stream["severity"]) res := fixtures.CompleteTargetSendResult.GetResource() - if !strings.Contains(labels, "kind=\""+res.Kind+"\"") { - t.Error("Missing Content for Label 'kind'") - } - if !strings.Contains(labels, "name=\""+res.Name+"\"") { - t.Error("Missing Content for Label 'name'") - } - if !strings.Contains(labels, "uid=\""+string(res.UID)+"\"") { - t.Error("Missing Content for Label 'uid'") - } - if !strings.Contains(labels, "namespace=\""+res.Namespace+"\"") { - t.Error("Missing Content for Label 'namespace'") - } - if !strings.Contains(labels, "version=\""+fixtures.CompleteTargetSendResult.Properties["version"]+"\"") { - t.Error("Missing Content for Label 'version'") - } + assert.Equal(t, res.Kind, stream.Stream["kind"]) + assert.Equal(t, res.Name, stream.Stream["name"]) + assert.Equal(t, string(res.UID), stream.Stream["uid"]) + assert.Equal(t, res.Namespace, stream.Stream["namespace"]) + + assert.Equal(t, fixtures.CompleteTargetSendResult.Properties["version"], stream.Stream["version"]) } client := loki.NewClient(loki.Options{ ClientOptions: target.ClientOptions{ Name: "Loki", }, - Host: "http://localhost:3100/api/prom/push", - CustomLabels: map[string]string{"custom": "label"}, + Host: "http://localhost:3100/loki/api/v1/push", + CustomFields: map[string]string{"custom": "label"}, HTTPClient: testClient{callback, 200}, Username: "username", Password: "password", @@ -119,56 +93,29 @@ func Test_LokiTarget(t *testing.T) { t.Errorf("Unexpected Host: %s", agend) } - if url := req.URL.String(); url != "http://localhost:3100/api/prom/push" { + if url := req.URL.String(); url != "http://localhost:3100/loki/api/v1/push" { t.Errorf("Unexpected Host: %s", url) } - expectedLine := fmt.Sprintf("[%s] %s", strings.ToUpper(fixtures.MinimalTargetSendResult.Priority.String()), fixtures.MinimalTargetSendResult.Message) - labels, line := convertAndValidateBody(req, t) - if line != expectedLine { - t.Errorf("Unexpected LineContent: %s", line) - } - if !strings.Contains(labels, "policy=\""+fixtures.MinimalTargetSendResult.Policy+"\"") { - t.Error("Missing Content for Label 'policy'") - } - if !strings.Contains(labels, "status=\""+string(fixtures.MinimalTargetSendResult.Result)+"\"") { - t.Error("Missing Content for Label 'status'") - } - if !strings.Contains(labels, "priority=\""+fixtures.MinimalTargetSendResult.Priority.String()+"\"") { - t.Error("Missing Content for Label 'priority'") - } - if !strings.Contains(labels, "source=\"policy-reporter\"") { - t.Error("Missing Content for Label 'policy-reporter'") - } - if strings.Contains(labels, "rule") { - t.Error("Unexpected Label 'rule'") - } - if strings.Contains(labels, "category") { - t.Error("Unexpected Label 'category'") - } - if strings.Contains(labels, "severity") { - t.Error("Unexpected 'severity'") - } - if strings.Contains(labels, "kind") { - t.Error("Unexpected Label 'kind'") - } - if strings.Contains(labels, "name") { - t.Error("Unexpected 'name'") - } - if strings.Contains(labels, "uid") { - t.Error("Unexpected 'uid'") - } - if strings.Contains(labels, "namespace") { - t.Error("Unexpected 'namespace'") - } + expectedLine := fmt.Sprintf("[%s] %s", strings.ToUpper(string(fixtures.MinimalTargetSendResult.Severity)), fixtures.MinimalTargetSendResult.Message) + stream := convertAndValidateBody(req, t) + + assert.Equal(t, expectedLine, stream.Values[0][1]) + assert.Equal(t, fixtures.MinimalTargetSendResult.Rule, stream.Stream["rule"]) + assert.Equal(t, fixtures.MinimalTargetSendResult.Policy, stream.Stream["policy"]) + assert.Equal(t, fixtures.MinimalTargetSendResult.Category, stream.Stream["category"]) + assert.Equal(t, string(fixtures.MinimalTargetSendResult.Result), stream.Stream["status"]) + assert.Equal(t, string(fixtures.MinimalTargetSendResult.Severity), stream.Stream["severity"]) + + assert.Equal(t, "policy-reporter", stream.Stream["createdBy"]) } client := loki.NewClient(loki.Options{ ClientOptions: target.ClientOptions{ Name: "Loki", }, - Host: "http://localhost:3100/api/prom/push", - CustomLabels: map[string]string{"custom": "label"}, + Host: "http://localhost:3100/loki/api/v1/push", + CustomFields: map[string]string{"custom": "label"}, HTTPClient: testClient{callback, 200}, }) client.Send(fixtures.MinimalTargetSendResult) @@ -178,8 +125,8 @@ func Test_LokiTarget(t *testing.T) { ClientOptions: target.ClientOptions{ Name: "Loki", }, - Host: "http://localhost:3100/api/prom/push", - CustomLabels: map[string]string{"custom": "label"}, + Host: "http://localhost:3100/loki/api/v1/push", + CustomFields: map[string]string{"custom": "label"}, HTTPClient: testClient{}, }) @@ -189,44 +136,16 @@ func Test_LokiTarget(t *testing.T) { }) } -func convertAndValidateBody(req *http.Request, t *testing.T) (string, string) { - payload := make(map[string]interface{}) +func convertAndValidateBody(req *http.Request, t *testing.T) loki.Stream { + payload := loki.Payload{} err := json.NewDecoder(req.Body).Decode(&payload) if err != nil { t.Fatal(err) } - streamsContent, ok := payload["streams"] - if !ok { - t.Errorf("Expected payload key 'streams' is missing") - } + assert.Len(t, payload.Streams[0].Values, 1) + assert.Len(t, payload.Streams[0].Values[0], 2) - streams := streamsContent.([]interface{}) - if len(streams) != 1 { - t.Errorf("Expected one streams entry") - } - - firstStream := streams[0].(map[string]interface{}) - entriesContent, ok := firstStream["entries"] - if !ok { - t.Errorf("Expected stream key 'entries' is missing") - } - labels, ok := firstStream["labels"] - if !ok { - t.Errorf("Expected stream key 'labels' is missing") - } - - entryContent := entriesContent.([]interface{})[0] - entry := entryContent.(map[string]interface{}) - _, ok = entry["ts"] - if !ok { - t.Errorf("Expected entry key 'ts' is missing") - } - line, ok := entry["line"] - if !ok { - t.Errorf("Expected entry key 'line' is missing") - } - - return labels.(string), line.(string) + return payload.Streams[0] } diff --git a/pkg/helper/aws.go b/pkg/target/provider/aws/aws.go similarity index 97% rename from pkg/helper/aws.go rename to pkg/target/provider/aws/aws.go index e9d3d1fe..3001ed07 100644 --- a/pkg/helper/aws.go +++ b/pkg/target/provider/aws/aws.go @@ -1,4 +1,4 @@ -package helper +package aws import ( "bytes" @@ -21,7 +21,7 @@ import ( var enable = true -type AWSClient interface { +type Client interface { // Upload given Data the configured AWS storage Upload(body *bytes.Buffer, key string) error } @@ -62,7 +62,7 @@ func (s *s3Client) Upload(body *bytes.Buffer, key string) error { } // NewS3Client creates a new S3.client to send Results to S3 -func NewS3Client(accessKeyID, secretAccessKey, region, endpoint, bucket string, pathStyle bool, opts ...Options) AWSClient { +func NewS3Client(accessKeyID, secretAccessKey, region, endpoint, bucket string, pathStyle bool, opts ...Options) Client { config, err := createConfig(accessKeyID, secretAccessKey, region) if err != nil { zap.L().Error("error while creating config", zap.Error(err)) @@ -111,7 +111,7 @@ func (k *kinesisClient) Upload(body *bytes.Buffer, key string) error { } // NewKinesisClient creates a new S3.client to send Results to S3 -func NewKinesisClient(accessKeyID, secretAccessKey, region, endpoint, streamName string) AWSClient { +func NewKinesisClient(accessKeyID, secretAccessKey, region, endpoint, streamName string) Client { config, err := createConfig(accessKeyID, secretAccessKey, region) if err != nil { zap.L().Error("error while creating config", zap.Error(err)) diff --git a/pkg/target/provider/aws/aws_test.go b/pkg/target/provider/aws/aws_test.go new file mode 100644 index 00000000..9f7bdeca --- /dev/null +++ b/pkg/target/provider/aws/aws_test.go @@ -0,0 +1,28 @@ +package aws_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/kyverno/policy-reporter/pkg/helper" + "github.com/kyverno/policy-reporter/pkg/target/provider/aws" +) + +func TestS3Client(t *testing.T) { + client := aws.NewS3Client("access", "secret", "eu-central-1", "http://s3.aws.com", "policy-reporter", false, aws.WithKMS(true, helper.ToPointer("kms"), helper.ToPointer("encryption"))) + + assert.NotNil(t, client) +} + +func TestKinesisClient(t *testing.T) { + client := aws.NewKinesisClient("access", "secret", "eu-central-1", "http://kinesis.aws.com", "policy-reporter") + + assert.NotNil(t, client) +} + +func TestSecurityHubClient(t *testing.T) { + client := aws.NewHubClient("access", "secret", "eu-central-1", "http://securityhub.aws.com") + + assert.NotNil(t, client) +} diff --git a/pkg/helper/gcp.go b/pkg/target/provider/gcs/gcs.go similarity index 72% rename from pkg/helper/gcp.go rename to pkg/target/provider/gcs/gcs.go index 44355eee..96c7a7fa 100644 --- a/pkg/helper/gcp.go +++ b/pkg/target/provider/gcs/gcs.go @@ -1,4 +1,4 @@ -package helper +package gcs import ( "bytes" @@ -10,17 +10,17 @@ import ( "google.golang.org/api/option" ) -type GCPClient interface { +type Client interface { // Upload given Data the configured AWS storage Upload(body *bytes.Buffer, key string) error } -type gcsClient struct { +type client struct { bucket string client *storage.Client } -func (c *gcsClient) Upload(body *bytes.Buffer, key string) error { +func (c *client) Upload(body *bytes.Buffer, key string) error { object := c.client.Bucket(c.bucket).Object(key) writer := object.NewWriter(context.Background()) @@ -34,8 +34,8 @@ func (c *gcsClient) Upload(body *bytes.Buffer, key string) error { return writer.Close() } -// NewGCSClient creates a new GCS.client to send Results to GCS Bucket -func NewGCSClient(ctx context.Context, credentials, bucket string) GCPClient { +// NewClient creates a new GCS.client to send Results to GCS Bucket +func NewClient(ctx context.Context, credentials, bucket string) Client { options := make([]option.ClientOption, 0, 1) if credentials != "" { @@ -48,14 +48,14 @@ func NewGCSClient(ctx context.Context, credentials, bucket string) GCPClient { options = append(options, option.WithCredentials(cred)) } - client, err := storage.NewClient(ctx, options...) + baseClient, err := storage.NewClient(ctx, options...) if err != nil { zap.L().Error("error while creating GCS client", zap.Error(err)) return nil } - return &gcsClient{ + return &client{ bucket, - client, + baseClient, } } diff --git a/pkg/target/s3/s3.go b/pkg/target/s3/s3.go index 45333223..2fafa38c 100644 --- a/pkg/target/s3/s3.go +++ b/pkg/target/s3/s3.go @@ -2,7 +2,6 @@ package s3 import ( "bytes" - "context" "encoding/json" "fmt" "time" @@ -10,23 +9,23 @@ import ( "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/http" + "github.com/kyverno/policy-reporter/pkg/target/provider/aws" ) // Options to configure the S3 target type Options struct { target.ClientOptions CustomFields map[string]string - S3 helper.AWSClient + S3 aws.Client Prefix string } type client struct { target.BaseClient customFields map[string]string - s3 helper.AWSClient + s3 aws.Client prefix string } @@ -54,8 +53,7 @@ func (c *client) Send(result v1alpha2.PolicyReportResult) { t := time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) key := fmt.Sprintf("%s/%s/%s-%s-%s.json", c.prefix, t.Format("2006-01-02"), result.Policy, result.ID, t.Format(time.RFC3339Nano)) - err := c.s3.Upload(body, key) - if err != nil { + if err := c.s3.Upload(body, key); err != nil { zap.L().Error(c.Name()+": S3 Upload error", zap.Error(err)) return } @@ -63,7 +61,9 @@ func (c *client) Send(result v1alpha2.PolicyReportResult) { zap.L().Info(c.Name() + ": PUSH OK") } -func (c *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (c *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new S3.client to send Results to S3. func NewClient(options Options) target.Client { diff --git a/pkg/target/securityhub/securityhub.go b/pkg/target/securityhub/securityhub.go index cf763675..448e4c77 100644 --- a/pkg/target/securityhub/securityhub.go +++ b/pkg/target/securityhub/securityhub.go @@ -3,6 +3,7 @@ package securityhub import ( "context" "fmt" + "strings" "time" hub "github.com/aws/aws-sdk-go-v2/service/securityhub" @@ -10,12 +11,20 @@ import ( "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" ) +var schema = toPointer("2018-10-08") + type HubClient interface { BatchImportFindings(ctx context.Context, params *hub.BatchImportFindingsInput, optFns ...func(*hub.Options)) (*hub.BatchImportFindingsOutput, error) GetFindings(ctx context.Context, params *hub.GetFindingsInput, optFns ...func(*hub.Options)) (*hub.GetFindingsOutput, error) + BatchUpdateFindings(ctx context.Context, params *hub.BatchUpdateFindingsInput, optFns ...func(*hub.Options)) (*hub.BatchUpdateFindingsOutput, error) +} + +type PolrClient interface { + Get(ctx context.Context, name, namespace string) (v1alpha2.ReportInterface, error) } // Options to configure the SecurityHub target @@ -28,7 +37,7 @@ type Options struct { ProductName string CompanyName string Delay time.Duration - Cleanup bool + Synchronize bool } type client struct { @@ -40,116 +49,205 @@ type client struct { productName string companyName string delay time.Duration - cleanup bool + synchronize bool + arn *string } -func (c *client) Send(result v1alpha2.PolicyReportResult) { - generator := result.Policy - if generator == "" { - generator = result.Rule - } - - title := generator - if result.HasResource() { - title = fmt.Sprintf("%s: %s", title, result.ResourceString()) - } - - t := time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) - +func (c *client) mapFindings(polr v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) []types.AwsSecurityFinding { var accID *string if c.accountID != "" { accID = toPointer(c.accountID) } - res, err := c.hub.BatchImportFindings(context.TODO(), &hub.BatchImportFindingsInput{ - Findings: []types.AwsSecurityFinding{ - { - Id: toPointer(result.GetID()), - AwsAccountId: accID, - SchemaVersion: toPointer("2018-10-08"), - ProductArn: toPointer("arn:aws:securityhub:" + c.region + ":" + c.accountID + ":product/" + c.accountID + "/default"), - GeneratorId: toPointer(fmt.Sprintf("%s/%s", result.Source, generator)), - Types: []string{mapType(result.Source)}, - CreatedAt: toPointer(t.Format("2006-01-02T15:04:05.999999999Z07:00")), - UpdatedAt: toPointer(t.Format("2006-01-02T15:04:05.999999999Z07:00")), - Severity: &types.Severity{ - Label: MapSeverity(result.Severity), - }, - Title: &title, - Description: &result.Message, - ProductName: &c.productName, - CompanyName: &c.companyName, - Compliance: &types.Compliance{ - Status: types.ComplianceStatusFailed, - }, - Resources: []types.Resource{ - { - Type: toPointer("Other"), - Region: &c.region, - Partition: types.PartitionAws, - Id: mapResourceID(result), - Details: &types.ResourceDetails{ - Other: c.mapOtherDetails(result), - }, + return helper.Map(results, func(result v1alpha2.PolicyReportResult) types.AwsSecurityFinding { + generator := result.Policy + if generator == "" { + generator = result.Rule + } + + title := generator + if result.HasResource() { + title = fmt.Sprintf("%s: %s", title, result.ResourceString()) + } + + t := time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) + + return types.AwsSecurityFinding{ + Id: toPointer(result.GetID()), + AwsAccountId: accID, + SchemaVersion: schema, + ProductArn: c.arn, + GeneratorId: toPointer(fmt.Sprintf("%s/%s", result.Source, generator)), + Types: []string{mapType(result.Source)}, + CreatedAt: toPointer(t.Format("2006-01-02T15:04:05.999999999Z07:00")), + UpdatedAt: toPointer(t.Format("2006-01-02T15:04:05.999999999Z07:00")), + Severity: &types.Severity{ + Label: MapSeverity(result.Severity), + }, + Title: &title, + Description: &result.Message, + ProductName: &c.productName, + CompanyName: &c.companyName, + Compliance: &types.Compliance{ + Status: types.ComplianceStatusFailed, + }, + Workflow: &types.Workflow{ + Status: types.WorkflowStatusNew, + }, + Resources: []types.Resource{ + { + Type: toPointer("Other"), + Region: &c.region, + Partition: types.PartitionAws, + Id: mapResourceID(result), + Details: &types.ResourceDetails{ + Other: c.mapOtherDetails(polr, result), }, }, - RecordState: types.RecordStateActive, }, - }, + RecordState: types.RecordStateActive, + } + }) +} + +func (c *client) Send(result v1alpha2.PolicyReportResult) { + c.BatchSend(&v1alpha2.PolicyReport{}, []v1alpha2.PolicyReportResult{result}) +} + +func filterResults(results []v1alpha2.PolicyReportResult) []v1alpha2.PolicyReportResult { + return helper.Filter(results, func(r v1alpha2.PolicyReportResult) bool { + if r.Result == v1alpha2.StatusFail { + return true + } + if r.Result == v1alpha2.StatusWarn { + return true + } + if r.Result == v1alpha2.StatusError { + return true + } + + return false + }) +} + +func (c *client) BatchSend(polr v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) { + results = filterResults(results) + if len(results) == 0 { + return + } + + list, err := c.getFindingsByIDs(context.Background(), polr, toResourceIDFilter(polr, results), "") + if err != nil { + zap.L().Error(c.Name()+": failed to get findings", zap.Error(err)) + return + } + + list = filterFindings(list, results) + findings := helper.Map(list, func(f types.AwsSecurityFinding) types.AwsSecurityFindingIdentifier { + return types.AwsSecurityFindingIdentifier{ + Id: f.Id, + ProductArn: f.ProductArn, + } + }) + + if len(findings) > 0 { + updated, err := c.batchUpdate(context.Background(), findings, types.WorkflowStatusNew) + if err != nil { + zap.L().Error(c.Name()+": PUSH FAILED", zap.Error(err)) + return + } else if updated > 0 { + zap.L().Info(c.Name()+": PUSH OK", zap.Int("updated", updated)) + } + + mapping := make(map[string]bool, len(list)) + for _, f := range list { + mapping[*f.Id] = true + } + + results = helper.Filter(results, func(result v1alpha2.PolicyReportResult) bool { + return !mapping[result.GetID()] + }) + } + + if len(results) == 0 { + return + } + + res, err := c.hub.BatchImportFindings(context.Background(), &hub.BatchImportFindingsInput{ + Findings: c.mapFindings(polr, results), }) if err != nil { zap.L().Error(c.Name()+": PUSH FAILED", zap.Error(err), zap.Any("response", res)) return } - zap.L().Info(c.Name()+": PUSH OK", zap.Int32("successCount", *res.SuccessCount), zap.Int32("failedCount", *res.FailedCount)) + zap.L().Info(c.Name()+": PUSH OK", zap.Int32("imported", *res.SuccessCount), zap.Int32("failed", *res.FailedCount), zap.String("report", polr.GetKey())) +} + +func (c *client) Reset(ctx context.Context) error { + if !c.synchronize { + return nil + } + + zap.L().Info(c.Name() + ": START SYNC") + + list, err := c.getFindings(ctx) + if err != nil { + zap.L().Error(c.Name()+": failed to get findings", zap.Error(err)) + return err + } + + if len(list) == 0 { + zap.L().Info(c.Name() + ": no findings to sync") + return nil + } + + findings := helper.Map(list, func(f types.AwsSecurityFinding) types.AwsSecurityFindingIdentifier { + return types.AwsSecurityFindingIdentifier{ + Id: f.Id, + ProductArn: f.ProductArn, + } + }) + + count, err := c.batchUpdate(ctx, findings, types.WorkflowStatusResolved) + if err != nil { + zap.L().Error(c.Name()+": failed to sync findings", zap.Error(err)) + return err + } + + zap.L().Info(c.Name()+": FINISHED SYNC", zap.Int("updated", count)) + + return nil } func (c *client) CleanUp(ctx context.Context, report v1alpha2.ReportInterface) { - if !c.cleanup { + if !c.synchronize { return } - resourceIds := toResourceIDFilter(report) - if len(resourceIds) == 0 { - return + zap.L().Info(c.Name()+": start cleanup", zap.String("report", report.GetKey())) + + if report.GetSource() != "" { + if !c.BaseClient.ValidateReport(report) { + return + } } - findings, err := c.hub.GetFindings(ctx, &hub.GetFindingsInput{ - Filters: &types.AwsSecurityFindingFilters{ - Region: []types.StringFilter{ - { - Comparison: types.StringFilterComparisonEquals, - Value: &c.region, - }, - }, - Type: []types.StringFilter{ - { - Comparison: types.StringFilterComparisonPrefix, - Value: toPointer(mapType(report.GetSource())), - }, - }, - ResourceId: resourceIds, - RecordState: []types.StringFilter{ - { - Comparison: types.StringFilterComparisonEquals, - Value: toPointer("ACTIVE"), - }, - }, - }, - }) + resourceIds := toResourceIDFilter(report, report.GetResults()) + + findings, err := c.getFindingsByIDs(ctx, report, resourceIds, "") if err != nil { zap.L().Error(c.Name()+": failed to get findings", zap.Error(err)) return } + defer time.Sleep(c.delay) - if len(findings.Findings) == 0 { - time.Sleep(c.delay) + if len(findings) == 0 { return } - mapping := make(map[string]types.AwsSecurityFinding, len(findings.Findings)) - for _, f := range findings.Findings { + mapping := make(map[string]types.AwsSecurityFinding, len(findings)) + for _, f := range findings { mapping[*f.Id] = f } @@ -162,39 +260,34 @@ func (c *client) CleanUp(ctx context.Context, report v1alpha2.ReportInterface) { } if len(mapping) == 0 { - time.Sleep(c.delay) return } - list := make([]types.AwsSecurityFinding, 0) + list := make([]types.AwsSecurityFindingIdentifier, 0, len(mapping)) for _, f := range mapping { - f.UpdatedAt = toPointer(time.Now().Format("2006-01-02T15:04:05.999999999Z07:00")) - f.RecordState = types.RecordStateArchived - f.Workflow = &types.Workflow{ - Status: types.WorkflowStatusResolved, - } - - list = append(list, f) + list = append(list, types.AwsSecurityFindingIdentifier{ + Id: f.Id, + ProductArn: f.ProductArn, + }) } - if _, err = c.hub.BatchImportFindings(ctx, &hub.BatchImportFindingsInput{Findings: list}); err != nil { - zap.L().Error(c.Name()+": failed to batch archived findings", zap.Error(err)) - time.Sleep(c.delay) + count, err := c.batchUpdate(ctx, list, types.WorkflowStatusResolved) + if err != nil { + zap.L().Error(c.Name()+": failed to batch resolve findings", zap.Error(err)) return } - zap.L().Info(c.Name()+": Findings updated", zap.Int("count", len(list))) - time.Sleep(c.delay) + zap.L().Info(c.Name()+": CLEANUP OK", zap.Int("count", count), zap.String("report", report.GetKey())) } -func (c *client) mapOtherDetails(result v1alpha2.PolicyReportResult) map[string]string { +func (c *client) mapOtherDetails(polr v1alpha2.ReportInterface, result v1alpha2.PolicyReportResult) map[string]string { details := map[string]string{ "Source": result.Source, "Category": result.Category, "Policy": result.Policy, "Rule": result.Rule, "Result": string(result.Result), - "Priority": result.Priority.String(), + "Report": polr.GetKey(), } if len(c.customFields) > 0 { @@ -230,8 +323,177 @@ func (c *client) mapOtherDetails(result v1alpha2.PolicyReportResult) map[string] return details } +func (c *client) getFindings(ctx context.Context) ([]types.AwsSecurityFinding, error) { + list := make([]types.AwsSecurityFinding, 0) + + var token *string + + for { + resp, err := c.hub.GetFindings(ctx, &hub.GetFindingsInput{ + NextToken: token, + Filters: c.BaseFilter(nil), + }) + if err != nil { + return nil, err + } + + if len(resp.Findings) == 0 { + return list, nil + } + + list = append(list, resp.Findings...) + if resp.NextToken == nil { + return list, nil + } + + token = resp.NextToken + } +} + +func (c *client) batchUpdate(ctx context.Context, findings []types.AwsSecurityFindingIdentifier, status types.WorkflowStatus) (int, error) { + if len(findings) == 0 { + return 0, nil + } + + chunks := helper.ChunkSlice(findings, 100) + + var updated int + for _, chunk := range chunks { + response, err := c.hub.BatchUpdateFindings(ctx, &hub.BatchUpdateFindingsInput{ + FindingIdentifiers: chunk, + Workflow: &types.WorkflowUpdate{ + Status: status, + }, + }) + if err != nil { + return updated, err + } + + updated += len(response.ProcessedFindings) + } + + return updated, nil +} + +func (c *client) getFindingsByIDs(ctx context.Context, report v1alpha2.ReportInterface, resources []types.StringFilter, status string) ([]types.AwsSecurityFinding, error) { + list := make([]types.AwsSecurityFinding, 0) + + chunks := helper.ChunkSlice(resources, 20) + + for _, res := range chunks { + filter := c.BaseFilter(report) + if len(res) > 0 { + filter.ResourceId = res + } + + if status != "" { + filter.WorkflowStatus = []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: toPointer(status), + }, + } + } + + var token *string + + for { + resp, err := c.hub.GetFindings(ctx, &hub.GetFindingsInput{ + NextToken: token, + Filters: filter, + }) + if err != nil { + return nil, err + } + + if len(resp.Findings) == 0 { + break + } + + list = append(list, resp.Findings...) + if resp.NextToken == nil { + break + } + + token = resp.NextToken + } + } + + return list, nil +} + +func (c *client) BaseFilter(report v1alpha2.ReportInterface) *types.AwsSecurityFindingFilters { + source := "" + if report != nil { + source = report.GetSource() + } + + filter := &types.AwsSecurityFindingFilters{ + ProductArn: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: c.arn, + }, + }, + AwsAccountId: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: &c.accountID, + }, + }, + Region: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: &c.region, + }, + }, + Type: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonPrefix, + Value: toPointer(mapType(source)), + }, + }, + ProductName: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: &c.productName, + }, + }, + RecordState: []types.StringFilter{ + { + Comparison: types.StringFilterComparisonEquals, + Value: toPointer("ACTIVE"), + }, + }, + } + + if report != nil { + filter.ResourceDetailsOther = []types.MapFilter{ + { + Comparison: types.MapFilterComparisonEquals, + Key: toPointer("Report"), + Value: toPointer(report.GetKey()), + }, + } + } + + return filter +} + +func (c *client) Type() target.ClientType { + if !c.synchronize { + return target.BatchSend + } + + return target.SyncSend +} + // NewClient creates a new SecurityHub.client to send Results to SecurityHub. -func NewClient(options Options) target.Client { +func NewClient(options Options) *client { + if options.Delay == 0 { + options.Delay = 2 * time.Second + } + return &client{ target.NewBaseClient(options.ClientOptions), options.CustomFields, @@ -241,7 +503,8 @@ func NewClient(options Options) target.Client { options.ProductName, options.CompanyName, options.Delay, - options.Cleanup, + options.Synchronize, + toPointer("arn:aws:securityhub:" + options.Region + ":" + options.AccountID + ":product/" + options.AccountID + "/default"), } } @@ -287,7 +550,7 @@ func mapType(source string) string { return "Software and Configuration Checks/Kubernetes Policies/" + source } -func toResourceIDFilter(report v1alpha2.ReportInterface) []types.StringFilter { +func toResourceIDFilter(report v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) []types.StringFilter { res := report.GetScope() if res != nil { var value string @@ -305,7 +568,7 @@ func toResourceIDFilter(report v1alpha2.ReportInterface) []types.StringFilter { } } - if len(report.GetResults()) == 0 { + if len(results) == 0 { return []types.StringFilter{ { Comparison: types.StringFilterComparisonEquals, @@ -315,7 +578,7 @@ func toResourceIDFilter(report v1alpha2.ReportInterface) []types.StringFilter { } list := map[string]bool{} - for _, result := range report.GetResults() { + for _, result := range results { list[*mapResourceID(result)] = true } @@ -329,3 +592,29 @@ func toResourceIDFilter(report v1alpha2.ReportInterface) []types.StringFilter { return filter } + +func splitPolrKey(key string) (string, string) { + parts := strings.Split(key, "/") + if len(parts) == 1 { + return parts[0], "" + } + + return parts[1], parts[0] +} + +func filterFindings(findings []types.AwsSecurityFinding, results []v1alpha2.PolicyReportResult) []types.AwsSecurityFinding { + filtered := make([]types.AwsSecurityFinding, 0, len(findings)) + + mapping := make(map[string]bool, len(results)) + for _, r := range results { + mapping[r.GetID()] = true + } + + for _, finding := range findings { + if _, ok := mapping[*finding.Id]; ok { + filtered = append(filtered, finding) + } + } + + return filtered +} diff --git a/pkg/target/securityhub/securityhub_test.go b/pkg/target/securityhub/securityhub_test.go index 211af6ee..5ea020bd 100644 --- a/pkg/target/securityhub/securityhub_test.go +++ b/pkg/target/securityhub/securityhub_test.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" hub "github.com/aws/aws-sdk-go-v2/service/securityhub" "github.com/aws/aws-sdk-go-v2/service/securityhub/types" + "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/fixtures" "github.com/kyverno/policy-reporter/pkg/target/securityhub" @@ -40,10 +41,16 @@ func (c *client) GetFindings(ctx context.Context, params *hub.GetFindingsInput, }, nil } +func (c *client) BatchUpdateFindings(ctx context.Context, params *hub.BatchUpdateFindingsInput, optFns ...func(*hub.Options)) (*hub.BatchUpdateFindingsOutput, error) { + c.batched = true + + return &hub.BatchUpdateFindingsOutput{}, nil +} + func TestSecurityHub(t *testing.T) { t.Run("send result", func(t *testing.T) { c := securityhub.NewClient(securityhub.Options{ - AccountID: "accountID", + AccountID: "accountId", Region: "eu-central-1", ProductName: "Policy Reporter", CompanyName: "Kyverno", @@ -56,13 +63,13 @@ func TestSecurityHub(t *testing.T) { finding := findings[0] - if *finding.AwsAccountId != "accountID" { - t.Errorf("unexpected accountID: %s", *finding.AwsAccountId) + if *finding.AwsAccountId != "accountId" { + t.Errorf("unexpected accountId: %s", *finding.AwsAccountId) } if *finding.Id != fixtures.CompleteTargetSendResult.GetID() { t.Errorf("unexpected id: %s", *finding.Id) } - if *finding.ProductArn != "arn:aws:securityhub:eu-central-1:accountID:product/accountID/default" { + if *finding.ProductArn != "arn:aws:securityhub:eu-central-1:accountId:product/accountId/default" { t.Errorf("unexpected product arn: %s", *finding.ProductArn) } if *finding.ProductName != "Policy Reporter" { @@ -81,12 +88,12 @@ func TestSecurityHub(t *testing.T) { h := &client{} c := securityhub.NewClient(securityhub.Options{ - AccountID: "accountID", + AccountID: "accountId", Region: "eu-central-1", ProductName: "Policy Reporter", CompanyName: "Kyverno", Client: h, - Cleanup: false, + Synchronize: false, }) c.CleanUp(context.TODO(), fixtures.DefaultPolicyReport) @@ -102,12 +109,12 @@ func TestSecurityHub(t *testing.T) { h := &client{} c := securityhub.NewClient(securityhub.Options{ - AccountID: "accountID", + AccountID: "accountId", Region: "eu-central-1", ProductName: "Policy Reporter", CompanyName: "Kyverno", Client: h, - Cleanup: true, + Synchronize: true, }) c.CleanUp(context.TODO(), fixtures.DefaultPolicyReport) @@ -129,12 +136,12 @@ func TestSecurityHub(t *testing.T) { } c := securityhub.NewClient(securityhub.Options{ - AccountID: "accountID", + AccountID: "accountId", Region: "eu-central-1", ProductName: "Policy Reporter", CompanyName: "Kyverno", Client: h, - Cleanup: true, + Synchronize: true, }) c.CleanUp(context.TODO(), fixtures.DefaultPolicyReport) @@ -156,12 +163,12 @@ func TestSecurityHub(t *testing.T) { } c := securityhub.NewClient(securityhub.Options{ - AccountID: "accountID", + AccountID: "accountId", Region: "eu-central-1", ProductName: "Policy Reporter", CompanyName: "Kyverno", Client: h, - Cleanup: true, + Synchronize: true, }) c.CleanUp(context.TODO(), fixtures.DefaultPolicyReport) diff --git a/pkg/target/slack/slack.go b/pkg/target/slack/slack.go index e69a907f..35b33449 100644 --- a/pkg/target/slack/slack.go +++ b/pkg/target/slack/slack.go @@ -1,192 +1,169 @@ package slack import ( - "context" - "strings" + "fmt" + + "github.com/slack-go/slack" + "go.uber.org/zap" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" + "github.com/kyverno/policy-reporter/pkg/helper" "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/formatting" "github.com/kyverno/policy-reporter/pkg/target/http" ) // Options to configure the Slack target type Options struct { target.ClientOptions - Webhook string Channel string + Webhook string CustomFields map[string]string + Headers map[string]string HTTPClient http.Client } -type text struct { - Type string `json:"type"` - Text string `json:"text"` -} - -type block struct { - Type string `json:"type"` - Text *text `json:"text,omitempty"` - Fields []field `json:"fields,omitempty"` -} - -type field struct { - Type string `json:"type"` - Text string `json:"text"` -} - -type attachment struct { - Color string `json:"color"` - Blocks []block `json:"blocks"` -} - -type payload struct { - Channel string `json:"channel,omitempty"` - Username string `json:"username,omitempty"` - Attachments []attachment `json:"attachments,omitempty"` -} - type client struct { target.BaseClient - webhook string channel string + webhook string client http.Client customFields map[string]string + headers map[string]string } -var colors = map[v1alpha2.Priority]string{ - v1alpha2.DebugPriority: "#68c2ff", - v1alpha2.InfoPriority: "#36a64f", - v1alpha2.WarningPriority: "#f2c744", - v1alpha2.CriticalPriority: "#b80707", - v1alpha2.ErrorPriority: "#e20b0b", +var colors = map[v1alpha2.PolicySeverity]string{ + v1alpha2.SeverityInfo: "#68c2ff", + v1alpha2.SeverityLow: "#36a64f", + v1alpha2.SeverityMedium: "#f2c744", + v1alpha2.SeverityHigh: "#b80707", + v1alpha2.SeverityCritical: "#e20b0b", } -func (s *client) newPayload(result v1alpha2.PolicyReportResult) payload { - p := payload{ - Attachments: make([]attachment, 0, 1), +func (s *client) message(result v1alpha2.PolicyReportResult) *slack.WebhookMessage { + p := &slack.WebhookMessage{ + Attachments: make([]slack.Attachment, 0, 1), + Channel: s.channel, } if s.channel != "" { p.Channel = s.channel } - att := attachment{ - Color: colors[result.Priority], - Blocks: make([]block, 0), + att := slack.Attachment{ + Color: colors[result.Severity], + Blocks: slack.Blocks{ + BlockSet: make([]slack.Block, 0), + }, } - policyBlock := block{ - Type: "section", - Fields: []field{{Type: "mrkdwn", Text: "*Policy*\n" + result.Policy}}, - } + policyBlock := slack.NewSectionBlock(nil, []*slack.TextBlockObject{slack.NewTextBlockObject(slack.MarkdownType, "*Policy*\n"+result.Policy, false, false)}, nil) if result.Rule != "" { - policyBlock.Fields = append(policyBlock.Fields, field{Type: "mrkdwn", Text: "*Rule*\n" + result.Rule}) + policyBlock.Fields = append(policyBlock.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*Rule*\n"+result.Rule, false, false)) } - att.Blocks = append( - att.Blocks, - block{Type: "header", Text: &text{Type: "plain_text", Text: "New Policy Report Result"}}, + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewHeaderBlock(slack.NewTextBlockObject(slack.PlainTextType, "New Policy Report Result", false, false)), policyBlock, ) - att.Blocks = append( - att.Blocks, - block{Type: "section", Text: &text{Type: "mrkdwn", Text: "*Message*\n" + result.Message}}, - block{ - Type: "section", - Fields: []field{ - {Type: "mrkdwn", Text: "*Priority*\n" + result.Priority.String()}, - {Type: "mrkdwn", Text: "*Status*\n" + string(result.Result)}, - }, - }, + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Message*\n"+result.Message, false, false), nil, nil), + slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Status*\n"+string(result.Result), false, false), + }, nil), ) - b := block{ - Type: "section", - Fields: make([]field, 0, 2), - } + b := slack.NewSectionBlock(nil, make([]*slack.TextBlockObject, 0, 2), nil) if result.Category != "" { - b.Fields = append(b.Fields, field{Type: "mrkdwn", Text: "*Category*\n" + result.Category}) + b.Fields = append(b.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*Category*\n"+result.Category, false, false)) } if result.Severity != "" { - b.Fields = append(b.Fields, field{Type: "mrkdwn", Text: "*Severity*\n" + string(result.Severity)}) + b.Fields = append(b.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*Severity*\n"+string(result.Severity), false, false)) } if len(b.Fields) > 0 { - att.Blocks = append(att.Blocks, b) + att.Blocks.BlockSet = append(att.Blocks.BlockSet, b) } if result.HasResource() { res := result.GetResource() - att.Blocks = append(att.Blocks, block{Type: "section", Text: &text{Type: "mrkdwn", Text: "*Resource*"}}) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Resource*", false, false), nil, nil), + ) if res.APIVersion != "" { - att.Blocks = append(att.Blocks, block{ - Type: "section", - Fields: []field{ - {Type: "mrkdwn", Text: "*Kind*\n" + res.Kind}, - {Type: "mrkdwn", Text: "*API Version*\n" + res.APIVersion}, - }, - }) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Kind*\n"+res.Kind, false, false), + slack.NewTextBlockObject(slack.MarkdownType, "*API Version*\n"+res.APIVersion, false, false), + }, nil), + ) } else if res.APIVersion == "" && res.UID != "" { - att.Blocks = append(att.Blocks, block{ - Type: "section", - Text: &text{Type: "mrkdwn", Text: "*Kind*\n" + res.Kind}, - }) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Kind*\n"+res.Kind, false, false), + }, nil), + ) } if res.UID != "" { - att.Blocks = append(att.Blocks, block{ - Type: "section", - Fields: []field{ - {Type: "mrkdwn", Text: "*Name*\n" + res.Name}, - {Type: "mrkdwn", Text: "*UID*\n" + string(res.UID)}, - }, - }) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Name*\n"+res.Name, false, false), + slack.NewTextBlockObject(slack.MarkdownType, "*UID*\n"+string(res.UID), false, false), + }, nil), + ) } else if res.UID == "" && res.APIVersion != "" { - att.Blocks = append(att.Blocks, block{ - Type: "section", - Text: &text{Type: "mrkdwn", Text: "*Name*\n" + res.Name}, - }) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{slack.NewTextBlockObject(slack.MarkdownType, "*Name*\n"+res.Name, false, false)}, nil), + ) } if res.APIVersion == "" && res.UID == "" { - att.Blocks = append(att.Blocks, block{ - Type: "section", - Fields: []field{ - {Type: "mrkdwn", Text: "*Kind*\n" + res.Kind}, - {Type: "mrkdwn", Text: "*Name*\n" + res.Name}, - }, - }) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Kind*\n"+res.Kind, false, false), + slack.NewTextBlockObject(slack.MarkdownType, "*Name*\n"+res.Name, false, false), + }, nil), + ) } if res.Namespace != "" { - att.Blocks = append(att.Blocks, block{Type: "section", Fields: []field{{Type: "mrkdwn", Text: "*Namespace*\n" + res.Namespace}}}) + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(nil, []*slack.TextBlockObject{slack.NewTextBlockObject(slack.MarkdownType, "*Namespace*\n"+res.Namespace, false, false)}, nil), + ) } } if len(result.Properties) > 0 || len(s.customFields) > 0 { - att.Blocks = append( - att.Blocks, - block{Type: "section", Text: &text{Type: "mrkdwn", Text: "*Properties*"}}, + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Properties*", false, false), nil, nil), ) - propBlock := block{ - Type: "section", - Fields: []field{}, - } + propBlock := slack.NewSectionBlock(nil, make([]*slack.TextBlockObject, 0), nil) for property, value := range result.Properties { - propBlock.Fields = append(propBlock.Fields, field{Type: "mrkdwn", Text: "*" + strings.Title(property) + "*\n" + value}) + propBlock.Fields = append(propBlock.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*"+helper.Title(property)+"*\n"+value, false, false)) } for property, value := range s.customFields { - propBlock.Fields = append(propBlock.Fields, field{Type: "mrkdwn", Text: "*" + strings.Title(property) + "*\n" + value}) + propBlock.Fields = append(propBlock.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*"+helper.Title(property)+"*\n"+value, false, false)) } - att.Blocks = append(att.Blocks, propBlock) + att.Blocks.BlockSet = append(att.Blocks.BlockSet, propBlock) } p.Attachments = append(p.Attachments, att) @@ -194,25 +171,155 @@ func (s *client) newPayload(result v1alpha2.PolicyReportResult) payload { return p } +func (s *client) batchMessage(polr v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) *slack.WebhookMessage { + scope := polr.GetScope() + resource := formatting.ResourceString(scope) + + p := &slack.WebhookMessage{ + Attachments: make([]slack.Attachment, 0, 1), + Channel: s.channel, + } + + if s.channel != "" { + p.Channel = s.channel + } + + att := slack.Attachment{ + Color: colors[v1alpha2.SeverityInfo], + Blocks: slack.Blocks{ + BlockSet: make([]slack.Block, 0), + }, + } + + att.Blocks.BlockSet = append( + att.Blocks.BlockSet, + slack.NewHeaderBlock(slack.NewTextBlockObject(slack.PlainTextType, resource+" Policy Report Result", false, false)), + slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, fmt.Sprintf("Received %d new Policy Report Results", len(results)), false, false), nil, nil), + ) + + cfl := len(s.customFields) + if cfl > 0 { + att.Blocks.BlockSet = append(att.Blocks.BlockSet, slack.NewDividerBlock(), slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Custom Fields*", false, false), nil, nil)) + + i := 0 + + var propBlock *slack.SectionBlock + for property, value := range s.customFields { + if i%2 == 0 { + propBlock = slack.NewSectionBlock(nil, make([]*slack.TextBlockObject, 0, 2), nil) + att.Blocks.BlockSet = append(att.Blocks.BlockSet, propBlock) + } + + propBlock.Fields = append(propBlock.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*"+helper.Title(property)+"*\n"+value, false, false)) + i++ + } + } + + p.Attachments = append(p.Attachments, att) + + for _, result := range results { + resultAttachment := slack.Attachment{ + Color: colors[result.Severity], + Blocks: slack.Blocks{ + BlockSet: make([]slack.Block, 0), + }, + } + + policy := fmt.Sprintf("Policy: %s", result.Policy) + + if result.Rule != "" { + policy = fmt.Sprintf("%s/%s", policy, result.Rule) + } + + resultAttachment.Blocks.BlockSet = append( + resultAttachment.Blocks.BlockSet, + slack.NewHeaderBlock(slack.NewTextBlockObject(slack.PlainTextType, policy, false, false)), + ) + + if result.Category != "" { + resultAttachment.Blocks.BlockSet = append( + resultAttachment.Blocks.BlockSet, + slack.NewContextBlock("", slack.NewTextBlockObject(slack.MarkdownType, "*"+result.Category+"*", false, false)), + ) + } + + b := slack.NewSectionBlock(nil, []*slack.TextBlockObject{ + slack.NewTextBlockObject(slack.MarkdownType, "*Status*\n"+string(result.Result), false, false), + }, nil) + + if result.Severity != "" { + b.Fields = append(b.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*Severity*\n"+string(result.Severity), false, false)) + } + + resultAttachment.Blocks.BlockSet = append(resultAttachment.Blocks.BlockSet, b) + + resultAttachment.Blocks.BlockSet = append( + resultAttachment.Blocks.BlockSet, + slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Message*\n"+result.Message, false, false), nil, nil), + ) + + if len(result.Properties) > 0 { + resultAttachment.Blocks.BlockSet = append(resultAttachment.Blocks.BlockSet, slack.NewSectionBlock(slack.NewTextBlockObject(slack.MarkdownType, "*Properties*", false, false), nil, nil)) + + propBlock := slack.NewSectionBlock(nil, make([]*slack.TextBlockObject, 0), nil) + + for property, value := range result.Properties { + propBlock.Fields = append(propBlock.Fields, slack.NewTextBlockObject(slack.MarkdownType, "*"+helper.Title(property)+"*\n"+value, false, false)) + } + + resultAttachment.Blocks.BlockSet = append(resultAttachment.Blocks.BlockSet, propBlock) + } + + p.Attachments = append(p.Attachments, resultAttachment) + } + + return p +} + func (s *client) Send(result v1alpha2.PolicyReportResult) { - req, err := http.CreateJSONRequest(s.Name(), "POST", s.webhook, s.newPayload(result)) - if err != nil { + s.PostMessage(s.message(result)) +} + +func (s *client) BatchSend(report v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) { + if report.GetScope() == nil { + for _, result := range results { + s.Send(result) + } + return } + s.PostMessage(s.batchMessage(report, results)) +} + +func (s *client) PostMessage(message *slack.WebhookMessage) { + req, err := http.CreateJSONRequest("POST", s.webhook, message) + if err != nil { + zap.L().Error(s.Name()+": PUSH FAILED", zap.Error(err)) + return + } + + for k, v := range s.headers { + req.Header.Set(k, v) + } + resp, err := s.client.Do(req) + http.ProcessHTTPResponse(s.Name(), resp, err) } -func (s *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (s *client) Type() target.ClientType { + return target.BatchSend +} // NewClient creates a new slack.client to send Results to Slack func NewClient(options Options) target.Client { return &client{ target.NewBaseClient(options.ClientOptions), - options.Webhook, options.Channel, + options.Webhook, options.HTTPClient, options.CustomFields, + options.Headers, } } diff --git a/pkg/target/teams/card.go b/pkg/target/teams/card.go new file mode 100644 index 00000000..d4154ab8 --- /dev/null +++ b/pkg/target/teams/card.go @@ -0,0 +1,55 @@ +package teams + +import ( + "github.com/atc0005/go-teams-notify/v2/adaptivecard" + + "github.com/kyverno/policy-reporter/pkg/helper" +) + +func newFactSet() adaptivecard.Element { + factSet := adaptivecard.Element{ + Type: adaptivecard.TypeElementFactSet, + } + + return factSet +} + +func newFactSetPointer() *adaptivecard.Element { + factSet := newFactSet() + + return &factSet +} + +func newSubTitle(title string) adaptivecard.Element { + text := adaptivecard.NewTextBlock(title, true) + text.Weight = adaptivecard.WeightBolder + text.IsSubtle = true + + return text +} + +func MapToColumnSet(list map[string]string) adaptivecard.Element { + i := 0 + + first := adaptivecard.NewColumn() + first.Items = append(first.Items, newFactSetPointer()) + + second := adaptivecard.NewColumn() + second.Items = append(second.Items, newFactSetPointer()) + + propBlock := adaptivecard.NewColumnSet() + propBlock.Columns = []adaptivecard.Column{first, second} + + for property, value := range list { + index := i % 2 + + propBlock.Columns[index].Items[0].Facts = append(propBlock.Columns[index].Items[0].Facts, adaptivecard.Fact{ + Title: helper.Title(property), + Value: value, + }) + + i++ + } + + return propBlock +} diff --git a/pkg/target/teams/teams.go b/pkg/target/teams/teams.go index cf84d7b5..ede446fb 100644 --- a/pkg/target/teams/teams.go +++ b/pkg/target/teams/teams.go @@ -2,11 +2,15 @@ package teams import ( "context" - "strings" - "time" + "fmt" + + "github.com/atc0005/go-teams-notify/v2/adaptivecard" + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/target" + "github.com/kyverno/policy-reporter/pkg/target/formatting" "github.com/kyverno/policy-reporter/pkg/target/http" ) @@ -15,125 +19,120 @@ type Options struct { target.ClientOptions Webhook string CustomFields map[string]string + Headers map[string]string HTTPClient http.Client } -type fact struct { - Name string `json:"name"` - Value string `json:"value"` -} - -type section struct { - Title string `json:"activityTitle"` - SubTitle string `json:"activitySubtitle"` - Text string `json:"text"` - Facts []fact `json:"facts,omitempty"` -} - -type payload struct { - Type string `json:"@type"` - Context string `json:"@context"` - Summary string `json:"summary,omitempty"` - ThemeColor string `json:"themeColor,omitempty"` - Sections []section `json:"sections"` -} - -var colors = map[v1alpha2.Priority]string{ - v1alpha2.DebugPriority: "68c2ff", - v1alpha2.InfoPriority: "36a64f", - v1alpha2.WarningPriority: "f2c744", - v1alpha2.CriticalPriority: "b80707", - v1alpha2.ErrorPriority: "e20b0b", -} - -func newPayload(result v1alpha2.PolicyReportResult, customFields map[string]string) payload { - facts := make([]fact, 0) - - facts = append(facts, fact{"Policy", result.Policy}) - - if result.Rule != "" { - facts = append(facts, fact{"Rule", result.Rule}) - } - - facts = append(facts, fact{"Priority", result.Priority.String()}) - - if result.Category != "" { - facts = append(facts, fact{"Category", result.Category}) - } - if result.Severity != "" { - facts = append(facts, fact{"Severity", string(result.Severity)}) - } - - if result.HasResource() { - res := result.GetResource() - - facts = append(facts, fact{"Kind", res.Kind}) - facts = append(facts, fact{"Name", res.Name}) - if res.UID != "" { - facts = append(facts, fact{"UID", string(res.UID)}) - } - if res.Namespace != "" { - facts = append(facts, fact{"Namespace", res.Namespace}) - } - if res.APIVersion != "" { - facts = append(facts, fact{"API Version", res.APIVersion}) - } - } - - for property, value := range result.Properties { - facts = append(facts, fact{strings.Title(property), value}) - } - for property, value := range customFields { - facts = append(facts, fact{strings.Title(property), value}) - } - - timestamp := time.Now() - if result.Timestamp.Seconds == 0 { - timestamp = time.Unix(result.Timestamp.Seconds, int64(result.Timestamp.Nanos)) - } - - sections := make([]section, 0, 1) - sections = append(sections, section{ - Title: "New Policy Report Result", - SubTitle: timestamp.Format(time.RFC3339), - Text: result.Message, - Facts: facts, - }) - - return payload{ - Type: "MessageCard", - Context: "http://schema.org/extensions", - Summary: result.Message, - ThemeColor: colors[result.Priority], - Sections: sections, - } -} - type client struct { target.BaseClient webhook string customFields map[string]string + headers map[string]string client http.Client } func (s *client) Send(result v1alpha2.PolicyReportResult) { - req, err := http.CreateJSONRequest(s.Name(), "POST", s.webhook, newPayload(result, s.customFields)) - if err != nil { - return - } - - resp, err := s.client.Do(req) - http.ProcessHTTPResponse(s.Name(), resp, err) + s.PostMessage(s.newMessage(result.GetResource(), []v1alpha2.PolicyReportResult{result})) } func (s *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (s *client) BatchSend(report v1alpha2.ReportInterface, results []v1alpha2.PolicyReportResult) { + if report.GetScope() == nil { + for _, r := range results { + s.Send(r) + } + } + + s.PostMessage(s.newMessage(report.GetScope(), results)) +} + +func (s *client) PostMessage(message *adaptivecard.Message) { + if err := message.Validate(); err != nil { + zap.L().Error(s.Name()+": PUSH FAILED", zap.Error(err)) + return + } + + req, err := http.CreateJSONRequest("POST", s.webhook, message) + if err != nil { + zap.L().Error(s.Name()+": PUSH FAILED", zap.Error(err)) + return + } + + for k, v := range s.headers { + req.Header.Set(k, v) + } + + resp, err := s.client.Do(req) + + http.ProcessHTTPResponse(s.Name(), resp, err) +} + +func (s *client) Type() target.ClientType { + return target.BatchSend +} + +func (s *client) newMessage(resource *corev1.ObjectReference, results []v1alpha2.PolicyReportResult) *adaptivecard.Message { + header := adaptivecard.NewContainer() + + if resource != nil { + header.AddElement(false, adaptivecard.NewTitleTextBlock(formatting.ResourceString(resource), true)) + } else { + header.AddElement(false, adaptivecard.NewTitleTextBlock("New PolicyReport Results", true)) + } + + header.AddElement(false, adaptivecard.NewTextBlock(fmt.Sprintf("Received %d new Policy Report Results", len(results)), true)) + + if len(s.customFields) > 0 { + header.AddElement(false, MapToColumnSet(s.customFields)) + } + + card := adaptivecard.NewCard() + card.SetFullWidth() + card.AddContainer(true, header) + + for _, result := range results { + stats := newFactSet() + stats.Facts = append(stats.Facts, adaptivecard.Fact{Title: "Status", Value: string(result.Result)}) + + if result.Severity != "" { + stats.Facts = append(stats.Facts, adaptivecard.Fact{Title: "Severity", Value: string(result.Severity)}) + } + + policy := fmt.Sprintf("Policy: %s", result.Policy) + + if result.Rule != "" { + policy = fmt.Sprintf("%s/%s", policy, result.Rule) + } + + r := adaptivecard.NewContainer() + r.Separator = true + r.Spacing = adaptivecard.SpacingLarge + r.AddElement(false, newSubTitle(policy)) + r.AddElement(false, adaptivecard.NewTextBlock(result.Category, true)) + r.AddElement(false, stats) + r.AddElement(false, adaptivecard.NewTextBlock(result.Message, true)) + + if len(result.Properties) > 0 { + r.AddElement(false, MapToColumnSet(result.Properties)) + } + + card.AddContainer(false, r) + } + + msg := adaptivecard.NewMessage() + msg.Attach(card) + + return msg +} + // NewClient creates a new teams.client to send Results to MS Teams func NewClient(options Options) target.Client { return &client{ target.NewBaseClient(options.ClientOptions), options.Webhook, options.CustomFields, + options.Headers, options.HTTPClient, } } diff --git a/pkg/target/teams/teams_test.go b/pkg/target/teams/teams_test.go index decc9473..0ec1f637 100644 --- a/pkg/target/teams/teams_test.go +++ b/pkg/target/teams/teams_test.go @@ -5,6 +5,8 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/kyverno/policy-reporter/pkg/fixtures" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/teams" @@ -44,10 +46,6 @@ func Test_TeamsTarget(t *testing.T) { if err != nil { t.Fatal(err) } - - if payload["themeColor"] != "f2c744" { - t.Errorf("Unexpected ThemeColor %s", payload["themeColor"]) - } } client := teams.NewClient(teams.Options{ @@ -81,10 +79,6 @@ func Test_TeamsTarget(t *testing.T) { if err != nil { t.Fatal(err) } - - if payload["themeColor"] != "b80707" { - t.Errorf("Unexpected ThemeColor %s", payload["themeColor"]) - } } client := teams.NewClient(teams.Options{ @@ -105,10 +99,6 @@ func Test_TeamsTarget(t *testing.T) { if err != nil { t.Fatal(err) } - - if payload["themeColor"] != "36a64f" { - t.Errorf("Unexpected ThemeColor %s", payload["themeColor"]) - } } client := teams.NewClient(teams.Options{ @@ -129,10 +119,6 @@ func Test_TeamsTarget(t *testing.T) { if err != nil { t.Fatal(err) } - - if payload["themeColor"] != "e20b0b" { - t.Errorf("Unexpected ThemeColor %s", payload["themeColor"]) - } } client := teams.NewClient(teams.Options{ @@ -165,10 +151,6 @@ func Test_TeamsTarget(t *testing.T) { if err != nil { t.Fatal(err) } - - if payload["themeColor"] != "68c2ff" { - t.Errorf("Unexpected ThemeColor %s", payload["themeColor"]) - } } client := teams.NewClient(teams.Options{ @@ -191,8 +173,18 @@ func Test_TeamsTarget(t *testing.T) { HTTPClient: testClient{}, }) - if client.Name() != "Teams" { - t.Errorf("Unexpected Name %s", client.Name()) - } + assert.Equal(t, "Teams", client.Name()) + }) + t.Run("SupportBatchSend", func(t *testing.T) { + client := teams.NewClient(teams.Options{ + ClientOptions: target.ClientOptions{ + Name: "Teams", + }, + Webhook: "http://hook.teams:80", + CustomFields: map[string]string{"Cluster": "Name"}, + HTTPClient: testClient{}, + }) + + assert.Equal(t, target.BatchSend, client.Type()) }) } diff --git a/pkg/target/telegram/telegram.go b/pkg/target/telegram/telegram.go index ca67fd12..dbbf075b 100644 --- a/pkg/target/telegram/telegram.go +++ b/pkg/target/telegram/telegram.go @@ -27,7 +27,7 @@ func escape(text interface{}) string { return replacer.Replace(fmt.Sprintf("%v", text)) } -var notificationTempl = `*\[Policy Reporter\] \[{{ .Priority }}\] {{ escape (or .Result.Policy .Result.Rule) }}* +var notificationTempl = `*\[Policy Reporter\] \[{{ .Result.Severity }}\] {{ escape (or .Result.Policy .Result.Rule) }}* {{- if .Resource }} *Resource*: {{ .Resource.Kind }} {{ if .Resource.Namespace }}{{ escape .Resource.Namespace }}/{{ end }}{{ escape .Resource.Name }} @@ -118,16 +118,10 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { res = result.GetResource() } - prio := result.Priority.String() - if prio == "" { - prio = v1alpha2.DebugPriority.String() - } - err = ttmpl.Execute(&textBuffer, values{ Result: result, Time: time.Now(), Resource: res, - Priority: prio, }) if err != nil { zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err)) @@ -136,7 +130,7 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { payload.Text = textBuffer.String() - req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, payload) + req, err := http.CreateJSONRequest("POST", e.host, payload) if err != nil { zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err)) fmt.Println(err) @@ -153,6 +147,16 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { func (e *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (e *client) Reset(_ context.Context) error { + return nil +} + +func (e *client) BatchSend(_ v1alpha2.ReportInterface, _ []v1alpha2.PolicyReportResult) {} + +func (e *client) Type() target.ClientType { + return target.SingleSend +} + // NewClient creates a new loki.client to send Results to Elasticsearch func NewClient(options Options) target.Client { return &client{ diff --git a/pkg/target/ui/ui.go b/pkg/target/ui/ui.go deleted file mode 100644 index c6437708..00000000 --- a/pkg/target/ui/ui.go +++ /dev/null @@ -1,43 +0,0 @@ -package ui - -import ( - "context" - - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" - "github.com/kyverno/policy-reporter/pkg/target" - "github.com/kyverno/policy-reporter/pkg/target/http" -) - -// Options to configure the Discord target -type Options struct { - target.ClientOptions - Host string - HTTPClient http.Client -} - -type client struct { - target.BaseClient - host string - client http.Client -} - -func (e *client) Send(result v1alpha2.PolicyReportResult) { - req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, http.NewJSONResult(result)) - if err != nil { - return - } - - resp, err := e.client.Do(req) - http.ProcessHTTPResponse(e.Name(), resp, err) -} - -func (e *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} - -// NewClient creates a new loki.client to send Results to Elasticsearch -func NewClient(options Options) target.Client { - return &client{ - target.NewBaseClient(options.ClientOptions), - options.Host + "/api/push", - options.HTTPClient, - } -} diff --git a/pkg/target/ui/ui_test.go b/pkg/target/ui/ui_test.go deleted file mode 100644 index 9da0c6d5..00000000 --- a/pkg/target/ui/ui_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package ui_test - -import ( - "net/http" - "testing" - - "github.com/kyverno/policy-reporter/pkg/fixtures" - "github.com/kyverno/policy-reporter/pkg/target" - "github.com/kyverno/policy-reporter/pkg/target/ui" -) - -type testClient struct { - callback func(req *http.Request) - statusCode int -} - -func (c testClient) Do(req *http.Request) (*http.Response, error) { - c.callback(req) - - return &http.Response{ - StatusCode: c.statusCode, - }, nil -} - -func Test_UITarget(t *testing.T) { - t.Run("Send", func(t *testing.T) { - callback := func(req *http.Request) { - if contentType := req.Header.Get("Content-Type"); contentType != "application/json; charset=utf-8" { - t.Errorf("Unexpected Content-Type: %s", contentType) - } - - if agend := req.Header.Get("User-Agent"); agend != "Policy-Reporter" { - t.Errorf("Unexpected Host: %s", agend) - } - - if url := req.URL.String(); url != "http://localhost:8080/api/push" { - t.Errorf("Unexpected Host: %s", url) - } - } - - client := ui.NewClient(ui.Options{ - ClientOptions: target.ClientOptions{ - Name: "UI", - }, - Host: "http://localhost:8080", - HTTPClient: testClient{callback, 200}, - }) - client.Send(fixtures.CompleteTargetSendResult) - }) - t.Run("Name", func(t *testing.T) { - client := ui.NewClient(ui.Options{ - ClientOptions: target.ClientOptions{ - Name: "UI", - }, - Host: "http://localhost:8080", - HTTPClient: testClient{}, - }) - - if client.Name() != "UI" { - t.Errorf("Unexpected Name %s", client.Name()) - } - }) -} diff --git a/pkg/target/webhook/webhook.go b/pkg/target/webhook/webhook.go index cedc6e93..032b7378 100644 --- a/pkg/target/webhook/webhook.go +++ b/pkg/target/webhook/webhook.go @@ -1,8 +1,6 @@ package webhook import ( - "context" - "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" "github.com/kyverno/policy-reporter/pkg/target" "github.com/kyverno/policy-reporter/pkg/target/http" @@ -40,7 +38,7 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { result.Properties = props } - req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, http.NewJSONResult(result)) + req, err := http.CreateJSONRequest("POST", e.host, http.NewJSONResult(result)) if err != nil { return } @@ -53,7 +51,9 @@ func (e *client) Send(result v1alpha2.PolicyReportResult) { http.ProcessHTTPResponse(e.Name(), resp, err) } -func (e *client) CleanUp(_ context.Context, _ v1alpha2.ReportInterface) {} +func (e *client) Type() target.ClientType { + return target.SingleSend +} // NewClient creates a new loki.client to send Results to Elasticsearch func NewClient(options Options) target.Client { diff --git a/pkg/target/webhook/webhook_test.go b/pkg/target/webhook/webhook_test.go index e429d010..d7290cd3 100644 --- a/pkg/target/webhook/webhook_test.go +++ b/pkg/target/webhook/webhook_test.go @@ -76,4 +76,20 @@ func Test_UITarget(t *testing.T) { t.Errorf("Unexpected Name %s", client.Name()) } }) + t.Run("Request Error", func(t *testing.T) { + callback := func(req *http.Request) error { + t.Fail() + + return nil + } + + client := webhook.NewClient(webhook.Options{ + ClientOptions: target.ClientOptions{ + Name: "UI", + }, + Host: "\\localhost:8080", + HTTPClient: testClient{callback, 200}, + }) + client.Send(fixtures.CompleteTargetSendResult) + }) } diff --git a/pkg/validate/model.go b/pkg/validate/model.go index 22468fea..54ffc0a5 100644 --- a/pkg/validate/model.go +++ b/pkg/validate/model.go @@ -1,10 +1,15 @@ package validate type RuleSets struct { - Exclude []string - Include []string + Exclude []string + Include []string + Selector map[string]string } func (r RuleSets) Count() int { return len(r.Exclude) + len(r.Include) } + +func (r RuleSets) Enabled() bool { + return r.Count() > 0 +} diff --git a/policy.yaml b/policy.yaml new file mode 100644 index 00000000..ed32e280 --- /dev/null +++ b/policy.yaml @@ -0,0 +1,22 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-labels +spec: + validationFailureAction: Audit + rules: + - name: check-for-labels + match: + any: + - resources: + kinds: + - Pod + namespaces: + - policy-reporter + + validate: + message: "label 'app.kubernetes.io/test' is required" + pattern: + metadata: + labels: + app.kubernetes.io/test: "?*" \ No newline at end of file diff --git a/scripts/kind.yaml b/scripts/kind.yaml new file mode 100644 index 00000000..c3f5f173 --- /dev/null +++ b/scripts/kind.yaml @@ -0,0 +1,34 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +kubeadmConfigPatches: + - |- + kind: ClusterConfiguration + controllerManager: + extraArgs: + bind-address: 0.0.0.0 + etcd: + local: + extraArgs: + listen-metrics-urls: http://0.0.0.0:2382 + scheduler: + extraArgs: + bind-address: 0.0.0.0 + - |- + kind: KubeProxyConfiguration + metricsBindAddress: 0.0.0.0 +nodes: + - role: control-plane + kubeadmConfigPatches: + - |- + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP + - role: worker diff --git a/test b/test new file mode 100644 index 00000000..b586b48c --- /dev/null +++ b/test @@ -0,0 +1,2 @@ +Pushed: ghcr.io/fjogeleit/charts/policy-reporter:3.0.0-beta.18 +Digest: sha256:ebc720b178dbbdc5def056e0d8c57a9475180d087c68c7afdf64ea5bbaff6eab

    zg;ugb^+GsYE%170_dK55XJEU$9}zBoA4+lDC(Cyo z2F3BDgY|pZc~QluIo%@RaN?w%6Qb6KaHyOC8xa2Rz3r5-_b3Nc$mUVUm3n%?lx@N( z!tNz{4qq9MW23#=P>a;4=23D@extSf?Lxbn28P+Rn-BAP_G(=73P;AqY6S5%dGo@H zIAEP;_?vPKHeHTeU7t*Jbw5QN@r1o;C}{DB-(_&7Is*1A0S=%a+O(>bbb)U5Q06i4 zI(t{377}tZz^Zf*t+jGn;DY#~wB9Xe+Q?Jx?R7LA86eyKn9#7fMPFU;c6}z2!^30U z99x<@I^4I2=h)!#$l!S8jZzJ80F);u{bD-t4nFoKAUO0*tXr~^hJc%ALZMYv+Gn;?GatSM>Q1f3aLj?u#*o6AIO_I zKUUcp)3J3HCu4i(bg1Ni$Yy{DtHo>QnoDgByk~PpMIPph(_>jV>ykux&G)pGx`q#F z)Jt?}Q@u)jGUJOnNKH04Gde?vaMj}p@A=KTuO;tLu(j76cL3#|+=j1`;$!7+HHKH# zt+LznOF?$aEQUW!NGooR++Mv%ZrXz2vtZ*X=;Uj3lzQ+=&svs=sr%R0j0I*X zKAMR7-3FwtX=224kiZ zd#hdHO5Pi)J1IoillafQ@^}YZVvcxkU;keJPO78bgLt^j<2AL%7C{#D$}q)bV`}!F zxloa0KYP^e!aeVsBY(e z-+NI)Cnso7{oDiLeHzBz$n4|F2WFPDSw9^zyza>q#N;V$w0~6STQ5ibjwku@#P@P7 z(F0m$_w3bsj0M2G(`UZ&82tH#Ui>ZGPW*eivFKF^hj)}<&h_HqJo!g;yR z+0PS0`DrV0^~a4d{9lUsi4$CB z612V3>8MX+BH4|H_;jS>yF}f}g9Dw6dNqAHKj$r~^+e5*f-}+I-=8+Ixy?{9QMq}K z>m!KedkD59CJ9U8H5yh{R+;uaqC3|hl466e9{GiUuV23dQ|4j|31GQ-t=~!v}@#3Q5oJpY<*byj8ETfhs=} z+O2c+fH}G~rfq%Aa+qH8-4__VZb|W3eqxv{es3VXY;uhDpyGts!)=ZN1i128~ zF%?27YKvjo=UpXCTn_qM+abzs%PCGO9 z6L2Ji5NR_d&F!(o({a`YrM-+P+YHfXA&T#Rs8>}aDYjpa+3iB(D^7#?$EAJ`qm6GV z2_BHCGb7Ic(%v1&yTNZ1d1t1HsC?;piA6()!1LRr(N)!!@@1V=o@Lx%@L*z_Kxbl* zJAduV(@tTxzQi>k{{)h~@d*!~sN$NO zI8uuF^iL|qX{uDlortpX~((D%}WTEwi#T(Iy}Cho&o z8Ct*3s!kMxI}0!IY*gbF4om?j)YXhqI7m89!@17p@?yH|PRsj*d!=+33Xa@pF8+;s zEw^-h8VDq`itU3xs8vHq!tb(7ce1h$>+SIjJCMO&zY~v)TyK70EghKQ4TQThqf;Nf zeDEbFX@e<-+8VM?VxyJTvjxeEk}9mWsZ=}SRMYKyVxYA67=K*3nCK=HCM+hO@++pk z051<0R+UvGoj{QY2p7qlo9+5c>Of z--J-{^=Vx6;>s-ZxkqY5e2xe)&OXH8pt_-l`B2H95rd!=HUnPKb(3di)YZBL80{U5 za5Nx!k7cXo9jdW&LuWYpqq(7`c)T;>{^9+h{`WU-1dYY3q}1)$?DgdC{7|0^d}KK` zxhv58+Sj?Wk|U&>)<;Xoh|Wgw>#$stl|{3$J)bx7M(B zdE0nPv2s~IeIxIknKv{xES(tJ??#(r;oY3OpoIC+exs*)aEI*VxUPwZ1!oz!tq>Nm zf;MsST(Pne;jUMBQxW9$uNOk!9h1Uza;B4=q&^&#JkO{@t%KxT3r@KgJ}mfh*L7#s zy%Gfl{=9k(F;Io%B&2wnil*7gE-#jYOn?_c!-qX2H>(FNHr``JlF3onw}H18jYgfq z$CC8yzKLO#llP@-b%Q+0`69Tx?d}`Rh#xvijN=+V#}!)^G~u%t)v$#17?@IpGe87=I=B%Z*6pUYOjEe>;qeWWeLeT)TxLvb&VzbS)qOKiCs z$PY%1@o_tCazOr?Q3eT3fU<~+Cei!m_ZEdiYLr0G`jq^!hhI>zWzpuL@gm|vZ;`!X zBHdcf*3L{8#Jga!Bc&rf@M_4=_Km_ri$Ra{$;68rK~V|}iRG{h>Qy|fB$%v<{T&&W zmOl6tB%4I)-EpFrY-y02yhV^h20F|1MdY=raFb?+o1%g#2|?UBIh5}IR1|2XJa(;Z-0oK z%#?PgV)^ z%0zJ2MDtCUX4SM!Z8;0ngliL<{Eb#=w_AUrJe4UavI_eJ6FU9FvBXZzP;+wxQK@(y zt+}r8hm}%?8NPh`kLUa9KGWyXR}62Gr(1Y0wUGN*lwaij@-yOh^HCTNK9Mn#bJ})< z%6nn^b2A%qN%q3aXu$@|$xctgPkBaLwb^fY-*C9`jH<(EHtquXxgc++Dtv| zxp2%UIy~IRdR_3N66FWIdEDMS4-8;z4%4%1lEH_(xZkAe9(NTpur{J{9 z+L52xHnNDguI1~5B>7U@_+GnJBBv8AJ(B8se{5t>Jr6gBf66@LA#PHUOxrVog)b^Wsj;D9zU@77kw znrjyg92Wy|R>dm64=>Zx_@hsKQCwr(w7NutHicalgbBn?fvm zd>{Ec&YcNvk^YfCo$SAu;)-6s&V!Ly+nGgB z_{dgYt`YE~D?<2OT|`(~ujf>o{$`&zry~qeJwcxz*F@0rYkuj@!g7~YnRVgI$UZd@! z!*Ab1nXeOK&oVNPfUjfQ!5$d1&EuLY3_Mt1a=R-}-mBfZi@MO;ySv9~H=#~}osqZ% zFG;A+TU~wGyuVYsJLk3c4PWJL_wm3hJeXE`1~Vn$i;Gq`OhmQ0ycJ5N>dU!7f0GU4 zNzKNIx*h5d(*=Cy@nFv2JeYIjjmy;E|9P#V} zQ>Cku=b6I<*4bW6a_*lH#Ba@-HGFms~aNasxI9~r++<=tWOu?d_ME;K@p+I z^Q4@^9v{}vARbpH7%o9y-mclgb0hQg*X{Bm)saPJks{Y%t{#%n?ukMEjNpN$ou+Ge zR_X7XGnp|7GlWN4JYLRk^;}xdGr7LR))|B4m_Hm2vFrBE>d*GTe`}uqJ84ND+g#=Q$eXs$wkWV<~ z0jckcv@jIYB0OISFzWS>rpW6ztNe2TS1@-KC|@ z8pg+p8vupv6bO-k-ehfqXw6c%OlfQ*vAw?rdsJZ$4ln3m*67&YtSmXoU+1TzM1;;N z`&nIIQ~Gm73T&Fd=h^|oIbRH1TDN>C?tLoBvrNlR66#-mKfGh~?tl#eTlmLpuT2@= zWd;+1&WjM|UV)g=iD-kNQ5+nTZ~JoY@h0}Iab!Ao&EOJR-D3}z@tyZneRhihCk;Q5 z1LH`ibC<6%@?wne$0GmPe%&0)w54RI@5a8+X!$JeyB864QeRYi1g{CFVkV8o4vZD*eM7%|U^a}0?v7Y=byAuYiAu}Jw+)Vx z;MXkKV-0UQ&RmbdWZ1qE^qO#^#7;d!lHS2vj(U&l$6JQFALdZhe;b9rNNUbuseYgJ z1cHAF>-rjvZf`vjWD!KCmr1Dbn9FG`Nyfxb*o!qKdlP)NH(j>orq9{69!wBcE_Mml zK&Za7TfJxS*7Q}3oa2;5_M@^1iiD`s?AyY*^Q^IA!uo28+XJ3|llBx`Re|x5n2Z-8 z_CxLYhZi#{Op(PBvu@5axZ`(qzUp)a_2iMRJ*{p%?9Shhu%&-w@FC-QB+e)zr1x`&9{+kzEnx6US^PqBq8zmO=y2-sY z8ia>fJx3_aS|4gmGks~?KS(>zdB|pB9z~*KL6K@s!%jJ0HrP|)r0=ED5mPT%_W8UG zgV{ZJRgQW0+W@Uu=V-WpiMp!du34tNF!7(RCN0+-X2i7u1X9&)AO(qEe&#@JR9~<&ytm`~cNv1$Q(ei2!8zKA*#9)ts@y;6-CAf&3<o9s zhAP-AC|$+qo|r|IUh1aa`!KXT@79yhZfCEutI{)(Ia4xs*Q7>{GZOEWj{tlK?%j z^gr|K2=t>ay2@+Rmi7zgPCN9l*IHN3RtPNy64sQD>(^qxG+BB+^K%Nt^b0q_x}Zz* zKu&b_Dxo~f=>re90TQx(N2R;@AU_k=?vAv7Nb~bYld^^YI5rz_{Z?=?Gk+Dojt{_3N^;QzBK=pIkirJ;2Ubv28?EgB#Sw|`tN^T5qHq( z7H*JReM|P(_&i&^mNIQ!2k*E_>k~BdsMiyj0UYayMS~BN%>z(RcBpUs6Z|^>8fV!5 zFRuN;5>g=ypQ13dx~-C)npD(bHu$omAb3d`7)=#H(d~~GjYnLW_D7DA$T(2b9R=Z| zzvG6#ctHfhN56>Cv#meMiV>9gLsY{2?lrzU*5N~4P@(T_2$uk{?%x9avtc4Z12yc- zVq1EAHLqTCjNAe9-DR);Gs%BXII!sxCLNk$7&F%Ymd@vdfOM83Ip=;M)<4hr=OKpe zgnOUTHGkiqJc&QZZ&;FN^`Bq5FzGgqBmxZ_cT7U9SzR6uM>i6$tp8g^=fBebKP{c=P2pp!f z)l|h-3&Oul{LvWBQIn(Nebn2Vs%IvuP5vu!0a~jvivmUYy-EDG-R}Upk*N^`HSGf< z^-Iuokl{D$|FEi|BKwOL{~-^FgP0&cxm-%X=nU#nt!doBxO4q+^9f_YwpymQh4k+z z)^v!U18T~=$L@%m5Trg7)O3>uA8vbHRPoL)T>q(?;aB!dGC4Ub=og~?^=B^x1CV-y z)a>@({QRf%l!l06HffDaTDLbn4ZM$Xk1qF* z(@6W@@vgl%nriI0Yv}|)@E3&_$B`-7s&LhmK@X;$PAunqz{n<}it6j+C%t-Ht=++j z)xR)$SPakdgWer8C{l~CjF??}r0pXBne19$DxdFZJsq)|&)Iag z;`4YRgV;*_F|kx5m0tAa{EKVVwqt!zCo{V*hJCiz7oMQqDDd08vn!|>ldf~L_LIlP zX%WSGG3Vl1Ne_o*9cTUFP`tcWM#U$=c&6E$=~I@*^iDd9@DmbK(fL{ zuAqv{wMtL$008iL{e1nUc`dW#(PY5LS~q(2%k*C1U6sN^PxaLFt?@QLdv73ScYVeK zC6V!OrS*N-E=d|sB~Px>2L~c7@S-VwXSYJZ7xQ+t5YEt7F5tVq01i{xU_iEHi%35C z)f^;7G=0G3pRsHFO0WW0uBH)ed>j~M91Gvk2R&)gGXNqM@id5aj>~ihY_?rCsi#o= zhnnx({OC_?sL|)fgw&&bB-_na)7F*N6g~h{@c_y-MrEo7Mdm>earr(7`?h6|@mhVt z(zilew$uCZcvaoL0I=+e2LP2i5RBxC#iLFrsu)PDY}dTHMe?v&330Xz+_66aK&_ge zj=&p5!Oyj*qr%3-<-HGi9v`5j`_$u``X@EBS8-AIlSY!uT<^WbcBt`U{jT@!j@E#O zx+_qP^^kjCaJ;%7cyll3MvE+j6E&^QG$z2+Yh~hZRJ=lX+qK~!S;rfIWL$(GDvcEZ z`^nl!y?6?KK*DfaW42#wM< zP}i{@tzVC{wOYCk4ir7Tg8h(lCk^8;)_^YMK!-t^oRCBZFk%tUcOuzyr&=L`Zs&tT z_dWJYTpPQWF7~l0MUESvvt3|(Box#8Y)K);jSe8jq1;`7rIv&`LDLgpjl_%dmGByn zv=^~yCdDe@v$6{;=&4wE-RmeniK4~Y3w=z62DTnKh>8)OThp}~iQA7pdA8A04TAeX zZh>q^`0qkgBb27Zo(|nc@um|GT5jf7+RR8A&H)(xE`S#_?)aS48XS<32$y9~iJLEz z%u|;7nxCnWkG@K7D7%REJHS1ZkS6+*Hv{zs~L77(p zijFScR+`HFnd>t7d{wzjb(NZL&r3FgFCtNk6+jlmP%lE+8X7wSp`%XaHkxWNTf>{Tqxn*QzRI~vbyC$?Zo&@~u8dWMwq<)8V?3Ni%)wDP(zS|mtf3t4c~Fs8+b=&`pK?y?z4d6 zuh^t|A6ppLo`t^p)8qX|%}JSog|G87|B@W&J|j8?h+Z9^0Rj(I;!A6R1l&;R54VHo z+j{5Lc8cr_imW{vSofKf&IdnOxwojG6?kh2JN7Z=C}3_*m_jCfMlz^Its4;EXI&eS zvrJ(usdfh+u|#qtwZWC2YS$HPr@EPDgprd2HUXrIuS8*=XcyvW+6Lq}sy~IgGJd(Y z=8xxPNEiij!2CSxGMyhPv!Mzx>N?a@@d~`Z4vSrE!V-UDG6crQ)}HFb%3_C6AI)s2 zSH5V$M^_eU6Gai+LRhe}i9Hd*mT4;s!y)WrI*S^mB(ahVyqDD2o*Lc85I{DMkjcw~ z94g`?Q74V_iQsN|6SWR0a_f;cO?TMf>`{TM^~J}=?}ry3Im6Zy8V)m=&wrBOcP{i=WlQ3c znxGK`2h72vT=^CQV}Qk})(MN+%Z_<}lf$)Ij!-0o5>`+Nlx`@XRnKnQjMoFq+-LwQ zs$8yW3z9&Y!b=mwDaU2scK}Sbe~0#h&m;ib2wv2BdlPcnjOU`{-mO}*CbH|UVEA^e zjZn#oF6|;P|DTw7`r09VQ2F)S-*MdJ*1xS)EtAQy0$4vDqyX|ECX*;J4_|;WS;(Jc7@f+S5RL1n4CzmMO z6F+@j(}{*nz1@vDz(_w-d5hl(oQX+t4ndtRlb2q}+P0U|3_=vsyM-|2o5)G^fOQ0P z&mWI3WlHk=`#>wzanacL`En0({t`uOog0x6CHSRwdUj_lof4tZlIqCvcgEwdsB2k@ z2JE*yMh|Dkj1NGgee9$r8RdPkX|S78Jgk_H8S4TgU7D8D-+#??6Wk5bhLN|B62c|X zjK>tGjl{7gO6q7YcHb;v`^+P*L! zF5NKzS)S7^2_Jn{vK~$ewP_<$)wHz_*D33IBu-KsQuVx>BTcD{68z+loLluUgU@Se z&C@d$kAIu!IupVETYU;bZW+=cy!3vMJ4}?0F!ilc44nXAe^a5P+{4dSRXD{$=dacY zooDF{i%|Mr*7-7%fQ%mk>BP`ehS#sbuH{N1>0oZ7K%K|53H-`9!t{3BkrdUJvGFjCyoGlW(&=J_8ub%)I>FI znQ~f+Gd0IQ;!mF57h=x0M2!2q;20jystuocTIm=8za{;gUEW)|s$;3o*2fXaVKtjd zj%j=$W;kNg@?w>Db_&rownL9ro@_*$e-QQvdh~L)D;RQ^_T4}-LH(1ZT;e|f>Yu(d z7ZWDxAlzD>B8(ik(<9|)PA}f`Rv9C-{A+iJW;z-+D~wj+ z3HX`sW_9?}I1p_c{EfwYd^*A$Owi69gz!+U3|Ln%vwIw zFn#IJKL-LKY;xIX*R~|zf7i9a+Zf`R)lGnXM2Q|@Cxz2KaW~rQVP7J6rl^$onS!2L zbb}hl;#+(R9UYiJ!@_k=^Cb?0vPJUwQzlD!jit2UF5<{)>0c@ zD_w3fV{p^P<9B~390KzeSE4cx*N!esMZ}Cb3+6X7w31EE-i{)E987r|Z2Gpa+sAXN zp}dh@N_6z-@u0^OjBdOa*-(>T;vQNqMIiKwQnhVMz}J+*2n>Jk@mQE1M=Lc7)Ive% z-5KJ6$t5l?2~j(Ye=OQU0Dc)7RPvA-9EvY}NL%2wCNyu+8EPL$0(PQCPIOKYDaNY8 z?%=87XSNH!Z6T5ct7{O3dDzR$9)r;&>%cr@#a|!N>w}F#UbIoU!>Y7;qDf(P^eC-M zMLx2@$Zryfw0q!&vV7QG@SD-+5H%4P?enC@EK-v+5qX~_MQo|=d&Sa-wqawRH%T*} zYD;!WEU-*|sRcXJ&s zQ5*Wy4SZ9QC@i29mHb0&iIY&zLa=CkN`N)#GG!x|`r*d-qGzuO)$o`K0|Oxrwqrk8 zx|w9hI&vuoPmU&Oxblw1<|B3Oqk=i4dYu)Cbm}VO#|?wJ%ZXIpK+&LRlwtaw9pU=v z-yS1b$tCDYsuxWS!0b1xF^4U!J7ZU65!`4 zAZ@yoVpfId6FdHs1)TvB7!;LMp-|c)983^3qhd%K{i$$9v@WZC(1LxbKFEkJ0VE0& zi`C787jFTuGtIY@f5i#0M@*wCGLG57A1mSz(TFA1bcE@6StJ`&u8DS>fsu(Oq#m8S%jHt4X&4$kc^;Da$|Q7y5-<;y<(;2w;H z(YG+hhU2r{jmnXfXIvmazBuEfjTA6_UjX?ASg@rJ6}&#@6}Ft{Vc*<`ovh zSc+{Z331KC3e0)k%U*({@>D7`x~nDT|d|EN*v$FwQ*e-eNHf*7D_ZW1twG4z1J%=b-6X_g#0omBUvL&hs`q%YqGa z3{t)+T_d6Vv0mHCqHLUculn@!fP1=aXb>i3yF4rX0kuLSQ&H&0WoX63-o>4ZvS)Nm z)WnCz8r+N0-eWt0C&K3K+EHUjM=E?jGL&1~*JWWE^RQ!v3Gn1dhWA<1-FQ0PWJgR@ zx=*eF6tP8T*F9I+2JXgHC5i9M+_`g)lK50;9u{c>)CK3~GtP`5G>xe)H$H$vSuf!i z*Q8Fvbrh`Q8w8$C{}=LLOKSRnlAiKmn+_eJ#>l;i4n<*8FcRHYs0|U$N>P71_{<#} zN5UxJn~m9Db9SzQ!oO%h2S;(tcIH%Y*|C4|zs@=pJI2bx*Fd zOqGE`A5;9psWj|$rv!Uh&wFPWBL=Av7H6yzqb4{8=3zm|p>a5!KC`8o{X-a%t3(dl zTa-v7%70!jviU$esUKl1o9jdWZ9keb3Y>Gio^f|uwZVIXenNXX2451h^|g5xic||9C?UP@KI8iO2fkE+iPr>++*{|-A3O7h3RDI20WROcz+P_Lnv$DsNS)(pUgS* z$+OB0E#nvLGV{EsQz}BdP2?oO_rLMozcRh@yy%U^#P>D7`B*A2f{e;hSc7rHTM}Wn z{I%r#euyU01j&!eve58_e#td2{rvqTli7g_YzLz-zD^qwibF3o>M}ifd5<>4aM4(- z3_s0uBcCT!4YS(a`|TK6{bPPUCC5?qrP*&GI)Thfca2QV_Y)mtSjZl@hlG1E`+QCa zk!ZSmmpjIYQP$QRlL`W!4wB+(o#1XsxR(N>k|JgB3FV=9kD}L}Z0J>E zDlmzlcU@2X7>GV7yFyAEhcCeAOqk3yzINs>Dme8#ou0{y+B(SryWlM1U6_X~bk*6s z|9Y(5IVro2PhNO%*_rsK`EOr#52;lgMn1@OH($%%FFnhxU`yTaPVm^ULC~-s2Bgdu z7QRqjg+o-3Wqq#wkJ6MtO_)OB3qcpf%z?PQSZH+^&_ZyTz<`r%afot)}Kcm>WtbV&XNVS5MVUsj5j8sc4lI5F~~hVQI}$DvpuuNGd46t!kn%u?sTOp;V>O7^YiDJK>Ag-;41MlI>FD< zl-7No5pCxtiSgfAxBzn9p6z*NAjQ+O7JAA`JZ{)OdWRb5DKCC?$3a^s28?1RM&VXp%%@{tVv^$}Hd5?yyh_I7(gdXv?`ICnr6&&Yb| zh5nS@*xBb310U+{E$S=}0w4H;FQF!ge zXRmzs_Y|Op>T4Ng5H?pg$iA9T@kzDUH{$IAYaioqepMHHj@#R!|5Tv-2@*9q&?q;0 z(xGu+Ro&yk%o6u=E8@WvO@Dc-DF^pt{CW$-XDa1!9_e=#{Y?4-#C_YaZoxhJfhE~E7G=I*Ud zajvI30=XV_3AhJSg(3>tWZx@AHpXE`T^U<~O!KgZWWj>!yK%l% zB3dG&K`OqvA3Uhp2T+XMv17R#$vHSksh<0{GZ3u4bHAd7hPt40vz^H*HzMe-{@q{c zSKxkDB!DwnNW2U9pWiV&zj6i}A)(U0y7GTT-n3lSS8xh>HxbeQfTHj*mZbr_I z_~x%Eqra1b7FU4QlycU`zwi9oAcbCK4-1u+RDM*lVHc(!}S)<8W))#sP3_JA?#1<>^G+Y3BXcPHh>_@#^nU=KWU_uB z0iZabARR4xC<5fCn)a5Dwg>}sx>QiRQ!{&o`@@<(2f+)_#-B+3W&nXrvP`1PRpvg*Zop(J+o)F{1JtQD@2PP2wK^iNgM1onKSBWOxlwJYZRDQ^fal zA3r8DEv}5VhyoiQT@t+j0I?MC>rR)#Yk>^ieenf{XDR8wN*N$Zz#08-^=US2n**-T z*0~?Nw^43}sluUu5+jcWqoFSSGQ^Jx7qfzA9-h_7x0TGa<3*7o40A%YyvN=}!2EK<0w#XTnP-w>qN3xo0a9k*t>K|QC! zCSa*>^FQJG-+_H>=uJnjr$Z~C+561&tG)x0-w`6Ze$C1MtnU7fB$_Vqi?09-k=Rs@ zcwK0yp{n9A6O&t9j8vmiOhTT_sc7=5RTxl}lX21o&;S)s%;P7|CU(snXVXc!{%FR`olqy)+P*sf?gtKtF?>!;cr38@h1) z)WUe0t31qauAn{U`wijM(J?OZye#kC7DIuB(SUz4 Ml8Uebal?TB2j`KK)c^nh literal 0 HcmV?d00001 diff --git a/docs/images/exceptions/exception-dialog.png b/docs/images/exceptions/exception-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..982c6aa202127e7024020ddffd8d00f888a1b5bc GIT binary patch literal 435951 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%0D)+-Q@|lypzbqy1 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