2019-05-09 22:26:22 -07:00
|
|
|
package policyengine
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
kubeClient "github.com/nirmata/kube-policy/kubeclient"
|
|
|
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
2019-05-10 12:36:55 -07:00
|
|
|
event "github.com/nirmata/kube-policy/pkg/event"
|
2019-05-09 22:26:22 -07:00
|
|
|
"github.com/nirmata/kube-policy/pkg/policyengine/mutation"
|
2019-05-10 12:36:55 -07:00
|
|
|
policyviolation "github.com/nirmata/kube-policy/pkg/policyviolation"
|
2019-05-09 22:26:22 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
type PolicyEngine interface {
|
|
|
|
// ProcessMutation should be called from admission contoller
|
|
|
|
// when there is an creation / update of the resource
|
|
|
|
// ProcessMutation(policy types.Policy, rawResource []byte) (patchBytes []byte, events []Events, err error)
|
|
|
|
ProcessMutation(policy types.Policy, rawResource []byte) ([]mutation.PatchBytes, error)
|
|
|
|
|
|
|
|
// ProcessValidation should be called from admission contoller
|
|
|
|
// when there is an creation / update of the resource
|
|
|
|
ProcessValidation(policy types.Policy, rawResource []byte)
|
|
|
|
|
|
|
|
// ProcessExisting should be called from policy controller
|
|
|
|
// when there is an create / update of the policy
|
|
|
|
// we should process the policy on matched resources, generate violations accordingly
|
2019-05-10 12:36:55 -07:00
|
|
|
ProcessExisting(policy types.Policy, rawResource []byte) ([]policyviolation.Info, []event.Info, error)
|
2019-05-09 22:26:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
type policyEngine struct {
|
|
|
|
kubeClient *kubeClient.KubeClient
|
2019-05-10 12:36:55 -07:00
|
|
|
logger *log.Logger
|
2019-05-09 22:26:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewPolicyEngine(kubeClient *kubeClient.KubeClient, logger *log.Logger) PolicyEngine {
|
|
|
|
return &policyEngine{
|
|
|
|
kubeClient: kubeClient,
|
|
|
|
logger: logger,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-10 12:36:55 -07:00
|
|
|
func (p *policyEngine) ProcessExisting(policy types.Policy, rawResource []byte) ([]policyviolation.Info, []event.Info, error) {
|
|
|
|
var violations []policyviolation.Info
|
|
|
|
var events []event.Info
|
2019-05-09 22:26:22 -07:00
|
|
|
|
|
|
|
patchingSets := mutation.GetPolicyPatchingSets(policy)
|
|
|
|
|
|
|
|
for _, rule := range policy.Spec.Rules {
|
|
|
|
err := rule.Validate()
|
|
|
|
if err != nil {
|
|
|
|
p.logger.Printf("Invalid rule detected: #%s in policy %s, err: %v\n", rule.Name, policy.ObjectMeta.Name, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if ok, err := mutation.IsRuleApplicableToResource(rawResource, rule.Resource); !ok {
|
|
|
|
p.logger.Printf("Rule %s of policy %s is not applicable to the request", rule.Name, policy.Name)
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
violation, eventInfos, err := p.processRuleOnResource(policy.Name, rule, rawResource, patchingSets)
|
|
|
|
if err != nil {
|
|
|
|
p.logger.Printf("Failed to process rule %s, err: %v\n", rule.Name, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// } else {
|
|
|
|
// policyPatches = append(policyPatches, processedPatches...)
|
|
|
|
// }
|
|
|
|
violations = append(violations, violation)
|
|
|
|
events = append(events, eventInfos...)
|
|
|
|
}
|
|
|
|
return violations, events, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *policyEngine) processRuleOnResource(policyName string, rule types.PolicyRule, rawResource []byte, patchingSets mutation.PatchingSets) (
|
2019-05-10 12:36:55 -07:00
|
|
|
policyviolation.Info, []event.Info, error) {
|
2019-05-09 22:26:22 -07:00
|
|
|
|
2019-05-10 12:36:55 -07:00
|
|
|
var violationInfo policyviolation.Info
|
|
|
|
var eventInfos []event.Info
|
2019-05-09 22:26:22 -07:00
|
|
|
|
|
|
|
resourceKind := mutation.ParseKindFromObject(rawResource)
|
|
|
|
resourceName := mutation.ParseNameFromObject(rawResource)
|
|
|
|
resourceNamespace := mutation.ParseNamespaceFromObject(rawResource)
|
|
|
|
|
|
|
|
rulePatchesProcessed, err := mutation.ProcessPatches(rule.Patches, nil, patchingSets)
|
|
|
|
if err != nil {
|
|
|
|
return violationInfo, eventInfos, fmt.Errorf("Failed to process patches from rule %s: %v", rule.Name, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if rulePatchesProcessed != nil {
|
|
|
|
log.Printf("Rule %s: prepared %d patches", rule.Name, len(rulePatchesProcessed))
|
|
|
|
|
2019-05-10 12:36:55 -07:00
|
|
|
violationInfo = policyviolation.NewViolation(policyName, resourceKind, resourceNamespace+"/"+resourceName, rule.Name)
|
2019-05-09 22:26:22 -07:00
|
|
|
// add a violation to queue
|
|
|
|
|
|
|
|
// add an event to policy
|
2019-05-10 12:36:55 -07:00
|
|
|
//TODO: event msg
|
|
|
|
eventInfos = append(eventInfos, event.NewEvent("Policy", policyName, event.PolicyViolation, event.FResourcePolcy))
|
2019-05-09 22:26:22 -07:00
|
|
|
// add an event to resource
|
2019-05-10 12:36:55 -07:00
|
|
|
eventInfos = append(eventInfos, event.NewEvent(resourceKind, resourceNamespace+"/"+resourceName, event.PolicyViolation, event.FResourcePolcy))
|
2019-05-09 22:26:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return violationInfo, eventInfos, nil
|
|
|
|
}
|