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

Added set flag

This commit is contained in:
NoSkillGirl 2020-08-05 23:53:27 +05:30
parent 1b7a295860
commit afe98bb93c
7 changed files with 62 additions and 35 deletions

View file

@ -278,7 +278,7 @@ func main() {
// Sync openAPI definitions of resources // Sync openAPI definitions of resources
openAPISync := openapi.NewCRDSync(client, openAPIController) openAPISync := openapi.NewCRDSync(client, openAPIController)
supportMudateValidate := utils.HigherThanKubernetesVersion(client, log.Log, 1, 14, 0) supportMutateValidate := utils.HigherThanKubernetesVersion(client, log.Log, 1, 14, 0)
// WEBHOOK // WEBHOOK
// - https server to provide endpoints called based on rules defined in Mutating & Validation webhook configuration // - https server to provide endpoints called based on rules defined in Mutating & Validation webhook configuration
@ -304,7 +304,7 @@ func main() {
grgen, grgen,
rWebhookWatcher, rWebhookWatcher,
auditHandler, auditHandler,
supportMudateValidate, supportMutateValidate,
cleanUp, cleanUp,
log.Log.WithName("WebhookServer"), log.Log.WithName("WebhookServer"),
openAPIController, openAPIController,

View file

@ -5,8 +5,12 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"github.com/nirmata/kyverno/pkg/engine/context"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
@ -50,7 +54,8 @@ func Command() *cobra.Command {
var cmd *cobra.Command var cmd *cobra.Command
var resourcePaths []string var resourcePaths []string
var cluster bool var cluster bool
var mutateLogPath string var mutatelogPath, variablesString string
variables := make(map[string]string)
kubernetesConfig := genericclioptions.NewConfigFlags(true) kubernetesConfig := genericclioptions.NewConfigFlags(true)
@ -63,11 +68,17 @@ func Command() *cobra.Command {
if err != nil { if err != nil {
if !sanitizedError.IsErrorSanitized(err) { if !sanitizedError.IsErrorSanitized(err) {
log.Log.Error(err, "failed to sanitize") log.Log.Error(err, "failed to sanitize")
err = fmt.Errorf("Internal error") err = fmt.Errorf("internal error")
} }
} }
}() }()
kvpairs := strings.Split(strings.Trim(variablesString, " "), ",")
for _, kvpair := range kvpairs {
kvs := strings.Split(strings.Trim(kvpair, " "), "=")
variables[strings.Trim(kvs[0], " ")] = strings.Trim(kvs[1], " ")
}
if len(resourcePaths) == 0 && !cluster { if len(resourcePaths) == 0 && !cluster {
return sanitizedError.NewWithError(fmt.Sprintf("resource file(s) or cluster required"), err) return sanitizedError.NewWithError(fmt.Sprintf("resource file(s) or cluster required"), err)
} }
@ -150,7 +161,7 @@ func Command() *cobra.Command {
} }
for _, resource := range resources { for _, resource := range resources {
applyPolicyOnResource(policy, resource, rc) err = applyPolicyOnResource(policy, resource, mutatelogPath, mutatelogPathIsDir, variables, rc)
if err != nil { if err != nil {
return sanitizedError.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err) return sanitizedError.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err)
} }
@ -170,7 +181,8 @@ func Command() *cobra.Command {
cmd.Flags().StringArrayVarP(&resourcePaths, "resource", "r", []string{}, "Path to resource files") cmd.Flags().StringArrayVarP(&resourcePaths, "resource", "r", []string{}, "Path to resource files")
cmd.Flags().BoolVarP(&cluster, "cluster", "c", false, "Checks if policies should be applied to cluster in the current context") cmd.Flags().BoolVarP(&cluster, "cluster", "c", false, "Checks if policies should be applied to cluster in the current context")
cmd.Flags().StringVarP(&mutateLogPath, "output", "o", "", "Prints the mutated resources in provided file/directory") cmd.Flags().StringVarP(&mutatelogPath, "output", "o", "", "Prints the mutated resources in provided file/directory")
cmd.Flags().StringVarP(&variablesString, "set", "s", "", "Variables that are required")
return cmd return cmd
} }
@ -300,13 +312,29 @@ func getResource(path string) ([]*unstructured.Unstructured, error) {
} }
// applyPolicyOnResource - function to apply policy on resource // applyPolicyOnResource - function to apply policy on resource
func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured, rc *resultCounts) { func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured, mutatelogPath string, mutatelogPathIsDir bool, variables map[string]string, rc *resultCounts) error {
responseError := false responseError := false
resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName()) resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
log.Log.V(3).Info("applying policy on resource", "policy", policy.Name, "resource", resPath) log.Log.V(3).Info("applying policy on resource", "policy", policy.Name, "resource", resPath)
mutateResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource}) // build context
ctx := context.NewContext()
for key, value := range variables {
startString := ""
endString := ""
for _, k := range strings.Split(key, ".") {
startString += fmt.Sprintf(`{"%s":`, k)
endString += `}`
}
midString := fmt.Sprintf(`"%s"`, value)
finalString := startString + midString + endString
var jsonData = []byte(finalString)
ctx.AddJSON(jsonData)
}
mutateResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource, Context: ctx})
if !mutateResponse.IsSuccessful() { if !mutateResponse.IsSuccessful() {
fmt.Printf("Failed to apply mutate policy %s -> resource %s", policy.Name, resPath) fmt.Printf("Failed to apply mutate policy %s -> resource %s", policy.Name, resPath)
for i, r := range mutateResponse.PolicyResponse.Rules { for i, r := range mutateResponse.PolicyResponse.Rules {
@ -329,7 +357,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
} }
} }
validateResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource}) validateResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource, Context: ctx})
if !validateResponse.IsSuccessful() { if !validateResponse.IsSuccessful() {
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath) fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
for i, r := range validateResponse.PolicyResponse.Rules { for i, r := range validateResponse.PolicyResponse.Rules {

View file

@ -9,7 +9,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
jsonpatch "github.com/evanphx/json-patch" jsonpatch "github.com/evanphx/json-patch"
"github.com/go-logr/logr" "github.com/go-logr/logr"
@ -69,10 +68,10 @@ func GetPolicies(paths []string) (policies []*v1.ClusterPolicy, error error) {
} }
} }
for i := range policies { // for i := range policies {
setFalse := false // setFalse := false
policies[i].Spec.Background = &setFalse // policies[i].Spec.Background = &setFalse
} // }
return policies, nil return policies, nil
} }
@ -152,11 +151,11 @@ func GetPoliciesValidation(policyPaths []string) ([]*v1.ClusterPolicy, *openapi.
} }
// PolicyHasVariables - check for variables in policy // PolicyHasVariables - check for variables in policy
func PolicyHasVariables(policy v1.ClusterPolicy) bool { // func PolicyHasVariables(policy v1.ClusterPolicy) bool {
policyRaw, _ := json.Marshal(policy) // policyRaw, _ := json.Marshal(policy)
regex := regexp.MustCompile(`\{\{([^{}]*)\}\}`) // regex := regexp.MustCompile(`\{\{([^{}]*)\}\}`)
return len(regex.FindAllStringSubmatch(string(policyRaw), -1)) > 0 // return len(regex.FindAllStringSubmatch(string(policyRaw), -1)) > 0
} // }
// MutatePolicy - applies mutation to a policy // MutatePolicy - applies mutation to a policy
func MutatePolicy(policy *v1.ClusterPolicy, logger logr.Logger) (*v1.ClusterPolicy, error) { func MutatePolicy(policy *v1.ClusterPolicy, logger logr.Logger) (*v1.ClusterPolicy, error) {

View file

@ -49,12 +49,12 @@ func Command() *cobra.Command {
invalidPolicyFound := false invalidPolicyFound := false
for _, policy := range policies { for _, policy := range policies {
if common.PolicyHasVariables(*policy) { // if common.PolicyHasVariables(*policy) {
invalidPolicyFound = true // invalidPolicyFound = true
fmt.Printf("Policy %s is invalid.\n", policy.Name) // fmt.Printf("Policy %s is invalid.\n", policy.Name)
log.Log.Error(errors.New("'validate' does not support policies with variables"), "Policy "+policy.Name+" is invalid") // log.Log.Error(errors.New("'validate' does not support policies with variables"), "Policy "+policy.Name+" is invalid")
continue // continue
} // }
err := policy2.Validate(utils.MarshalPolicy(*policy), nil, true, openAPIController) err := policy2.Validate(utils.MarshalPolicy(*policy), nil, true, openAPIController)
if err != nil { if err != nil {
fmt.Printf("Policy %s is invalid.\n", policy.Name) fmt.Printf("Policy %s is invalid.\n", policy.Name)

View file

@ -79,7 +79,7 @@ func defaultvalidationFailureAction(policy *kyverno.ClusterPolicy, log logr.Logg
// set ValidationFailureAction to "audit" if not specified // set ValidationFailureAction to "audit" if not specified
Audit := common.Audit Audit := common.Audit
if policy.Spec.ValidationFailureAction == "" { if policy.Spec.ValidationFailureAction == "" {
log.V(4).Info("setting defautl value", "spec.validationFailureAction", Audit) log.V(4).Info("setting default value", "spec.validationFailureAction", Audit)
jsonPatch := struct { jsonPatch := struct {
Path string `json:"path"` Path string `json:"path"`

View file

@ -18,7 +18,7 @@ func (ws *WebhookServer) policyMutation(request *v1beta1.AdmissionRequest) *v1be
//TODO: can this happen? wont this be picked by OpenAPI spec schema ? //TODO: can this happen? wont this be picked by OpenAPI spec schema ?
if err := json.Unmarshal(raw, &policy); err != nil { if err := json.Unmarshal(raw, &policy); err != nil {
logger.Error(err, "faield to unmarshall policy admission request") logger.Error(err, "failed to unmarshall policy admission request")
return &v1beta1.AdmissionResponse{ return &v1beta1.AdmissionResponse{
Allowed: true, Allowed: true,
Result: &metav1.Status{ Result: &metav1.Status{

View file

@ -110,7 +110,7 @@ type WebhookServer struct {
log logr.Logger log logr.Logger
openAPIController *openapi.Controller openAPIController *openapi.Controller
supportMudateValidate bool supportMutateValidate bool
} }
// NewWebhookServer creates new instance of WebhookServer accordingly to given configuration // NewWebhookServer creates new instance of WebhookServer accordingly to given configuration
@ -133,7 +133,7 @@ func NewWebhookServer(
grGenerator *generate.Generator, grGenerator *generate.Generator,
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister, resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister,
auditHandler AuditHandler, auditHandler AuditHandler,
supportMudateValidate bool, supportMutateValidate bool,
cleanUp chan<- struct{}, cleanUp chan<- struct{},
log logr.Logger, log logr.Logger,
openAPIController *openapi.Controller, openAPIController *openapi.Controller,
@ -177,11 +177,11 @@ func NewWebhookServer(
auditHandler: auditHandler, auditHandler: auditHandler,
log: log, log: log,
openAPIController: openAPIController, openAPIController: openAPIController,
supportMudateValidate: supportMudateValidate, supportMutateValidate: supportMutateValidate,
} }
mux := httprouter.New() mux := httprouter.New()
mux.HandlerFunc("POST", config.MutatingWebhookServicePath, ws.handlerFunc(ws.resourceMutation, true)) mux.HandlerFunc("POST", config.MutatingWebhookServicePath, ws.handlerFunc(ws.ResourceMutation, true))
mux.HandlerFunc("POST", config.ValidatingWebhookServicePath, ws.handlerFunc(ws.resourceValidation, true)) mux.HandlerFunc("POST", config.ValidatingWebhookServicePath, ws.handlerFunc(ws.resourceValidation, true))
mux.HandlerFunc("POST", config.PolicyMutatingWebhookServicePath, ws.handlerFunc(ws.policyMutation, true)) mux.HandlerFunc("POST", config.PolicyMutatingWebhookServicePath, ws.handlerFunc(ws.policyMutation, true))
mux.HandlerFunc("POST", config.PolicyValidatingWebhookServicePath, ws.handlerFunc(ws.policyValidation, true)) mux.HandlerFunc("POST", config.PolicyValidatingWebhookServicePath, ws.handlerFunc(ws.policyValidation, true))
@ -260,9 +260,9 @@ func writeResponse(rw http.ResponseWriter, admissionReview *v1beta1.AdmissionRev
} }
} }
func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
logger := ws.log.WithName("resourceMutation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) logger := ws.log.WithName("ResourceMutation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
if excludeKyvernoResources(request.Kind.Kind) { if excludeKyvernoResources(request.Kind.Kind) {
return &v1beta1.AdmissionResponse{ return &v1beta1.AdmissionResponse{
@ -329,7 +329,7 @@ func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1
var patches []byte var patches []byte
patchedResource := request.Object.Raw patchedResource := request.Object.Raw
if ws.supportMudateValidate { if ws.supportMutateValidate {
// MUTATION // MUTATION
// mutation failure should not block the resource creation // mutation failure should not block the resource creation
// any mutation failure is reported as the violation // any mutation failure is reported as the violation
@ -398,7 +398,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
} }
} }
if !ws.supportMudateValidate { if !ws.supportMutateValidate {
logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0") logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0")
return &v1beta1.AdmissionResponse{ return &v1beta1.AdmissionResponse{
Allowed: true, Allowed: true,