Skip to content

Commit

Permalink
Merge pull request kubewarden#814 from viccuad/matchconds
Browse files Browse the repository at this point in the history
feat: Add new `spec.matchConditions` to (Cluster)AdmissionPolicies
  • Loading branch information
flavio authored Jul 19, 2024
2 parents 54489d6 + 0efab71 commit 625659f
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 14 deletions.
4 changes: 4 additions & 0 deletions api/policies/v1/admissionpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ func (r *AdmissionPolicy) GetMatchPolicy() *admissionregistrationv1.MatchPolicyT
return r.Spec.MatchPolicy
}

func (r *AdmissionPolicy) GetMatchConditions() []admissionregistrationv1.MatchCondition {
return r.Spec.MatchConditions
}

// GetNamespaceSelector returns the namespace of the AdmissionPolicy since it is the only namespace we want the policy to be applied to.
func (r *AdmissionPolicy) GetUpdatedNamespaceSelector(string) *metav1.LabelSelector {
return &metav1.LabelSelector{
Expand Down
4 changes: 4 additions & 0 deletions api/policies/v1/clusteradmissionpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ func (r *ClusterAdmissionPolicy) GetRules() []admissionregistrationv1.RuleWithOp
return r.Spec.Rules
}

func (r *ClusterAdmissionPolicy) GetMatchConditions() []admissionregistrationv1.MatchCondition {
return r.Spec.MatchConditions
}

func (r *ClusterAdmissionPolicy) GetUpdatedNamespaceSelector(deploymentNamespace string) *metav1.LabelSelector {
// exclude namespace where kubewarden was deployed
if r.Spec.NamespaceSelector != nil {
Expand Down
1 change: 1 addition & 0 deletions api/policies/v1/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ type Policy interface {
GetRules() []admissionregistrationv1.RuleWithOperations
GetFailurePolicy() *admissionregistrationv1.FailurePolicyType
GetMatchPolicy() *admissionregistrationv1.MatchPolicyType
GetMatchConditions() []admissionregistrationv1.MatchCondition
GetUpdatedNamespaceSelector(deploymentNamespace string) *metav1.LabelSelector
GetObjectSelector() *metav1.LabelSelector
GetTimeoutSeconds() *int32
Expand Down
15 changes: 15 additions & 0 deletions api/policies/v1/policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ type PolicySpec struct {
// +optional
MatchPolicy *admissionregistrationv1.MatchPolicyType `json:"matchPolicy,omitempty"`

// MatchConditions is a list of conditions that must be met for a request to be
// validated. Match conditions filter requests that have already been matched by
// the rules, namespaceSelector, and objectSelector. An empty list of
// matchConditions matches all requests. There are a maximum of 64 match
// conditions allowed. If a parameter object is provided, it can be accessed via
// the `params` handle in the same manner as validation expressions. The exact
// matching logic is (in order): 1. If ANY matchCondition evaluates to FALSE,
// the policy is skipped. 2. If ALL matchConditions evaluate to TRUE, the policy
// is evaluated. 3. If any matchCondition evaluates to an error (but none are
// FALSE): - If failurePolicy=Fail, reject the request - If
// failurePolicy=Ignore, the policy is skipped
// Only available if the feature gate AdmissionWebhookMatchConditions is enabled.
// +optional
MatchConditions []admissionregistrationv1.MatchCondition `json:"matchConditions,omitempty"`

// ObjectSelector decides whether to run the webhook based on if the
// object has matching labels. objectSelector is evaluated against both
// the oldObject and newObject that would be sent to the webhook, and
Expand Down
5 changes: 5 additions & 0 deletions api/policies/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/kubewarden/kubewarden-controller/api/policies/v1alpha2"
"github.com/kubewarden/kubewarden-controller/internal/constants"
"github.com/kubewarden/kubewarden-controller/internal/controller"
"github.com/kubewarden/kubewarden-controller/internal/featuregates"
"github.com/kubewarden/kubewarden-controller/internal/metrics"
//+kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -129,7 +130,14 @@ func main() {
return
}

if err = setupReconcilers(mgr, deploymentsNamespace, enableMetrics, enableTracing, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace); err != nil {
featureGateAdmissionWebhookMatchConditions, err := featuregates.CheckAdmissionWebhookMatchConditions(ctrl.GetConfigOrDie())
if err != nil {
setupLog.Error(err, "unable to check for feature gate AdmissionWebhookMatchConditions")
retcode = 1
return
}

if err = setupReconcilers(mgr, deploymentsNamespace, enableMetrics, enableTracing, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace, featureGateAdmissionWebhookMatchConditions); err != nil {
setupLog.Error(err, "unable to create controllers")
retcode = 1
return
Expand Down Expand Up @@ -217,7 +225,7 @@ func setupProbes(mgr ctrl.Manager) error {
return nil
}

func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace string, enableMetrics, enableTracing, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace bool) error {
func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace string, enableMetrics, enableTracing, alwaysAcceptAdmissionReviewsOnDeploymentsNamespace bool, featureGateAdmissionWebhookMatchConditions bool) error {
if err := (&controller.PolicyServerReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand All @@ -235,6 +243,7 @@ func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace string, enableMetri
Scheme: mgr.GetScheme(),
Log: ctrl.Log.WithName("admission-policy-reconciler"),
DeploymentsNamespace: deploymentsNamespace,
FeatureGateAdmissionWebhookMatchConditions: featureGateAdmissionWebhookMatchConditions,
}).SetupWithManager(mgr); err != nil {
return errors.Join(errors.New("unable to create AdmissionPolicy controller"), err)
}
Expand All @@ -244,6 +253,7 @@ func setupReconcilers(mgr ctrl.Manager, deploymentsNamespace string, enableMetri
Scheme: mgr.GetScheme(),
Log: ctrl.Log.WithName("cluster-admission-policy-reconciler"),
DeploymentsNamespace: deploymentsNamespace,
FeatureGateAdmissionWebhookMatchConditions: featureGateAdmissionWebhookMatchConditions,
}).SetupWithManager(mgr); err != nil {
return errors.Join(errors.New("unable to create ClusterAdmissionPolicy controller"), err)
}
Expand Down
54 changes: 54 additions & 0 deletions config/crd/bases/policies.kubewarden.io_admissionpolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,60 @@ spec:
fail and the API request to be rejected.
The default behaviour is "Fail"
type: string
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be
validated. Match conditions filter requests that have already been matched by
the rules, namespaceSelector, and objectSelector. An empty list of
matchConditions matches all requests. There are a maximum of 64 match
conditions allowed. If a parameter object is provided, it can be accessed via
the `params` handle in the same manner as validation expressions. The exact
matching logic is (in order): 1. If ANY matchCondition evaluates to FALSE,
the policy is skipped. 2. If ALL matchConditions evaluate to TRUE, the policy
is evaluated. 3. If any matchCondition evaluates to an error (but none are
FALSE): - If failurePolicy=Fail, reject the request - If
failurePolicy=Ignore, the policy is skipped
Only available if the feature gate AdmissionWebhookMatchConditions is enabled.
items:
description: MatchCondition represents a condition which must by
fulfilled for a request to be sent to a webhook.
properties:
expression:
description: |-
Expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables:
'object' - The object from the incoming request. The value is null for DELETE requests.
'oldObject' - The existing object. The value is null for CREATE requests.
'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest).
'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request.
See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the
request resource.
Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
Required.
type: string
name:
description: |-
Name is an identifier for this match condition, used for strategic merging of MatchConditions,
as well as providing an identifier for logging purposes. A good name should be descriptive of
the associated expression.
Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and
must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or
'123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an
optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName')
Required.
type: string
required:
- expression
- name
type: object
type: array
matchPolicy:
description: |-
matchPolicy defines how the "rules" list is used to match incoming requests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,60 @@ spec:
fail and the API request to be rejected.
The default behaviour is "Fail"
type: string
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be
validated. Match conditions filter requests that have already been matched by
the rules, namespaceSelector, and objectSelector. An empty list of
matchConditions matches all requests. There are a maximum of 64 match
conditions allowed. If a parameter object is provided, it can be accessed via
the `params` handle in the same manner as validation expressions. The exact
matching logic is (in order): 1. If ANY matchCondition evaluates to FALSE,
the policy is skipped. 2. If ALL matchConditions evaluate to TRUE, the policy
is evaluated. 3. If any matchCondition evaluates to an error (but none are
FALSE): - If failurePolicy=Fail, reject the request - If
failurePolicy=Ignore, the policy is skipped
Only available if the feature gate AdmissionWebhookMatchConditions is enabled.
items:
description: MatchCondition represents a condition which must by
fulfilled for a request to be sent to a webhook.
properties:
expression:
description: |-
Expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
CEL expressions have access to the contents of the AdmissionRequest and Authorizer, organized into CEL variables:
'object' - The object from the incoming request. The value is null for DELETE requests.
'oldObject' - The existing object. The value is null for CREATE requests.
'request' - Attributes of the admission request(/pkg/apis/admission/types.go#AdmissionRequest).
'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request.
See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the
request resource.
Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
Required.
type: string
name:
description: |-
Name is an identifier for this match condition, used for strategic merging of MatchConditions,
as well as providing an identifier for logging purposes. A good name should be descriptive of
the associated expression.
Name must be a qualified name consisting of alphanumeric characters, '-', '_' or '.', and
must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or
'123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]') with an
optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName')
Required.
type: string
required:
- expression
- name
type: object
type: array
matchPolicy:
description: |-
matchPolicy defines how the "rules" list is used to match incoming requests.
Expand Down
Loading

0 comments on commit 625659f

Please sign in to comment.