1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

adding any/all under match and exclude blocks (#2130)

* intial commit

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* update types

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* updated all type

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* extract to single struct

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* updated match resource description function

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* minor test working

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* match resources test is working

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* exclude resources test is working

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* changed double negetive in logic

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* yamls updated and added validation and cache loops

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* match exclude working but need to fix matchExcludeConflict function

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* restored doMatchAndExcludeConflict function

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* rewrote the matchExcludeConflictFunction

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* finalizing completed till utils_test.go

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* ready for review complete

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* update yamls

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* one more merge conflict solved

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* regenerates YAMLs

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* possible fix for failing tests

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* removed duplicate any/all logic and added a test, (rest refacotring is in progress)

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* cache test is working

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* improved cache test and it is working

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* added check for mutate and generate policies too

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* reverted validate.go to older logic

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* removed commented code

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>

* removed extra comments

Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
This commit is contained in:
Arsh Sharma 2021-07-29 01:29:53 +05:30 committed by GitHub
parent a3dfe3c647
commit 97eaa7e854
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 11806 additions and 1123 deletions

File diff suppressed because it is too large Load diff

View file

@ -117,6 +117,436 @@ spec:
information (e.g. kind, name, namespace, labels) and admission information (e.g. kind, name, namespace, labels) and admission
review request information like the name or role. review request information like the name or role.
properties: properties:
all:
description: All allows specifying resources which will
be ANDed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
any:
description: Any allows specifying resources which will
be ORed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
clusterRoles: clusterRoles:
description: ClusterRoles is the list of cluster-wide role description: ClusterRoles is the list of cluster-wide role
names for the user. names for the user.
@ -360,6 +790,436 @@ spec:
request information like the user name or role. At least one request information like the user name or role. At least one
kind is required. kind is required.
properties: properties:
all:
description: All allows specifying resources which will
be ANDed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
any:
description: Any allows specifying resources which will
be ORed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
clusterRoles: clusterRoles:
description: ClusterRoles is the list of cluster-wide role description: ClusterRoles is the list of cluster-wide role
names for the user. names for the user.
@ -687,8 +1547,9 @@ spec:
ruleStatus: ruleStatus:
description: Rules provides per rule statistics description: Rules provides per rule statistics
items: items:
description: RuleStats provides statistics for an individual rule description: 'RuleStats provides statistics for an individual rule
within a policy. within a policy. Deprecated. Policy metrics are now available
via the "/metrics" endpoint. See: https://kyverno.io/docs/monitoring-kyverno-with-prometheus-metrics/'
properties: properties:
appliedCount: appliedCount:
description: AppliedCount is the total number of times this description: AppliedCount is the total number of times this

View file

@ -118,6 +118,436 @@ spec:
information (e.g. kind, name, namespace, labels) and admission information (e.g. kind, name, namespace, labels) and admission
review request information like the name or role. review request information like the name or role.
properties: properties:
all:
description: All allows specifying resources which will
be ANDed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
any:
description: Any allows specifying resources which will
be ORed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
clusterRoles: clusterRoles:
description: ClusterRoles is the list of cluster-wide role description: ClusterRoles is the list of cluster-wide role
names for the user. names for the user.
@ -361,6 +791,436 @@ spec:
request information like the user name or role. At least one request information like the user name or role. At least one
kind is required. kind is required.
properties: properties:
all:
description: All allows specifying resources which will
be ANDed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
any:
description: Any allows specifying resources which will
be ORed
items:
description: ResourceFilters allow users to "AND" or "OR"
between resources
properties:
clusterRoles:
description: ClusterRoles is the list of cluster-wide
role names for the user.
items:
type: string
type: array
resources:
description: ResourceDescription contains information
about the resource being created or modified.
properties:
annotations:
additionalProperties:
type: string
description: Annotations is a map of annotations
(key-value pairs of type string). Annotation
keys and values support the wildcard characters
"*" (matches zero or many characters) and "?"
(matches at least one character).
type: object
kinds:
description: Kinds is a list of resource kinds.
items:
type: string
type: array
name:
description: Name is the name of the resource.
The name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character).
type: string
names:
description: 'Names are the names of the resources.
Each name supports wildcard characters "*" (matches
zero or many characters) and "?" (at least one
character). NOTE: "Name" is being deprecated
in favor of "Names".'
items:
type: string
type: array
namespaceSelector:
description: 'NamespaceSelector is a label selector
for the resource namespace. Label keys and values
in `matchLabels` support the wildcard characters
`*` (matches zero or many characters) and `?`
(matches one character).Wildcards allows writing
label selectors like ["storage.k8s.io/*": "*"].
Note that using ["*" : "*"] matches any key
and value but does not match an empty label
set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
namespaces:
description: Namespaces is a list of namespaces
names. Each name supports wildcard characters
"*" (matches zero or many characters) and "?"
(at least one character).
items:
type: string
type: array
selector:
description: 'Selector is a label selector. Label
keys and values in `matchLabels` support the
wildcard characters `*` (matches zero or many
characters) and `?` (matches one character).
Wildcards allows writing label selectors like
["storage.k8s.io/*": "*"]. Note that using ["*"
: "*"] matches any key and value but does not
match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of
label selector requirements. The requirements
are ANDed.
items:
description: A label selector requirement
is a selector that contains values, a
key, and an operator that relates the
key and values.
properties:
key:
description: key is the label key that
the selector applies to.
type: string
operator:
description: operator represents a key's
relationship to a set of values. Valid
operators are In, NotIn, Exists and
DoesNotExist.
type: string
values:
description: values is an array of string
values. If the operator is In or NotIn,
the values array must be non-empty.
If the operator is Exists or DoesNotExist,
the values array must be empty. This
array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value}
pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions,
whose key field is "key", the operator is
"In", and the values array contains only
"value". The requirements are ANDed.
type: object
type: object
type: object
roles:
description: Roles is the list of namespaced role
names for the user.
items:
type: string
type: array
subjects:
description: Subjects is the list of subject names
like users, user groups, and service accounts.
items:
description: Subject contains a reference to the
object or user identities a role binding applies
to. This can either hold a direct API object
reference, or a value for non-objects such as
user and group names.
properties:
apiGroup:
description: APIGroup holds the API group of
the referenced subject. Defaults to "" for
ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io"
for User and Group subjects.
type: string
kind:
description: Kind of object being referenced.
Values defined by this API group are "User",
"Group", and "ServiceAccount". If the Authorizer
does not recognized the kind value, the Authorizer
should report an error.
type: string
name:
description: Name of the object being referenced.
type: string
namespace:
description: Namespace of the referenced object. If
the object kind is non-namespace, such as
"User" or "Group", and this value is not empty
the Authorizer should report an error.
type: string
required:
- kind
- name
type: object
type: array
type: object
type: array
clusterRoles: clusterRoles:
description: ClusterRoles is the list of cluster-wide role description: ClusterRoles is the list of cluster-wide role
names for the user. names for the user.
@ -667,7 +1527,8 @@ spec:
type: string type: string
type: object type: object
status: status:
description: Status contains policy runtime information. description: Status contains policy runtime information. Deprecated. Policy
metrics are available via the metrics endpoint
properties: properties:
averageExecutionTime: averageExecutionTime:
description: AvgExecutionTime is the average time taken to process description: AvgExecutionTime is the average time taken to process
@ -688,8 +1549,9 @@ spec:
ruleStatus: ruleStatus:
description: Rules provides per rule statistics description: Rules provides per rule statistics
items: items:
description: RuleStats provides statistics for an individual rule description: 'RuleStats provides statistics for an individual rule
within a policy. within a policy. Deprecated. Policy metrics are now available
via the "/metrics" endpoint. See: https://kyverno.io/docs/monitoring-kyverno-with-prometheus-metrics/'
properties: properties:
appliedCount: appliedCount:
description: AppliedCount is the total number of times this description: AppliedCount is the total number of times this

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -220,18 +220,35 @@ const (
// MatchResources is used to specify resource and admission review request data for // MatchResources is used to specify resource and admission review request data for
// which a policy rule is applicable. // which a policy rule is applicable.
type MatchResources struct { type MatchResources struct {
// Any allows specifying resources which will be ORed
// +optional
Any ResourceFilters `json:"any,omitempty" yaml:"any,omitempty"`
// All allows specifying resources which will be ANDed
// +optional
All ResourceFilters `json:"all,omitempty" yaml:"all,omitempty"`
// UserInfo contains information about the user performing the operation. // UserInfo contains information about the user performing the operation.
// +optional // +optional
UserInfo `json:",omitempty" yaml:",omitempty"` UserInfo `json:",omitempty" yaml:",omitempty"`
// ResourceDescription contains information about the resource being created or modified. // ResourceDescription contains information about the resource being created or modified.
// Requires at least one tag to be specified when under MatchResources. // Requires at least one tag to be specified when under MatchResources.
// +optional
ResourceDescription `json:"resources,omitempty" yaml:"resources,omitempty"` ResourceDescription `json:"resources,omitempty" yaml:"resources,omitempty"`
} }
// ExcludeResources specifies resource and admission review request data for // ExcludeResources specifies resource and admission review request data for
// which a policy rule is not applicable. // which a policy rule is not applicable.
type ExcludeResources struct { type ExcludeResources struct {
// Any allows specifying resources which will be ORed
// +optional
Any ResourceFilters `json:"any,omitempty" yaml:"any,omitempty"`
// All allows specifying resources which will be ANDed
// +optional
All ResourceFilters `json:"all,omitempty" yaml:"all,omitempty"`
// UserInfo contains information about the user performing the operation. // UserInfo contains information about the user performing the operation.
// +optional // +optional
UserInfo `json:",omitempty" yaml:",omitempty"` UserInfo `json:",omitempty" yaml:",omitempty"`
@ -241,6 +258,18 @@ type ExcludeResources struct {
ResourceDescription `json:"resources,omitempty" yaml:"resources,omitempty"` ResourceDescription `json:"resources,omitempty" yaml:"resources,omitempty"`
} }
type ResourceFilters []ResourceFilter
// ResourceFilters allow users to "AND" or "OR" between resources
type ResourceFilter struct {
// UserInfo contains information about the user performing the operation.
// +optional
UserInfo `json:",omitempty" yaml:",omitempty"`
// ResourceDescription contains information about the resource being created or modified.
ResourceDescription `json:"resources,omitempty" yaml:"resources,omitempty"`
}
// UserInfo contains information about the user performing the operation. // UserInfo contains information about the user performing the operation.
type UserInfo struct { type UserInfo struct {
// Roles is the list of namespaced role names for the user. // Roles is the list of namespaced role names for the user.

View file

@ -263,27 +263,52 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
admissionInfo := *admissionInfoRef.DeepCopy() admissionInfo := *admissionInfoRef.DeepCopy()
var reasonsForFailure []error var reasonsForFailure []error
if len(rule.MatchResources.Any) > 0 {
if reflect.DeepEqual(admissionInfo, kyverno.RequestInfo{}) { // inlcude object if ANY of the criterias match
rule.MatchResources.UserInfo = kyverno.UserInfo{} // so if one matches then break from loop
} oneMatched := false
for _, rmr := range rule.MatchResources.Any {
// checking if resource matches the rule // if there are no errors it means it was a match
if !reflect.DeepEqual(rule.MatchResources.ResourceDescription, kyverno.ResourceDescription{}) || if len(matchesResourceDescriptionMatchHelper(rmr, admissionInfo, resource, dynamicConfig, namespaceLabels)) == 0 {
!reflect.DeepEqual(rule.MatchResources.UserInfo, kyverno.UserInfo{}) { oneMatched = true
matchErrs := doesResourceMatchConditionBlock(rule.MatchResources.ResourceDescription, rule.MatchResources.UserInfo, admissionInfo, resource, dynamicConfig, namespaceLabels) break
reasonsForFailure = append(reasonsForFailure, matchErrs...) }
} else {
reasonsForFailure = append(reasonsForFailure, fmt.Errorf("match cannot be empty"))
}
// checking if resource has been excluded
if !reflect.DeepEqual(rule.ExcludeResources.ResourceDescription, kyverno.ResourceDescription{}) ||
!reflect.DeepEqual(rule.ExcludeResources.UserInfo, kyverno.UserInfo{}) {
excludeErrs := doesResourceMatchConditionBlock(rule.ExcludeResources.ResourceDescription, rule.ExcludeResources.UserInfo, admissionInfo, resource, dynamicConfig, namespaceLabels)
if excludeErrs == nil {
reasonsForFailure = append(reasonsForFailure, fmt.Errorf("resource excluded"))
} }
if !oneMatched {
reasonsForFailure = append(reasonsForFailure, fmt.Errorf("no resource matched"))
}
} else if len(rule.MatchResources.All) > 0 {
// include object if ALL of the criterias match
for _, rmr := range rule.MatchResources.All {
reasonsForFailure = append(reasonsForFailure, matchesResourceDescriptionMatchHelper(rmr, admissionInfo, resource, dynamicConfig, namespaceLabels)...)
}
} else {
rmr := kyverno.ResourceFilter{UserInfo: rule.MatchResources.UserInfo, ResourceDescription: rule.MatchResources.ResourceDescription}
reasonsForFailure = append(reasonsForFailure, matchesResourceDescriptionMatchHelper(rmr, admissionInfo, resource, dynamicConfig, namespaceLabels)...)
}
if len(rule.ExcludeResources.Any) > 0 {
// exclude the object if ANY of the criterias match
for _, rer := range rule.ExcludeResources.Any {
reasonsForFailure = append(reasonsForFailure, matchesResourceDescriptionExcludeHelper(rer, admissionInfo, resource, dynamicConfig, namespaceLabels)...)
}
} else if len(rule.ExcludeResources.All) > 0 {
// exlcude the object if ALL the criterias match
excludedByAll := true
for _, rer := range rule.ExcludeResources.All {
// we got no errors inplying a resource did NOT exclude it
// "matchesResourceDescriptionExcludeHelper" returns errors if resource is excluded by a filter
if len(matchesResourceDescriptionExcludeHelper(rer, admissionInfo, resource, dynamicConfig, namespaceLabels)) == 0 {
excludedByAll = false
break
}
}
if excludedByAll {
reasonsForFailure = append(reasonsForFailure, fmt.Errorf("resource excluded since the combination of all criterias exclude it"))
}
} else {
rer := kyverno.ResourceFilter{UserInfo: rule.ExcludeResources.UserInfo, ResourceDescription: rule.ExcludeResources.ResourceDescription}
reasonsForFailure = append(reasonsForFailure, matchesResourceDescriptionExcludeHelper(rer, admissionInfo, resource, dynamicConfig, namespaceLabels)...)
} }
// creating final error // creating final error
@ -301,6 +326,39 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
return nil return nil
} }
func matchesResourceDescriptionMatchHelper(rmr kyverno.ResourceFilter, admissionInfo kyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
var errs []error
if reflect.DeepEqual(admissionInfo, kyverno.RequestInfo{}) {
rmr.UserInfo = kyverno.UserInfo{}
}
// checking if resource matches the rule
if !reflect.DeepEqual(rmr.ResourceDescription, kyverno.ResourceDescription{}) ||
!reflect.DeepEqual(rmr.UserInfo, kyverno.UserInfo{}) {
matchErrs := doesResourceMatchConditionBlock(rmr.ResourceDescription, rmr.UserInfo, admissionInfo, resource, dynamicConfig, namespaceLabels)
errs = append(errs, matchErrs...)
} else {
errs = append(errs, fmt.Errorf("match cannot be empty"))
}
return errs
}
func matchesResourceDescriptionExcludeHelper(rer kyverno.ResourceFilter, admissionInfo kyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
var errs []error
// checking if resource matches the rule
if !reflect.DeepEqual(rer.ResourceDescription, kyverno.ResourceDescription{}) ||
!reflect.DeepEqual(rer.UserInfo, kyverno.UserInfo{}) {
excludeErrs := doesResourceMatchConditionBlock(rer.ResourceDescription, rer.UserInfo, admissionInfo, resource, dynamicConfig, namespaceLabels)
// it was a match so we want to exclude it
if len(excludeErrs) == 0 {
errs = append(errs, fmt.Errorf("resource excluded since one of the criterias excluded it"))
errs = append(errs, excludeErrs...)
}
}
// len(errs) != 0 if the filter excluded the resource
return errs
}
func copyAnyAllConditions(original kyverno.AnyAllConditions) kyverno.AnyAllConditions { func copyAnyAllConditions(original kyverno.AnyAllConditions) kyverno.AnyAllConditions {
if reflect.DeepEqual(original, kyverno.AnyAllConditions{}) { if reflect.DeepEqual(original, kyverno.AnyAllConditions{}) {
return kyverno.AnyAllConditions{} return kyverno.AnyAllConditions{}

View file

@ -18,6 +18,746 @@ func TestMatchesResourceDescription(t *testing.T) {
Policy []byte Policy []byte
areErrorsExpected bool areErrorsExpected bool
}{ }{
{
Description: "Match Any matches the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "any-match-rule",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names" : ["dev"]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces" : ["prod"]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: false,
},
{
Description: "Match Any does not match the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "default"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names" : ["dev"]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces" : ["prod"]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: true,
},
{
Description: "Match All matches the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
],
"names" : ["abc"]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces" : ["prod"]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: false,
},
{
Description: "Match All does not match the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
],
"names" : ["xyz"]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces" : ["prod"]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: true,
},
{
Description: "Exclude Any excludes the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "dev",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
]
}
}
]
},
"exclude": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"default"
]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: true,
},
{
Description: "Exclude Any does not exclude the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
]
}
}
]
},
"exclude": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"default"
]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: false,
},
{
Description: "Exclude All excludes the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "dev",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
]
}
}
]
},
"exclude": {
"all": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"prod"
]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: true,
},
{
Description: "Exclude All does not exclude the Pod",
AdmissionInfo: kyverno.RequestInfo{
ClusterRoles: []string{"admin"},
},
Resource: []byte(`{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "abc",
"namespace" : "prod"
},
"spec": {
"containers": [
{
"name": "cont-name",
"image": "cont-img",
"ports": [
{
"containerPort": 81
}
],
"resources": {
"limits": {
"memory": "30Mi",
"cpu": "0.2"
},
"requests": {
"memory": "20Mi",
"cpu": "0.1"
}
}
}
]
}
}`),
Policy: []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "test-policy"
},
"spec": {
"background": false,
"rules": [
{
"name": "test-rule",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
]
}
}
]
},
"exclude": {
"all": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"abc"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"default"
]
}
}
]
},
"mutate": {
"overlay": {
"spec": {
"containers": [
{
"(image)": "*",
"imagePullPolicy": "IfNotPresent"
}
]
}
}
}
}
]
}
}`),
areErrorsExpected: false,
},
{ {
Description: "Should match pod and not exclude it", Description: "Should match pod and not exclude it",
AdmissionInfo: kyverno.RequestInfo{ AdmissionInfo: kyverno.RequestInfo{

View file

@ -109,14 +109,24 @@ func Validate(policy *kyverno.ClusterPolicy, client *dclient.Client, mock bool,
return err return err
} }
// If a rules match block does not match any kind, // If a rule's match block does not match any kind,
// we should only allow such rules to have metadata in its overlay // we should only allow it to have metadata in its overlay
if len(rule.MatchResources.Kinds) == 0 { if len(rule.MatchResources.Any) > 0 {
if !ruleOnlyDealsWithResourceMetaData(rule) { for _, rmr := range rule.MatchResources.Any {
return fmt.Errorf("policy can only deal with the metadata field of the resource if" + if len(rmr.Kinds) == 0 {
" the rule does not match an kind") return validateMatchKindHelper(rule)
}
}
} else if len(rule.MatchResources.All) > 0 {
for _, rmr := range rule.MatchResources.All {
if len(rmr.Kinds) == 0 {
return validateMatchKindHelper(rule)
}
}
} else {
if len(rule.MatchResources.Kinds) == 0 {
return validateMatchKindHelper(rule)
} }
return fmt.Errorf("at least one element must be specified in a kind block. the kind attribute is mandatory when working with the resources element")
} }
if utils.ContainsString(rule.MatchResources.Kinds, "*") || utils.ContainsString(rule.ExcludeResources.Kinds, "*") { if utils.ContainsString(rule.MatchResources.Kinds, "*") || utils.ContainsString(rule.ExcludeResources.Kinds, "*") {
@ -182,11 +192,35 @@ func Validate(policy *kyverno.ClusterPolicy, client *dclient.Client, mock bool,
return nil return nil
} }
func validateMatchKindHelper(rule kyverno.Rule) error {
if !ruleOnlyDealsWithResourceMetaData(rule) {
return fmt.Errorf("policy can only deal with the metadata field of the resource if" +
" the rule does not match an kind")
}
return fmt.Errorf("At least one element must be specified in a kind block. The kind attribute is mandatory when working with the resources element")
}
// doMatchAndExcludeConflict checks if the resultant // doMatchAndExcludeConflict checks if the resultant
// of match and exclude block is not an empty set // of match and exclude block is not an empty set
// returns true if it is an empty set // returns true if it is an empty set
func doMatchAndExcludeConflict(rule kyverno.Rule) bool { func doMatchAndExcludeConflict(rule kyverno.Rule) bool {
if len(rule.ExcludeResources.All) > 0 || len(rule.MatchResources.All) > 0 {
return false
}
// if both have any then no resource should be common
if len(rule.MatchResources.Any) > 0 && len(rule.ExcludeResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
for _, rer := range rule.ExcludeResources.Any {
if reflect.DeepEqual(rmr, rer) {
return true
}
}
}
return false
}
if reflect.DeepEqual(rule.ExcludeResources, kyverno.ExcludeResources{}) { if reflect.DeepEqual(rule.ExcludeResources, kyverno.ExcludeResources{}) {
return false return false
} }
@ -506,13 +540,62 @@ func validateResources(rule kyverno.Rule) (string, error) {
return fmt.Sprintf("resources.%s", path), err return fmt.Sprintf("resources.%s", path), err
} }
// matched resources if (len(rule.MatchResources.Any) > 0 || len(rule.MatchResources.All) > 0) && !reflect.DeepEqual(rule.MatchResources.ResourceDescription, kyverno.ResourceDescription{}) {
if path, err := validateMatchedResourceDescription(rule.MatchResources.ResourceDescription); err != nil { return "match.", fmt.Errorf("Can't specify any/all together with match resources")
return fmt.Sprintf("match.resources.%s", path), err
} }
// exclude resources
if path, err := validateExcludeResourceDescription(rule.ExcludeResources.ResourceDescription); err != nil { if (len(rule.ExcludeResources.Any) > 0 || len(rule.ExcludeResources.All) > 0) && !reflect.DeepEqual(rule.ExcludeResources.ResourceDescription, kyverno.ResourceDescription{}) {
return fmt.Sprintf("exclude.resources.%s", path), err return "exclude.", fmt.Errorf("Can't specify any/all together with exclude resources")
}
if len(rule.MatchResources.Any) > 0 && len(rule.MatchResources.All) > 0 {
return "match.", fmt.Errorf("Can't specify any and all together.")
}
if len(rule.ExcludeResources.Any) > 0 && len(rule.ExcludeResources.All) > 0 {
return "match.", fmt.Errorf("Can't specify any and all together.")
}
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
// matched resources
if path, err := validateMatchedResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
} else if len(rule.MatchResources.All) > 0 {
for _, rmr := range rule.MatchResources.All {
// matched resources
if path, err := validateMatchedResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
} else {
// matched resources
if path, err := validateMatchedResourceDescription(rule.MatchResources.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
if len(rule.ExcludeResources.Any) > 0 {
for _, rmr := range rule.ExcludeResources.Any {
// exclude resources
if path, err := validateExcludeResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
}
} else if len(rule.ExcludeResources.All) > 0 {
for _, rmr := range rule.ExcludeResources.All {
// exclude resources
if path, err := validateExcludeResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
}
} else {
// exclude resources
if path, err := validateExcludeResourceDescription(rule.ExcludeResources.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
} }
//validating the values present under validate.preconditions, if they exist //validating the values present under validate.preconditions, if they exist

View file

@ -1287,6 +1287,55 @@ func Test_Validate_Kind(t *testing.T) {
assert.Assert(t, err != nil) assert.Assert(t, err != nil)
} }
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)
openAPIController, _ := openapi.NewOpenAPIController()
err = Validate(policy, nil, true, openAPIController)
assert.Assert(t, err != nil)
}
func Test_checkAutoGenRules(t *testing.T) { func Test_checkAutoGenRules(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string

View file

@ -118,58 +118,17 @@ func (m *pMap) add(policy *kyverno.ClusterPolicy) {
for _, rule := range policy.Spec.Rules { for _, rule := range policy.Spec.Rules {
for _, gvk := range rule.MatchResources.Kinds { if len(rule.MatchResources.Any) > 0 {
_, kind := common.GetKindFromGVK(gvk) for _, rmr := range rule.MatchResources.Any {
_, ok := m.kindDataMap[kind] addCacheHelper(rmr, m, rule, mutateMap, pName, enforcePolicy, validateEnforceMap, validateAuditMap, generateMap, imageVerifyMap)
if !ok {
m.kindDataMap[kind] = make(map[PolicyType][]string)
} }
} else if len(rule.MatchResources.All) > 0 {
if rule.HasMutate() { for _, rmr := range rule.MatchResources.All {
if !mutateMap[kind+"/"+pName] { addCacheHelper(rmr, m, rule, mutateMap, pName, enforcePolicy, validateEnforceMap, validateAuditMap, generateMap, imageVerifyMap)
mutateMap[kind+"/"+pName] = true
mutatePolicy := m.kindDataMap[kind][Mutate]
m.kindDataMap[kind][Mutate] = append(mutatePolicy, pName)
}
continue
}
if rule.HasValidate() {
if enforcePolicy {
if !validateEnforceMap[kind+"/"+pName] {
validateEnforceMap[kind+"/"+pName] = true
validatePolicy := m.kindDataMap[kind][ValidateEnforce]
m.kindDataMap[kind][ValidateEnforce] = append(validatePolicy, pName)
}
continue
}
// ValidateAudit
if !validateAuditMap[kind+"/"+pName] {
validateAuditMap[kind+"/"+pName] = true
validatePolicy := m.kindDataMap[kind][ValidateAudit]
m.kindDataMap[kind][ValidateAudit] = append(validatePolicy, pName)
}
continue
}
if rule.HasGenerate() {
if !generateMap[kind+"/"+pName] {
generateMap[kind+"/"+pName] = true
generatePolicy := m.kindDataMap[kind][Generate]
m.kindDataMap[kind][Generate] = append(generatePolicy, pName)
}
continue
}
if rule.HasVerifyImages() {
if !imageVerifyMap[kind+"/"+pName] {
imageVerifyMap[kind+"/"+pName] = true
imageVerifyMapPolicy := m.kindDataMap[kind][VerifyImages]
m.kindDataMap[kind][VerifyImages] = append(imageVerifyMapPolicy, pName)
}
continue
} }
} else {
r := kyverno.ResourceFilter{UserInfo: rule.MatchResources.UserInfo, ResourceDescription: rule.MatchResources.ResourceDescription}
addCacheHelper(r, m, rule, mutateMap, pName, enforcePolicy, validateEnforceMap, validateAuditMap, generateMap, imageVerifyMap)
} }
} }
@ -180,6 +139,62 @@ func (m *pMap) add(policy *kyverno.ClusterPolicy) {
m.nameCacheMap[VerifyImages] = imageVerifyMap m.nameCacheMap[VerifyImages] = imageVerifyMap
} }
func addCacheHelper(rmr kyverno.ResourceFilter, m *pMap, rule kyverno.Rule, mutateMap map[string]bool, pName string, enforcePolicy bool, validateEnforceMap map[string]bool, validateAuditMap map[string]bool, generateMap map[string]bool, imageVerifyMap map[string]bool) {
for _, gvk := range rmr.Kinds {
_, kind := common.GetKindFromGVK(gvk)
_, ok := m.kindDataMap[kind]
if !ok {
m.kindDataMap[kind] = make(map[PolicyType][]string)
}
if rule.HasMutate() {
if !mutateMap[kind+"/"+pName] {
mutateMap[kind+"/"+pName] = true
mutatePolicy := m.kindDataMap[kind][Mutate]
m.kindDataMap[kind][Mutate] = append(mutatePolicy, pName)
}
continue
}
if rule.HasValidate() {
if enforcePolicy {
if !validateEnforceMap[kind+"/"+pName] {
validateEnforceMap[kind+"/"+pName] = true
validatePolicy := m.kindDataMap[kind][ValidateEnforce]
m.kindDataMap[kind][ValidateEnforce] = append(validatePolicy, pName)
}
continue
}
// ValidateAudit
if !validateAuditMap[kind+"/"+pName] {
validateAuditMap[kind+"/"+pName] = true
validatePolicy := m.kindDataMap[kind][ValidateAudit]
m.kindDataMap[kind][ValidateAudit] = append(validatePolicy, pName)
}
continue
}
if rule.HasGenerate() {
if !generateMap[kind+"/"+pName] {
generateMap[kind+"/"+pName] = true
generatePolicy := m.kindDataMap[kind][Generate]
m.kindDataMap[kind][Generate] = append(generatePolicy, pName)
}
continue
}
if rule.HasVerifyImages() {
if !imageVerifyMap[kind+"/"+pName] {
imageVerifyMap[kind+"/"+pName] = true
imageVerifyMapPolicy := m.kindDataMap[kind][VerifyImages]
m.kindDataMap[kind][VerifyImages] = append(imageVerifyMapPolicy, pName)
}
continue
}
}
}
func (pc *pMap) get(key PolicyType, gvk, namespace string) (names []string) { func (pc *pMap) get(key PolicyType, gvk, namespace string) (names []string) {
pc.RLock() pc.RLock()
defer pc.RUnlock() defer pc.RUnlock()
@ -207,28 +222,44 @@ func (m *pMap) remove(policy *kyverno.ClusterPolicy) {
} }
for _, rule := range policy.Spec.Rules { for _, rule := range policy.Spec.Rules {
for _, gvk := range rule.MatchResources.Kinds {
_, kind := common.GetKindFromGVK(gvk)
dataMap := m.kindDataMap[kind]
for policyType, policies := range dataMap {
var newPolicies []string
for _, p := range policies {
if p == pName {
continue
}
newPolicies = append(newPolicies, p)
}
m.kindDataMap[kind][policyType] = newPolicies
}
for _, nameCache := range m.nameCacheMap {
if ok := nameCache[kind+"/"+pName]; ok {
delete(nameCache, kind+"/"+pName)
}
}
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
removeCacheHelper(rmr, m, pName)
}
} else if len(rule.MatchResources.All) > 0 {
for _, rmr := range rule.MatchResources.All {
removeCacheHelper(rmr, m, pName)
}
} else {
r := kyverno.ResourceFilter{UserInfo: rule.MatchResources.UserInfo, ResourceDescription: rule.MatchResources.ResourceDescription}
removeCacheHelper(r, m, pName)
} }
} }
} }
func removeCacheHelper(rmr kyverno.ResourceFilter, m *pMap, pName string) {
for _, gvk := range rmr.Kinds {
_, kind := common.GetKindFromGVK(gvk)
dataMap := m.kindDataMap[kind]
for policyType, policies := range dataMap {
var newPolicies []string
for _, p := range policies {
if p == pName {
continue
}
newPolicies = append(newPolicies, p)
}
m.kindDataMap[kind][policyType] = newPolicies
}
for _, nameCache := range m.nameCacheMap {
if ok := nameCache[kind+"/"+pName]; ok {
delete(nameCache, kind+"/"+pName)
}
}
}
}
func (m *policyCache) getPolicyObject(key PolicyType, gvk string, nspace string) (policyObject []*kyverno.ClusterPolicy) { func (m *policyCache) getPolicyObject(key PolicyType, gvk string, nspace string) (policyObject []*kyverno.ClusterPolicy) {
_, kind := common.GetKindFromGVK(gvk) _, kind := common.GetKindFromGVK(gvk)
policyNames := m.pMap.get(key, kind, nspace) policyNames := m.pMap.get(key, kind, nspace)

View file

@ -133,11 +133,50 @@ func Test_Add_Remove(t *testing.T) {
policy := newPolicy(t) policy := newPolicy(t)
kind := "Pod" kind := "Pod"
pCache.Add(policy) pCache.Add(policy)
validateEnforce := pCache.get(ValidateEnforce, kind, "") validateEnforce := pCache.get(ValidateEnforce, kind, "")
if len(validateEnforce) != 1 { if len(validateEnforce) != 1 {
t.Errorf("expected 1 validate enforce policy, found %v", len(validateEnforce)) t.Errorf("expected 1 validate enforce policy, found %v", len(validateEnforce))
} }
mutate := pCache.get(Mutate, kind, "")
if len(mutate) != 1 {
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
}
generate := pCache.get(Generate, kind, "")
if len(mutate) != 1 {
t.Errorf("expected 1 generate policy, found %v", len(generate))
}
pCache.Remove(policy)
deletedValidateEnforce := pCache.get(ValidateEnforce, kind, "")
if len(deletedValidateEnforce) != 0 {
t.Errorf("expected 0 validate enforce policy, found %v", len(deletedValidateEnforce))
}
}
func Test_Add_Remove_Any(t *testing.T) {
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
policy := newAnyPolicy(t)
kind := "Pod"
pCache.Add(policy)
validateEnforce := pCache.get(ValidateEnforce, kind, "")
if len(validateEnforce) != 1 {
t.Errorf("expected 1 validate enforce policy, found %v", len(validateEnforce))
}
mutate := pCache.get(Mutate, kind, "")
if len(mutate) != 1 {
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
}
generate := pCache.get(Generate, kind, "")
if len(mutate) != 1 {
t.Errorf("expected 1 generate policy, found %v", len(generate))
}
pCache.Remove(policy) pCache.Remove(policy)
deletedValidateEnforce := pCache.get(ValidateEnforce, kind, "") deletedValidateEnforce := pCache.get(ValidateEnforce, kind, "")
if len(deletedValidateEnforce) != 0 { if len(deletedValidateEnforce) != 0 {
@ -261,6 +300,179 @@ func newPolicy(t *testing.T) *kyverno.ClusterPolicy {
return policy return policy
} }
func newAnyPolicy(t *testing.T) *kyverno.ClusterPolicy {
rawPolicy := []byte(`{
"metadata": {
"name": "test-policy"
},
"spec": {
"validationFailureAction": "enforce",
"rules": [
{
"name": "deny-privileged-disallowpriviligedescalation",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"prod"
]
}
}
]
},
"validate": {
"deny": {
"conditions": {
"all": [
{
"key": "a",
"operator": "Equals",
"value": "a"
}
]
}
}
}
},
{
"name": "deny-privileged-disallowpriviligedescalation",
"match": {
"all": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"prod"
]
}
}
]
},
"validate": {
"pattern": {
"spec": {
"containers": [
{
"image": "!*:latest"
}
]
}
}
}
},
{
"name": "annotate-host-path",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"prod"
]
}
}
]
},
"mutate": {
"overlay": {
"metadata": {
"annotations": {
"+(cluster-autoscaler.kubernetes.io/safe-to-evict)": true
}
}
}
}
},
{
"name": "default-deny-ingress",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
],
"names": [
"dev"
]
}
},
{
"resources": {
"kinds": [
"Pod"
],
"namespaces": [
"prod"
]
}
}
]
},
"generate": {
"kind": "NetworkPolicy",
"name": "default-deny-ingress",
"namespace": "{{request.object.metadata.name}}",
"data": {
"spec": {
"podSelector": {},
"policyTypes": [
"Ingress"
]
}
}
}
}
]
}
}`)
var policy *kyverno.ClusterPolicy
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
return policy
}
func newNsPolicy(t *testing.T) *kyverno.ClusterPolicy { func newNsPolicy(t *testing.T) *kyverno.ClusterPolicy {
rawPolicy := []byte(`{ rawPolicy := []byte(`{
"metadata": { "metadata": {