mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-23 00:01:55 +00:00
feat: support mock in CLI for VPs (#12344)
* feat: support mock in CLI for VPs Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * implement get cm mock Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * move into cel package Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
0e76c0ed4b
commit
1c3bddf8ca
15 changed files with 823 additions and 1 deletions
22
cmd/cli/kubectl-kyverno/apis/v1alpha1/context.go
Normal file
22
cmd/cli/kubectl-kyverno/apis/v1alpha1/context.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:scope="Cluster"
|
||||
|
||||
// Values declares values to be loaded by the Kyverno CLI
|
||||
type Context struct {
|
||||
metav1.TypeMeta `json:",inline,omitempty"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
ContextSpec `json:"spec"`
|
||||
}
|
||||
|
||||
type ContextSpec struct {
|
||||
Resources []unstructured.Unstructured `json:"resources,omitempty"`
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
||||
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/command"
|
||||
clicontext "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/context"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/data"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/deprecations"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/exception"
|
||||
|
@ -65,6 +66,7 @@ type ApplyCommandConfig struct {
|
|||
Variables []string
|
||||
ValuesFile string
|
||||
UserInfoPath string
|
||||
ContextPath string
|
||||
Cluster bool
|
||||
PolicyReport bool
|
||||
OutputFormat string
|
||||
|
@ -162,6 +164,7 @@ func Command() *cobra.Command {
|
|||
cmd.Flags().StringVarP(&applyCommandConfig.UserInfoPath, "userinfo", "u", "", "Admission Info including Roles, Cluster Roles and Subjects")
|
||||
cmd.Flags().StringSliceVarP(&applyCommandConfig.Variables, "set", "s", nil, "Variables that are required")
|
||||
cmd.Flags().StringVarP(&applyCommandConfig.ValuesFile, "values-file", "f", "", "File containing values for policy variables")
|
||||
cmd.Flags().StringVarP(&applyCommandConfig.ContextPath, "context-file", "", "", "File containing context data for CEL policies")
|
||||
cmd.Flags().BoolVarP(&applyCommandConfig.PolicyReport, "policy-report", "p", false, "Generates policy report when passed (default policyviolation)")
|
||||
cmd.Flags().StringVarP(&applyCommandConfig.OutputFormat, "output-format", "", "yaml", "Specifies the policy report format (json or yaml). Default: yaml.")
|
||||
cmd.Flags().StringVarP(&applyCommandConfig.Namespace, "namespace", "n", "", "Optional Policy parameter passed with cluster flag")
|
||||
|
@ -373,6 +376,24 @@ func (c *ApplyCommandConfig) applyValidatingPolicies(
|
|||
return nil, err
|
||||
}
|
||||
restMapper = restmapper.NewDiscoveryRESTMapper(apiGroupResources)
|
||||
fakeContextProvider := celpolicy.NewFakeContextProvider()
|
||||
if c.ContextPath != "" {
|
||||
ctx, err := clicontext.Load(nil, c.ContextPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, resource := range ctx.ContextSpec.Resources {
|
||||
gvk := resource.GroupVersionKind()
|
||||
mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fakeContextProvider.AddResource(mapping.Resource, &resource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
contextProvider = fakeContextProvider
|
||||
}
|
||||
responses := make([]engineapi.EngineResponse, 0)
|
||||
responsesTemp := make([]engine.EngineResponse, 0)
|
||||
|
@ -398,7 +419,7 @@ func (c *ApplyCommandConfig) applyValidatingPolicies(
|
|||
"",
|
||||
resource.GetName(),
|
||||
resource.GetNamespace(),
|
||||
// TODO
|
||||
// TODO: how to manage other operations ?
|
||||
admissionv1.Create,
|
||||
resource,
|
||||
nil,
|
||||
|
|
|
@ -586,6 +586,40 @@ func Test_Apply_ValidatingPolicies(t *testing.T) {
|
|||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
config: ApplyCommandConfig{
|
||||
PolicyPaths: []string{"../../../../../test/cli/test-validating-policy/policy-with-cm/policy.yaml"},
|
||||
ResourcePaths: []string{"../../../../../test/cli/test-validating-policy/policy-with-cm/pod1.yaml"},
|
||||
ContextPath: "../../../../../test/cli/test-validating-policy/policy-with-cm/context.yaml",
|
||||
PolicyReport: true,
|
||||
},
|
||||
expectedPolicyReports: []policyreportv1alpha2.PolicyReport{{
|
||||
Summary: policyreportv1alpha2.PolicyReportSummary{
|
||||
Pass: 1,
|
||||
Fail: 0,
|
||||
Skip: 0,
|
||||
Error: 0,
|
||||
Warn: 0,
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
config: ApplyCommandConfig{
|
||||
PolicyPaths: []string{"../../../../../test/cli/test-validating-policy/policy-with-cm/policy.yaml"},
|
||||
ResourcePaths: []string{"../../../../../test/cli/test-validating-policy/policy-with-cm/pod2.yaml"},
|
||||
ContextPath: "../../../../../test/cli/test-validating-policy/policy-with-cm/context.yaml",
|
||||
PolicyReport: true,
|
||||
},
|
||||
expectedPolicyReports: []policyreportv1alpha2.PolicyReport{{
|
||||
Summary: policyreportv1alpha2.PolicyReportSummary{
|
||||
Pass: 0,
|
||||
Fail: 1,
|
||||
Skip: 0,
|
||||
Error: 0,
|
||||
Warn: 0,
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
compareSummary := func(expected policyreportv1alpha2.PolicyReportSummary, actual policyreportv1alpha2.PolicyReportSummary, desc string) {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
name: contexts.cli.kyverno.io
|
||||
spec:
|
||||
group: cli.kyverno.io
|
||||
names:
|
||||
kind: Context
|
||||
listKind: ContextList
|
||||
plural: contexts
|
||||
singular: context
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Values declares values to be loaded by the Kyverno CLI
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
resources:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
34
cmd/cli/kubectl-kyverno/context/load.go
Normal file
34
cmd/cli/kubectl-kyverno/context/load.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
)
|
||||
|
||||
func Load(f billy.Filesystem, filepath string) (*v1alpha1.Context, error) {
|
||||
yamlBytes, err := readFile(f, filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals := &v1alpha1.Context{}
|
||||
if err := yaml.UnmarshalStrict(yamlBytes, vals); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
func readFile(f billy.Filesystem, filepath string) ([]byte, error) {
|
||||
if f != nil {
|
||||
file, err := f.Open(filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
return io.ReadAll(file)
|
||||
}
|
||||
return os.ReadFile(filepath)
|
||||
}
|
149
cmd/cli/kubectl-kyverno/context/load_test.go
Normal file
149
cmd/cli/kubectl-kyverno/context/load_test.go
Normal file
|
@ -0,0 +1,149 @@
|
|||
package context
|
||||
|
||||
// import (
|
||||
// "os"
|
||||
// "reflect"
|
||||
// "testing"
|
||||
|
||||
// "github.com/go-git/go-billy/v5"
|
||||
// "github.com/go-git/go-billy/v5/memfs"
|
||||
// "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/v1alpha1"
|
||||
// )
|
||||
|
||||
// func Test_readFile(t *testing.T) {
|
||||
// mustReadFile := func(path string) []byte {
|
||||
// t.Helper()
|
||||
// data, err := os.ReadFile(path)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// return data
|
||||
// }
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// f billy.Filesystem
|
||||
// filepath string
|
||||
// want []byte
|
||||
// wantErr bool
|
||||
// }{{
|
||||
// name: "empty",
|
||||
// filepath: "",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "does not exist",
|
||||
// filepath: "../_testdata/values/doesnotexist",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "bad format",
|
||||
// filepath: "../_testdata/values/bad-format.yaml",
|
||||
// want: mustReadFile("../_testdata/values/bad-format.yaml"),
|
||||
// wantErr: false,
|
||||
// }, {
|
||||
// name: "valid",
|
||||
// filepath: "../_testdata/values/limit-configmap-for-sa.yaml",
|
||||
// want: mustReadFile("../_testdata/values/limit-configmap-for-sa.yaml"),
|
||||
// wantErr: false,
|
||||
// }, {
|
||||
// name: "empty (billy)",
|
||||
// f: memfs.New(),
|
||||
// filepath: "",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "valid (billy)",
|
||||
// f: func() billy.Filesystem {
|
||||
// f := memfs.New()
|
||||
// file, err := f.Create("valid.yaml")
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// defer file.Close()
|
||||
// if _, err := file.Write([]byte("foo: bar")); err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// return f
|
||||
// }(),
|
||||
// filepath: "valid.yaml",
|
||||
// want: []byte("foo: bar"),
|
||||
// wantErr: false,
|
||||
// }}
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// got, err := readFile(tt.f, tt.filepath)
|
||||
// if (err != nil) != tt.wantErr {
|
||||
// t.Errorf("readFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
// return
|
||||
// }
|
||||
// if !reflect.DeepEqual(got, tt.want) {
|
||||
// t.Errorf("readFile() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestLoad(t *testing.T) {
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// f billy.Filesystem
|
||||
// filepath string
|
||||
// want *v1alpha1.Values
|
||||
// wantErr bool
|
||||
// }{{
|
||||
// name: "empty",
|
||||
// filepath: "",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "does not exist",
|
||||
// filepath: "../_testdata/values/doesnotexist",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "bad format",
|
||||
// filepath: "../_testdata/values/bad-format.yaml",
|
||||
// want: nil,
|
||||
// wantErr: true,
|
||||
// }, {
|
||||
// name: "valid",
|
||||
// filepath: "../_testdata/values/limit-configmap-for-sa.yaml",
|
||||
// want: &v1alpha1.Values{
|
||||
// ValuesSpec: v1alpha1.ValuesSpec{
|
||||
// NamespaceSelectors: []v1alpha1.NamespaceSelector{{
|
||||
// Name: "test1",
|
||||
// Labels: map[string]string{
|
||||
// "foo.com/managed-state": "managed",
|
||||
// },
|
||||
// }},
|
||||
// Policies: []v1alpha1.Policy{{
|
||||
// Name: "limit-configmap-for-sa",
|
||||
// Resources: []v1alpha1.Resource{{
|
||||
// Name: "any-configmap-name-good",
|
||||
// Values: map[string]interface{}{
|
||||
// "request.operation": "UPDATE",
|
||||
// },
|
||||
// }, {
|
||||
// Name: "any-configmap-name-bad",
|
||||
// Values: map[string]interface{}{
|
||||
// "request.operation": "UPDATE",
|
||||
// },
|
||||
// }},
|
||||
// }},
|
||||
// },
|
||||
// },
|
||||
// wantErr: false,
|
||||
// }}
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// got, err := Load(tt.f, tt.filepath)
|
||||
// if (err != nil) != tt.wantErr {
|
||||
// t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
|
||||
// return
|
||||
// }
|
||||
// if !reflect.DeepEqual(got, tt.want) {
|
||||
// t.Errorf("Load() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
name: contexts.cli.kyverno.io
|
||||
spec:
|
||||
group: cli.kyverno.io
|
||||
names:
|
||||
kind: Context
|
||||
listKind: ContextList
|
||||
plural: contexts
|
||||
singular: context
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Values declares values to be loaded by the Kyverno CLI
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
properties:
|
||||
resources:
|
||||
items:
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
|
@ -40,6 +40,7 @@ kyverno apply [flags]
|
|||
--audit-warn If set to true, will flag audit policies as warnings instead of failures
|
||||
-c, --cluster Checks if policies should be applied to cluster in the current context
|
||||
--context string The name of the kubeconfig context to use
|
||||
--context-file string File containing context data for CEL policies
|
||||
--continue-on-fail If set to true, will continue to apply policies on the next resource upon failure to apply to the current resource instead of exiting out
|
||||
--detailed-results If set to true, display detailed results
|
||||
-e, --exception strings Policy exception to be considered when evaluating policies against resources
|
||||
|
|
|
@ -25,6 +25,8 @@ background-color: #1589dd;
|
|||
<h2 id="cli.kyverno.io/v1alpha1">cli.kyverno.io/v1alpha1</h2>
|
||||
Resource Types:
|
||||
<ul><li>
|
||||
<a href="#cli.kyverno.io/v1alpha1.Context">Context</a>
|
||||
</li><li>
|
||||
<a href="#cli.kyverno.io/v1alpha1.Test">Test</a>
|
||||
</li><li>
|
||||
<a href="#cli.kyverno.io/v1alpha1.UserInfo">UserInfo</a>
|
||||
|
@ -32,6 +34,81 @@ Resource Types:
|
|||
<a href="#cli.kyverno.io/v1alpha1.Values">Values</a>
|
||||
</li></ul>
|
||||
<hr />
|
||||
<h3 id="cli.kyverno.io/v1alpha1.Context">Context
|
||||
</h3>
|
||||
<p>
|
||||
<p>Values declares values to be loaded by the Kyverno CLI</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>apiVersion</code><br/>
|
||||
string</td>
|
||||
<td>
|
||||
<code>
|
||||
cli.kyverno.io/v1alpha1
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>kind</code><br/>
|
||||
string
|
||||
</td>
|
||||
<td><code>Context</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>metadata</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code><br/>
|
||||
<em>
|
||||
<a href="#cli.kyverno.io/v1alpha1.ContextSpec">
|
||||
ContextSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<br/>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<td>
|
||||
<code>resources</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#unstructured-unstructured-v1">
|
||||
[]Kubernetes meta/v1/unstructured.Unstructured
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="cli.kyverno.io/v1alpha1.Test">Test
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -426,6 +503,37 @@ github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any
|
|||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="cli.kyverno.io/v1alpha1.ContextSpec">ContextSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#cli.kyverno.io/v1alpha1.Context">Context</a>)
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>resources</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#unstructured-unstructured-v1">
|
||||
[]Kubernetes meta/v1/unstructured.Unstructured
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="cli.kyverno.io/v1alpha1.NamespaceSelector">NamespaceSelector
|
||||
</h3>
|
||||
<p>
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
<h3>Resource Types:</h3>
|
||||
<ul><li>
|
||||
<a href="#cli-kyverno-io-v1alpha1-Context">Context</a>
|
||||
</li><li>
|
||||
<a href="#cli-kyverno-io-v1alpha1-Test">Test</a>
|
||||
</li><li>
|
||||
<a href="#cli-kyverno-io-v1alpha1-UserInfo">UserInfo</a>
|
||||
|
@ -34,6 +36,149 @@
|
|||
|
||||
|
||||
|
||||
<H3 id="cli-kyverno-io-v1alpha1-Context">Context
|
||||
</H3>
|
||||
|
||||
|
||||
|
||||
<p><p>Values declares values to be loaded by the Kyverno CLI</p>
|
||||
</p>
|
||||
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>apiVersion</code></br>string</td>
|
||||
<td><code>cli.kyverno.io/v1alpha1</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>kind</code></br>string</td>
|
||||
<td><code>Context</code></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>metadata</code>
|
||||
|
||||
<span style="color:blue;"> *</span>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<span style="font-family: monospace">meta/v1.ObjectMeta</span>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>spec</code>
|
||||
|
||||
<span style="color:blue;"> *</span>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="#cli-kyverno-io-v1alpha1-ContextSpec">
|
||||
<span style="font-family: monospace">ContextSpec</span>
|
||||
</a>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>resources</code>
|
||||
|
||||
<span style="color:blue;"> *</span>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<span style="font-family: monospace">[]meta/v1/unstructured.Unstructured</span>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<H3 id="cli-kyverno-io-v1alpha1-Test">Test
|
||||
</H3>
|
||||
|
||||
|
@ -856,6 +1001,69 @@ This field is deprecated, use <code>metadata.name</code> instead</p>
|
|||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<H3 id="cli-kyverno-io-v1alpha1-ContextSpec">ContextSpec
|
||||
</H3>
|
||||
|
||||
|
||||
<p>
|
||||
(<em>Appears in:</em>
|
||||
<a href="#cli-kyverno-io-v1alpha1-Context">Context</a>)
|
||||
</p>
|
||||
|
||||
|
||||
<p></p>
|
||||
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>resources</code>
|
||||
|
||||
<span style="color:blue;"> *</span>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<span style="font-family: monospace">[]meta/v1/unstructured.Unstructured</span>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
84
pkg/cel/policy/fake_context.go
Normal file
84
pkg/cel/policy/fake_context.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"github.com/kyverno/kyverno/pkg/imageverification/imagedataloader"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type FakeContextProvider struct {
|
||||
resources map[string]map[string]map[string]*unstructured.Unstructured
|
||||
}
|
||||
|
||||
func NewFakeContextProvider() *FakeContextProvider {
|
||||
return &FakeContextProvider{
|
||||
resources: map[string]map[string]map[string]*unstructured.Unstructured{},
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) AddResource(gvr schema.GroupVersionResource, obj runtime.Object) error {
|
||||
object, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resource := &unstructured.Unstructured{Object: object}
|
||||
resources := cp.resources[gvr.String()]
|
||||
if resources == nil {
|
||||
resources = map[string]map[string]*unstructured.Unstructured{}
|
||||
cp.resources[gvr.String()] = resources
|
||||
}
|
||||
namespace := resources[resource.GetNamespace()]
|
||||
if namespace == nil {
|
||||
namespace = map[string]*unstructured.Unstructured{}
|
||||
resources[resource.GetNamespace()] = namespace
|
||||
}
|
||||
namespace[resource.GetName()] = resource
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) GetConfigMap(ns, n string) (unstructured.Unstructured, error) {
|
||||
cm, err := cp.GetResource("v1", "configmaps", ns, n)
|
||||
if err != nil {
|
||||
return unstructured.Unstructured{}, err
|
||||
}
|
||||
return *cm, nil
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) GetGlobalReference(string, string) (any, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) GetImageData(string) (*imagedataloader.ImageData, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) ParseImageReference(string) (imagedataloader.ImageReference, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) ListResources(apiVersion, resource, namespace string) (*unstructured.UnstructuredList, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (cp *FakeContextProvider) GetResource(apiVersion, resource, namespace, name string) (*unstructured.Unstructured, error) {
|
||||
gv, err := schema.ParseGroupVersion(apiVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvr := gv.WithResource(resource)
|
||||
resources := cp.resources[gvr.String()]
|
||||
if resources == nil {
|
||||
return nil, kerrors.NewNotFound(gvr.GroupResource(), name)
|
||||
}
|
||||
namespaced := resources[namespace]
|
||||
if namespaced == nil {
|
||||
return nil, kerrors.NewNotFound(gvr.GroupResource(), name)
|
||||
}
|
||||
resourced := namespaced[name]
|
||||
if resourced == nil {
|
||||
return nil, kerrors.NewNotFound(gvr.GroupResource(), name)
|
||||
}
|
||||
return resourced, nil
|
||||
}
|
14
test/cli/test-validating-policy/policy-with-cm/context.yaml
Normal file
14
test/cli/test-validating-policy/policy-with-cm/context.yaml
Normal file
|
@ -0,0 +1,14 @@
|
|||
apiVersion: cli.kyverno.io/v1alpha1
|
||||
kind: Context
|
||||
metadata:
|
||||
name: kyverno-test.yaml
|
||||
spec:
|
||||
resources:
|
||||
- apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
namespace: default
|
||||
name: policy-cm
|
||||
data:
|
||||
name: good-pod
|
||||
|
14
test/cli/test-validating-policy/policy-with-cm/pod1.yaml
Normal file
14
test/cli/test-validating-policy/policy-with-cm/pod1.yaml
Normal file
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: good-pod
|
||||
spec:
|
||||
containers:
|
||||
- name:
|
||||
image: nginx
|
||||
volumeMounts:
|
||||
- name: udev
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: udev
|
||||
emptyDir: {}
|
15
test/cli/test-validating-policy/policy-with-cm/pod2.yaml
Normal file
15
test/cli/test-validating-policy/policy-with-cm/pod2.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: bad-pod
|
||||
spec:
|
||||
containers:
|
||||
- name:
|
||||
image: nginx
|
||||
volumeMounts:
|
||||
- name: udev
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: udev
|
||||
hostPath:
|
||||
path: /etc/udev
|
18
test/cli/test-validating-policy/policy-with-cm/policy.yaml
Normal file
18
test/cli/test-validating-policy/policy-with-cm/policy.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
apiVersion: policies.kyverno.io/v1alpha1
|
||||
kind: ValidatingPolicy
|
||||
metadata:
|
||||
name: disallow-host-path
|
||||
spec:
|
||||
matchConstraints:
|
||||
resourceRules:
|
||||
- apiGroups: [""]
|
||||
apiVersions: ["v1"]
|
||||
operations: ["CREATE", "UPDATE"]
|
||||
resources: ["pods"]
|
||||
variables:
|
||||
- name: cm
|
||||
expression: >-
|
||||
context.GetConfigMap(object.metadata.namespace, "policy-cm")
|
||||
validations:
|
||||
- expression: >-
|
||||
object.metadata.name == variables.cm.data.name
|
Loading…
Add table
Reference in a new issue