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:
parent
1b7a295860
commit
afe98bb93c
7 changed files with 62 additions and 35 deletions
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"`
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue