1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

feat: support exclude block in generating VAPs ()

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
Mariam Fahmy 2024-07-16 18:06:58 +03:00 committed by GitHub
parent 35494bd8bb
commit b0cef72df1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 942 additions and 81 deletions
pkg/validatingadmissionpolicy
test/conformance/chainsaw/generate-validating-admission-policy/clusterpolicy/standard

View file

@ -14,7 +14,11 @@ import (
)
// BuildValidatingAdmissionPolicy is used to build a Kubernetes ValidatingAdmissionPolicy from a Kyverno policy
func BuildValidatingAdmissionPolicy(discoveryClient dclient.IDiscovery, vap *admissionregistrationv1alpha1.ValidatingAdmissionPolicy, cpol kyvernov1.PolicyInterface) error {
func BuildValidatingAdmissionPolicy(
discoveryClient dclient.IDiscovery,
vap *admissionregistrationv1alpha1.ValidatingAdmissionPolicy,
cpol kyvernov1.PolicyInterface,
) error {
// set owner reference
vap.OwnerReferences = []metav1.OwnerReference{
{
@ -25,30 +29,51 @@ func BuildValidatingAdmissionPolicy(discoveryClient dclient.IDiscovery, vap *adm
},
}
// construct validating admission policy resource rules
// construct the rules
var matchResources admissionregistrationv1alpha1.MatchResources
var matchRules []admissionregistrationv1alpha1.NamedRuleWithOperations
var matchRules, excludeRules []admissionregistrationv1alpha1.NamedRuleWithOperations
rule := cpol.GetSpec().Rules[0]
// convert the match block
match := rule.MatchResources
if !match.ResourceDescription.IsEmpty() {
if err := translateResource(discoveryClient, &matchResources, &matchRules, match.ResourceDescription); err != nil {
if err := translateResource(discoveryClient, &matchResources, &matchRules, match.ResourceDescription, true); err != nil {
return err
}
}
if match.Any != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &matchRules, match.Any); err != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &matchRules, match.Any, true); err != nil {
return err
}
}
if match.All != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &matchRules, match.All); err != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &matchRules, match.All, true); err != nil {
return err
}
}
// set validating admission policy spec
// convert the exclude block
exclude := rule.ExcludeResources
if !exclude.ResourceDescription.IsEmpty() {
if err := translateResource(discoveryClient, &matchResources, &excludeRules, exclude.ResourceDescription, false); err != nil {
return err
}
}
if exclude.Any != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.Any, false); err != nil {
return err
}
}
if exclude.All != nil {
if err := translateResourceFilters(discoveryClient, &matchResources, &excludeRules, exclude.All, false); err != nil {
return err
}
}
// set policy spec
vap.Spec = admissionregistrationv1alpha1.ValidatingAdmissionPolicySpec{
MatchConstraints: &matchResources,
ParamKind: rule.Validation.CEL.ParamKind,
@ -64,7 +89,10 @@ func BuildValidatingAdmissionPolicy(discoveryClient dclient.IDiscovery, vap *adm
}
// BuildValidatingAdmissionPolicyBinding is used to build a Kubernetes ValidatingAdmissionPolicyBinding from a Kyverno policy
func BuildValidatingAdmissionPolicyBinding(vapbinding *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding, cpol kyvernov1.PolicyInterface) error {
func BuildValidatingAdmissionPolicyBinding(
vapbinding *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding,
cpol kyvernov1.PolicyInterface,
) error {
// set owner reference
vapbinding.OwnerReferences = []metav1.OwnerReference{
{
@ -98,9 +126,14 @@ func BuildValidatingAdmissionPolicyBinding(vapbinding *admissionregistrationv1al
return nil
}
func translateResourceFilters(discoveryClient dclient.IDiscovery, matchResources *admissionregistrationv1alpha1.MatchResources, rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations, resFilters kyvernov1.ResourceFilters) error {
func translateResourceFilters(discoveryClient dclient.IDiscovery,
matchResources *admissionregistrationv1alpha1.MatchResources,
rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations,
resFilters kyvernov1.ResourceFilters,
isMatch bool,
) error {
for _, filter := range resFilters {
err := translateResource(discoveryClient, matchResources, rules, filter.ResourceDescription)
err := translateResource(discoveryClient, matchResources, rules, filter.ResourceDescription, isMatch)
if err != nil {
return err
}
@ -108,32 +141,47 @@ func translateResourceFilters(discoveryClient dclient.IDiscovery, matchResources
return nil
}
func translateResource(discoveryClient dclient.IDiscovery, matchResources *admissionregistrationv1alpha1.MatchResources, rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations, res kyvernov1.ResourceDescription) error {
err := constructValidatingAdmissionPolicyRules(discoveryClient, rules, res)
func translateResource(
discoveryClient dclient.IDiscovery,
matchResources *admissionregistrationv1alpha1.MatchResources,
rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations,
res kyvernov1.ResourceDescription,
isMatch bool,
) error {
err := constructValidatingAdmissionPolicyRules(discoveryClient, rules, res, isMatch)
if err != nil {
return err
}
matchResources.ResourceRules = *rules
if len(res.Namespaces) > 0 {
namespaceSelector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "kubernetes.io/metadata.name",
Operator: "In",
Values: res.Namespaces,
if isMatch {
matchResources.ResourceRules = *rules
if len(res.Namespaces) > 0 {
namespaceSelector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: "kubernetes.io/metadata.name",
Operator: "In",
Values: res.Namespaces,
},
},
},
}
matchResources.NamespaceSelector = namespaceSelector
} else {
matchResources.NamespaceSelector = res.NamespaceSelector
}
matchResources.NamespaceSelector = namespaceSelector
matchResources.ObjectSelector = res.Selector
} else {
matchResources.NamespaceSelector = res.NamespaceSelector
matchResources.ExcludeResourceRules = *rules
}
matchResources.ObjectSelector = res.Selector
return nil
}
func constructValidatingAdmissionPolicyRules(discoveryClient dclient.IDiscovery, rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations, res kyvernov1.ResourceDescription) error {
func constructValidatingAdmissionPolicyRules(
discoveryClient dclient.IDiscovery,
rules *[]admissionregistrationv1alpha1.NamedRuleWithOperations,
res kyvernov1.ResourceDescription,
isMatch bool,
) error {
// translate operations to their corresponding values in validating admission policy.
ops := translateOperations(res.GetOperations())
@ -191,6 +239,22 @@ func constructValidatingAdmissionPolicyRules(discoveryClient dclient.IDiscovery,
}
}
}
// if exclude block has namespaces but no kinds, we need to add a rule for the namespaces
if !isMatch && len(res.Namespaces) > 0 && len(res.Kinds) == 0 {
r := admissionregistrationv1alpha1.NamedRuleWithOperations{
ResourceNames: res.Namespaces,
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
Resources: []string{"namespaces"},
APIGroups: []string{""},
APIVersions: []string{"v1"},
},
Operations: ops,
},
}
*rules = append(*rules, r)
}
return nil
}
@ -227,7 +291,7 @@ func translateOperations(operations []string) []admissionregistrationv1.Operatio
}
}
// set default values for operations since it's a required field in validating admission policies
// set default values for operations since it's a required field in ValidatingAdmissionPolicies
if len(vapOperations) == 0 {
vapOperations = append(vapOperations, admissionregistrationv1.Create)
vapOperations = append(vapOperations, admissionregistrationv1.Update)

View file

@ -8,14 +8,12 @@ import (
// CanGenerateVAP check if Kyverno policy can be translated to a Kubernetes ValidatingAdmissionPolicy
func CanGenerateVAP(spec *kyvernov1.Spec) (bool, string) {
var msg string
if len(spec.Rules) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple rules are not applicable."
if ok, msg := checkRuleCount(spec); !ok {
return false, msg
}
rule := spec.Rules[0]
if !rule.HasValidateCEL() {
msg = "skip generating ValidatingAdmissionPolicy for non CEL rules."
if ok, msg := checkRuleType(rule); !ok {
return false, msg
}
@ -32,65 +30,74 @@ func CanGenerateVAP(spec *kyvernov1.Spec) (bool, string) {
// check the matched/excluded resources of the CEL rule.
match, exclude := rule.MatchResources, rule.ExcludeResources
if !exclude.UserInfo.IsEmpty() || !exclude.ResourceDescription.IsEmpty() || exclude.All != nil || exclude.Any != nil {
msg = "skip generating ValidatingAdmissionPolicy: Exclude is not applicable."
return false, msg
}
if ok, msg := checkUserInfo(match.UserInfo); !ok {
return false, msg
}
if ok, msg := checkResources(match.ResourceDescription); !ok {
if ok, msg := checkUserInfo(exclude.UserInfo); !ok {
return false, msg
}
var (
containsNamespaceSelector = false
containsObjectSelector = false
)
// since 'any' specify resources which will be ORed, it can be converted into multiple NamedRuleWithOperations in ValidatingAdmissionPolicy
for _, value := range match.Any {
if ok, msg := checkUserInfo(value.UserInfo); !ok {
return false, msg
}
if ok, msg := checkResources(value.ResourceDescription); !ok {
return false, msg
}
if value.NamespaceSelector != nil {
containsNamespaceSelector = true
}
if value.Selector != nil {
containsObjectSelector = true
}
if ok, msg := checkResources(match.ResourceDescription, true); !ok {
return false, msg
}
// since namespace/object selectors are applied to all NamedRuleWithOperations in ValidatingAdmissionPolicy, then
// we can't have more than one resource with namespace/object selectors.
if len(match.Any) > 1 && (containsNamespaceSelector || containsObjectSelector) {
msg = "skip generating ValidatingAdmissionPolicy: NamespaceSelector / ObjectSelector across multiple resources are not applicable."
if ok, msg := checkResources(exclude.ResourceDescription, false); !ok {
return false, msg
}
// since 'all' specify resources which will be ANDed, we can't have more than one resource.
if match.All != nil {
if len(match.All) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' is not applicable."
return false, msg
} else {
if ok, msg := checkUserInfo(match.All[0].UserInfo); !ok {
return false, msg
}
if ok, msg := checkResources(match.All[0].ResourceDescription); !ok {
return false, msg
}
}
if ok, msg := checkResourceFilter(match.Any, true); !ok {
return false, msg
}
if len(match.All) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' in the match block is not applicable."
return false, msg
}
if ok, msg := checkResourceFilter(match.All, true); !ok {
return false, msg
}
if ok, msg := checkResourceFilter(exclude.Any, false); !ok {
return false, msg
}
if len(exclude.All) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple 'all' in the exclude block is not applicable."
return false, msg
}
if ok, msg := checkResourceFilter(exclude.All, false); !ok {
return false, msg
}
return true, msg
}
func checkResources(resource kyvernov1.ResourceDescription) (bool, string) {
func checkRuleCount(spec *kyvernov1.Spec) (bool, string) {
var msg string
if len(spec.Rules) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple rules are not applicable."
return false, msg
}
return true, msg
}
func checkRuleType(rule kyvernov1.Rule) (bool, string) {
var msg string
if !rule.HasValidateCEL() {
msg = "skip generating ValidatingAdmissionPolicy for non CEL rules."
return false, msg
}
return true, msg
}
func checkResources(resource kyvernov1.ResourceDescription, isMatch bool) (bool, string) {
var msg string
if !isMatch {
if len(resource.Kinds) != 0 && len(resource.Namespaces) != 0 {
msg = "skip generating ValidatingAdmissionPolicy: excluding a resource within a namespace is not applicable."
return false, msg
}
}
if len(resource.Annotations) != 0 {
msg = "skip generating ValidatingAdmissionPolicy: Annotations in resource description is not applicable."
return false, msg
@ -122,3 +129,38 @@ func checkUserInfo(info kyvernov1.UserInfo) (bool, string) {
}
return true, msg
}
func checkResourceFilter(resFilters kyvernov1.ResourceFilters, isMatch bool) (bool, string) {
var msg string
containsNamespaceSelector := false
containsObjectSelector := false
for _, value := range resFilters {
if ok, msg := checkUserInfo(value.UserInfo); !ok {
return false, msg
}
if ok, msg := checkResources(value.ResourceDescription, isMatch); !ok {
return false, msg
}
if value.NamespaceSelector != nil {
containsNamespaceSelector = true
}
if value.Selector != nil {
containsObjectSelector = true
}
}
if !isMatch {
if containsNamespaceSelector || containsObjectSelector {
msg = "skip generating ValidatingAdmissionPolicy: NamespaceSelector / ObjectSelector in the exclude block is not applicable."
return false, msg
}
} else {
if len(resFilters) > 1 && (containsNamespaceSelector || containsObjectSelector) {
return false, "skip generating ValidatingAdmissionPolicy: NamespaceSelector / ObjectSelector across multiple resources in the match block are not applicable."
}
}
return true, msg
}

View file

@ -131,7 +131,7 @@ func Test_Check_Resources(t *testing.T) {
var res kyvernov1.ResourceDescription
err := json.Unmarshal(test.resource, &res)
assert.NilError(t, err)
out, _ := checkResources(res)
out, _ := checkResources(res, true)
assert.Equal(t, out, test.expected)
})
}

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-any-exclude-namespace-match-resource
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- assert:
file: validatingadmissionpolicy.yaml
- assert:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,10 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t16
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -1,7 +1,7 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t10
name: disallow-host-path-t16
spec:
validationFailureAction: Audit
background: false
@ -17,8 +17,10 @@ spec:
- UPDATE
exclude:
any:
- clusterRoles:
- cluster-admin
- resources:
namespaces:
- testing-ns
- staging-ns
validate:
cel:
expressions:

View file

@ -0,0 +1,41 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t16
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t16
spec:
failurePolicy: Fail
matchConstraints:
excludeResourceRules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resourceNames:
- testing-ns
- staging-ns
resources:
- namespaces
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
validations:
- expression: '!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume,
!has(volume.hostPath))'
message: HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath
must be unset.

View file

@ -0,0 +1,15 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t16-binding
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t16
spec:
policyName: disallow-host-path-t16
validationActions:
- Audit
- Warn

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-any-exclude-resource-match-with-namespace-selector
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- assert:
file: validatingadmissionpolicy.yaml
- assert:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,10 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t14
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,35 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t14
spec:
validationFailureAction: Audit
background: false
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
namespaceSelector:
matchLabels:
app: critical
exclude:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
names:
- "testing"
validate:
cel:
expressions:
- expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

View file

@ -0,0 +1,43 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t14
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t14
spec:
failurePolicy: Fail
matchConstraints:
excludeResourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resourceNames:
- testing
resources:
- deployments
namespaceSelector:
matchLabels:
app: critical
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
validations:
- expression: '!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume,
!has(volume.hostPath))'
message: HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath
must be unset.

View file

@ -0,0 +1,15 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t14-binding
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t14
spec:
policyName: disallow-host-path-t14
validationActions:
- Audit
- Warn

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-any-exclude-resource-match-with-object-selector
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- assert:
file: validatingadmissionpolicy.yaml
- assert:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,10 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t15
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,35 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t15
spec:
validationFailureAction: Audit
background: false
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
selector:
matchLabels:
app: critical
exclude:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
names:
- "testing"
validate:
cel:
expressions:
- expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

View file

@ -0,0 +1,43 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t15
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t15
spec:
failurePolicy: Fail
matchConstraints:
excludeResourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resourceNames:
- testing
resources:
- deployments
objectSelector:
matchLabels:
app: critical
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
validations:
- expression: '!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume,
!has(volume.hostPath))'
message: HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath
must be unset.

View file

@ -0,0 +1,15 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t15-binding
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t15
spec:
policyName: disallow-host-path-t15
validationActions:
- Audit
- Warn

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-any-exclude-resource
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- assert:
file: validatingadmissionpolicy.yaml
- assert:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,10 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t13
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,35 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t13
spec:
validationFailureAction: Audit
background: false
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Deployment
- StatefulSet
- ReplicaSet
- DaemonSet
operations:
- CREATE
- UPDATE
exclude:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
names:
- "testing"
validate:
cel:
expressions:
- expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

View file

@ -0,0 +1,43 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t13
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t13
spec:
failurePolicy: Fail
matchConstraints:
excludeResourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resourceNames:
- testing
resources:
- deployments
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
- statefulsets
- replicasets
- daemonsets
validations:
- expression: '!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume,
!has(volume.hostPath))'
message: HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath
must be unset.

View file

@ -0,0 +1,15 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t13-binding
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: disallow-host-path-t13
spec:
policyName: disallow-host-path-t13
validationActions:
- Audit
- Warn

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-match-kind-with-wildcard
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- assert:
file: validatingadmissionpolicy.yaml
- assert:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,10 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-label-app5
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,30 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-label-app5
spec:
validationFailureAction: Audit
background: false
rules:
- name: check-label-app
match:
all:
- resources:
kinds:
- '*'
operations:
- CREATE
namespaces:
- production
- staging
exclude:
all:
- resources:
kinds:
- "Deployment"
operations:
- CREATE
validate:
cel:
expressions:
- expression: "'app' in object.metadata.labels"

View file

@ -0,0 +1,41 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: check-label-app5
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: check-label-app5
spec:
failurePolicy: Fail
matchConstraints:
excludeResourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
resources:
- deployments
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: In
values:
- production
- staging
resourceRules:
- apiGroups:
- '*'
apiVersions:
- '*'
operations:
- CREATE
resources:
- '*'
scope: '*'
validations:
- expression: '''app'' in object.metadata.labels'

View file

@ -0,0 +1,15 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: check-label-app5-binding
ownerReferences:
- apiVersion: kyverno.io/v1
kind: ClusterPolicy
name: check-label-app5
spec:
policyName: check-label-app5
validationActions:
- Audit
- Warn

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-exclude-resources-in-specific-namespace
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- error:
file: validatingadmissionpolicy.yaml
- error:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,12 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t17
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready
validatingadmissionpolicy:
generated: false

View file

@ -0,0 +1,33 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t17
spec:
validationFailureAction: Audit
background: false
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
exclude:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
namespaces:
- testing-ns
- staging-ns
validate:
cel:
expressions:
- expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

View file

@ -0,0 +1,7 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t17
spec: {}

View file

@ -0,0 +1,7 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: disallow-host-path-t17-binding
spec: {}

View file

@ -0,0 +1,19 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-exclude-resources-with-namespace-selector
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- assert:
file: policy-assert.yaml
- name: step-02
try:
- error:
file: validatingadmissionpolicy.yaml
- error:
file: validatingadmissionpolicybinding.yaml

View file

@ -0,0 +1,36 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path-t10
spec:
validationFailureAction: Audit
background: false
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
exclude:
any:
- resources:
kinds:
- Deployment
operations:
- CREATE
- UPDATE
namespaceSelector:
matchExpressions:
- key: type
operator: In
values:
- connector
validate:
cel:
expressions:
- expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

View file

@ -2,7 +2,7 @@ apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-exclude
name: cpol-exclude-resources-with-object-selector
spec:
steps:
- name: step-01

View file

@ -2,7 +2,7 @@ apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: cpol-exclude-namespace
name: cpol-exclude-user-and-roles
spec:
steps:
- name: step-01

View file

@ -0,0 +1,12 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-label-app1
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready
validatingadmissionpolicy:
generated: false

View file

@ -0,0 +1,25 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-label-app1
spec:
validationFailureAction: Audit
background: false
rules:
- name: check-label-app
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- clusterRoles:
- cluster-admin
- subjects:
- kind: User
name: John
validate:
cel:
expressions:
- expression: "'app' in object.metadata.labels"

View file

@ -0,0 +1,7 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: check-label-app1
spec: {}

View file

@ -0,0 +1,7 @@
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
labels:
app.kubernetes.io/managed-by: kyverno
name: check-label-app1-binding
spec: {}