Skip to content

Commit

Permalink
adding generate operation
Browse files Browse the repository at this point in the history
Signed-off-by: Jaydip Gabani <[email protected]>
  • Loading branch information
JaydipGabani committed Oct 5, 2024
1 parent 0d4a1cd commit e9bb4bf
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 196 deletions.
1 change: 1 addition & 0 deletions cmd/build/helmify/kustomize-for-helm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ spec:
- --audit-events-involved-namespace={{ .Values.auditEventsInvolvedNamespace }}
- --operation=audit
- --operation=status
- --operation=generate
- HELMSUBST_PUBSUB_ARGS
- HELMSUBST_MUTATION_STATUS_ENABLED_ARG
- --logtostderr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ spec:
- --audit-events-involved-namespace={{ .Values.auditEventsInvolvedNamespace }}
- --operation=audit
- --operation=status
- --operation=generate
{{ if .Values.audit.enablePubsub}}
- --enable-pub-sub={{ .Values.audit.enablePubsub }}
- --audit-connection={{ .Values.audit.connection }}
Expand Down
190 changes: 97 additions & 93 deletions pkg/controller/constraint/constraint_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"reflect"
"strings"
"sync"
"time"

"github.com/go-logr/logr"
"github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1beta1"
Expand Down Expand Up @@ -65,10 +66,11 @@ import (
)

var (
log = logf.Log.V(logging.DebugLevel).WithName("controller").WithValues(logging.Process, "constraint_controller")
discoveryErr *apiutil.ErrResourceDiscoveryFailed
DefaultGenerateVAPB = flag.Bool("default-create-vap-binding-for-constraints", false, "Create VAPBinding resource for constraint of the template containing VAP-style CEL source. Allowed values are false: do not create Validating Admission Policy Binding, true: create Validating Admission Policy Binding.")
DefaultGenerateVAP = flag.Bool("default-create-vap-for-templates", false, "Create VAP resource for template containing VAP-style CEL source. Allowed values are false: do not create Validating Admission Policy unless generateVAP: true is set on constraint template explicitly, true: create Validating Admission Policy unless generateVAP: false is set on constraint template explicitly.")
log = logf.Log.V(logging.DebugLevel).WithName("controller").WithValues(logging.Process, "constraint_controller")
discoveryErr *apiutil.ErrResourceDiscoveryFailed
defaultWaitForGeneration = flag.Int("default-wait-for-generation", 30, "Wait to generate ValidatingAdmissionPolicyBinding after the constraint is created. Defaults to 30 seconds.")
DefaultGenerateVAPB = flag.Bool("default-create-vap-binding-for-constraints", false, "Create VAPBinding resource for constraint of the template containing VAP-style CEL source. Allowed values are false: do not create Validating Admission Policy Binding, true: create Validating Admission Policy Binding.")
DefaultGenerateVAP = flag.Bool("default-create-vap-for-templates", false, "Create VAP resource for template containing VAP-style CEL source. Allowed values are false: do not create Validating Admission Policy unless generateVAP: true is set on constraint template explicitly, true: create Validating Admission Policy unless generateVAP: false is set on constraint template explicitly.")
)

var (
Expand Down Expand Up @@ -305,106 +307,108 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
status.Status.Errors = nil

if c, err := r.cfClient.GetConstraint(instance); err != nil || !reflect.DeepEqual(instance, c) {
err := util.ValidateEnforcementAction(enforcementAction, instance.Object)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not validate enforcement actions")
}
generateVAPB, VAPEnforcementActions, err := shouldGenerateVAPB(*DefaultGenerateVAPB, enforcementAction, instance)
if err != nil {
log.Error(err, "could not determine if ValidatingAdmissionPolicyBinding should be generated")
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not determine if ValidatingAdmissionPolicyBinding should be generated")
}
isAPIEnabled := false
var groupVersion *schema.GroupVersion
if generateVAPB {
isAPIEnabled, groupVersion = IsVapAPIEnabled()
}
if generateVAPB {
if !isAPIEnabled {
log.Error(ErrValidatingAdmissionPolicyAPIDisabled, "Cannot generate ValidatingAdmissionPolicyBinding", "constraint", instance.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, ErrValidatingAdmissionPolicyAPIDisabled, "cannot generate ValidatingAdmissionPolicyBinding")
generateVAPB = false
} else {
unversionedCT := &templates.ConstraintTemplate{}
if err := r.scheme.Convert(ct, unversionedCT, nil); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not convert ConstraintTemplate to unversioned")
}
hasVAP, err := ShouldGenerateVAP(unversionedCT)
switch {
case errors.Is(err, celSchema.ErrCodeNotDefined):
generateVAPB = false
case err != nil:
log.Error(err, "could not determine if ConstraintTemplate is configured to generate ValidatingAdmissionPolicy", "constraint", instance.GetName(), "constraint_template", ct.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, err, "could not determine if ConstraintTemplate is configured to generate ValidatingAdmissionPolicy")
generateVAPB = false
case !hasVAP:
log.Error(ErrVAPConditionsNotSatisfied, "Cannot generate ValidatingAdmissionPolicyBinding", "constraint", instance.GetName(), "constraint_template", ct.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, ErrVAPConditionsNotSatisfied, "Cannot generate ValidatingAdmissionPolicyBinding")
generateVAPB = false
default:
}
}
}
r.log.Info("constraint controller", "generateVAPB", generateVAPB)
// generate vapbinding resources
if generateVAPB && groupVersion != nil {
currentVapBinding, err := vapBindingForVersion(*groupVersion)
if operations.IsAssigned(operations.Generate) {
err := util.ValidateEnforcementAction(enforcementAction, instance.Object)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding API version")
}
vapBindingName := fmt.Sprintf("gatekeeper-%s", instance.GetName())
log.Info("check if vapbinding exists", "vapBindingName", vapBindingName)
if err := r.reader.Get(ctx, types.NamespacedName{Name: vapBindingName}, currentVapBinding); err != nil {
if !apierrors.IsNotFound(err) && !errors.As(err, &discoveryErr) && !meta.IsNoMatchError(err) {
return reconcile.Result{}, err
}
currentVapBinding = nil
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not validate enforcement actions")
}
transformedVapBinding, err := transform.ConstraintToBinding(instance, VAPEnforcementActions)
generateVAPB, VAPEnforcementActions, err := shouldGenerateVAPB(*DefaultGenerateVAPB, enforcementAction, instance)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not transform constraint to ValidatingAdmissionPolicyBinding")
log.Error(err, "could not determine if ValidatingAdmissionPolicyBinding should be generated")
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not determine if ValidatingAdmissionPolicyBinding should be generated")
}

newVapBinding, err := getRunTimeVAPBinding(groupVersion, transformedVapBinding, currentVapBinding)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding object with runtime group version")
isAPIEnabled := false
var groupVersion *schema.GroupVersion
if generateVAPB {
isAPIEnabled, groupVersion = IsVapAPIEnabled()
}

if err := controllerutil.SetControllerReference(instance, newVapBinding, r.scheme); err != nil {
return reconcile.Result{}, err
if generateVAPB {
if !isAPIEnabled {
log.Error(ErrValidatingAdmissionPolicyAPIDisabled, "Cannot generate ValidatingAdmissionPolicyBinding", "constraint", instance.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, ErrValidatingAdmissionPolicyAPIDisabled, "cannot generate ValidatingAdmissionPolicyBinding")
generateVAPB = false
} else {
unversionedCT := &templates.ConstraintTemplate{}
if err := r.scheme.Convert(ct, unversionedCT, nil); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not convert ConstraintTemplate to unversioned")
}
hasVAP, err := ShouldGenerateVAP(unversionedCT)
switch {
case errors.Is(err, celSchema.ErrCodeNotDefined):
generateVAPB = false
case err != nil:
log.Error(err, "could not determine if ConstraintTemplate is configured to generate ValidatingAdmissionPolicy", "constraint", instance.GetName(), "constraint_template", ct.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, err, "could not determine if ConstraintTemplate is configured to generate ValidatingAdmissionPolicy")
generateVAPB = false
case !hasVAP:
log.Error(ErrVAPConditionsNotSatisfied, "Cannot generate ValidatingAdmissionPolicyBinding", "constraint", instance.GetName(), "constraint_template", ct.GetName())
_ = r.reportErrorOnConstraintStatus(ctx, status, ErrVAPConditionsNotSatisfied, "Cannot generate ValidatingAdmissionPolicyBinding")
generateVAPB = false
default:
}
}
}

if currentVapBinding == nil {
log.Info("creating vapbinding")
if err := r.writer.Create(ctx, newVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not create ValidatingAdmissionPolicyBinding: %s", vapBindingName))
r.log.Info("constraint controller", "generateVAPB", generateVAPB)
// generate vapbinding resources
if generateVAPB && groupVersion != nil {
currentVapBinding, err := vapBindingForVersion(*groupVersion)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding API version")
}
} else if !reflect.DeepEqual(currentVapBinding, newVapBinding) {
log.Info("updating vapbinding")
if err := r.writer.Update(ctx, newVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not update ValidatingAdmissionPolicyBinding: %s", vapBindingName))
vapBindingName := fmt.Sprintf("gatekeeper-%s", instance.GetName())
log.Info("check if vapbinding exists", "vapBindingName", vapBindingName)
if err := r.reader.Get(ctx, types.NamespacedName{Name: vapBindingName}, currentVapBinding); err != nil {
if !apierrors.IsNotFound(err) && !errors.As(err, &discoveryErr) && !meta.IsNoMatchError(err) {
return reconcile.Result{}, err
}
currentVapBinding = nil
}
}
}
// do not generate vapbinding resources
// remove if exists
if !generateVAPB && groupVersion != nil {
currentVapBinding, err := vapBindingForVersion(*groupVersion)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding API version")
}
vapBindingName := fmt.Sprintf("gatekeeper-%s", instance.GetName())
log.Info("check if vapbinding exists", "vapBindingName", vapBindingName)
if err := r.reader.Get(ctx, types.NamespacedName{Name: vapBindingName}, currentVapBinding); err != nil {
if !apierrors.IsNotFound(err) && !errors.As(err, &discoveryErr) && !meta.IsNoMatchError(err) {
transformedVapBinding, err := transform.ConstraintToBinding(instance, VAPEnforcementActions)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not transform constraint to ValidatingAdmissionPolicyBinding")
}

newVapBinding, err := getRunTimeVAPBinding(groupVersion, transformedVapBinding, currentVapBinding)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding object with runtime group version")
}

if err := controllerutil.SetControllerReference(instance, newVapBinding, r.scheme); err != nil {
return reconcile.Result{}, err
}
currentVapBinding = nil

if currentVapBinding == nil && instance.GetCreationTimestamp().Add(time.Duration(*defaultWaitForGeneration)).Before(time.Now()) {
log.Info("creating vapbinding")
if err := r.writer.Create(ctx, newVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not create ValidatingAdmissionPolicyBinding: %s", vapBindingName))
}
} else if !reflect.DeepEqual(currentVapBinding, newVapBinding) {
log.Info("updating vapbinding")
if err := r.writer.Update(ctx, newVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not update ValidatingAdmissionPolicyBinding: %s", vapBindingName))
}
}
}
if currentVapBinding != nil {
log.Info("deleting vapbinding")
if err := r.writer.Delete(ctx, currentVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not delete ValidatingAdmissionPolicyBinding: %s", vapBindingName))
// do not generate vapbinding resources
// remove if exists
if !generateVAPB && groupVersion != nil {
currentVapBinding, err := vapBindingForVersion(*groupVersion)
if err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, "could not get ValidatingAdmissionPolicyBinding API version")
}
vapBindingName := fmt.Sprintf("gatekeeper-%s", instance.GetName())
log.Info("check if vapbinding exists", "vapBindingName", vapBindingName)
if err := r.reader.Get(ctx, types.NamespacedName{Name: vapBindingName}, currentVapBinding); err != nil {
if !apierrors.IsNotFound(err) && !errors.As(err, &discoveryErr) && !meta.IsNoMatchError(err) {
return reconcile.Result{}, err
}
currentVapBinding = nil
}
if currentVapBinding != nil {
log.Info("deleting vapbinding")
if err := r.writer.Delete(ctx, currentVapBinding); err != nil {
return reconcile.Result{}, r.reportErrorOnConstraintStatus(ctx, status, err, fmt.Sprintf("could not delete ValidatingAdmissionPolicyBinding: %s", vapBindingName))
}
}
}
}
Expand Down
Loading

0 comments on commit e9bb4bf

Please sign in to comment.