-
Notifications
You must be signed in to change notification settings - Fork 25
/
validator.go
92 lines (83 loc) · 2.75 KB
/
validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package controlplane
import (
"context"
"errors"
policiesv1 "github.com/fluxninja/aperture/api/gen/proto/go/aperture/policy/language/v1"
policysyncv1 "github.com/fluxninja/aperture/api/gen/proto/go/aperture/policy/sync/v1"
"github.com/fluxninja/aperture/pkg/config"
"github.com/fluxninja/aperture/pkg/log"
"github.com/fluxninja/aperture/pkg/policies/dataplane/resources/classifier/compiler"
"github.com/fluxninja/aperture/pkg/status"
"github.com/fluxninja/aperture/pkg/webhooks/policyvalidator"
"go.uber.org/fx"
)
// FxOut is the output of the controlplane module.
type FxOut struct {
fx.Out
Validator policyvalidator.PolicySpecValidator `group:"policy-validators"`
}
// providePolicyValidator provides classification Policy Custom Resource validator
//
// Note: This validator must be registered to be accessible.
func providePolicyValidator() FxOut {
return FxOut{
Validator: &PolicySpecValidator{},
}
}
// PolicySpecValidator Policy implementation of PolicySpecValidator interface.
type PolicySpecValidator struct{}
// ValidateSpec checks the validity of a Policy spec
//
// returns:
// * true, "", nil when Policy is valid
// * false, message, nil when Policy is invalid
// and
// * false, "", err on other errors.
//
// ValidateSpec checks the syntax, validity of extractors, and validity of
// rego modules (by attempting to compile them).
func (v *PolicySpecValidator) ValidateSpec(
ctx context.Context,
name string,
yamlSrc []byte,
) (bool, string, error) {
_, valid, msg, err := ValidateAndCompile(ctx, name, yamlSrc)
return valid, msg, err
}
// ValidateAndCompile checks the validity of a single Policy and compiles it.
func ValidateAndCompile(ctx context.Context, name string, yamlSrc []byte) (CompiledCircuit, bool, string, error) {
if len(yamlSrc) == 0 {
return nil, false, "Empty yaml", nil
}
policy := &policiesv1.Policy{}
err := config.UnmarshalYAML(yamlSrc, policy)
if err != nil {
return nil, false, err.Error(), nil
}
registry := status.NewRegistry(log.GetGlobalLogger())
circuit, err := CompilePolicy(policy, registry)
if err != nil {
return nil, false, err.Error(), err
}
if policy.GetResources() != nil {
for _, c := range policy.GetResources().Classifiers {
_, err = compiler.CompileRuleset(ctx, name, &policysyncv1.ClassifierWrapper{
Classifier: c,
CommonAttributes: &policysyncv1.CommonAttributes{
PolicyName: "dummy",
PolicyHash: "dummy",
ComponentIndex: 0,
},
})
if err != nil {
if errors.Is(err, compiler.BadExtractor) || errors.Is(err, compiler.BadSelector) ||
errors.Is(err, compiler.BadRego) || errors.Is(err, compiler.BadLabelName) {
return nil, false, err.Error(), nil
} else {
return nil, false, err.Error(), err
}
}
}
}
return circuit, true, "", nil
}