Skip to content

Commit

Permalink
adding generateVAP field
Browse files Browse the repository at this point in the history
Signed-off-by: Jaydip Gabani <[email protected]>
  • Loading branch information
JaydipGabani committed May 23, 2024
1 parent 38e29e4 commit d9f165a
Show file tree
Hide file tree
Showing 152 changed files with 21,616 additions and 7,072 deletions.
26 changes: 14 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/open-policy-agent/gatekeeper/v3

go 1.21

replace github.com/open-policy-agent/frameworks/constraint => /mount/d/go/src/github.com/open-policy-agent/frameworks/constraint

require (
cloud.google.com/go/trace v1.10.6
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.44.0
Expand All @@ -13,7 +15,7 @@ require (
github.com/golang/protobuf v1.5.4
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/onsi/gomega v1.31.1
github.com/onsi/gomega v1.33.1
github.com/open-policy-agent/cert-controller v0.10.1
github.com/open-policy-agent/frameworks/constraint v0.0.0-20240411024313-c2efb00269a8
github.com/pkg/errors v0.9.1
Expand All @@ -30,11 +32,11 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.19.0
go.uber.org/automaxprocs v1.5.3
go.uber.org/zap v1.26.0
golang.org/x/net v0.24.0
golang.org/x/net v0.25.0
golang.org/x/oauth2 v0.17.0
golang.org/x/sync v0.6.0
golang.org/x/sync v0.7.0
golang.org/x/time v0.5.0
google.golang.org/grpc v1.62.1
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -68,7 +70,7 @@ require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/containerd/containerd v1.7.14 // indirect
github.com/containerd/containerd v1.7.15 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/cli v25.0.1+incompatible // indirect
Expand Down Expand Up @@ -111,11 +113,11 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/open-policy-agent/opa v0.63.0 // indirect
github.com/open-policy-agent/opa v0.64.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc6 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
Expand All @@ -136,15 +138,15 @@ require (
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/api v0.169.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
Expand Down
69 changes: 34 additions & 35 deletions go.sum

Large diffs are not rendered by default.

12 changes: 3 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ var (
disabledBuiltins = util.NewFlagSet()
enableK8sCel = flag.Bool("experimental-enable-k8s-native-validation", false, "Alpha: enable the validating admission policy driver")
externaldataProviderResponseCacheTTL = flag.Duration("external-data-provider-response-cache-ttl", 3*time.Minute, "TTL for the external data provider response cache. Specify the duration in 'h', 'm', or 's' for hours, minutes, or seconds respectively. Defaults to 3 minutes if unspecified. Setting the TTL to 0 disables the cache.")
deferAdmissionToVAP = flag.Bool("defer-admission-to-vap", false, "When set to false, Gatekeeper webhook can act as a fallback in case K8s' Validating Admission Policy fails. When set to true, Gatekeeper validating webhook will not evaluate a policy for an admission request it expects vap to enforce. May improve resource usage at the cost of race conditions detecting whether VAP enforcement is in effect. This does not impact audit results. Defaults to false.")
deferAdmissionToVAP = flag.Bool("defer-admission-to-vap", false, "When set to false, Gatekeeper webhook can act as a fallback in case K8s' Validating Admission Policy fails. When set to true, Gatekeeper validating webhook will not evaluate a policy for an admission request it expects vap to enforce. May improve resource usage at the cost of race conditions detecting whether VAP enforcement is in effect. This does not impact audit results. Defaults to false.")
)

func init() {
Expand All @@ -134,7 +134,6 @@ func init() {

// +kubebuilder:scaffold:scheme
flag.Var(disabledBuiltins, "disable-opa-builtin", "disable opa built-in function, this flag can be declared more than once.")
flag.Var(&constraint.VapEnforcement, "vap-enforcement", "control VAP resource generation. Allowed values are NONE: do not generate, GATEKEEPER_DEFAULT: do not generate unless label gatekeeper.sh/use-vap: yes is added to policy explicitly, VAP_DEFAULT: generate unless label gatekeeper.sh/use-vap: no is added to policy explicitly.")
}

func main() {
Expand Down Expand Up @@ -416,13 +415,8 @@ func setupControllers(ctx context.Context, mgr ctrl.Manager, sw *watch.Controlle
if *enableK8sCel {
// initialize K8sValidation
var k8scelArgs []k8scel.Arg
if *deferAdmissionToVAP && constraint.VapEnforcement != constraint.VapFlagNone {
switch constraint.VapEnforcement {
case constraint.VapFlagGatekeeperDefault:
k8scelArgs = append(k8scelArgs, k8scel.VAPGenerationDefault(k8scel.VAPDefaultNo))
case constraint.VapFlagVapDefault:
k8scelArgs = append(k8scelArgs, k8scel.VAPGenerationDefault(k8scel.VAPDefaultYes))
}
if *deferAdmissionToVAP {
k8scelArgs = append(k8scelArgs, k8scel.VAPGenerationDefault(*constraint.VapEnforcement))
}
k8sDriver, err := k8scel.New(k8scelArgs...)
if err != nil {
Expand Down
16 changes: 0 additions & 16 deletions pkg/controller/constraint/constants.go

This file was deleted.

96 changes: 26 additions & 70 deletions pkg/controller/constraint/constraint_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package constraint
import (
"context"
"errors"
"flag"
"fmt"
"reflect"
"strings"
Expand All @@ -27,6 +28,7 @@ import (
v1beta1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1beta1"
constraintclient "github.com/open-policy-agent/frameworks/constraint/pkg/client"
"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/k8scel/transform"
k8scelSchema"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/k8scel/schema"
constraintstatusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1"
"github.com/open-policy-agent/gatekeeper/v3/pkg/controller/config/process"
"github.com/open-policy-agent/gatekeeper/v3/pkg/controller/constraintstatus"
Expand Down Expand Up @@ -61,45 +63,13 @@ import (
var (
log = logf.Log.V(logging.DebugLevel).WithName("controller").WithValues(logging.Process, "constraint_controller")
discoveryErr *apiutil.ErrResourceDiscoveryFailed
VapEnforcement = flag.Bool("vap-enforcement", false, "control VAP resource generation. Allowed values are false: do not generate unless enforceVAP: true is added to policy explicitly, true: generate unless enforceVAP: false is added to policy explicitly.")
)

var vapMux sync.RWMutex

var VapAPIEnabled *bool

var VapEnforcement VapFlagType

// VapFlagType is the custom type for the vap-enforcement flag.
type VapFlagType string

// Allowed values for VapFlagType.
var allowedVapFlagVals = []string{VapFlagNone, VapFlagGatekeeperDefault, VapFlagVapDefault}

// String returns the string representation of the flag value.
func (v *VapFlagType) String() string {
return string(*v)
}

// Set validates and sets the value for the VapFlagType.
func (v *VapFlagType) Set(value string) error {
for _, val := range allowedVapFlagVals {
if val == value {
*v = VapFlagType(value)
return nil
}
}
return fmt.Errorf("invalid value %s. Allowed values are %s, %s, %s", value, VapFlagNone, VapFlagGatekeeperDefault, VapFlagVapDefault)
}

// setting defaults when not set; required for unit test.
func (v *VapFlagType) SetDefaultIfEmpty() {
if *v == "" {
*v = VapFlagType(VapFlagGatekeeperDefault)
VapAPIEnabled = new(bool)
*VapAPIEnabled = true
}
}

type Adder struct {
CFClient *constraintclient.Client
ConstraintsCache *ConstraintsCache
Expand Down Expand Up @@ -300,26 +270,14 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R

deleted = deleted || !instance.GetDeletionTimestamp().IsZero()

labels := instance.GetLabels()
log.Info("constraint resource", "labels", labels)
useVap, ok := labels[VapGenerationLabel]
if ok {
log.Info("constraint resource", "useVap", useVap)
}
// unless constraint vap label is false, default to parent
if useVap == No {
generateVapBinding = false
} else {
log.Info("constraint resource use-vap label is not no; will default to parent constraint template label")
parentCTUseVap, err := r.getCTVapLabel(ctx, instance.GetKind())
if err != nil {
log.Error(err, "could not get parent constraint template object")
return reconcile.Result{}, err
}
log.Info("constraint resource", "parentCTUseVap", parentCTUseVap)
generateVapBinding = ShouldGenerateVap(parentCTUseVap)
log.Info("constraint resource", "generateVapBinding", generateVapBinding)
log.Info("constraint resource use-vap label is not no; will default to parent constraint template label")
generateVapBinding, err = r.shouldGenerateVAPB(ctx, instance.GetKind())
if err != nil {
log.Error(err, "could not get parent constraint template object")
return reconcile.Result{}, err
}
log.Info("constraint resource", "generateVapBinding", generateVapBinding)

constraintKey := strings.Join([]string{instance.GetKind(), instance.GetName()}, "/")
enforcementAction, err := util.GetEnforcementAction(instance.Object)
if err != nil {
Expand Down Expand Up @@ -555,20 +513,24 @@ func (r *ReconcileConstraint) cacheConstraint(ctx context.Context, instance *uns
return nil
}

func (r *ReconcileConstraint) getCTVapLabel(ctx context.Context, gvk string) (string, error) {
func (r *ReconcileConstraint) shouldGenerateVAPB(ctx context.Context, gvk string) (bool, error) {
ct := &v1beta1.ConstraintTemplate{}
ctName := strings.ToLower(gvk)
log.Info("get parent constraint template and its labels", "ctName", ctName)
log.Info("get parent constraint template", "ctName", ctName)
if err := r.reader.Get(ctx, types.NamespacedName{Name: ctName}, ct); err != nil {
return "", err
}
labels := ct.GetLabels()
log.Info("parent constraint template", "labels", labels)
useVap, ok := labels[VapGenerationLabel]
if !ok {
return "", nil
return false, err
}
generateVap := false
for _, c := range ct.Spec.Targets[0].Code {
if c.Engine == k8scelSchema.Name {
if c.GenerateVAP == nil {
generateVap = ShouldGenerateVap()
} else {
generateVap = *c.GenerateVAP
}
}
}
return useVap, nil
return generateVap, nil
}

func NewConstraintsCache() *ConstraintsCache {
Expand Down Expand Up @@ -617,14 +579,8 @@ func (c *ConstraintsCache) reportTotalConstraints(ctx context.Context, reporter
}
}

func ShouldGenerateVap(useVapLabel string) bool {
if VapEnforcement == VapFlagGatekeeperDefault {
return useVapLabel == Yes
}
if VapEnforcement == VapFlagVapDefault {
return useVapLabel != No
}
return false
func ShouldGenerateVap() bool {
return *VapEnforcement
}

func IsVapAPIEnabled() bool {
Expand Down
26 changes: 9 additions & 17 deletions pkg/controller/constrainttemplate/constrainttemplate_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1beta1"
constraintclient "github.com/open-policy-agent/frameworks/constraint/pkg/client"
k8scelSchema"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/k8scel/schema"
"github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/k8scel/transform"
"github.com/open-policy-agent/frameworks/constraint/pkg/core/templates"
statusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1"
Expand Down Expand Up @@ -121,7 +122,6 @@ func (a *Adder) InjectGetPod(getPod func(context.Context) (*corev1.Pod, error))
// regEvents is the channel registered by Registrar to put the events in
// cstrEvents and regEvents point to same event channel except for testing.
func newReconciler(mgr manager.Manager, cfClient *constraintclient.Client, wm *watch.Manager, cs *watch.ControllerSwitch, tracker *readiness.Tracker, cstrEvents <-chan event.GenericEvent, regEvents chan<- event.GenericEvent, getPod func(context.Context) (*corev1.Pod, error)) (*ReconcileConstraintTemplate, error) {
constraint.VapEnforcement.SetDefaultIfEmpty()
// constraintsCache contains total number of constraints and shared mutex and vap label
constraintsCache := constraint.NewConstraintsCache()

Expand Down Expand Up @@ -381,22 +381,14 @@ func (r *ReconcileConstraintTemplate) Reconcile(ctx context.Context, request rec
}

generateVap := false
labels := ct.GetLabels()
logger.Info("constraint template resource", "labels", labels)
useVap, ok := labels[constraint.VapGenerationLabel]
if !ok {
logger.Info("constraint template resource does not have a label for use-vap; will default to flag behavior", "VapEnforcement", constraint.VapEnforcement)
generateVap = constraint.ShouldGenerateVap("")
} else {
logger.Info("constraint template resource", "useVap", useVap)
generateVap = constraint.ShouldGenerateVap(useVap)
if useVap != constraint.No && useVap != constraint.Yes {
labelErr := &v1beta1.CreateCRDError{Code: ErrCreateCode, Message: fmt.Sprintf("constraint template resource has an invalid value for %s, allowed values are yes and no", constraint.VapGenerationLabel)}
status.Status.Errors = append(status.Status.Errors, labelErr)

if updateErr := r.Update(ctx, status); updateErr != nil {
logger.Error(updateErr, "update status error")
return reconcile.Result{Requeue: true}, nil
for _, c := range ct.Spec.Targets[0].Code {
if c.Engine == k8scelSchema.Name {
if c.GenerateVAP == nil {
logger.Info("constraint template resource does not have a field `generateVAP`; will default to flag behavior", "VapEnforcement", constraint.VapEnforcement)
generateVap = constraint.ShouldGenerateVap()
} else {
logger.Info("constraint template resource", "useVap", c.GenerateVAP)
generateVap = *c.GenerateVAP
}
}
}
Expand Down
Loading

0 comments on commit d9f165a

Please sign in to comment.