2019-10-18 17:45:24 -07:00
package policy
2019-10-01 11:50:10 -07:00
import (
"encoding/json"
2022-10-06 11:46:12 +05:30
"errors"
2021-04-29 22:21:23 +05:30
"fmt"
2019-10-01 11:50:10 -07:00
"testing"
2021-10-29 18:13:20 +02:00
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
2022-10-02 20:45:03 +01:00
"github.com/kyverno/kyverno/pkg/logging"
2021-02-22 17:22:34 -08:00
"github.com/kyverno/kyverno/pkg/openapi"
2019-10-01 11:50:10 -07:00
"gotest.tools/assert"
2022-10-06 11:46:12 +05:30
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
2019-10-01 11:50:10 -07:00
)
func Test_Validate_ResourceDescription_Empty ( t * testing . T ) {
2019-10-21 14:22:31 -07:00
var err error
2019-10-01 11:50:10 -07:00
rawResourcedescirption := [ ] byte ( ` { } ` )
2019-10-18 17:45:24 -07:00
var rd kyverno . ResourceDescription
2019-10-21 14:22:31 -07:00
err = json . Unmarshal ( rawResourcedescirption , & rd )
2019-10-01 11:50:10 -07:00
assert . NilError ( t , err )
2019-10-21 14:22:31 -07:00
_ , err = validateMatchedResourceDescription ( rd )
assert . Assert ( t , err != nil )
2019-10-01 11:50:10 -07:00
}
2019-10-21 14:22:31 -07:00
func Test_Validate_ResourceDescription_MatchedValid ( t * testing . T ) {
rawResourcedescirption := [ ] byte ( `
2019-10-01 11:50:10 -07:00
{
2019-10-21 14:22:31 -07:00
"kinds" : [
"Deployment"
] ,
2019-10-01 11:50:10 -07:00
"selector" : {
"matchLabels" : {
"app.type" : "prod"
}
}
} ` )
2019-10-18 17:45:24 -07:00
var rd kyverno . ResourceDescription
2019-10-21 14:22:31 -07:00
err := json . Unmarshal ( rawResourcedescirption , & rd )
2019-10-01 11:50:10 -07:00
assert . NilError ( t , err )
2019-10-21 14:22:31 -07:00
_ , err = validateMatchedResourceDescription ( rd )
assert . NilError ( t , err )
2019-10-01 11:50:10 -07:00
}
2019-10-01 15:01:24 -07:00
2021-02-02 02:57:16 +05:30
func Test_Validate_DenyConditions_KeyRequestOperation_Empty ( t * testing . T ) {
denyConditions := [ ] byte ( ` [] ` )
2021-03-02 10:01:06 +05:30
var dcs apiextensions . JSON
2021-02-02 02:57:16 +05:30
err := json . Unmarshal ( denyConditions , & dcs )
assert . NilError ( t , err )
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-02-02 02:57:16 +05:30
}
func Test_Validate_Preconditions_KeyRequestOperation_Empty ( t * testing . T ) {
preConditions := [ ] byte ( ` [] ` )
2021-03-02 10:01:06 +05:30
var pcs apiextensions . JSON
2021-02-02 02:57:16 +05:30
err := json . Unmarshal ( preConditions , & pcs )
assert . NilError ( t , err )
_ , err = validateConditions ( pcs , "preconditions" )
assert . NilError ( t , err )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( pcs , "preconditions" )
assert . NilError ( t , err )
2021-02-02 02:57:16 +05:30
}
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_ExpectedValue ( t * testing . T ) {
denyConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : "DELETE"
} ,
{
"key" : "{{request.operation}}" ,
"operator" : "NotEquals" ,
"value" : "CREATE"
} ,
{
"key" : "{{request.operation}}" ,
"operator" : "NotEquals" ,
"value" : "CONNECT"
} ,
{
"key" : "{{ request.operation }}" ,
"operator" : "NotEquals" ,
"value" : "UPDATE"
} ,
{
"key" : "{{lbServiceCount}}" ,
"operator" : "Equals" ,
"value" : "2"
}
]
` )
2021-03-02 10:01:06 +05:30
var dcs apiextensions . JSON
2021-02-02 02:57:16 +05:30
err := json . Unmarshal ( denyConditions , & dcs )
assert . NilError ( t , err )
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-02-02 02:57:16 +05:30
}
2021-02-17 02:36:07 +05:30
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_RightfullyTemplatizedValue ( t * testing . T ) {
denyConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : "{{ \"ops-cm\".data.\"deny-ops\"}}"
} ,
{
"key" : "{{ request.operation }}" ,
"operator" : "NotEquals" ,
"value" : "UPDATE"
}
]
` )
2021-03-02 10:01:06 +05:30
var dcs apiextensions . JSON
2021-02-17 02:36:07 +05:30
err := json . Unmarshal ( denyConditions , & dcs )
assert . NilError ( t , err )
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
2021-02-17 02:36:07 +05:30
}
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_WrongfullyTemplatizedValue ( t * testing . T ) {
denyConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : "{{ \"ops-cm\".data.\"deny-ops\" }"
} ,
{
"key" : "{{ request.operation }}" ,
"operator" : "NotEquals" ,
"value" : "UPDATE"
}
]
` )
var dcs [ ] kyverno . Condition
err := json . Unmarshal ( denyConditions , & dcs )
assert . NilError ( t , err )
_ , err = validateConditions ( dcs , "conditions" )
assert . Assert ( t , err != nil )
}
2021-02-02 02:57:16 +05:30
func Test_Validate_PreconditionsValuesString_KeyRequestOperation_UnknownValue ( t * testing . T ) {
preConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : "foobar"
} ,
{
"key" : "{{request.operation}}" ,
"operator" : "NotEquals" ,
"value" : "CREATE"
}
]
` )
2021-03-02 10:01:06 +05:30
var pcs apiextensions . JSON
2021-02-02 02:57:16 +05:30
err := json . Unmarshal ( preConditions , & pcs )
assert . NilError ( t , err )
_ , err = validateConditions ( pcs , "preconditions" )
assert . Assert ( t , err != nil )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( pcs , "preconditions" )
assert . Assert ( t , err != nil )
2021-02-02 02:57:16 +05:30
}
func Test_Validate_DenyConditionsValuesList_KeyRequestOperation_ExpectedItem ( t * testing . T ) {
denyConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : [
"CREATE" ,
"DELETE" ,
"CONNECT"
]
} ,
{
"key" : "{{request.operation}}" ,
"operator" : "NotEquals" ,
"value" : [
"UPDATE"
]
} ,
{
"key" : "{{lbServiceCount}}" ,
"operator" : "Equals" ,
"value" : "2"
}
]
` )
var dcs [ ] kyverno . Condition
err := json . Unmarshal ( denyConditions , & dcs )
assert . NilError ( t , err )
_ , err = validateConditions ( dcs , "conditions" )
assert . NilError ( t , err )
}
func Test_Validate_PreconditionsValuesList_KeyRequestOperation_UnknownItem ( t * testing . T ) {
preConditions := [ ] byte ( `
[
{
"key" : "{{request.operation}}" ,
"operator" : "Equals" ,
"value" : [
"foobar" ,
"CREATE"
]
} ,
{
"key" : "{{request.operation}}" ,
"operator" : "NotEquals" ,
"value" : [
"foobar"
]
}
]
` )
2021-03-02 10:01:06 +05:30
var pcs apiextensions . JSON
2021-02-02 02:57:16 +05:30
err := json . Unmarshal ( preConditions , & pcs )
assert . NilError ( t , err )
_ , err = validateConditions ( pcs , "preconditions" )
assert . Assert ( t , err != nil )
2021-03-02 10:01:06 +05:30
_ , err = validateConditions ( pcs , "preconditions" )
assert . Assert ( t , err != nil )
2021-02-02 02:57:16 +05:30
}
2019-10-01 11:50:10 -07:00
func Test_Validate_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
2019-11-13 13:56:07 -08:00
"apiVersion" : "kyverno.io/v1" ,
2019-10-01 11:50:10 -07:00
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "container-security-context"
} ,
"spec" : {
"rules" : [
{
2019-10-03 14:47:50 -07:00
"name" : "validate-runAsNonRoot" ,
2019-10-01 11:50:10 -07:00
"match" : {
"resources" : {
"kinds" : [
"Deployment"
] ,
"selector" : {
"matchLabels" : {
"app.type" : "prod"
}
}
}
} ,
"validate" : {
"message" : "validate container security contexts" ,
"anyPattern" : [
{
"spec" : {
"template" : {
"spec" : {
"^(containers)" : [
{
"securityContext" : {
2019-10-03 14:47:50 -07:00
"runAsNonRoot" : "true"
2019-10-01 11:50:10 -07:00
}
}
]
}
}
}
}
]
}
2019-10-03 14:47:50 -07:00
} ,
{
"name" : "validate-allowPrivilegeEscalation" ,
"match" : {
"resources" : {
"kinds" : [
"Deployment"
] ,
"selector" : {
"matchLabels" : {
"app.type" : "prod"
}
}
}
} ,
"validate" : {
"message" : "validate container security contexts" ,
"pattern" : {
"spec" : {
"template" : {
"spec" : {
"^(containers)" : [
{
"securityContext" : {
"allowPrivilegeEscalation" : "false"
}
}
]
}
}
}
}
}
2019-10-01 11:50:10 -07:00
}
]
}
} ` )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
2021-01-06 16:32:02 -08:00
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2019-10-03 12:52:58 -07:00
2022-10-12 18:54:16 +02:00
_ , err = Validate ( policy , nil , true , openApiManager )
2019-10-03 12:52:58 -07:00
assert . NilError ( t , err )
2019-10-03 16:49:41 -07:00
}
func Test_Validate_ErrorFormat ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
2019-11-13 13:56:07 -08:00
"apiVersion" : "kyverno.io/v1" ,
2019-10-03 16:49:41 -07:00
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "test-error-format"
} ,
"spec" : {
"rules" : [
{
"name" : "image-pull-policy" ,
"match" : {
"resources" : {
"kinds" : [
"Deployment"
] ,
"selector" : {
"matchLabels" : {
"app" : "nginxlatest"
}
}
}
} ,
"exclude" : {
"resources" : {
"selector" : {
"app" : "nginxlatest"
}
}
} ,
"mutate" : {
2022-01-04 17:36:33 -08:00
"patchStrategicMerge" : {
2019-10-03 16:49:41 -07:00
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"=(image)" : "*latest" ,
"imagePullPolicy" : "IfNotPresent"
}
]
}
}
}
}
}
} ,
{
"name" : "validate-user-privilege" ,
"match" : {
"resources" : {
"kinds" : [ ] ,
"selector" : {
"matchLabels" : {
"app.type" : "prod"
}
}
}
} ,
"validate" : {
"message" : "validate container security contexts" ,
"anyPattern" : [
{
"spec" : {
"template" : {
"spec" : {
"^(containers)" : [
{
"securityContext" : {
"runAsNonRoot" : "true"
}
}
]
}
}
}
}
]
}
} ,
{
"name" : "validate-user-privilege" ,
"match" : {
"resources" : {
"kinds" : [
"Deployment"
] ,
"selector" : {
"matchLabels" : {
"app.type" : "prod"
}
}
}
} ,
"validate" : {
"message" : "validate container security contexts" ,
"pattern" : {
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"^(securityContext)" : {
"allowPrivilegeEscalation" : "false"
}
}
]
}
}
}
}
}
} ,
{
"name" : "default-networkpolicy" ,
"match" : {
"resources" : {
"kinds" : [
"Namespace"
] ,
"name" : "devtest"
}
} ,
"generate" : {
"kind" : "ConfigMap" ,
"name" : "copied-cm" ,
"clone" : {
"^(namespace)" : "default" ,
"name" : "game-config"
}
}
}
]
}
}
` )
2021-01-06 16:32:02 -08:00
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2019-10-21 14:22:31 -07:00
assert . Assert ( t , err != nil )
2019-10-03 14:47:50 -07:00
}
2019-12-05 11:55:00 -08:00
2019-12-30 17:08:50 -08:00
func Test_BackGroundUserInfo_match_roles ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "match.roles" ,
"match" : {
"roles" : [
"a" ,
"b"
]
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = containsUserVariables ( policy , nil )
2020-05-06 19:46:32 +05:30
assert . Equal ( t , err . Error ( ) , "invalid variable used at path: spec/rules[0]/match/roles" )
2019-12-30 17:08:50 -08:00
}
func Test_BackGroundUserInfo_match_clusterRoles ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "match.clusterRoles" ,
"match" : {
"clusterRoles" : [
"a" ,
"b"
]
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = containsUserVariables ( policy , nil )
2020-05-06 19:46:32 +05:30
assert . Equal ( t , err . Error ( ) , "invalid variable used at path: spec/rules[0]/match/clusterRoles" )
2019-12-30 17:08:50 -08:00
}
func Test_BackGroundUserInfo_match_subjects ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "match.subjects" ,
"match" : {
"subjects" : [
{
"Name" : "a"
} ,
{
"Name" : "b"
}
]
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = containsUserVariables ( policy , nil )
2020-05-06 19:46:32 +05:30
assert . Equal ( t , err . Error ( ) , "invalid variable used at path: spec/rules[0]/match/subjects" )
2019-12-30 17:08:50 -08:00
}
2022-01-04 17:36:33 -08:00
func Test_BackGroundUserInfo_mutate_patchStrategicMerge1 ( t * testing . T ) {
2019-12-30 17:08:50 -08:00
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "mutate.overlay1" ,
"mutate" : {
2022-01-04 17:36:33 -08:00
"patchStrategicMerge" : {
2019-12-30 17:08:50 -08:00
"var1" : "{{request.userInfo}}"
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 17:22:34 -08:00
assert . Assert ( t , err != nil )
2019-12-30 17:08:50 -08:00
}
2022-01-04 17:36:33 -08:00
func Test_BackGroundUserInfo_mutate_patchStrategicMerge2 ( t * testing . T ) {
2019-12-30 17:08:50 -08:00
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "mutate.overlay2" ,
"mutate" : {
2022-01-04 17:36:33 -08:00
"patchStrategicMerge" : {
2019-12-30 17:08:50 -08:00
"var1" : "{{request.userInfo.userName}}"
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 17:22:34 -08:00
assert . Assert ( t , err != nil )
2019-12-30 17:08:50 -08:00
}
func Test_BackGroundUserInfo_validate_pattern ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
2022-01-04 17:36:33 -08:00
"name" : "validate-patch-strategic-merge" ,
2019-12-30 17:08:50 -08:00
"validate" : {
"pattern" : {
"var1" : "{{request.userInfo}}"
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 12:08:26 -08:00
assert . Assert ( t , err != nil , err )
2019-12-30 17:08:50 -08:00
}
func Test_BackGroundUserInfo_validate_anyPattern ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "validate.anyPattern" ,
"validate" : {
"anyPattern" : [
{
"var1" : "temp"
} ,
{
"var1" : "{{request.userInfo}}"
}
]
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 17:22:34 -08:00
assert . Assert ( t , err != nil )
2019-12-30 17:08:50 -08:00
}
2020-01-13 18:56:11 -08:00
func Test_BackGroundUserInfo_validate_anyPattern_multiple_var ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "validate.anyPattern" ,
"validate" : {
"anyPattern" : [
{
"var1" : "temp"
} ,
{
"var1" : "{{request.userInfo}}-{{temp}}"
}
]
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 17:22:34 -08:00
assert . Assert ( t , err != nil )
2020-01-13 18:56:11 -08:00
}
func Test_BackGroundUserInfo_validate_anyPattern_serviceAccount ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "disallow-root-user"
} ,
"spec" : {
"rules" : [
{
"name" : "validate.anyPattern" ,
"validate" : {
"anyPattern" : [
{
"var1" : "temp"
} ,
{
"var1" : "{{serviceAccountName}}"
}
]
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2021-11-03 11:16:55 -07:00
err = ValidateVariables ( policy , true )
2021-02-22 17:22:34 -08:00
assert . Assert ( t , err != nil )
2020-01-13 18:56:11 -08:00
}
2020-02-26 16:08:56 +05:30
func Test_ruleOnlyDealsWithResourceMetaData ( t * testing . T ) {
testcases := [ ] struct {
description string
rule [ ] byte
expectedOutput bool
} {
{
2022-01-04 17:36:33 -08:00
description : "Test mutate patchStrategicMerge - pass" ,
rule : [ ] byte ( ` { "name":"testPatches1","mutate": { "patchStrategicMerge": { "metadata": { "containers":[ { "(image)":"*","imagePullPolicy":"IfNotPresent"}]}}}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : true ,
} ,
{
2022-01-04 17:36:33 -08:00
description : "Test mutate patchStrategicMerge - fail" ,
rule : [ ] byte ( ` { "name":"testPatches2","mutate": { "patchStrategicMerge": { "spec": { "containers":[ { "(image)":"*","imagePullPolicy":"IfNotPresent"}]}}}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : false ,
} ,
{
description : "Test mutate patch - pass" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testPatches3","mutate": { "patchesJson6902": "[ { \"path\":\"/metadata/labels/isMutated\",\"op\":\"add\",\"value\":\"true\"}, { \"path\":\"/metadata/labels/app\",\"op\":\"replace\",\"value\":\"nginx_is_mutated\"}]"}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : true ,
} ,
{
description : "Test mutate patch - fail" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testPatches4","mutate": { "patchesJson6902": "[ { \"path\":\"/spec/labels/isMutated\",\"op\":\"add\",\"value\":\"true\"}, { \"path\":\"/metadata/labels/app\",\"op\":\"replace\",\"value\":\"nginx_is_mutated\"}]" }} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : false ,
} ,
{
description : "Test validate - pass" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testValidate1","validate": { "message":"CPU and memory resource requests and limits are required","pattern": { "metadata": { "containers":[ { "(name)":"*","ports":[ { "containerPort":80}]}]}}}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : true ,
} ,
{
description : "Test validate - fail" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testValidate2","validate": { "message":"CPU and memory resource requests and limits are required","pattern": { "spec": { "containers":[ { "(name)":"*","ports":[ { "containerPort":80}]}]}}}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : false ,
} ,
{
description : "Test validate any pattern - pass" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testValidateAnyPattern1","validate": { "message":"Volumes white list","anyPattern":[ { "metadata": { "volumes":[ { "hostPath":"*"}]}}, { "metadata": { "volumes":[ { "emptyDir":"*"}]}}, { "metadata": { "volumes":[ { "configMap":"*"}]}}]}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : true ,
} ,
{
description : "Test validate any pattern - fail" ,
2022-01-04 17:36:33 -08:00
rule : [ ] byte ( ` { "name":"testValidateAnyPattern2","validate": { "message":"Volumes white list","anyPattern":[ { "spec": { "volumes":[ { "hostPath":"*"}]}}, { "metadata": { "volumes":[ { "emptyDir":"*"}]}}, { "metadata": { "volumes":[ { "configMap":"*"}]}}]}} ` ) ,
2020-02-26 16:08:56 +05:30
expectedOutput : false ,
} ,
}
for i , testcase := range testcases {
var rule kyverno . Rule
_ = json . Unmarshal ( testcase . rule , & rule )
output := ruleOnlyDealsWithResourceMetaData ( rule )
if output != testcase . expectedOutput {
2022-01-04 17:36:33 -08:00
t . Errorf ( "Testcase [%d] (%s) failed" , i + 1 , testcase . description )
2020-02-26 16:08:56 +05:30
}
}
2020-03-20 20:23:34 +05:30
}
2021-04-29 22:21:23 +05:30
2021-04-29 23:44:55 +05:30
func Test_Validate_Kind ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "policy-to-monitor-root-user-access"
} ,
"spec" : {
"validationFailureAction" : "audit" ,
"rules" : [
{
"name" : "monitor-annotation-for-root-user-access" ,
"match" : {
"resources" : {
"selector" : {
"matchLabels" : {
"AllowRootUserAccess" : "true"
}
}
}
} ,
"validate" : {
"message" : "Label provisioner.wg.net/cloudprovider is required" ,
"pattern" : {
"metadata" : {
"labels" : {
"provisioner.wg.net/cloudprovider" : "*"
}
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2021-04-29 23:44:55 +05:30
assert . Assert ( t , err != nil )
}
2021-05-04 18:28:30 +02:00
2021-07-29 01:29:53 +05:30
func Test_Validate_Any_Kind ( t * testing . T ) {
rawPolicy := [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "policy-to-monitor-root-user-access"
} ,
"spec" : {
"validationFailureAction" : "audit" ,
"rules" : [
{
"name" : "monitor-annotation-for-root-user-access" ,
"match" : {
"any" : [
{
"resources" : {
"selector" : {
"matchLabels" : {
"AllowRootUserAccess" : "true"
}
}
}
}
]
} ,
"validate" : {
"message" : "Label provisioner.wg.net/cloudprovider is required" ,
"pattern" : {
"metadata" : {
"labels" : {
"provisioner.wg.net/cloudprovider" : "*"
}
}
}
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2021-07-29 01:29:53 +05:30
assert . Assert ( t , err != nil )
}
2021-04-29 22:21:23 +05:30
func Test_checkAutoGenRules ( t * testing . T ) {
testCases := [ ] struct {
name string
policy [ ] byte
expectedResult bool
} {
{
2021-04-29 14:59:37 -07:00
name : "rule-missing-autogen-cronjob" ,
policy : [ ] byte ( ` { "apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata": { "name":"test","annotations": { "pod-policies.kyverno.io/autogen-controllers":"Deployment,CronJob"}},"spec": { "rules":[ { "match": { "resources": { "kinds":["Pod"]}},"name":"block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}, { "match": { "resources": { "kinds":["Deployment"]}},"name":"autogen-block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "spec": { "template": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}}}]}} ` ) ,
expectedResult : true ,
2021-04-29 22:21:23 +05:30
} ,
{
2021-04-29 14:59:37 -07:00
name : "rule-missing-autogen-deployment" ,
policy : [ ] byte ( ` { "apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata": { "name":"test","annotations": { "pod-policies.kyverno.io/autogen-controllers":"Deployment,CronJob"}},"spec": { "rules":[ { "match": { "resources": { "kinds":["Pod"]}},"name":"block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}, { "match": { "resources": { "kinds":["CronJob"]}},"name":"autogen-cronjob-block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "spec": { "jobTemplate": { "spec": { "template": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}}}}}]}} ` ) ,
expectedResult : true ,
2021-04-29 22:21:23 +05:30
} ,
{
2021-04-29 14:59:37 -07:00
name : "rule-missing-autogen-all" ,
policy : [ ] byte ( ` { "apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata": { "name":"test","annotations": { "pod-policies.kyverno.io/autogen-controllers":"Deployment,CronJob,StatefulSet,Job,DaemonSet"}},"spec": { "rules":[ { "match": { "resources": { "kinds":["Pod"]}},"name":"block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}]}} ` ) ,
2021-04-29 22:21:23 +05:30
expectedResult : true ,
} ,
{
2021-04-29 14:59:37 -07:00
name : "rule-with-autogen-disabled" ,
policy : [ ] byte ( ` { "apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata": { "name":"test","annotations": { "pod-policies.kyverno.io/autogen-controllers":"none"}},"spec": { "rules":[ { "match": { "resources": { "kinds":["Pod"]}},"name":"block-old-flux","validate": { "message":"CannotuseoldFluxv1annotation.","pattern": { "metadata": { "=(annotations)": { "X(fluxcd.io/*)":"*?"}}}}}]}} ` ) ,
expectedResult : false ,
2021-04-29 22:21:23 +05:30
} ,
}
for _ , test := range testCases {
var policy kyverno . ClusterPolicy
err := json . Unmarshal ( test . policy , & policy )
assert . NilError ( t , err )
2022-10-02 20:45:03 +01:00
res := missingAutoGenRules ( & policy , logging . GlobalLogger ( ) )
2021-04-29 22:21:23 +05:30
assert . Equal ( t , test . expectedResult , res , fmt . Sprintf ( "test %s failed" , test . name ) )
}
}
2021-05-04 18:28:30 +02:00
func Test_Validate_ApiCall ( t * testing . T ) {
testCases := [ ] struct {
resource kyverno . ContextEntry
expectedResult interface { }
} {
{
resource : kyverno . ContextEntry {
APICall : & kyverno . APICall {
URLPath : "/apis/networking.k8s.io/v1/namespaces/{{request.namespace}}/networkpolicies" ,
JMESPath : "" ,
} ,
} ,
expectedResult : nil ,
} ,
{
resource : kyverno . ContextEntry {
APICall : & kyverno . APICall {
URLPath : "/apis/networking.k8s.io/v1/namespaces/{{request.namespace}}/networkpolicies" ,
JMESPath : "items[" ,
} ,
} ,
expectedResult : "failed to parse JMESPath items[: SyntaxError: Expected tStar, received: tEOF" ,
} ,
{
resource : kyverno . ContextEntry {
APICall : & kyverno . APICall {
URLPath : "/apis/networking.k8s.io/v1/namespaces/{{request.namespace}}/networkpolicies" ,
JMESPath : "items[{{request.namespace}}" ,
} ,
} ,
expectedResult : nil ,
} ,
}
for _ , testCase := range testCases {
err := validateAPICall ( testCase . resource )
if err == nil {
assert . Equal ( t , err , testCase . expectedResult )
} else {
assert . Equal ( t , err . Error ( ) , testCase . expectedResult )
}
}
}
2022-10-06 11:46:12 +05:30
2021-07-14 23:49:15 +05:30
func Test_Wildcards_Kind ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "require-labels"
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"rules" : [
{
"name" : "check-for-labels" ,
"match" : {
"resources" : {
"kinds" : [
"*"
]
}
} ,
"validate" : {
"message" : "label 'app.kubernetes.io/name' is required" ,
"pattern" : {
"metadata" : {
"labels" : {
"app.kubernetes.io/name" : "?*"
}
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2021-07-14 23:49:15 +05:30
assert . Assert ( t , err != nil )
}
2021-10-22 01:48:22 +05:30
func Test_Namespced_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "Policy" ,
"metadata" : {
"name" : "evil-policy-match-foreign-pods" ,
"namespace" : "customer-foo"
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"rules" : [
{
"name" : "evil-validation" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
] ,
"namespaces" : [
"customer-bar"
]
}
} ,
"validate" : {
"message" : "Mua ah ah ... you've been pwned by customer-foo" ,
"pattern" : {
"metadata" : {
"annotations" : {
"pwned-by-customer-foo" : "true"
}
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2021-10-22 01:48:22 +05:30
assert . Assert ( t , err != nil )
}
2021-11-30 18:14:58 +01:00
func Test_patchesJson6902_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "set-max-surge-yaml-to-json"
} ,
"spec" : {
"background" : false ,
"schemaValidation" : false ,
"rules" : [
{
"name" : "set-max-surge" ,
"context" : [
{
"name" : "source" ,
"configMap" : {
"name" : "source-yaml-to-json" ,
"namespace" : "default"
}
}
] ,
"match" : {
"resources" : {
"kinds" : [
"Deployment"
]
}
} ,
"mutate" : {
"patchesJson6902" : "- op: replace\n path: /spec/strategy\n value: {{ source.data.strategy }}"
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2021-11-30 18:14:58 +01:00
assert . NilError ( t , err )
}
2022-03-11 15:09:32 +05:30
func Test_deny_exec ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "deny-exec-to-pod"
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"schemaValidation" : false ,
"rules" : [
{
"name" : "deny-pod-exec" ,
"match" : {
"resources" : {
"kinds" : [
"PodExecOptions"
]
}
} ,
"preconditions" : {
"all" : [
{
"key" : "{{ request.operation }}" ,
"operator" : "Equals" ,
"value" : "CONNECT"
}
]
} ,
"validate" : {
"message" : "Containers can't be exec'd into in production." ,
"deny" : { }
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2022-03-11 15:09:32 +05:30
assert . NilError ( t , err )
}
2022-03-14 16:03:13 +05:30
2022-10-14 11:09:57 +05:30
func Test_SignatureAlgorithm ( t * testing . T ) {
testcases := [ ] struct {
description string
policy [ ] byte
expectedOutput bool
} {
{
description : "Test empty signature algorithm - pass" ,
policy : [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-empty-signature-algorithm"
} ,
"spec" : {
"rules" : [
{
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"count" : 1 ,
"entries" : [
{
"keys" : {
"publicKeys" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM\n5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----"
}
}
]
}
]
}
]
}
]
}
} ` ) ,
expectedOutput : true ,
} ,
{
description : "Test invalid signature algorithm - fail" ,
policy : [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-invalid-signature-algorithm"
} ,
"spec" : {
"rules" : [
{
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"count" : 1 ,
"entries" : [
{
"keys" : {
"publicKeys" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM\n5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----" ,
"signatureAlgorithm" : "sha123"
}
}
]
}
]
}
]
}
]
}
} ` ) ,
expectedOutput : false ,
} ,
{
description : "Test invalid signature algorithm - fail" ,
policy : [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-valid-signature-algorithm"
} ,
"spec" : {
"rules" : [
{
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"count" : 1 ,
"entries" : [
{
"keys" : {
"publicKeys" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM\n5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----" ,
"signatureAlgorithm" : "sha256"
}
}
]
}
]
}
]
}
]
}
} ` ) ,
expectedOutput : true ,
} ,
}
for _ , testcase := range testcases {
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( testcase . policy , & policy )
assert . NilError ( t , err )
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
if testcase . expectedOutput {
assert . NilError ( t , err )
} else {
assert . ErrorContains ( t , err , "Invalid signature algorithm provided" )
}
}
}
2022-03-14 16:03:13 +05:30
func Test_existing_resource_policy ( t * testing . T ) {
var err error
rawPolicy := [ ] byte ( ` {
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "np-test-1"
} ,
"spec" : {
"validationFailureAction" : "audit" ,
"rules" : [
{
"name" : "no-LoadBalancer" ,
"match" : {
"any" : [
{
"resources" : {
"kinds" : [
"networking.k8s.io/v1/NetworkPolicy"
]
}
}
]
} ,
"validate" : {
"message" : "np-test" ,
"pattern" : {
"metadata" : {
"name" : "?*"
}
}
}
}
]
}
} ` )
var policy * kyverno . ClusterPolicy
err = json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
_ , err = Validate ( policy , nil , true , openApiManager )
2022-03-16 00:50:33 -04:00
assert . NilError ( t , err )
}
func Test_PodControllerAutoGenExclusion_All_Controllers_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "add-all-pod-controller-annotations" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "DaemonSet,Job,CronJob,Deployment,StatefulSet"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"rules" : [
{
"name" : "validate-livenessProbe-readinessProbe" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"validate" : {
"message" : "Liveness and readiness probes are required." ,
"pattern" : {
"spec" : {
"containers" : [
{
"livenessProbe" : {
"periodSeconds" : ">0"
} ,
"readinessProbe" : {
"periodSeconds" : ">0"
}
}
]
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
res , err := Validate ( policy , nil , true , openApiManager )
2022-03-16 00:50:33 -04:00
assert . NilError ( t , err )
assert . Assert ( t , res == nil )
}
func Test_PodControllerAutoGenExclusion_Not_All_Controllers_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "add-not-all-pod-controller-annotations" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "DaemonSet,Job,CronJob,Deployment"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"rules" : [
{
"name" : "validate-livenessProbe-readinessProbe" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"validate" : {
"message" : "Liveness and readiness probes are required." ,
"pattern" : {
"spec" : {
"containers" : [
{
"livenessProbe" : {
"periodSeconds" : ">0"
} ,
"readinessProbe" : {
"periodSeconds" : ">0"
}
}
]
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
2022-11-03 09:05:23 +00:00
warnings , err := Validate ( policy , nil , true , openApiManager )
assert . Assert ( t , warnings != nil )
2022-03-16 00:50:33 -04:00
assert . NilError ( t , err )
}
func Test_PodControllerAutoGenExclusion_None_Policy ( t * testing . T ) {
rawPolicy := [ ] byte ( `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "add-none-pod-controller-annotations" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "none"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"rules" : [
{
"name" : "validate-livenessProbe-readinessProbe" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"validate" : {
"message" : "Liveness and readiness probes are required." ,
"pattern" : {
"spec" : {
"containers" : [
{
"livenessProbe" : {
"periodSeconds" : ">0"
} ,
"readinessProbe" : {
"periodSeconds" : ">0"
}
}
]
}
}
}
}
]
}
}
` )
var policy * kyverno . ClusterPolicy
err := json . Unmarshal ( rawPolicy , & policy )
assert . NilError ( t , err )
2022-10-12 18:54:16 +02:00
openApiManager , _ := openapi . NewManager ( )
2022-11-03 09:05:23 +00:00
warnings , err := Validate ( policy , nil , true , openApiManager )
assert . Assert ( t , warnings == nil )
2022-03-14 16:03:13 +05:30
assert . NilError ( t , err )
}
2022-10-06 11:46:12 +05:30
2022-10-17 20:55:03 +05:30
func Test_ValidateJSON6902 ( t * testing . T ) {
var patch string = ` - path : "/metadata/labels/img"
op : addition
value : "nginx" `
err := validateJSONPatch ( patch , 0 )
assert . Error ( t , err , "Unexpected kind: spec.rules[0]: addition" )
patch = ` - path : "/metadata/labels/img"
op : add
value : "nginx" `
err = validateJSONPatch ( patch , 0 )
assert . NilError ( t , err )
patch = ` - path : "/metadata/labels/img"
op : add
value : nginx " `
err = validateJSONPatch ( patch , 0 )
assert . Error ( t , err , ` missing quote around value: spec.rules[0]: nginx" ` )
patch = ` - path : "/metadata/labels/img"
op : add
value : { "node.kubernetes.io/role" : test " } `
err = validateJSONPatch ( patch , 0 )
assert . Error ( t , err , ` missing quote around value: spec.rules[0]: map[node.kubernetes.io/role:test"] ` )
patch = ` - path : "/metadata/labels/img"
op : add
value : "nginx" `
err = validateJSONPatch ( patch , 0 )
assert . NilError ( t , err )
}
2022-10-06 11:46:12 +05:30
func Test_ValidateNamespace ( t * testing . T ) {
testcases := [ ] struct {
description string
spec * kyverno . Spec
expectedError error
} {
{
description : "tc1" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "conflicting namespaces found in path: spec.validationFailureActionOverrides[1].namespaces: default" ) ,
} ,
{
description : "tc2" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Mutation : kyverno . Mutation {
RawPatchStrategicMerge : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "labels": { "app-name": " {{ request .object .metadata .name }} "}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "conflicting namespaces found in path: spec.validationFailureActionOverrides[1].namespaces: default" ) ,
} ,
{
description : "tc3" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default*" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'default*' matches with namespace 'default'" ) ,
} ,
{
description : "tc4" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '*' matches with namespace 'default'" ) ,
} ,
{
description : "tc5" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"?*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' matches with namespace 'default'" ) ,
} ,
{
description : "tc6" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default?" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default1" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'default?' matches with namespace 'default1'" ) ,
} ,
{
description : "tc7" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default*" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"?*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' matches with namespace 'test'" ) ,
} ,
{
description : "tc8" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"*" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"?*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '?*' conflicts with the pattern '*'" ) ,
} ,
{
description : "tc9" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default*" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern 'test*' matches with namespace 'test'" ) ,
} ,
{
description : "tc10" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"*efault" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
expectedError : errors . New ( "path: spec.validationFailureActionOverrides[1].namespaces: wildcard pattern '*efault' matches with namespace 'default'" ) ,
} ,
{
description : "tc11" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default-*" ,
"test" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
} ,
{
description : "tc12" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default*?" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
"test*" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
} ,
{
description : "tc13" ,
spec : & kyverno . Spec {
2022-11-01 09:56:52 +00:00
ValidationFailureAction : "Enforce" ,
2022-10-06 11:46:12 +05:30
ValidationFailureActionOverrides : [ ] kyverno . ValidationFailureActionOverride {
{
2022-11-01 09:56:52 +00:00
Action : "Enforce" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default?" ,
} ,
} ,
{
2022-11-01 09:56:52 +00:00
Action : "Audit" ,
2022-10-06 11:46:12 +05:30
Namespaces : [ ] string {
"default" ,
} ,
} ,
} ,
Rules : [ ] kyverno . Rule {
{
Name : "require-labels" ,
MatchResources : kyverno . MatchResources { ResourceDescription : kyverno . ResourceDescription { Kinds : [ ] string { "Pod" } } } ,
Validation : kyverno . Validation {
Message : "label 'app.kubernetes.io/name' is required" ,
RawPattern : & apiextv1 . JSON { Raw : [ ] byte ( ` "metadata": { "lables": { "app.kubernetes.io/name": "?*"}} ` ) } ,
} ,
} ,
} ,
} ,
} ,
}
for _ , tc := range testcases {
t . Run ( tc . description , func ( t * testing . T ) {
err := validateNamespaces ( tc . spec , field . NewPath ( "spec" ) . Child ( "validationFailureActionOverrides" ) )
if tc . expectedError != nil {
assert . Error ( t , err , tc . expectedError . Error ( ) )
} else {
assert . NilError ( t , err )
}
} )
}
}