Skip to content

Commit

Permalink
Update to go-template-utils v4.0.0
Browse files Browse the repository at this point in the history
This adds additional Sprig functions as well as a temporary cache to
prevent duplicate API queries in a single ResolveTemplate call.

Relates:
https://issues.redhat.com/browse/ACM-7652
https://issues.redhat.com/browse/ACM-7398

Signed-off-by: mprahl <mprahl@users.noreply.github.com>
  • Loading branch information
mprahl authored and openshift-ci[bot] committed Oct 18, 2023
1 parent 8d561ad commit 4fc8c53
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 80 deletions.
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 @@ -885,12 +871,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 @@ -906,7 +890,7 @@ func (r *ConfigurationPolicyReconciler) handleObjectTemplates(plc policyv1.Confi
return
}

tmplResolverCfg.EncryptionConfig = encryptionConfig
resolveOptions.EncryptionConfig = encryptionConfig
}

annotations := plc.GetAnnotations()
Expand Down Expand Up @@ -939,15 +923,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 @@ -986,32 +965,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 @@ -1025,26 +986,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 @@ -275,8 +273,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

0 comments on commit 4fc8c53

Please sign in to comment.