1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00
kyverno/pkg/engine/exceptions.go
Charles-Edouard Brétéché 784ca07419
refactor: engine rule response creation (#6784)
* refactor: engine rule response creation

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* private fields

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more private

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix unit tests

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2023-04-05 10:35:38 +00:00

96 lines
2.9 KiB
Go

package engine
import (
"fmt"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
"github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
matched "github.com/kyverno/kyverno/pkg/utils/match"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
func findExceptions(
selector engineapi.PolicyExceptionSelector,
policy kyvernov1.PolicyInterface,
rule string,
) ([]*kyvernov2alpha1.PolicyException, error) {
if selector == nil {
return nil, nil
}
polexs, err := selector.List(labels.Everything())
if err != nil {
return nil, err
}
var result []*kyvernov2alpha1.PolicyException
policyName, err := cache.MetaNamespaceKeyFunc(policy)
if err != nil {
return nil, fmt.Errorf("failed to compute policy key: %w", err)
}
for _, polex := range polexs {
if polex.Contains(policyName, rule) {
result = append(result, polex)
}
}
return result, nil
}
// matchesException checks if an exception applies to the resource being admitted
func matchesException(
selector engineapi.PolicyExceptionSelector,
policyContext engineapi.PolicyContext,
rule kyvernov1.Rule,
cfg config.Configuration,
) (*kyvernov2alpha1.PolicyException, error) {
candidates, err := findExceptions(selector, policyContext.Policy(), rule.Name)
if err != nil {
return nil, err
}
gvk, subresource := policyContext.ResourceKind()
for _, candidate := range candidates {
err := matched.CheckMatchesResources(
policyContext.NewResource(),
candidate.Spec.Match,
policyContext.NamespaceLabels(),
policyContext.AdmissionInfo(),
cfg.GetExcludedGroups(),
gvk,
subresource,
)
// if there's no error it means a match
if err == nil {
return candidate, nil
}
}
return nil, nil
}
// hasPolicyExceptions returns nil when there are no matching exceptions.
// A rule response is returned when an exception is matched, or there is an error.
func (e *engine) hasPolicyExceptions(
logger logr.Logger,
ruleType engineapi.RuleType,
ctx engineapi.PolicyContext,
rule kyvernov1.Rule,
) *engineapi.RuleResponse {
// if matches, check if there is a corresponding policy exception
exception, err := matchesException(e.exceptionSelector, ctx, rule, e.configuration)
if err != nil {
logger.Error(err, "failed to match exceptions")
return nil
}
if exception == nil {
return nil
}
key, err := cache.MetaNamespaceKeyFunc(exception)
if err != nil {
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
return engineapi.RuleError(rule.Name, ruleType, "failed to compute exception key", err)
} else {
logger.V(3).Info("policy rule skipped due to policy exception", "exception", key)
return engineapi.RuleSkip(rule.Name, ruleType, "rule skipped due to policy exception "+key).WithException(exception)
}
}