1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

Implement Generate()

This commit is contained in:
shuting 2019-05-14 18:20:41 -07:00
parent 5dedbd844a
commit a36bb2fbac
7 changed files with 72 additions and 126 deletions

View file

@ -59,7 +59,7 @@ func main() {
log.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err)
}
server, err := webhooks.NewWebhookServer(tlsPair, kubeclient, policyInformer.Lister(), nil)
server, err := webhooks.NewWebhookServer(tlsPair, policyInformer.Lister(), nil)
if err != nil {
log.Fatalf("Unable to create webhook server: %v\n", err)
}

View file

@ -74,8 +74,8 @@ func (pcf *CopyFrom) Validate() error {
// Validate returns error if generator is configured incompletely
func (pcg *Generation) Validate() error {
if pcg.Name == "" {
return errors.New("The generator is unnamed")
if pcg.Name == "" || pcg.Kind == "" {
return errors.New("Name or/and Kind of generator is not specified")
}
return pcg.CopyFrom.Validate()

View file

@ -12,86 +12,11 @@ import (
// the caller is responsible to apply the changes to the resource
func ProcessExisting(policy types.Policy, rawResource []byte) ([]violation.Info, []event.Info, error) {
return nil, nil, nil
var violations []violation.Info
var events []event.Info
// TODO:
// Mutate()
// Validate()
return violations, events, nil
}
// 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)
// Mutate(policy types.Policy, rawResource []byte) []mutation.PatchBytes
// // ProcessValidation should be called from admission contoller
// // when there is an creation / update of the resource
// Validate(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
// // TODO: This method should not be in PolicyEngine. Validate will do this work instead
// ProcessExisting(policy types.Policy, rawResource []byte) ([]violation.Info, []event.Info, error)
// // TODO: Add Generate method
// // Generate()
// }
// func (p *policyEngine) ProcessExisting(policy types.Policy, rawResource []byte) ([]violation.Info, []event.Info, error) {
// var violations []violation.Info
// var events []event.Info
// 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.ResourceDescription); !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)
// 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.Rule, rawResource []byte) (
// violation.Info, []event.Info, error) {
// var violationInfo violation.Info
// var eventInfos []event.Info
// resourceKind := mutation.ParseKindFromObject(rawResource)
// resourceName := mutation.ParseNameFromObject(rawResource)
// resourceNamespace := mutation.ParseNamespaceFromObject(rawResource)
// rulePatchesProcessed, err := mutation.ProcessPatches(rule.Mutation.Patches, nil)
// 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))
// violationInfo = violation.NewViolation(policyName, resourceKind, resourceNamespace+"/"+resourceName, rule.Name)
// // add a violation to queue
// // add an event to policy
// //TODO: event msg
// eventInfos = append(eventInfos, event.NewEvent("Policy", policyName, event.PolicyViolation, event.FResourcePolcy))
// // add an event to resource
// eventInfos = append(eventInfos, event.NewEvent(resourceKind, resourceNamespace+"/"+resourceName, event.PolicyViolation, event.FResourcePolcy))
// }
// return violationInfo, eventInfos, nil
// }

View file

@ -2,54 +2,77 @@ package engine
import (
"fmt"
"log"
kubepolicy "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
"github.com/nirmata/kube-policy/pkg/engine/mutation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// TODO: To be reworked due to spec policy-v2
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
func applyRuleGenerators(rawResource []byte, rule kubepolicy.Rule) error {
kind := mutation.ParseKindFromObject(rawResource)
// configMapGenerator and secretGenerator can be applied only to namespaces
if kind == "Namespace" {
namespaceName := mutation.ParseNameFromObject(rawResource)
err := applyConfigGenerator(rule.Generation, namespaceName, "ConfigMap")
if err == nil {
err = applyConfigGenerator(rule.Generation, namespaceName, "Secret")
}
return err
}
return nil
type GenerationResponse struct {
Generator *kubepolicy.Generation
Namespace string
}
// Creates resourceKind (ConfigMap or Secret) with parameters specified in generator in cluster specified in request.
func applyConfigGenerator(generator *kubepolicy.Generation, namespace string, configKind string) error {
if generator == nil {
// Generate should be called to process generate rules on the resource
// TODO: extend kubeclient(will change to dynamic client) to create resources
func Generate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) []GenerationResponse {
// configMapGenerator and secretGenerator can be applied only to namespaces
if gvk.Kind != "Namespace" {
return nil
}
var generateResps []GenerationResponse
for i, rule := range policy.Spec.Rules {
// Checks for preconditions
// TODO: Rework PolicyEngine interface that it receives not a policy, but mutation object for
// Mutate, validation for Validate and so on. It will allow to bring this checks outside of PolicyEngine
// to common part as far as they present for all: mutation, validation, generation
err := rule.Validate()
if err != nil {
log.Printf("Rule has invalid structure: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
continue
}
ok, err := mutation.ResourceMeetsRules(rawResource, rule.ResourceDescription, gvk)
if err != nil {
log.Printf("Rule has invalid data: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
continue
}
if !ok {
log.Printf("Rule is not applicable to the request: rule name = %s in policy %s \n", rule.Name, policy.ObjectMeta.Name)
continue
}
generateResps, err = applyRuleGenerator(rawResource, rule.Generation)
if err != nil {
log.Printf("Failed to apply rule generator: %v", err)
} else {
generateResps = append(generateResps, generateResps...)
}
}
return generateResps
}
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
// TODO: plan to support all kinds of generator
func applyRuleGenerator(rawResource []byte, generator *kubepolicy.Generation) ([]GenerationResponse, error) {
var generateResps []GenerationResponse
if generator == nil {
return nil, nil
}
err := generator.Validate()
if err != nil {
return fmt.Errorf("Generator for '%s' is invalid: %s", configKind, err)
return nil, fmt.Errorf("Generator for '%s' is invalid: %s", generator.Kind, err)
}
// TODO:
switch configKind {
case "ConfigMap":
// err = p.kubeClient.GenerateConfigMap(*generator, namespace)
case "Secret":
// err = p.kubeClient.GenerateSecret(*generator, namespace)
default:
err = fmt.Errorf("Unsupported config Kind '%s'", configKind)
}
if err != nil {
return fmt.Errorf("Unable to apply generator for %s '%s/%s' : %s", configKind, namespace, generator.Name, err)
}
return nil
namespaceName := mutation.ParseNameFromObject(rawResource)
generateResps = append(generateResps, GenerationResponse{generator, namespaceName})
return generateResps, nil
}

View file

@ -9,7 +9,7 @@ import (
)
// Mutate performs mutation. Overlay first and then mutation patches
// TODO: pass in logger?
// TODO: return events and violations
func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) []mutation.PatchBytes {
var policyPatches []mutation.PatchBytes
@ -33,7 +33,7 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
}
if !ok {
log.Printf("Rule is not applicable t the request: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
log.Printf("Rule is not applicable to the request: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
continue
}

View file

@ -35,7 +35,7 @@ func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVers
}
if !ok {
log.Printf("Rule is not applicable t the request: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
log.Printf("Rule is not applicable to the request: rule number = %d, rule name = %s in policy %s, err: %v\n", i, rule.Name, policy.ObjectMeta.Name, err)
continue
}

View file

@ -13,7 +13,6 @@ import (
"time"
"github.com/nirmata/kube-policy/config"
"github.com/nirmata/kube-policy/kubeclient"
policylister "github.com/nirmata/kube-policy/pkg/client/listers/policy/v1alpha1"
engine "github.com/nirmata/kube-policy/pkg/engine"
"github.com/nirmata/kube-policy/pkg/engine/mutation"
@ -35,7 +34,6 @@ type WebhookServer struct {
// Policy Controller and Kubernetes Client should be initialized in configuration
func NewWebhookServer(
tlsPair *tlsutils.TlsPemPair,
kubeClient *kubeclient.KubeClient,
policyLister policylister.PolicyLister,
logger *log.Logger) (*WebhookServer, error) {
if logger == nil {