1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-29 19:05:27 +00:00

Finished Generate() logic to actual generating the resource

This commit is contained in:
shuting 2019-05-16 14:09:02 -07:00
parent b58e4f5026
commit e8de9a111a
7 changed files with 78 additions and 53 deletions
examples/ConfigMapGenerator-SecretGenerator
kubeclient
main.go
pkg
apis/policy/v1alpha1
engine
webhooks

View file

@ -3,42 +3,47 @@
# To apply this policy you need to create secret and configMap in "default" namespace
# and then create a namespace
apiVersion : policy.nirmata.io/v1alpha1
apiVersion : kubepolicy.nirmata.io/v1alpha1
kind : Policy
metadata :
name : "policy-ns-patch-cmg-sg"
spec :
failurePolicy: stopOnError
rules:
- resource :
- name: "patchNamespace2"
resource :
kind : Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
patch:
- path: "/metadata/labels/isMutatedByPolicy"
op: add
value: "true"
mutate:
patches:
- path: "/metadata/labels/isMutatedByPolicy"
op: add
value: "true"
- resource :
- name: "copyCM"
resource :
kind : Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
configMapGenerator :
generate :
kind: ConfigMap
name : copied-cm
copyFrom :
namespace : default
name : game-config
data :
secretData: "data from cmg"
- resource :
- name: "generateCM"
resource :
kind : Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
configMapGenerator :
generate :
kind: ConfigMap
name : generated-cm
data :
secretData: "very sensitive data from cmg"
@ -49,13 +54,12 @@ spec :
image.public.key=771
rsa.public.key=42
- resource :
- name: "generateSecret"
resource :
kind : Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
secretGenerator :
name: ns2
generate :
kind: Secret
name : generated-secrets
data :
foo : bar
@ -66,13 +70,12 @@ spec :
foo1=bar1
foo2=bar2
- resource :
- name: "copySecret"
resource :
kind : Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
secretGenerator :
name: ns2
generate :
kind: Secret
name : copied-secrets
copyFrom :
namespace : default

View file

@ -67,10 +67,12 @@ func (kc *KubeClient) GenerateConfigMap(generator types.Generation, namespace st
var err error
kc.logger.Printf("Copying data from configmap %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
configMap, err = kc.client.CoreV1().ConfigMaps(generator.CopyFrom.Namespace).Get(generator.CopyFrom.Name, metav1.GetOptions{})
if err != nil {
return err
if generator.CopyFrom != nil {
kc.logger.Printf("Copying data from configmap %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
configMap, err = kc.client.CoreV1().ConfigMaps(generator.CopyFrom.Namespace).Get(generator.CopyFrom.Name, metav1.GetOptions{})
if err != nil {
return err
}
}
configMap.ObjectMeta = metav1.ObjectMeta{
@ -101,10 +103,12 @@ func (kc *KubeClient) GenerateSecret(generator types.Generation, namespace strin
var err error
kc.logger.Printf("Copying data from secret %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
secret, err = kc.client.CoreV1().Secrets(generator.CopyFrom.Namespace).Get(generator.CopyFrom.Name, metav1.GetOptions{})
if err != nil {
return err
if generator.CopyFrom != nil {
kc.logger.Printf("Copying data from secret %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
secret, err = kc.client.CoreV1().Secrets(generator.CopyFrom.Namespace).Get(generator.CopyFrom.Name, metav1.GetOptions{})
if err != nil {
return err
}
}
secret.ObjectMeta = metav1.ObjectMeta{

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, policyInformer.Lister(), nil)
server, err := webhooks.NewWebhookServer(tlsPair, policyInformer.Lister(), kubeclient, nil)
if err != nil {
log.Fatalf("Unable to create webhook server: %v\n", err)
}

View file

@ -60,9 +60,9 @@ type Validation struct {
// Generation describes which resources will be created when other resource is created
type Generation struct {
Kind string `json:"kind"`
Name string `json:"name"`
CopyFrom `json:"copyFrom"`
Kind string `json:"kind"`
Name string `json:"name"`
CopyFrom *CopyFrom `json:"copyFrom,omitempty"`
Data map[string]string `json:"data"`
Labels map[string]string `json:"labels"`
}

View file

@ -78,7 +78,10 @@ func (pcg *Generation) Validate() error {
return errors.New("Name or/and Kind of generator is not specified")
}
return pcg.CopyFrom.Validate()
if pcg.CopyFrom != nil {
return pcg.CopyFrom.Validate()
}
return nil
}
// DeepCopyInto is declared because k8s:deepcopy-gen is

View file

@ -4,6 +4,7 @@ import (
"fmt"
"log"
kubeClient "github.com/nirmata/kube-policy/kubeclient"
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"
@ -16,14 +17,12 @@ type GenerationResponse struct {
// 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 {
func Generate(policy kubepolicy.Policy, rawResource []byte, kubeClient *kubeClient.KubeClient, gvk metav1.GroupVersionKind) {
// configMapGenerator and secretGenerator can be applied only to namespaces
if gvk.Kind != "Namespace" {
return nil
return
}
var generateResps []GenerationResponse
for i, rule := range policy.Spec.Rules {
// Checks for preconditions
@ -48,31 +47,39 @@ func Generate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVers
continue
}
generateResps, err = applyRuleGenerator(rawResource, rule.Generation)
err = applyRuleGenerator(rawResource, rule.Generation, kubeClient)
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
func applyRuleGenerator(rawResource []byte, generator *kubepolicy.Generation, kubeClient *kubeClient.KubeClient) error {
if generator == nil {
return nil, nil
return nil
}
err := generator.Validate()
if err != nil {
return nil, fmt.Errorf("Generator for '%s' is invalid: %s", generator.Kind, err)
return fmt.Errorf("Generator for '%s/%s' is invalid: %s", generator.Kind, generator.Name, err)
}
namespaceName := mutation.ParseNameFromObject(rawResource)
generateResps = append(generateResps, GenerationResponse{generator, namespaceName})
return generateResps, nil
namespace := mutation.ParseNameFromObject(rawResource)
switch generator.Kind {
case "ConfigMap":
err = kubeClient.GenerateConfigMap(*generator, namespace)
case "Secret":
err = kubeClient.GenerateSecret(*generator, namespace)
default:
err = fmt.Errorf("Unsupported config Kind '%s'", generator.Kind)
}
if err != nil {
return fmt.Errorf("Unable to apply generator for %s '%s/%s' : %v", generator.Kind, namespace, generator.Name, err)
}
log.Printf("Successfully applied generator %s/%s", generator.Kind, generator.Name)
return nil
}

View file

@ -13,6 +13,7 @@ import (
"time"
"github.com/nirmata/kube-policy/config"
kubeClient "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"
@ -27,6 +28,7 @@ import (
type WebhookServer struct {
server http.Server
policyLister policylister.PolicyLister
kubeClient *kubeClient.KubeClient
logger *log.Logger
}
@ -35,6 +37,7 @@ type WebhookServer struct {
func NewWebhookServer(
tlsPair *tlsutils.TlsPemPair,
policyLister policylister.PolicyLister,
kubeClient *kubeClient.KubeClient,
logger *log.Logger) (*WebhookServer, error) {
if logger == nil {
logger = log.New(os.Stdout, "Webhook Server: ", log.LstdFlags)
@ -53,6 +56,7 @@ func NewWebhookServer(
ws := &WebhookServer{
policyLister: policyLister,
kubeClient: kubeClient,
logger: logger,
}
@ -174,6 +178,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
allowed := true
for _, policy := range policies {
// validation
ws.logger.Printf("Validating resource with policy %s with %d rules", policy.ObjectMeta.Name, len(policy.Spec.Rules))
if ok := engine.Validate(*policy, request.Object.Raw, request.Kind); !ok {
@ -183,6 +188,9 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
} else {
ws.logger.Println("Validation is successful")
}
// generation
engine.Generate(*policy, request.Object.Raw, ws.kubeClient, request.Kind)
}
return &v1beta1.AdmissionResponse{