Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-2.9] 🤖 Sync from open-cluster-management-io/config-policy-controller: #167 #604

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 27 additions & 67 deletions controllers/configurationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

gocmp "github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
templates "github.com/stolostron/go-template-utils/v3/pkg/templates"
templates "github.com/stolostron/go-template-utils/v4/pkg/templates"
"golang.org/x/mod/semver"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -432,20 +432,6 @@ func (r *ConfigurationPolicyReconciler) shouldEvaluatePolicy(
return true
}

// getTemplateConfigErrorMsg converts a configuration error from `NewResolver` or `SetEncryptionConfig` to a message
// to be used as a policy noncompliant message.
func getTemplateConfigErrorMsg(err error) string {
if errors.Is(err, templates.ErrInvalidAESKey) || errors.Is(err, templates.ErrAESKeyNotSet) {
return `The "policy-encryption-key" Secret contains an invalid AES key`
} else if errors.Is(err, templates.ErrInvalidIV) {
return fmt.Sprintf(`The "%s" annotation value is not a valid initialization vector`, IVAnnotation)
}

// This should never happen unless go-template-utils is updated and this doesn't account for a new error
// type that can happen with the input configuration.
return fmt.Sprintf("An unexpected error occurred when configuring the template resolver: %v", err)
}

type objectTemplateDetails struct {
kind string
name string
Expand Down Expand Up @@ -889,12 +875,10 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
r.checkRelatedAndUpdate(plc, relatedObjects, oldRelated, parentStatusUpdateNeeded, false)
}

// initialize apiresources for template processing before starting objectTemplate processing
// this is optional but since apiresourcelist is already available,
// use this rather than re-discovering the list for generic-lookup
r.lock.RLock()
tmplResolverCfg := templates.Config{KubeAPIResourceList: r.apiResourceList}
r.lock.RUnlock()
// Cache the result of a missing API resource. Note that it's not actually 10 seconds since the cache is
// cleared automatically after every ResolveTemplate call.
tmplResolverCfg := templates.Config{MissingAPIResourceCacheTTL: 10 * time.Second}
resolveOptions := templates.ResolveOptions{}

usedKeyCache := false

Expand All @@ -910,7 +894,7 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

tmplResolverCfg.EncryptionConfig = encryptionConfig
resolveOptions.EncryptionConfig = encryptionConfig
}

annotations := plc.GetAnnotations()
Expand Down Expand Up @@ -943,15 +927,10 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi

tmplResolverCfg.InputIsYAML = isRawObjTemplate

tmplResolver, err := templates.NewResolver(&r.TargetK8sClient, r.TargetK8sConfig, tmplResolverCfg)
tmplResolver, err := templates.NewResolver(r.TargetK8sConfig, tmplResolverCfg)
if err != nil {
// If the encryption key is invalid, clear the cache.
if errors.Is(err, templates.ErrInvalidAESKey) || errors.Is(err, templates.ErrAESKeyNotSet) {
r.cachedEncryptionKey = &cachedEncryptionKey{}
}

msg := getTemplateConfigErrorMsg(err)
addTemplateErrorViolation("", msg)
log.Error(err, "Failed to instantiate a template resolver")
addTemplateErrorViolation("", err.Error())

return
}
Expand Down Expand Up @@ -990,32 +969,14 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
if templates.HasTemplate(rawData, "", true) {
log.V(1).Info("Processing policy templates")

resolvedTemplate, tplErr := tmplResolver.ResolveTemplate(rawData, nil)

if errors.Is(tplErr, templates.ErrMissingAPIResource) ||
errors.Is(tplErr, templates.ErrMissingAPIResourceInvalidTemplate) {
log.V(2).Info(
"A template encountered an API resource which was not in the API resource list. Refreshing " +
"it and trying again.",
)

discoveryErr := r.refreshDiscoveryInfo()
if discoveryErr == nil {
tmplResolver.SetKubeAPIResourceList(r.apiResourceList)
resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(rawData, nil)
} else {
log.V(2).Info(
"Failed to refresh the API discovery information after a template encountered an unknown " +
"API resource type. Continuing with the assumption that the discovery information " +
"was correct.",
)
}
}
resolvedTemplate, tplErr := tmplResolver.ResolveTemplate(rawData, nil, &resolveOptions)

// If the error is because the padding is invalid, this either means the encrypted value was not
// generated by the "protect" template function or the AES key is incorrect. Control for a stale
// cached key.
if usedKeyCache && errors.Is(tplErr, templates.ErrInvalidPKCS7Padding) {
if usedKeyCache && (errors.Is(tplErr, templates.ErrInvalidPKCS7Padding) ||
errors.Is(tplErr, templates.ErrInvalidAESKey) ||
errors.Is(tplErr, templates.ErrAESKeyNotSet)) {
log.V(2).Info(
"The template decryption failed likely due to an invalid encryption key, will refresh " +
"the encryption key cache and try the decryption again",
Expand All @@ -1029,26 +990,25 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

tmplResolverCfg.EncryptionConfig = encryptionConfig
resolveOptions.EncryptionConfig = encryptionConfig

err := tmplResolver.SetEncryptionConfig(encryptionConfig)
if err != nil {
// If the encryption key is invalid, clear the cache.
if errors.Is(err, templates.ErrInvalidAESKey) || errors.Is(err, templates.ErrAESKeyNotSet) {
r.cachedEncryptionKey = &cachedEncryptionKey{}
}
resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(rawData, nil, &resolveOptions)
}

msg := getTemplateConfigErrorMsg(err)
addTemplateErrorViolation("", msg)
if tplErr != nil {
var msg string

return
if errors.Is(tplErr, templates.ErrInvalidAESKey) || errors.Is(tplErr, templates.ErrAESKeyNotSet) {
msg = `The "policy-encryption-key" Secret contains an invalid AES key`
} else if errors.Is(tplErr, templates.ErrInvalidIV) {
msg = fmt.Sprintf(
`The "%s" annotation value is not a valid initialization vector`, IVAnnotation,
)
} else {
msg = tplErr.Error()
}

resolvedTemplate, tplErr = tmplResolver.ResolveTemplate(rawData, nil)
}

if tplErr != nil {
addTemplateErrorViolation("", tplErr.Error())
addTemplateErrorViolation("", msg)

return
}
Expand Down
2 changes: 1 addition & 1 deletion controllers/encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"encoding/base64"
"fmt"

"github.com/stolostron/go-template-utils/v3/pkg/templates"
"github.com/stolostron/go-template-utils/v4/pkg/templates"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"

Expand Down
6 changes: 2 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/prometheus/client_golang v1.15.1
github.com/spf13/pflag v1.0.5
github.com/stolostron/go-log-utils v0.1.2
github.com/stolostron/go-template-utils/v3 v3.2.1
github.com/stolostron/go-template-utils/v4 v4.0.0
github.com/stretchr/testify v1.8.1
golang.org/x/mod v0.10.0
k8s.io/api v0.27.1
Expand Down Expand Up @@ -57,7 +57,6 @@ require (
github.com/google/uuid v1.3.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/jellydator/ttlcache/v3 v3.0.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand All @@ -76,7 +75,7 @@ require (
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/stolostron/kubernetes-dependency-watches v0.2.1 // indirect
github.com/stolostron/kubernetes-dependency-watches v0.5.1 // indirect
github.com/xlab/treeprint v1.1.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
go.uber.org/atomic v1.11.0 // indirect
Expand All @@ -85,7 +84,6 @@ require (
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
Expand Down
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jellydator/ttlcache/v3 v3.0.1 h1:cHgCSMS7TdQcoprXnWUptJZzyFsqs18Lt8VVhRuZYVU=
github.com/jellydator/ttlcache/v3 v3.0.1/go.mod h1:WwTaEmcXQ3MTjOm4bsZoDFiCu/hMvNWLO1w67RXz6h4=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
Expand Down Expand Up @@ -195,10 +193,10 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stolostron/go-log-utils v0.1.2 h1:7l1aJWvBqU2+DUyimcslT5SJpdygVY/clRDmX5sO29c=
github.com/stolostron/go-log-utils v0.1.2/go.mod h1:8zrB8UJmp1rXhv3Ck9bBl5SpNfKk3SApeElbo96YRtQ=
github.com/stolostron/go-template-utils/v3 v3.2.1 h1:wRiCgHG1pcRYa4ZOb/rbzP45Quh8ChNrqXjHDsSaTQg=
github.com/stolostron/go-template-utils/v3 v3.2.1/go.mod h1:D9uOV787ztGsIqh4FxZzkPfBQgy2zz9vK0cv8uDO5vM=
github.com/stolostron/kubernetes-dependency-watches v0.2.1 h1:42oLxw+wm/LxHj/3WkJOpyry6dy9Svwgm6jHCttQ6qs=
github.com/stolostron/kubernetes-dependency-watches v0.2.1/go.mod h1:u2NLFgX12/XwNJvxBpqEhfwGwx8dHWGPxzpDy5L3DIk=
github.com/stolostron/go-template-utils/v4 v4.0.0 h1:gvSfhXIoymo5Ql9MH/ofTTOtBVkaUBq8HokCGR4xkkc=
github.com/stolostron/go-template-utils/v4 v4.0.0/go.mod h1:svIOPUJpG/ObRn3WwZMBGMEMsBgKH8LVfhsaIArgAAQ=
github.com/stolostron/kubernetes-dependency-watches v0.5.1 h1:NZ9N5/VWtwKcawgg4TGI4A5+weSkLrXZMjU7w91xfvU=
github.com/stolostron/kubernetes-dependency-watches v0.5.1/go.mod h1:8vRsL1GGBw0jjCwP8CH8d30NVNYKhUy0rdBSQZ2znx8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
Expand Down Expand Up @@ -274,8 +272,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down