From 1ba891611241cfa2a742f84f2ab30afcb9bc35b9 Mon Sep 17 00:00:00 2001 From: Craig Trought Date: Sun, 22 Jan 2023 16:43:47 -0500 Subject: [PATCH 1/8] feat: optional flags to emit events in involved object namespace Signed-off-by: Craig Trought --- Makefile | 8 +++ cmd/build/helmify/kustomize-for-helm.yaml | 2 + cmd/build/helmify/static/README.md | 6 +- cmd/build/helmify/static/values.yaml | 2 + config/rbac/role.yaml | 7 +++ manifest_staging/charts/gatekeeper/README.md | 6 +- .../gatekeeper-audit-deployment.yaml | 1 + ...ekeeper-controller-manager-deployment.yaml | 1 + .../gatekeeper-manager-role-clusterrole.yaml | 7 +++ .../charts/gatekeeper/values.yaml | 2 + manifest_staging/deploy/gatekeeper.yaml | 7 +++ pkg/audit/manager.go | 49 ++++++++++------ pkg/audit/manager_test.go | 45 +++++++-------- pkg/controller/config/config_controller.go | 1 + pkg/webhook/common.go | 3 +- pkg/webhook/policy.go | 56 ++++++++++--------- website/docs/customize-startup.md | 10 +++- 17 files changed, 138 insertions(+), 75 deletions(-) diff --git a/Makefile b/Makefile index ca2010e7f7d..9345fe979e7 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,7 @@ MANAGER_IMAGE_PATCH := "apiVersion: apps/v1\ \n - --port=8443\ \n - --logtostderr\ \n - --emit-admission-events\ +\n - --admission-events-involved-namespace\ \n - --exempt-namespace=${GATEKEEPER_NAMESPACE}\ \n - --operation=webhook\ \n - --operation=mutation-webhook\ @@ -87,6 +88,7 @@ MANAGER_IMAGE_PATCH := "apiVersion: apps/v1\ \n name: manager\ \n args:\ \n - --emit-audit-events\ +\n - --audit-events-involved-namespace\ \n - --operation=audit\ \n - --operation=status\ \n - --operation=mutation-status\ @@ -190,6 +192,8 @@ e2e-helm-deploy: e2e-helm-install --set postInstall.probeWebhook.enabled=true \ --set emitAdmissionEvents=true \ --set emitAuditEvents=true \ + --set admissionEventsInvolvedNamespace=true \ + --set auditEventsInvolvedNamespace=true \ --set disabledBuiltins={http.send} \ --set logMutations=true \ --set mutationAnnotations=true;\ @@ -201,6 +205,8 @@ e2e-helm-upgrade-init: e2e-helm-install --debug --wait \ --set emitAdmissionEvents=true \ --set emitAuditEvents=true \ + --set admissionEventsInvolvedNamespace=true \ + --set auditEventsInvolvedNamespace=true \ --set postInstall.labelNamespace.enabled=true \ --set postInstall.probeWebhook.enabled=true \ --set disabledBuiltins={http.send} \ @@ -222,6 +228,8 @@ e2e-helm-upgrade: --set postInstall.probeWebhook.enabled=true \ --set emitAdmissionEvents=true \ --set emitAuditEvents=true \ + --set admissionEventsInvolvedNamespace=true \ + --set auditEventsInvolvedNamespace=true \ --set disabledBuiltins={http.send} \ --set logMutations=true \ --set mutationAnnotations=true;\ diff --git a/cmd/build/helmify/kustomize-for-helm.yaml b/cmd/build/helmify/kustomize-for-helm.yaml index 25ae92cf597..da09868d666 100644 --- a/cmd/build/helmify/kustomize-for-helm.yaml +++ b/cmd/build/helmify/kustomize-for-helm.yaml @@ -76,6 +76,7 @@ spec: - --logtostderr - --log-denies={{ .Values.logDenies }} - --emit-admission-events={{ .Values.emitAdmissionEvents }} + - --admission-events-involved-namespace={{ .Values.admissionEventsInvolvedNamespace }} - --log-level={{ (.Values.controllerManager.logLevel | empty | not) | ternary .Values.controllerManager.logLevel .Values.logLevel }} - --exempt-namespace={{ .Release.Namespace }} - --operation=webhook @@ -156,6 +157,7 @@ spec: - --audit-chunk-size={{ .Values.auditChunkSize }} - --audit-match-kind-only={{ .Values.auditMatchKindOnly }} - --emit-audit-events={{ .Values.emitAuditEvents }} + - --audit-events-involved-namespace={{ .Values.auditEventsInvolvedNamespace }} - --operation=audit - --operation=status - HELMSUBST_MUTATION_STATUS_ENABLED_ARG diff --git a/cmd/build/helmify/static/README.md b/cmd/build/helmify/static/README.md index 6e13a55b341..8b3ab950456 100644 --- a/cmd/build/helmify/static/README.md +++ b/cmd/build/helmify/static/README.md @@ -143,8 +143,10 @@ _See [Exempting Namespaces](https://open-policy-agent.github.io/gatekeeper/websi | mutatingWebhookObjectSelector | The label selector to further refine which namespaced resources will be selected by the webhook. Please note that an exemption label means users can circumvent Gatekeeper's mutation webhook unless measures are taken to control how exemption labels can be set. | `{}` | | mutatingWebhookTimeoutSeconds | The timeout for the mutating webhook in seconds | `3` | | mutatingWebhookCustomRules | Custom rules for selecting which API resources trigger the webhook. NOTE: If you change this, ensure all your constraints are still being enforced. | `{}` | -| emitAdmissionEvents | Emit K8s events in gatekeeper namespace for admission violations (alpha feature) | `false` | -| emitAuditEvents | Emit K8s events in gatekeeper namespace for audit violations (alpha feature) | `false` | +| emitAdmissionEvents | Emit K8s events in configurable namespace for admission violations (alpha feature) | `false` | +| emitAuditEvents | Emit K8s events in configurable namespace for audit violations (alpha feature) | `false` | +| auditEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | +| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | | logDenies | Log detailed info on each deny | `false` | | logLevel | Minimum log level | `INFO` | | image.pullPolicy | The image pull policy | `IfNotPresent` | diff --git a/cmd/build/helmify/static/values.yaml b/cmd/build/helmify/static/values.yaml index 364f5ed4794..0b0b34a1339 100644 --- a/cmd/build/helmify/static/values.yaml +++ b/cmd/build/helmify/static/values.yaml @@ -32,6 +32,8 @@ logDenies: false logMutations: false emitAdmissionEvents: false emitAuditEvents: false +admissionEventsInvolvedNamespace: false +auditEventsInvolvedNamespace: false resourceQuota: true postUpgrade: labelNamespace: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index a7a893f5933..b81a0171252 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -5,6 +5,13 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - '*' resources: diff --git a/manifest_staging/charts/gatekeeper/README.md b/manifest_staging/charts/gatekeeper/README.md index 6e13a55b341..8b3ab950456 100644 --- a/manifest_staging/charts/gatekeeper/README.md +++ b/manifest_staging/charts/gatekeeper/README.md @@ -143,8 +143,10 @@ _See [Exempting Namespaces](https://open-policy-agent.github.io/gatekeeper/websi | mutatingWebhookObjectSelector | The label selector to further refine which namespaced resources will be selected by the webhook. Please note that an exemption label means users can circumvent Gatekeeper's mutation webhook unless measures are taken to control how exemption labels can be set. | `{}` | | mutatingWebhookTimeoutSeconds | The timeout for the mutating webhook in seconds | `3` | | mutatingWebhookCustomRules | Custom rules for selecting which API resources trigger the webhook. NOTE: If you change this, ensure all your constraints are still being enforced. | `{}` | -| emitAdmissionEvents | Emit K8s events in gatekeeper namespace for admission violations (alpha feature) | `false` | -| emitAuditEvents | Emit K8s events in gatekeeper namespace for audit violations (alpha feature) | `false` | +| emitAdmissionEvents | Emit K8s events in configurable namespace for admission violations (alpha feature) | `false` | +| emitAuditEvents | Emit K8s events in configurable namespace for audit violations (alpha feature) | `false` | +| auditEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | +| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | | logDenies | Log detailed info on each deny | `false` | | logLevel | Minimum log level | `INFO` | | image.pullPolicy | The image pull policy | `IfNotPresent` | diff --git a/manifest_staging/charts/gatekeeper/templates/gatekeeper-audit-deployment.yaml b/manifest_staging/charts/gatekeeper/templates/gatekeeper-audit-deployment.yaml index 6088a432a3a..a89455fc29b 100644 --- a/manifest_staging/charts/gatekeeper/templates/gatekeeper-audit-deployment.yaml +++ b/manifest_staging/charts/gatekeeper/templates/gatekeeper-audit-deployment.yaml @@ -55,6 +55,7 @@ spec: - --audit-chunk-size={{ .Values.auditChunkSize }} - --audit-match-kind-only={{ .Values.auditMatchKindOnly }} - --emit-audit-events={{ .Values.emitAuditEvents }} + - --audit-events-involved-namespace={{ .Values.auditEventsInvolvedNamespace }} - --operation=audit - --operation=status {{ if not .Values.disableMutation}}- --operation=mutation-status{{- end }} diff --git a/manifest_staging/charts/gatekeeper/templates/gatekeeper-controller-manager-deployment.yaml b/manifest_staging/charts/gatekeeper/templates/gatekeeper-controller-manager-deployment.yaml index b1e5ea7f737..e645fe44d61 100644 --- a/manifest_staging/charts/gatekeeper/templates/gatekeeper-controller-manager-deployment.yaml +++ b/manifest_staging/charts/gatekeeper/templates/gatekeeper-controller-manager-deployment.yaml @@ -54,6 +54,7 @@ spec: - --logtostderr - --log-denies={{ .Values.logDenies }} - --emit-admission-events={{ .Values.emitAdmissionEvents }} + - --admission-events-involved-namespace={{ .Values.admissionEventsInvolvedNamespace }} - --log-level={{ (.Values.controllerManager.logLevel | empty | not) | ternary .Values.controllerManager.logLevel .Values.logLevel }} - --exempt-namespace={{ .Release.Namespace }} - --operation=webhook diff --git a/manifest_staging/charts/gatekeeper/templates/gatekeeper-manager-role-clusterrole.yaml b/manifest_staging/charts/gatekeeper/templates/gatekeeper-manager-role-clusterrole.yaml index 8b32f96014b..a36d6eb97a5 100644 --- a/manifest_staging/charts/gatekeeper/templates/gatekeeper-manager-role-clusterrole.yaml +++ b/manifest_staging/charts/gatekeeper/templates/gatekeeper-manager-role-clusterrole.yaml @@ -11,6 +11,13 @@ metadata: release: '{{ .Release.Name }}' name: gatekeeper-manager-role rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - '*' resources: diff --git a/manifest_staging/charts/gatekeeper/values.yaml b/manifest_staging/charts/gatekeeper/values.yaml index 364f5ed4794..0b0b34a1339 100644 --- a/manifest_staging/charts/gatekeeper/values.yaml +++ b/manifest_staging/charts/gatekeeper/values.yaml @@ -32,6 +32,8 @@ logDenies: false logMutations: false emitAdmissionEvents: false emitAuditEvents: false +admissionEventsInvolvedNamespace: false +auditEventsInvolvedNamespace: false resourceQuota: true postUpgrade: labelNamespace: diff --git a/manifest_staging/deploy/gatekeeper.yaml b/manifest_staging/deploy/gatekeeper.yaml index 5b7d55b4d62..d3d95c5be61 100644 --- a/manifest_staging/deploy/gatekeeper.yaml +++ b/manifest_staging/deploy/gatekeeper.yaml @@ -2930,6 +2930,13 @@ metadata: gatekeeper.sh/system: "yes" name: gatekeeper-manager-role rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - '*' resources: diff --git a/pkg/audit/manager.go b/pkg/audit/manager.go index 0b3d8d9dbfa..0ae9ac55c96 100644 --- a/pkg/audit/manager.go +++ b/pkg/audit/manager.go @@ -53,14 +53,15 @@ const ( ) var ( - auditInterval = flag.Uint("audit-interval", defaultAuditInterval, "interval to run audit in seconds. defaulted to 60 secs if unspecified, 0 to disable") - constraintViolationsLimit = flag.Uint("constraint-violations-limit", defaultConstraintViolationsLimit, "limit of number of violations per constraint. defaulted to 20 violations if unspecified") - auditChunkSize = flag.Uint64("audit-chunk-size", defaultListLimit, "(alpha) Kubernetes API chunking List results when retrieving cluster resources using discovery client. defaulted to 500 if unspecified") - auditFromCache = flag.Bool("audit-from-cache", false, "pull resources from audit cache when auditing") - emitAuditEvents = flag.Bool("emit-audit-events", false, "(alpha) emit Kubernetes events in gatekeeper namespace with detailed info for each violation from an audit") - auditMatchKindOnly = flag.Bool("audit-match-kind-only", false, "only use kinds specified in all constraints for auditing cluster resources. if kind is not specified in any of the constraints, it will audit all resources (same as setting this flag to false)") - apiCacheDir = flag.String("api-cache-dir", defaultAPICacheDir, "The directory where audit from api server cache are stored, defaults to /tmp/audit") - emptyAuditResults []updateListEntry + auditInterval = flag.Uint("audit-interval", defaultAuditInterval, "interval to run audit in seconds. defaulted to 60 secs if unspecified, 0 to disable") + constraintViolationsLimit = flag.Uint("constraint-violations-limit", defaultConstraintViolationsLimit, "limit of number of violations per constraint. defaulted to 20 violations if unspecified") + auditChunkSize = flag.Uint64("audit-chunk-size", defaultListLimit, "(alpha) Kubernetes API chunking List results when retrieving cluster resources using discovery client. defaulted to 500 if unspecified") + auditFromCache = flag.Bool("audit-from-cache", false, "pull resources from OPA cache when auditing") + emitAuditEvents = flag.Bool("emit-audit-events", false, "(alpha) emit Kubernetes events with detailed info for each violation from an audit") + auditEventsInvolvedNamespace = flag.Bool("audit-events-involved-namespace", false, "emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in") + auditMatchKindOnly = flag.Bool("audit-match-kind-only", false, "only use kinds specified in all constraints for auditing cluster resources. if kind is not specified in any of the constraints, it will audit all resources (same as setting this flag to false)") + apiCacheDir = flag.String("api-cache-dir", defaultAPICacheDir, "The directory where audit from api server cache are stored, defaults to /tmp/audit") + emptyAuditResults []updateListEntry ) // Manager allows us to audit resources periodically. @@ -737,6 +738,8 @@ func (am *Manager) addAuditResponsesToUpdateLists( gvk := r.obj.GroupVersionKind() namespace := r.obj.GetNamespace() name := r.obj.GetName() + uid := r.obj.GetUID() + rv := r.obj.GetResourceVersion() ea := util.EnforcementAction(r.EnforcementAction) // append audit results only if it is below violations limit @@ -760,7 +763,7 @@ func (am *Manager) addAuditResponsesToUpdateLists( totalViolationsPerEnforcementAction[ea]++ logViolation(am.log, r.Constraint, ea, gvk, namespace, name, r.Msg, details, r.obj.GetLabels()) if *emitAuditEvents { - emitEvent(r.Constraint, timestamp, ea, gvk, namespace, name, r.Msg, am.gkNamespace, am.eventRecorder) + emitEvent(r.Constraint, timestamp, ea, gvk, namespace, name, rv, r.Msg, am.gkNamespace, uid, am.eventRecorder) } } return nil @@ -1042,7 +1045,7 @@ func logViolation(l logr.Logger, } func emitEvent(constraint *unstructured.Unstructured, - timestamp string, enforcementAction util.EnforcementAction, resourceGroupVersionKind schema.GroupVersionKind, rnamespace, rname, message, gkNamespace string, + timestamp string, enforcementAction util.EnforcementAction, resourceGroupVersionKind schema.GroupVersionKind, rnamespace, rname, rrv, message, gkNamespace string, ruid types.UID, eventRecorder record.EventRecorder, ) { annotations := map[string]string{ @@ -1061,19 +1064,33 @@ func emitEvent(constraint *unstructured.Unstructured, logging.ResourceNamespace: rnamespace, logging.ResourceName: rname, } + reason := "AuditViolation" - ref := getViolationRef(gkNamespace, resourceGroupVersionKind.Kind, rname, rnamespace, constraint.GetKind(), constraint.GetName(), constraint.GetNamespace()) + enamespace := gkNamespace + if *auditEventsInvolvedNamespace && len(rnamespace) > 0 { + enamespace = rnamespace + } + + ref := getViolationRef(enamespace, resourceGroupVersionKind.Kind, rname, rrv, ruid) - eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Timestamp: %s, Resource Namespace: %s, Constraint: %s, Message: %s", timestamp, rnamespace, constraint.GetName(), message) + if *auditEventsInvolvedNamespace || len(rnamespace) == 0 { + eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Constraint: %s, Message: %s", constraint.GetName(), message) + } else { + eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Resource Namespace: %s, Constraint: %s, Message: %s", rnamespace, constraint.GetName(), message) + } } -func getViolationRef(gkNamespace, rkind, rname, rnamespace, ckind, cname, cnamespace string) *corev1.ObjectReference { - return &corev1.ObjectReference{ +func getViolationRef(enamespace, rkind, rname, rrv string, ruid types.UID) *corev1.ObjectReference { + ref := &corev1.ObjectReference{ Kind: rkind, Name: rname, - UID: types.UID(rkind + "/" + rnamespace + "/" + rname + "/" + ckind + "/" + cnamespace + "/" + cname), - Namespace: gkNamespace, + Namespace: enamespace, + } + if len(ruid) > 0 && len(rrv) > 0 { + ref.UID = ruid + ref.ResourceVersion = rrv } + return ref } // mergeErrors concatenates errs into a single error. None of the original errors diff --git a/pkg/audit/manager_test.go b/pkg/audit/manager_test.go index 38733e7d1d5..56fa0dd82a4 100644 --- a/pkg/audit/manager_test.go +++ b/pkg/audit/manager_test.go @@ -9,6 +9,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/types" ) func Test_newNSCache(t *testing.T) { @@ -183,13 +184,11 @@ func Test_nsMapFromObjs(t *testing.T) { func Test_getViolationRef(t *testing.T) { type args struct { - gkNamespace string + enamespace string rkind string rname string - rnamespace string - ckind string - cname string - cnamespace string + rrv string + ruid types.UID } tests := []struct { name string @@ -199,43 +198,41 @@ func Test_getViolationRef(t *testing.T) { { name: "Test case 1", args: args{ - gkNamespace: "default", rkind: "Pod", rname: "my-pod", - rnamespace: "default", - ckind: "LimitRange", - cname: "my-limit-range", - cnamespace: "default", + enamespace: "default", + rrv: "123456", + ruid: "abcde-123456", }, want: &corev1.ObjectReference{ - Kind: "Pod", - Name: "my-pod", - UID: "Pod/default/my-pod/LimitRange/default/my-limit-range", - Namespace: "default", + Kind: "Pod", + Name: "my-pod", + Namespace: "default", + ResourceVersion: "123456", + UID: "abcde-123456", }, }, { name: "Test case 2", args: args{ - gkNamespace: "kube-system", rkind: "Service", + enamespace: "kube-system", rname: "my-service", - rnamespace: "default", - ckind: "PodSecurityPolicy", - cname: "my-pod-security-policy", - cnamespace: "kube-system", + rrv: "123456", + ruid: "abcde-123456", }, want: &corev1.ObjectReference{ - Kind: "Service", - Name: "my-service", - UID: "Service/default/my-service/PodSecurityPolicy/kube-system/my-pod-security-policy", - Namespace: "kube-system", + Kind: "Service", + Name: "my-service", + Namespace: "kube-system", + ResourceVersion: "123456", + UID: "abcde-123456", }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := getViolationRef(tt.args.gkNamespace, tt.args.rkind, tt.args.rname, tt.args.rnamespace, tt.args.ckind, tt.args.cname, tt.args.cnamespace); !reflect.DeepEqual(got, tt.want) { + if got := getViolationRef(tt.args.enamespace, tt.args.rkind, tt.args.rname, tt.args.rrv, tt.args.ruid); !reflect.DeepEqual(got, tt.want) { t.Errorf("getViolationRef() = %v, want %v", got, tt.want) } }) diff --git a/pkg/controller/config/config_controller.go b/pkg/controller/config/config_controller.go index 81baf0c6876..b896a93dcb0 100644 --- a/pkg/controller/config/config_controller.go +++ b/pkg/controller/config/config_controller.go @@ -193,6 +193,7 @@ type ReconcileConfig struct { // +kubebuilder:rbac:groups=policy,resources=podsecuritypolicies,resourceNames=gatekeeper-admin,verbs=use // +kubebuilder:rbac:groups=config.gatekeeper.sh,resources=configs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=config.gatekeeper.sh,resources=configs/status,verbs=get;update;patch +// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch; // Reconcile reads that state of the cluster for a Config object and makes changes based on the state read // and what is in the Config.Spec diff --git a/pkg/webhook/common.go b/pkg/webhook/common.go index 63f255b1519..e1c8def5850 100644 --- a/pkg/webhook/common.go +++ b/pkg/webhook/common.go @@ -58,7 +58,8 @@ var ( deserializer = codecs.UniversalDeserializer() disableEnforcementActionValidation = flag.Bool("disable-enforcementaction-validation", false, "disable validation of the enforcementAction field of a constraint") logDenies = flag.Bool("log-denies", false, "log detailed info on each deny") - emitAdmissionEvents = flag.Bool("emit-admission-events", false, "(alpha) emit Kubernetes events in gatekeeper namespace for each admission violation") + emitAdmissionEvents = flag.Bool("emit-admission-events", false, "(alpha) emit Kubernetes events for each admission violation") + admissionEventsInvolvedNamespace = flag.Bool("admission-events-involved-namespace", false, "emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in") tlsMinVersion = flag.String("tls-min-version", "1.3", "minimum version of TLS supported") serviceaccount = fmt.Sprintf("system:serviceaccount:%s:%s", util.GetNamespace(), serviceAccountName) clientCAName = flag.String("client-ca-name", "", "name of the certificate authority bundle to authenticate the Kubernetes API server requests against") diff --git a/pkg/webhook/policy.go b/pkg/webhook/policy.go index 95663e692e1..7a905fda1c8 100644 --- a/pkg/webhook/policy.go +++ b/pkg/webhook/policy.go @@ -229,14 +229,17 @@ func (h *validationHandler) Handle(ctx context.Context, req admission.Request) a func (h *validationHandler) getValidationMessages(res []*rtypes.Result, req *admission.Request) ([]string, []string) { var denyMsgs, warnMsgs []string var resourceName string + obj := &unstructured.Unstructured{} + if len(res) > 0 && (*logDenies || *emitAdmissionEvents) { resourceName = req.AdmissionRequest.Name - if len(resourceName) == 0 && req.AdmissionRequest.Object.Raw != nil { - // On a CREATE operation, the client may omit name and - // rely on the server to generate the name. - obj := &unstructured.Unstructured{} + if req.AdmissionRequest.Object.Raw != nil { if _, _, err := deserializer.Decode(req.AdmissionRequest.Object.Raw, nil, obj); err == nil { - resourceName = obj.GetName() + // On a CREATE operation, the client may omit name and + // rely on the server to generate the name. + if len(resourceName) == 0 { + resourceName = obj.GetName() + } } } } @@ -289,24 +292,19 @@ func (h *validationHandler) getValidationMessages(res []*rtypes.Result, req *adm eventMsg = "Admission webhook \"validation.gatekeeper.sh\" denied request" reason = "FailedAdmission" } - ref := getViolationRef( - h.gkNamespace, - req.AdmissionRequest.Kind.Kind, - resourceName, - req.AdmissionRequest.Namespace, - r.Constraint.GetKind(), - r.Constraint.GetName(), - r.Constraint.GetNamespace()) - h.eventRecorder.AnnotatedEventf( - ref, - annotations, - corev1.EventTypeWarning, - reason, - "%s, Resource Namespace: %s, Constraint: %s, Message: %s", - eventMsg, - req.AdmissionRequest.Namespace, - r.Constraint.GetName(), - r.Msg) + + enamespace := h.gkNamespace + if *admissionEventsInvolvedNamespace && len(req.AdmissionRequest.Namespace) > 0 { + enamespace = req.AdmissionRequest.Namespace + } + + ref := getViolationRef(enamespace, req.AdmissionRequest.Kind.Kind, resourceName, obj.GetResourceVersion(), obj.GetUID()) + + if *admissionEventsInvolvedNamespace || len(req.AdmissionRequest.Namespace) == 0 { + h.eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "%s, Constraint: %s, Message: %s", eventMsg, r.Constraint.GetName(), r.Msg) + } else { + h.eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "%s, Resource Namespace: %s, Constraint: %s, Message: %s", eventMsg, req.AdmissionRequest.Namespace, r.Constraint.GetName(), r.Msg) + } } if r.EnforcementAction == string(util.Deny) { @@ -604,13 +602,17 @@ func createReviewForResultant(obj *unstructured.Unstructured, ns *corev1.Namespa } } -func getViolationRef(gkNamespace, rkind, rname, rnamespace, ckind, cname, cnamespace string) *corev1.ObjectReference { - return &corev1.ObjectReference{ +func getViolationRef(enamespace, rkind, rname, rrv string, ruid types.UID) *corev1.ObjectReference { + ref := &corev1.ObjectReference{ Kind: rkind, Name: rname, - UID: types.UID(rkind + "/" + rnamespace + "/" + rname + "/" + ckind + "/" + cnamespace + "/" + cname), - Namespace: gkNamespace, + Namespace: enamespace, + } + if len(ruid) > 0 && len(rrv) > 0 { + ref.UID = ruid + ref.ResourceVersion = rrv } + return ref } func AppendValidationWebhookIfEnabled(webhooks []rotator.WebhookInfo) []rotator.WebhookInfo { diff --git a/website/docs/customize-startup.md b/website/docs/customize-startup.md index 9fe4fad10b9..138e764c1e7 100644 --- a/website/docs/customize-startup.md +++ b/website/docs/customize-startup.md @@ -23,11 +23,15 @@ The `--disable-opa-builtin` flag disables specific [OPA built-ins functions](htt ## [Alpha] Emit admission and audit events -The `--emit-admission-events` flag enables the emission of all admission violations as Kubernetes events in the Gatekeeper namespace. This flag is in alpha stage and it is set to `false` by default. +The `--emit-admission-events` flag enables the emission of all admission violations as Kubernetes events. This flag is in alpha stage and it is set to `false` by default. -The `--emit-audit-events` flag enables the emission of all audit violation as Kubernetes events in the Gatekeeper namespace. This flag is in alpha stage and it is set to `false` by default. +The `--emit-audit-events` flag enables the emission of all audit violation as Kubernetes events. This flag is in alpha stage and it is set to `false` by default. -There are three types of events that are emitted by Gatekeeper when the above flags are enabled: +The `--admission-events-involved-namespace` flag controls which namespace admission events will be created in. When set to `true` admission events will be created in the involved objects namespace violating the constraint, if the object has no namespace (ie. cluster scoped resources) they will be created in the namespace gatekeeper is installed in. Setting to `false` will cause all admission events to be created in the gatekeeper namespace. + +The `--audit-events-involved-namespace` flag controls which namespace audit events will be created in. When set to `true` audit events will be created in the involved objects namespace violating the constraint, if the object has no namespace (ie. cluster scoped resources) they will be created in the namespace gatekeeper is installed in. Setting to `false` will cause all audit events to be created in the gatekeeper namespace. + +There are four types of events that are emitted by Gatekeeper when the emit event flags are enabled: | Event | Description | | ------------------ | ----------------------------------------------------------------------- | From 63f058f5584405e277201a9b22eaaca8f21f9bc6 Mon Sep 17 00:00:00 2001 From: Craig Trought Date: Wed, 22 Mar 2023 17:37:19 -0400 Subject: [PATCH 2/8] revert to original behaviour for event message when flag is disabled Signed-off-by: Craig Trought --- pkg/audit/manager.go | 2 +- pkg/webhook/policy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/audit/manager.go b/pkg/audit/manager.go index 0ae9ac55c96..a33f6b4846e 100644 --- a/pkg/audit/manager.go +++ b/pkg/audit/manager.go @@ -1073,7 +1073,7 @@ func emitEvent(constraint *unstructured.Unstructured, ref := getViolationRef(enamespace, resourceGroupVersionKind.Kind, rname, rrv, ruid) - if *auditEventsInvolvedNamespace || len(rnamespace) == 0 { + if *auditEventsInvolvedNamespace { eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Constraint: %s, Message: %s", constraint.GetName(), message) } else { eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Resource Namespace: %s, Constraint: %s, Message: %s", rnamespace, constraint.GetName(), message) diff --git a/pkg/webhook/policy.go b/pkg/webhook/policy.go index 71855618e91..00005dbab73 100644 --- a/pkg/webhook/policy.go +++ b/pkg/webhook/policy.go @@ -301,7 +301,7 @@ func (h *validationHandler) getValidationMessages(res []*rtypes.Result, req *adm ref := getViolationRef(enamespace, req.AdmissionRequest.Kind.Kind, resourceName, obj.GetResourceVersion(), obj.GetUID()) - if *admissionEventsInvolvedNamespace || len(req.AdmissionRequest.Namespace) == 0 { + if *admissionEventsInvolvedNamespace { h.eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "%s, Constraint: %s, Message: %s", eventMsg, r.Constraint.GetName(), r.Msg) } else { h.eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "%s, Resource Namespace: %s, Constraint: %s, Message: %s", eventMsg, req.AdmissionRequest.Namespace, r.Constraint.GetName(), r.Msg) From 7ac7cf90dd96765dd9e8137ecfe2a3434957fb9a Mon Sep 17 00:00:00 2001 From: Craig Trought Date: Wed, 22 Mar 2023 17:39:30 -0400 Subject: [PATCH 3/8] fix: golangci-lint error in test Signed-off-by: Craig Trought --- pkg/audit/manager_test.go | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pkg/audit/manager_test.go b/pkg/audit/manager_test.go index 56fa0dd82a4..5243042a303 100644 --- a/pkg/audit/manager_test.go +++ b/pkg/audit/manager_test.go @@ -185,10 +185,10 @@ func Test_nsMapFromObjs(t *testing.T) { func Test_getViolationRef(t *testing.T) { type args struct { enamespace string - rkind string - rname string - rrv string - ruid types.UID + rkind string + rname string + rrv string + ruid types.UID } tests := []struct { name string @@ -198,35 +198,35 @@ func Test_getViolationRef(t *testing.T) { { name: "Test case 1", args: args{ - rkind: "Pod", - rname: "my-pod", - enamespace: "default", - rrv: "123456", - ruid: "abcde-123456", + rkind: "Pod", + rname: "my-pod", + enamespace: "default", + rrv: "123456", + ruid: "abcde-123456", }, want: &corev1.ObjectReference{ - Kind: "Pod", - Name: "my-pod", - Namespace: "default", + Kind: "Pod", + Name: "my-pod", + Namespace: "default", ResourceVersion: "123456", - UID: "abcde-123456", + UID: "abcde-123456", }, }, { name: "Test case 2", args: args{ - rkind: "Service", - enamespace: "kube-system", - rname: "my-service", - rrv: "123456", - ruid: "abcde-123456", + rkind: "Service", + enamespace: "kube-system", + rname: "my-service", + rrv: "123456", + ruid: "abcde-123456", }, want: &corev1.ObjectReference{ - Kind: "Service", - Name: "my-service", - Namespace: "kube-system", + Kind: "Service", + Name: "my-service", + Namespace: "kube-system", ResourceVersion: "123456", - UID: "abcde-123456", + UID: "abcde-123456", }, }, } From 54d27614890cf9f11979e4a774ca40b93ea4478d Mon Sep 17 00:00:00 2001 From: Craig Trought Date: Wed, 22 Mar 2023 22:14:35 -0400 Subject: [PATCH 4/8] * revert event emission logic and uid when involved object flag is false * move emit namespace logic to getViolationRef for tests Signed-off-by: Craig Trought --- pkg/audit/manager.go | 17 +++++++++-------- pkg/webhook/policy.go | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pkg/audit/manager.go b/pkg/audit/manager.go index a33f6b4846e..ee885b8ab51 100644 --- a/pkg/audit/manager.go +++ b/pkg/audit/manager.go @@ -1066,12 +1066,7 @@ func emitEvent(constraint *unstructured.Unstructured, } reason := "AuditViolation" - enamespace := gkNamespace - if *auditEventsInvolvedNamespace && len(rnamespace) > 0 { - enamespace = rnamespace - } - - ref := getViolationRef(enamespace, resourceGroupVersionKind.Kind, rname, rrv, ruid) + ref := getViolationRef(gkNamespace, resourceGroupVersionKind.Kind, rname, rnamespace, rrv, ruid, constraint.GetKind(), constraint.GetName(), constraint.GetNamespace(), *auditEventsInvolvedNamespace) if *auditEventsInvolvedNamespace { eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "Constraint: %s, Message: %s", constraint.GetName(), message) @@ -1080,15 +1075,21 @@ func emitEvent(constraint *unstructured.Unstructured, } } -func getViolationRef(enamespace, rkind, rname, rrv string, ruid types.UID) *corev1.ObjectReference { +func getViolationRef(gkNamespace, rkind, rname, rnamespace, rrv string, ruid types.UID, ckind, cname, cnamespace string, emitInvolvedNamespace bool) *corev1.ObjectReference { + enamespace := gkNamespace + if emitInvolvedNamespace && len(rnamespace) > 0 { + enamespace = rnamespace + } ref := &corev1.ObjectReference{ Kind: rkind, Name: rname, Namespace: enamespace, } - if len(ruid) > 0 && len(rrv) > 0 { + if emitInvolvedNamespace && len(ruid) > 0 && len(rrv) > 0 { ref.UID = ruid ref.ResourceVersion = rrv + } else if !emitInvolvedNamespace { + ref.UID = types.UID(rkind + "/" + rnamespace + "/" + rname + "/" + ckind + "/" + cnamespace + "/" + cname) } return ref } diff --git a/pkg/webhook/policy.go b/pkg/webhook/policy.go index 00005dbab73..f32214b2004 100644 --- a/pkg/webhook/policy.go +++ b/pkg/webhook/policy.go @@ -294,12 +294,7 @@ func (h *validationHandler) getValidationMessages(res []*rtypes.Result, req *adm reason = "FailedAdmission" } - enamespace := h.gkNamespace - if *admissionEventsInvolvedNamespace && len(req.AdmissionRequest.Namespace) > 0 { - enamespace = req.AdmissionRequest.Namespace - } - - ref := getViolationRef(enamespace, req.AdmissionRequest.Kind.Kind, resourceName, obj.GetResourceVersion(), obj.GetUID()) + ref := getViolationRef(h.gkNamespace, req.AdmissionRequest.Kind.Kind, resourceName, obj.GetNamespace(), obj.GetResourceVersion(), obj.GetUID(), r.Constraint.GetKind(), r.Constraint.GetName(), r.Constraint.GetNamespace(), *admissionEventsInvolvedNamespace) if *admissionEventsInvolvedNamespace { h.eventRecorder.AnnotatedEventf(ref, annotations, corev1.EventTypeWarning, reason, "%s, Constraint: %s, Message: %s", eventMsg, r.Constraint.GetName(), r.Msg) @@ -622,15 +617,21 @@ func createReviewForResultant(obj *unstructured.Unstructured, ns *corev1.Namespa } } -func getViolationRef(enamespace, rkind, rname, rrv string, ruid types.UID) *corev1.ObjectReference { +func getViolationRef(gkNamespace, rkind, rname, rnamespace, rrv string, ruid types.UID, ckind, cname, cnamespace string, emitInvolvedNamespace bool) *corev1.ObjectReference { + enamespace := gkNamespace + if emitInvolvedNamespace && len(rnamespace) > 0 { + enamespace = rnamespace + } ref := &corev1.ObjectReference{ Kind: rkind, Name: rname, Namespace: enamespace, } - if len(ruid) > 0 && len(rrv) > 0 { + if emitInvolvedNamespace && len(ruid) > 0 && len(rrv) > 0 { ref.UID = ruid ref.ResourceVersion = rrv + } else if !emitInvolvedNamespace { + ref.UID = types.UID(rkind + "/" + rnamespace + "/" + rname + "/" + ckind + "/" + cnamespace + "/" + cname) } return ref } From 5070c36c57590d536a7561d457cbe71fe9df22ea Mon Sep 17 00:00:00 2001 From: Craig Trought Date: Wed, 22 Mar 2023 22:15:28 -0400 Subject: [PATCH 5/8] * revert original event tests * add tests for using emit involved namespace flags Signed-off-by: Craig Trought --- pkg/audit/manager_test.go | 110 +++++++++++++++++++++++++++++++------- 1 file changed, 92 insertions(+), 18 deletions(-) diff --git a/pkg/audit/manager_test.go b/pkg/audit/manager_test.go index 5243042a303..8f4a2e8e8e8 100644 --- a/pkg/audit/manager_test.go +++ b/pkg/audit/manager_test.go @@ -184,11 +184,16 @@ func Test_nsMapFromObjs(t *testing.T) { func Test_getViolationRef(t *testing.T) { type args struct { - enamespace string - rkind string - rname string - rrv string - ruid types.UID + gkNamespace string + rkind string + rname string + rnamespace string + rrv string + ckind string + cname string + cnamespace string + ruid types.UID + einvolved bool } tests := []struct { name string @@ -196,13 +201,56 @@ func Test_getViolationRef(t *testing.T) { want *corev1.ObjectReference }{ { - name: "Test case 1", + name: "Test case 1 - Gatekeeper Namespace", args: args{ - rkind: "Pod", - rname: "my-pod", - enamespace: "default", - rrv: "123456", - ruid: "abcde-123456", + gkNamespace: "default", + rkind: "Pod", + rname: "my-pod", + rnamespace: "default", + ckind: "LimitRange", + cname: "my-limit-range", + cnamespace: "default", + einvolved: false, + }, + want: &corev1.ObjectReference{ + Kind: "Pod", + Name: "my-pod", + UID: "Pod/default/my-pod/LimitRange/default/my-limit-range", + Namespace: "default", + }, + }, + { + name: "Test case 2 - GK Namespace", + args: args{ + gkNamespace: "kube-system", + rkind: "Service", + rname: "my-service", + rnamespace: "default", + ckind: "PodSecurityPolicy", + cname: "my-pod-security-policy", + cnamespace: "kube-system", + einvolved: false, + }, + want: &corev1.ObjectReference{ + Kind: "Service", + Name: "my-service", + UID: "Service/default/my-service/PodSecurityPolicy/kube-system/my-pod-security-policy", + Namespace: "kube-system", + }, + }, + { + name: "Test case 3 - Involved Namespace", + args: args{ + gkNamespace: "kube-system", + rkind: "Pod", + rname: "my-pod", + rrv: "123456", + ruid: "abcde-123456", + rnamespace: "default", + ckind: "LimitRange", + cname: "my-limit-range", + cnamespace: "default", + einvolved: true, }, want: &corev1.ObjectReference{ Kind: "Pod", @@ -213,13 +261,17 @@ func Test_getViolationRef(t *testing.T) { }, }, { - name: "Test case 2", + name: "Test case 4 - Involved Namespace Cluster Scoped", args: args{ - rkind: "Service", - enamespace: "kube-system", - rname: "my-service", - rrv: "123456", - ruid: "abcde-123456", + gkNamespace: "kube-system", + rkind: "Service", + rname: "my-service", + rrv: "123456", + ruid: "abcde-123456", + ckind: "PodSecurityPolicy", + cname: "my-pod-security-policy", + cnamespace: "kube-system", + einvolved: true, }, want: &corev1.ObjectReference{ Kind: "Service", @@ -229,10 +281,32 @@ func Test_getViolationRef(t *testing.T) { UID: "abcde-123456", }, }, + { + name: "Test case 5 - Involved Namespace RV/UID", + args: args{ + gkNamespace: "kube-system", + rkind: "Service", + rname: "my-service", + rrv: "", + ruid: "", + rnamespace: "default", + ckind: "PodSecurityPolicy", + cname: "my-pod-security-policy", + cnamespace: "kube-system", + einvolved: true, + }, + want: &corev1.ObjectReference{ + Kind: "Service", + Name: "my-service", + Namespace: "default", + ResourceVersion: "", + UID: "", + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := getViolationRef(tt.args.enamespace, tt.args.rkind, tt.args.rname, tt.args.rrv, tt.args.ruid); !reflect.DeepEqual(got, tt.want) { + if got := getViolationRef(tt.args.gkNamespace, tt.args.rkind, tt.args.rname, tt.args.rnamespace, tt.args.rrv, tt.args.ruid, tt.args.ckind, tt.args.cname, tt.args.cnamespace, tt.args.einvolved); !reflect.DeepEqual(got, tt.want) { t.Errorf("getViolationRef() = %v, want %v", got, tt.want) } }) From 6513e4ee787d64595ae7ac6b9b6f58387dfb09cf Mon Sep 17 00:00:00 2001 From: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:11:59 +0000 Subject: [PATCH 6/8] fix: added namespaces in e2e events test Signed-off-by: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> --- test/bats/test.bats | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/bats/test.bats b/test/bats/test.bats index 86a31b4f3d1..276d1aa58bb 100644 --- a/test/bats/test.bats +++ b/test/bats/test.bats @@ -228,14 +228,14 @@ __required_labels_audit_test() { @test "emit events test" { # list events for easy debugging - kubectl get events -n ${GATEKEEPER_NAMESPACE} - events=$(kubectl get events -n ${GATEKEEPER_NAMESPACE} --field-selector reason=FailedAdmission -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') + kubectl get events -n gatekeeper-test-playground + events=$(kubectl get events -n gatekeeper-test-playground --field-selector reason=FailedAdmission -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') [[ "$events" -ge 1 ]] - events=$(kubectl get events -n ${GATEKEEPER_NAMESPACE} --field-selector reason=DryrunViolation -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') + events=$(kubectl get events -n gatekeeper-test-playground --field-selector reason=DryrunViolation -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') [[ "$events" -ge 1 ]] - events=$(kubectl get events -n ${GATEKEEPER_NAMESPACE} --field-selector reason=AuditViolation -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') + events=$(kubectl get events -n gatekeeper-test-playground --field-selector reason=AuditViolation -o json | jq -r '.items[] | select(.metadata.annotations.constraint_kind=="K8sRequiredLabels" )' | jq -s '. | length') [[ "$events" -ge 1 ]] } From 64e5d66137c200a435f01f539815bf8d1ba10ac7 Mon Sep 17 00:00:00 2001 From: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:12:18 +0000 Subject: [PATCH 7/8] docs: added context for event handling in cluster-scoped resources Signed-off-by: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> --- cmd/build/helmify/static/README.md | 4 ++-- manifest_staging/charts/gatekeeper/README.md | 4 ++-- pkg/audit/manager.go | 2 +- pkg/webhook/common.go | 2 +- website/docs/customize-startup.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/build/helmify/static/README.md b/cmd/build/helmify/static/README.md index 8b3ab950456..2b96afbe309 100644 --- a/cmd/build/helmify/static/README.md +++ b/cmd/build/helmify/static/README.md @@ -145,8 +145,8 @@ _See [Exempting Namespaces](https://open-policy-agent.github.io/gatekeeper/websi | mutatingWebhookCustomRules | Custom rules for selecting which API resources trigger the webhook. NOTE: If you change this, ensure all your constraints are still being enforced. | `{}` | | emitAdmissionEvents | Emit K8s events in configurable namespace for admission violations (alpha feature) | `false` | | emitAuditEvents | Emit K8s events in configurable namespace for audit violations (alpha feature) | `false` | -| auditEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | -| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | +| auditEventsInvolvedNamespace | Emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will continue to generate events in the namespace that Gatekeeper is installed in | `false` | +| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Admission events from cluster-scoped resources will continue to generate events in the namespace that Gatekeeper is installed in | `false` | | logDenies | Log detailed info on each deny | `false` | | logLevel | Minimum log level | `INFO` | | image.pullPolicy | The image pull policy | `IfNotPresent` | diff --git a/manifest_staging/charts/gatekeeper/README.md b/manifest_staging/charts/gatekeeper/README.md index 8b3ab950456..78969e40ba9 100644 --- a/manifest_staging/charts/gatekeeper/README.md +++ b/manifest_staging/charts/gatekeeper/README.md @@ -145,8 +145,8 @@ _See [Exempting Namespaces](https://open-policy-agent.github.io/gatekeeper/websi | mutatingWebhookCustomRules | Custom rules for selecting which API resources trigger the webhook. NOTE: If you change this, ensure all your constraints are still being enforced. | `{}` | | emitAdmissionEvents | Emit K8s events in configurable namespace for admission violations (alpha feature) | `false` | | emitAuditEvents | Emit K8s events in configurable namespace for audit violations (alpha feature) | `false` | -| auditEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | -| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in | `false` | +| auditEventsInvolvedNamespace | Emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will still follow the default behavior | `false` | +| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Admission events from cluster-scoped resources will still follow the default behavior | `false` | | logDenies | Log detailed info on each deny | `false` | | logLevel | Minimum log level | `INFO` | | image.pullPolicy | The image pull policy | `IfNotPresent` | diff --git a/pkg/audit/manager.go b/pkg/audit/manager.go index ee885b8ab51..c8f90dc571b 100644 --- a/pkg/audit/manager.go +++ b/pkg/audit/manager.go @@ -58,7 +58,7 @@ var ( auditChunkSize = flag.Uint64("audit-chunk-size", defaultListLimit, "(alpha) Kubernetes API chunking List results when retrieving cluster resources using discovery client. defaulted to 500 if unspecified") auditFromCache = flag.Bool("audit-from-cache", false, "pull resources from OPA cache when auditing") emitAuditEvents = flag.Bool("emit-audit-events", false, "(alpha) emit Kubernetes events with detailed info for each violation from an audit") - auditEventsInvolvedNamespace = flag.Bool("audit-events-involved-namespace", false, "emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in") + auditEventsInvolvedNamespace = flag.Bool("audit-events-involved-namespace", false, "emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will still follow the default behavior") auditMatchKindOnly = flag.Bool("audit-match-kind-only", false, "only use kinds specified in all constraints for auditing cluster resources. if kind is not specified in any of the constraints, it will audit all resources (same as setting this flag to false)") apiCacheDir = flag.String("api-cache-dir", defaultAPICacheDir, "The directory where audit from api server cache are stored, defaults to /tmp/audit") emptyAuditResults []updateListEntry diff --git a/pkg/webhook/common.go b/pkg/webhook/common.go index e1c8def5850..99f737f5998 100644 --- a/pkg/webhook/common.go +++ b/pkg/webhook/common.go @@ -59,7 +59,7 @@ var ( disableEnforcementActionValidation = flag.Bool("disable-enforcementaction-validation", false, "disable validation of the enforcementAction field of a constraint") logDenies = flag.Bool("log-denies", false, "log detailed info on each deny") emitAdmissionEvents = flag.Bool("emit-admission-events", false, "(alpha) emit Kubernetes events for each admission violation") - admissionEventsInvolvedNamespace = flag.Bool("admission-events-involved-namespace", false, "emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace gatekeeper is installed in") + admissionEventsInvolvedNamespace = flag.Bool("admission-events-involved-namespace", false, "emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Admission events from cluster-scoped resources will still follow the default behavior") tlsMinVersion = flag.String("tls-min-version", "1.3", "minimum version of TLS supported") serviceaccount = fmt.Sprintf("system:serviceaccount:%s:%s", util.GetNamespace(), serviceAccountName) clientCAName = flag.String("client-ca-name", "", "name of the certificate authority bundle to authenticate the Kubernetes API server requests against") diff --git a/website/docs/customize-startup.md b/website/docs/customize-startup.md index 138e764c1e7..601f4d5f44a 100644 --- a/website/docs/customize-startup.md +++ b/website/docs/customize-startup.md @@ -27,9 +27,9 @@ The `--emit-admission-events` flag enables the emission of all admission violati The `--emit-audit-events` flag enables the emission of all audit violation as Kubernetes events. This flag is in alpha stage and it is set to `false` by default. -The `--admission-events-involved-namespace` flag controls which namespace admission events will be created in. When set to `true` admission events will be created in the involved objects namespace violating the constraint, if the object has no namespace (ie. cluster scoped resources) they will be created in the namespace gatekeeper is installed in. Setting to `false` will cause all admission events to be created in the gatekeeper namespace. +The `--admission-events-involved-namespace` flag controls which namespace admission events will be created in. When set to `true`, admission events will be created in the namespace of the object violating the constraint. If the object has no namespace (ie. cluster scoped resources), they will be created in the namespace Gatekeeper is installed in. Setting to `false` will cause all admission events to be created in the Gatekeeper namespace. -The `--audit-events-involved-namespace` flag controls which namespace audit events will be created in. When set to `true` audit events will be created in the involved objects namespace violating the constraint, if the object has no namespace (ie. cluster scoped resources) they will be created in the namespace gatekeeper is installed in. Setting to `false` will cause all audit events to be created in the gatekeeper namespace. +The `--audit-events-involved-namespace` flag controls which namespace audit events will be created in. When set to `true`, audit events will be created in the namespace of the object violating the constraint. If the object has no namespace (ie. cluster scoped resources), they will be created in the namespace Gatekeeper is installed in. Setting to `false` will cause all audit events to be created in the Gatekeeper namespace. There are four types of events that are emitted by Gatekeeper when the emit event flags are enabled: From 322b7c3070be2922061af29e2762baccd9444bc1 Mon Sep 17 00:00:00 2001 From: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> Date: Thu, 23 Mar 2023 04:07:40 +0000 Subject: [PATCH 8/8] fix: spacing issue in Helm README Signed-off-by: Eshaan Mathur <37758843+eshaanm25@users.noreply.github.com> --- manifest_staging/charts/gatekeeper/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest_staging/charts/gatekeeper/README.md b/manifest_staging/charts/gatekeeper/README.md index 78969e40ba9..2b96afbe309 100644 --- a/manifest_staging/charts/gatekeeper/README.md +++ b/manifest_staging/charts/gatekeeper/README.md @@ -145,8 +145,8 @@ _See [Exempting Namespaces](https://open-policy-agent.github.io/gatekeeper/websi | mutatingWebhookCustomRules | Custom rules for selecting which API resources trigger the webhook. NOTE: If you change this, ensure all your constraints are still being enforced. | `{}` | | emitAdmissionEvents | Emit K8s events in configurable namespace for admission violations (alpha feature) | `false` | | emitAuditEvents | Emit K8s events in configurable namespace for audit violations (alpha feature) | `false` | -| auditEventsInvolvedNamespace | Emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will still follow the default behavior | `false` | -| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Admission events from cluster-scoped resources will still follow the default behavior | `false` | +| auditEventsInvolvedNamespace | Emit audit events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Audit events from cluster-scoped resources will continue to generate events in the namespace that Gatekeeper is installed in | `false` | +| admissionEventsInvolvedNamespace | Emit admission events for each violation in the involved objects namespace, the default (false) generates events in the namespace Gatekeeper is installed in. Admission events from cluster-scoped resources will continue to generate events in the namespace that Gatekeeper is installed in | `false` | | logDenies | Log detailed info on each deny | `false` | | logLevel | Minimum log level | `INFO` | | image.pullPolicy | The image pull policy | `IfNotPresent` |