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

extended cli

This commit is contained in:
shravan 2020-01-17 00:05:15 +05:30
parent 8bba25bc7c
commit 79999c4948
19 changed files with 417 additions and 454 deletions

View file

@ -12,7 +12,6 @@ REGISTRY=index.docker.io
REPO=$(REGISTRY)/nirmata/kyverno
IMAGE_TAG=$(GIT_VERSION)
GOOS ?= $(shell go env GOOS)
PACKAGE ?=github.com/nirmata/kyverno
LD_FLAGS="-s -w -X $(PACKAGE)/pkg/version.BuildVersion=$(GIT_VERSION) -X $(PACKAGE)/pkg/version.BuildHash=$(GIT_HASH) -X $(PACKAGE)/pkg/version.BuildTime=$(TIMESTAMP)"
##################################

9
cmd/cli/kyverno/main.go Normal file
View file

@ -0,0 +1,9 @@
package main
import (
"github.com/nirmata/kyverno/pkg/kyverno"
)
func main() {
kyverno.CLI()
}

View file

@ -1,25 +0,0 @@
package main
import (
goflag "flag"
"fmt"
"os"
"github.com/nirmata/kyverno/pkg/config"
kyverno "github.com/nirmata/kyverno/pkg/kyverno"
flag "github.com/spf13/pflag"
)
func main() {
cmd := kyverno.NewDefaultKyvernoCommand()
if err := cmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
func init() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
config.LogDefaultFlags()
flag.Parse()
}

View file

@ -520,10 +520,10 @@ spec:
serviceAccountName: kyverno-service-account
initContainers:
- name: kyverno-pre
image: nirmata/kyvernopre:v1.1.1
image: nirmata/kyvernopre:v1.1.0
containers:
- name: kyverno
image: nirmata/kyverno:v1.1.1
image: nirmata/kyverno:v1.1.0
args:
- "--filterK8Resources=[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][*,kyverno,*]"
# customize webhook timout

View file

@ -83,6 +83,6 @@ func CreateClientConfig(kubeconfig string) (*rest.Config, error) {
glog.Info("Using in-cluster configuration")
return rest.InClusterConfig()
}
glog.Infof("Using configuration from '%s'", kubeconfig)
glog.V(4).Infof("Using configuration from '%s'", kubeconfig)
return clientcmd.BuildConfigFromFlags("", kubeconfig)
}

View file

@ -387,11 +387,11 @@ func preparePath(path string) string {
}
annPath := "/metadata/annotations/"
idx := strings.Index(path, annPath)
// escape slash in annotation patch
if strings.Contains(path, annPath) {
idx := strings.Index(path, annPath)
p := path[idx+len(annPath):]
path = path[:idx+len(annPath)] + strings.ReplaceAll(p, "/", "~1")
path = annPath + strings.ReplaceAll(p, "/", "~1")
}
return path
}

View file

@ -105,7 +105,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
continue
}
glog.Infof("Mutate overlay in rule '%s' successfully applied on %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName())
glog.V(4).Infof("Mutate overlay in rule '%s' successfully applied on %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName())
}
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
@ -156,7 +156,7 @@ var podTemplateRule = kyverno.Rule{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
"+(pod-policies.kyverno.io/autogen-applied)": "true",
"pod-policies.kyverno.io/autogen-applied": "true",
},
},
},

View file

@ -25,12 +25,11 @@ func (ri RuleType) String() string {
}
// ApplyPatches patches given resource with given patches and returns patched document
// return origin resource if any error occurs
func ApplyPatches(resource []byte, patches [][]byte) ([]byte, error) {
joinedPatches := JoinPatches(patches)
patch, err := jsonpatch.DecodePatch(joinedPatches)
if err != nil {
return resource, err
return nil, err
}
patchedDocument, err := patch.Apply(resource)

View file

@ -1,251 +0,0 @@
package apply
import (
"bytes"
"encoding/json"
"fmt"
"io"
"os"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/nirmata/kyverno/pkg/engine"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
yaml "k8s.io/apimachinery/pkg/util/yaml"
memory "k8s.io/client-go/discovery/cached/memory"
dynamic "k8s.io/client-go/dynamic"
kubernetes "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/restmapper"
)
const (
applyExample = ` # Apply a policy to the resource.
kyverno apply @policy.yaml @resource.yaml
kyverno apply @policy.yaml @resourceDir/
kyverno apply @policy.yaml @resource.yaml --kubeconfig=$PATH_TO_KUBECONFIG_FILE`
defaultYamlSeparator = "---"
)
// NewCmdApply returns the apply command for kyverno
func NewCmdApply(in io.Reader, out, errout io.Writer) *cobra.Command {
var kubeconfig string
cmd := &cobra.Command{
Use: "apply",
Short: "Apply policy on the resource(s)",
Example: applyExample,
Run: func(cmd *cobra.Command, args []string) {
policy, resources := complete(kubeconfig, args)
output := applyPolicy(policy, resources)
fmt.Printf("%v\n", output)
},
}
cmd.Flags().StringVar(&kubeconfig, "kubeconfig", "", "path to kubeconfig file")
return cmd
}
func complete(kubeconfig string, args []string) (*kyverno.ClusterPolicy, []*resourceInfo) {
policyDir, resourceDir, err := validateDir(args)
if err != nil {
glog.Errorf("Failed to parse file path, err: %v\n", err)
os.Exit(1)
}
// extract policy
policy, err := extractPolicy(policyDir)
if err != nil {
glog.Errorf("Failed to extract policy: %v\n", err)
os.Exit(1)
}
// extract rawResource
resources, err := extractResource(resourceDir, kubeconfig)
if err != nil {
glog.Errorf("Failed to parse resource: %v", err)
os.Exit(1)
}
return policy, resources
}
func applyPolicy(policy *kyverno.ClusterPolicy, resources []*resourceInfo) (output string) {
for _, resource := range resources {
patchedDocument, err := applyPolicyOnRaw(policy, resource.rawResource, resource.gvk)
if err != nil {
glog.Errorf("Error applying policy on resource %s, err: %v\n", resource.gvk.Kind, err)
continue
}
out, err := prettyPrint(patchedDocument)
if err != nil {
glog.Errorf("JSON parse error: %v\n", err)
continue
}
output = output + fmt.Sprintf("---\n%s", string(out))
}
return
}
func applyPolicyOnRaw(policy *kyverno.ClusterPolicy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]byte, error) {
patchedResource := rawResource
var err error
rname := engine.ParseNameFromObject(rawResource)
rns := engine.ParseNamespaceFromObject(rawResource)
resource, err := ConvertToUnstructured(rawResource)
if err != nil {
return nil, err
}
//TODO check if the kind information is present resource
// Process Mutation
engineResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
if !engineResponse.IsSuccesful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)
for _, r := range engineResponse.PolicyResponse.Rules {
glog.Warning(r.Message)
}
} else if len(engineResponse.PolicyResponse.Rules) > 0 {
glog.Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, gvk.Kind, rname, rns)
// Process Validation
engineResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
if !engineResponse.IsSuccesful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)
for _, r := range engineResponse.PolicyResponse.Rules {
glog.Warning(r.Message)
}
return patchedResource, fmt.Errorf("policy %s on resource %s/%s not satisfied", policy.Name, rname, rns)
} else if len(engineResponse.PolicyResponse.Rules) > 0 {
glog.Infof("Validation from policy %s has applied succesfully to %s %s/%s", policy.Name, gvk.Kind, rname, rns)
}
}
return patchedResource, nil
}
func extractPolicy(fileDir string) (*kyverno.ClusterPolicy, error) {
policy := &kyverno.ClusterPolicy{}
file, err := loadFile(fileDir)
if err != nil {
return nil, fmt.Errorf("failed to load file: %v", err)
}
policyBytes, err := yaml.ToJSON(file)
if err != nil {
return nil, err
}
if err := json.Unmarshal(policyBytes, policy); err != nil {
return nil, fmt.Errorf("failed to decode policy %s, err: %v", policy.Name, err)
}
if policy.TypeMeta.Kind != "ClusterPolicy" {
return nil, fmt.Errorf("failed to parse policy")
}
return policy, nil
}
type resourceInfo struct {
rawResource []byte
gvk *metav1.GroupVersionKind
}
func extractResource(fileDir, kubeconfig string) ([]*resourceInfo, error) {
var files []string
var resources []*resourceInfo
// check if applied on multiple resources
isDir, err := isDir(fileDir)
if err != nil {
return nil, err
}
if isDir {
files, err = scanDir(fileDir)
if err != nil {
return nil, err
}
} else {
files = []string{fileDir}
}
for _, dir := range files {
data, err := loadFile(dir)
if err != nil {
glog.Warningf("Error while loading file: %v\n", err)
continue
}
dd := bytes.Split(data, []byte(defaultYamlSeparator))
for _, d := range dd {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, gvk, err := decode([]byte(d), nil, nil)
if err != nil {
glog.Warningf("Error while decoding YAML object, err: %s\n", err)
continue
}
actualObj, err := convertToActualObject(kubeconfig, gvk, obj)
if err != nil {
glog.V(3).Infof("Failed to convert resource %s to actual k8s object: %v\n", gvk.Kind, err)
glog.V(3).Infof("Apply policy on raw resource.\n")
}
raw, err := json.Marshal(actualObj)
if err != nil {
glog.Warningf("Error while marshalling manifest, err: %v\n", err)
continue
}
gvkInfo := &metav1.GroupVersionKind{Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind}
resources = append(resources, &resourceInfo{rawResource: raw, gvk: gvkInfo})
}
}
return resources, err
}
func convertToActualObject(kubeconfig string, gvk *schema.GroupVersionKind, obj runtime.Object) (interface{}, error) {
clientConfig, err := createClientConfig(kubeconfig)
if err != nil {
return obj, err
}
dynamicClient, err := dynamic.NewForConfig(clientConfig)
if err != nil {
return obj, err
}
kclient, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return obj, err
}
asUnstructured := &unstructured.Unstructured{}
if err := scheme.Scheme.Convert(obj, asUnstructured, nil); err != nil {
return obj, err
}
mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(kclient.Discovery()))
mapping, err := mapper.RESTMapping(schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version)
if err != nil {
return obj, err
}
actualObj, err := dynamicClient.Resource(mapping.Resource).Namespace("default").Create(asUnstructured, metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}})
if err != nil {
return obj, err
}
return actualObj, nil
}

View file

@ -0,0 +1,267 @@
package apply
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"strings"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/nirmata/kyverno/pkg/config"
"k8s.io/client-go/discovery"
"k8s.io/apimachinery/pkg/util/yaml"
"github.com/nirmata/kyverno/pkg/engine"
engineutils "github.com/nirmata/kyverno/pkg/engine/utils"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/spf13/cobra"
yamlv2 "gopkg.in/yaml.v2"
"k8s.io/client-go/kubernetes/scheme"
)
func Command() *cobra.Command {
var resourcePath, kubeConfig string
cmd := &cobra.Command{
Use: "apply",
Short: "Applies policies on resources",
Example: fmt.Sprintf("To apply on a resource:\nkyverno apply /path/to/policy1 /path/to/policy2 --resource=/path/to/resource\n\nTo apply on a cluster\nkyverno apply /path/to/policy1 /path/to/policy2 --kubeConfig=/path/to/kubeConfig"),
RunE: func(cmd *cobra.Command, policyPaths []string) error {
if resourcePath == "" && kubeConfig == "" {
fmt.Println("Specify path to resource file or kube config")
}
var policies []*v1.ClusterPolicy
for _, policyPath := range policyPaths {
policy, err := getPolicy(policyPath)
if err != nil {
return err
}
policies = append(policies, policy)
}
resources, err := getResources(policies, kubeConfig, resourcePath)
if err != nil {
return err
}
for i, policy := range policies {
for j, resource := range resources {
if !(j == 0 && i == 0) {
fmt.Printf("\n\n=======================================================================\n")
}
err = applyPolicyOnResource(policy, resource)
if err != nil {
return err
}
}
}
return nil
},
}
cmd.Flags().StringVar(&resourcePath, "resource", "", "path to resource file")
cmd.Flags().StringVar(&kubeConfig, "kubeConfig", "", "path to .kube/config file")
return cmd
}
func getResources(policies []*v1.ClusterPolicy, kubeConfig, resourcePath string) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
var err error
if kubeConfig != "" {
var resourceTypesMap = make(map[string]bool)
var resourceTypes []string
for _, policy := range policies {
for _, rule := range policy.Spec.Rules {
for _, kind := range rule.MatchResources.Kinds {
resourceTypesMap[kind] = true
}
}
}
for kind := range resourceTypesMap {
resourceTypes = append(resourceTypes, kind)
}
resources, err = getResourcesOfTypeFromCluster(resourceTypes, kubeConfig)
if err != nil {
return nil, err
}
}
if resourcePath != "" {
resource, err := getResource(resourcePath)
if err != nil {
return nil, err
}
resources = append(resources, resource)
}
return resources, nil
}
func getResourcesOfTypeFromCluster(resourceTypes []string, kubeConfig string) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
clientConfig, err := config.CreateClientConfig(kubeConfig)
if err != nil {
return nil, err
}
dClient, err := discovery.NewDiscoveryClientForConfig(clientConfig)
if err != nil {
return nil, err
}
//var kindToListApi = map[string]string{
// "pod": "/api/v1/pods",
// "services": "/api/v1/services",
//}
for _, kind := range resourceTypes {
listObjectRaw, err := dClient.RESTClient().Get().RequestURI("/api/v1/" + strings.ToLower(kind) + "s").Do().Raw()
if err != nil {
log.Println(2, err)
}
listObject, err := engineutils.ConvertToUnstructured(listObjectRaw)
if err != nil {
return nil, err
}
resourceList, err := listObject.ToList()
if err != nil {
return nil, err
}
version := resourceList.GetAPIVersion()
for _, resource := range resourceList.Items {
resource.SetGroupVersionKind(schema.GroupVersionKind{
Group: "",
Version: version,
Kind: kind,
})
resources = append(resources, resource.DeepCopy())
}
}
return resources, nil
}
func getPolicy(path string) (*v1.ClusterPolicy, error) {
policy := &v1.ClusterPolicy{}
file, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to load file: %v", err)
}
policyBytes, err := yaml.ToJSON(file)
if err != nil {
return nil, err
}
if err := json.Unmarshal(policyBytes, policy); err != nil {
return nil, fmt.Errorf("failed to decode policy %s, err: %v", policy.Name, err)
}
if policy.TypeMeta.Kind != "ClusterPolicy" {
return nil, fmt.Errorf("failed to parse policy")
}
return policy, nil
}
func getResource(path string) (*unstructured.Unstructured, error) {
resourceYaml, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
decode := scheme.Codecs.UniversalDeserializer().Decode
resourceObject, metaData, err := decode(resourceYaml, nil, nil)
if err != nil {
return nil, err
}
resourceUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&resourceObject)
if err != nil {
return nil, err
}
resourceJSON, err := json.Marshal(resourceUnstructured)
if err != nil {
return nil, err
}
resource, err := engineutils.ConvertToUnstructured(resourceJSON)
if err != nil {
return nil, err
}
resource.SetGroupVersionKind(*metaData)
if resource.GetNamespace() == "" {
resource.SetNamespace("default")
}
return resource, nil
}
func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured) error {
fmt.Printf("\n\nApplying Policy %s on Resource %s/%s/%s/%s", policy.Name, resource.GetNamespace(), resource.GetKind(), resource.GetName(), resource.GetUID())
mutateResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
if !mutateResponse.IsSuccesful() {
fmt.Printf("\n\nMutation:")
fmt.Printf("\nFailed to apply mutation")
for i, r := range mutateResponse.PolicyResponse.Rules {
fmt.Printf("\n%d. %s", i+1, r.Message)
}
fmt.Printf("\n\n")
} else {
if len(mutateResponse.PolicyResponse.Rules) > 0 {
fmt.Printf("\n\nMutation:")
fmt.Printf("\nMutation has been applied succesfully")
yamlEncodedResource, err := yamlv2.Marshal(mutateResponse.PatchedResource.Object)
if err != nil {
return err
}
fmt.Printf("\n\n" + strings.ReplaceAll(string(yamlEncodedResource), "\n", "\n"))
}
}
validateResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource})
if !validateResponse.IsSuccesful() {
fmt.Printf("\n\nValidation:")
fmt.Printf("\nResource is invalid")
for i, r := range validateResponse.PolicyResponse.Rules {
fmt.Printf("\n%d. %s", i+1, r.Message)
}
fmt.Printf("\n\n")
} else {
if len(validateResponse.PolicyResponse.Rules) > 0 {
fmt.Printf("\n\nValidation:")
fmt.Printf("\nResource is valid")
}
}
return nil
}

View file

@ -1,105 +0,0 @@
package apply
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/golang/glog"
yamlv2 "gopkg.in/yaml.v2"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
rest "k8s.io/client-go/rest"
clientcmd "k8s.io/client-go/tools/clientcmd"
)
func createClientConfig(kubeconfig string) (*rest.Config, error) {
if kubeconfig == "" {
defaultKC := defaultKubeconfigPath()
if _, err := os.Stat(defaultKC); err == nil {
kubeconfig = defaultKC
}
}
return clientcmd.BuildConfigFromFlags("", kubeconfig)
}
func defaultKubeconfigPath() string {
home, err := os.UserHomeDir()
if err != nil {
glog.Warningf("Warning: failed to get home dir: %v\n", err)
return ""
}
return filepath.Join(home, ".kube", "config")
}
func loadFile(fileDir string) ([]byte, error) {
if _, err := os.Stat(fileDir); os.IsNotExist(err) {
return nil, err
}
return ioutil.ReadFile(fileDir)
}
func validateDir(args []string) (policyDir, resourceDir string, err error) {
if len(args) != 2 {
return "", "", fmt.Errorf("missing policy and/or resource manifest")
}
if strings.HasPrefix(args[0], "@") {
policyDir = args[0][1:]
}
if strings.HasPrefix(args[1], "@") {
resourceDir = args[1][1:]
}
return
}
func prettyPrint(data []byte) ([]byte, error) {
out := make(map[interface{}]interface{})
if err := yamlv2.Unmarshal(data, &out); err != nil {
return nil, err
}
return yamlv2.Marshal(&out)
}
func isDir(dir string) (bool, error) {
fi, err := os.Stat(dir)
if err != nil {
return false, err
}
return fi.IsDir(), nil
}
func scanDir(dir string) ([]string, error) {
var res []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("prevent panic by handling failure accessing a path %q: %v", dir, err)
}
res = append(res, path)
return nil
})
if err != nil {
return nil, fmt.Errorf("error walking the path %q: %v", dir, err)
}
return res[1:], nil
}
func ConvertToUnstructured(data []byte) (*unstructured.Unstructured, error) {
resource := &unstructured.Unstructured{}
err := resource.UnmarshalJSON(data)
if err != nil {
glog.V(4).Infof("failed to unmarshall resource: %v", err)
return nil, err
}
return resource, nil
}

View file

@ -1,27 +0,0 @@
package cmd
import (
"io"
"os"
"github.com/nirmata/kyverno/pkg/kyverno/apply"
"github.com/nirmata/kyverno/pkg/kyverno/version"
"github.com/spf13/cobra"
)
// NewDefaultKyvernoCommand ...
func NewDefaultKyvernoCommand() *cobra.Command {
return NewKyvernoCommand(os.Stdin, os.Stdout, os.Stderr)
}
// NewKyvernoCommand returns the new kynerno command
func NewKyvernoCommand(in io.Reader, out, errout io.Writer) *cobra.Command {
cmds := &cobra.Command{
Use: "kyverno",
Short: "kyverno manages native policies of Kubernetes",
}
cmds.AddCommand(apply.NewCmdApply(in, out, errout))
cmds.AddCommand(version.NewCmdVersion(out))
return cmds
}

48
pkg/kyverno/main.go Normal file
View file

@ -0,0 +1,48 @@
package kyverno
import (
"flag"
"os"
"github.com/nirmata/kyverno/pkg/kyverno/validate"
"github.com/nirmata/kyverno/pkg/kyverno/apply"
"github.com/nirmata/kyverno/pkg/kyverno/version"
"github.com/spf13/cobra"
)
func CLI() {
cli := &cobra.Command{
Use: "kyverno",
Short: "kyverno manages native policies of Kubernetes",
}
configureGlog(cli)
commands := []*cobra.Command{
version.Command(),
apply.Command(),
validate.Command(),
}
cli.AddCommand(commands...)
if err := cli.Execute(); err != nil {
os.Exit(1)
}
}
func configureGlog(cli *cobra.Command) {
flag.Parse()
flag.Set("logtostderr", "true")
cli.PersistentFlags().AddGoFlagSet(flag.CommandLine)
cli.PersistentFlags().MarkHidden("alsologtostderr")
cli.PersistentFlags().MarkHidden("logtostderr")
cli.PersistentFlags().MarkHidden("log_dir")
cli.PersistentFlags().MarkHidden("log_backtrace_at")
cli.PersistentFlags().MarkHidden("stderrthreshold")
cli.PersistentFlags().MarkHidden("vmodule")
}

View file

@ -0,0 +1,64 @@
package validate
import (
"encoding/json"
"fmt"
"io/ioutil"
policyvalidate "github.com/nirmata/kyverno/pkg/engine/policy"
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/yaml"
)
func Command() *cobra.Command {
cmd := &cobra.Command{
Use: "validate",
Short: "Validates kyverno policies",
Example: "kyverno validate /path/to/policy1 /path/to/policy2",
RunE: func(cmd *cobra.Command, policyPaths []string) error {
for _, policyPath := range policyPaths {
policy, err := getPolicy(policyPath)
if err != nil {
return err
}
err = policyvalidate.Validate(*policy)
if err != nil {
return err
}
fmt.Println("Policy " + policy.Name + " is valid")
}
return nil
},
}
return cmd
}
func getPolicy(path string) (*v1.ClusterPolicy, error) {
policy := &v1.ClusterPolicy{}
file, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to load file: %v", err)
}
policyBytes, err := yaml.ToJSON(file)
if err != nil {
return nil, err
}
if err := json.Unmarshal(policyBytes, policy); err != nil {
return nil, fmt.Errorf("failed to decode policy %s, err: %v", policy.Name, err)
}
if policy.TypeMeta.Kind != "ClusterPolicy" {
return nil, fmt.Errorf("failed to parse policy")
}
return policy, nil
}

View file

@ -0,0 +1,21 @@
package version
import (
"fmt"
"github.com/nirmata/kyverno/pkg/version"
"github.com/spf13/cobra"
)
func Command() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Shows current version of kyverno",
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Printf("Version: %s\n", version.BuildVersion)
fmt.Printf("Time: %s\n", version.BuildTime)
fmt.Printf("Git commit ID: %s\n", version.BuildHash)
return nil
},
}
}

View file

@ -1,29 +0,0 @@
package version
import (
"fmt"
"io"
"github.com/nirmata/kyverno/pkg/version"
"github.com/spf13/cobra"
)
// NewCmdVersion is a command to display the build version
func NewCmdVersion(cmdOut io.Writer) *cobra.Command {
versionCmd := &cobra.Command{
Use: "version",
Short: "",
Run: func(cmd *cobra.Command, args []string) {
showVersion()
},
}
return versionCmd
}
func showVersion() {
fmt.Printf("Version: %s\n", version.BuildVersion)
fmt.Printf("Time: %s\n", version.BuildTime)
fmt.Printf("Git commit ID: %s\n", version.BuildHash)
}

View file

@ -63,7 +63,6 @@ func (wrc *WebhookRegistrationClient) constructOwner() v1.OwnerReference {
func generateDebugWebhook(name, url string, caData []byte, validate bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.Webhook {
sideEffect := admregapi.SideEffectClassNoneOnDryRun
failurePolicy := admregapi.Ignore
return admregapi.Webhook{
Name: name,
ClientConfig: admregapi.WebhookClientConfig{
@ -89,13 +88,11 @@ func generateDebugWebhook(name, url string, caData []byte, validate bool, timeou
},
AdmissionReviewVersions: []string{"v1beta1"},
TimeoutSeconds: &timeoutSeconds,
FailurePolicy: &failurePolicy,
}
}
func generateWebhook(name, servicePath string, caData []byte, validation bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.Webhook {
sideEffect := admregapi.SideEffectClassNoneOnDryRun
failurePolicy := admregapi.Ignore
return admregapi.Webhook{
Name: name,
ClientConfig: admregapi.WebhookClientConfig{
@ -125,6 +122,5 @@ func generateWebhook(name, servicePath string, caData []byte, validation bool, t
},
AdmissionReviewVersions: []string{"v1beta1"},
TimeoutSeconds: &timeoutSeconds,
FailurePolicy: &failurePolicy,
}
}

View file

@ -91,8 +91,6 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou
// gather patches
patches = append(patches, engineResponse.GetPatches()...)
glog.V(4).Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, resource.GetNamespace(), resource.GetName())
policyContext.NewResource = engineResponse.PatchedResource
}
// generate annotations

View file

@ -3,7 +3,6 @@ kind: ClusterPolicy
metadata:
name: disallow-default-namespace
annotations:
pod-policies.kyverno.io/autogen-controllers: none
policies.kyverno.io/category: Workload Isolation
policies.kyverno.io/description: Kubernetes namespaces are an optional feature
that provide a way to segment and isolate cluster resources across multiple