mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Reconcile Generate request on policy update (#1096)
* policy report crd added * added namespaced rule * remove extra field from crd * revert crd change * remove policy report chnages * remove policy report chnages * remove policy report chnages * remove policy report chnages * added logic for gr * revert changes * fixed generate rules * fixed generate rules * fixed generate rules * fixed generate rules * remove extra logs * remove extra logs * fixed e2e test * remove extra logs * crd issue resolved * added check for sync * add labels update * add label update * added permission to role * roles added to helm * roles added to helm
This commit is contained in:
parent
154b1c1eb9
commit
b7524467a3
13 changed files with 313 additions and 231 deletions
|
@ -131,6 +131,7 @@ rules:
|
||||||
- limitranges
|
- limitranges
|
||||||
- clusterroles
|
- clusterroles
|
||||||
- rolebindings
|
- rolebindings
|
||||||
|
- namespaces
|
||||||
- clusterrolebindings
|
- clusterrolebindings
|
||||||
{{- range .Values.generatecontrollerExtraResources }}
|
{{- range .Values.generatecontrollerExtraResources }}
|
||||||
- {{ . }}
|
- {{ . }}
|
||||||
|
@ -139,6 +140,7 @@ rules:
|
||||||
- create
|
- create
|
||||||
- update
|
- update
|
||||||
- delete
|
- delete
|
||||||
|
- list
|
||||||
- get
|
- get
|
||||||
# dynamic watches on trigger resources for generate rules
|
# dynamic watches on trigger resources for generate rules
|
||||||
# re-evaluate the policy if the resource is updated
|
# re-evaluate the policy if the resource is updated
|
||||||
|
|
|
@ -194,6 +194,7 @@ func main() {
|
||||||
pInformer.Kyverno().V1().Policies(),
|
pInformer.Kyverno().V1().Policies(),
|
||||||
pInformer.Kyverno().V1().ClusterPolicyViolations(),
|
pInformer.Kyverno().V1().ClusterPolicyViolations(),
|
||||||
pInformer.Kyverno().V1().PolicyViolations(),
|
pInformer.Kyverno().V1().PolicyViolations(),
|
||||||
|
pInformer.Kyverno().V1().GenerateRequests(),
|
||||||
configData,
|
configData,
|
||||||
eventGenerator,
|
eventGenerator,
|
||||||
pvgen,
|
pvgen,
|
||||||
|
|
|
@ -14,7 +14,7 @@ spec:
|
||||||
plural: clusterpolicies
|
plural: clusterpolicies
|
||||||
singular: clusterpolicy
|
singular: clusterpolicy
|
||||||
shortNames:
|
shortNames:
|
||||||
- cpol
|
- cpol
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
validation:
|
validation:
|
||||||
|
@ -23,14 +23,14 @@ spec:
|
||||||
status: {}
|
status: {}
|
||||||
spec:
|
spec:
|
||||||
required:
|
required:
|
||||||
- rules
|
- rules
|
||||||
properties:
|
properties:
|
||||||
# default values to be handled by user
|
# default values to be handled by user
|
||||||
validationFailureAction:
|
validationFailureAction:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- enforce # blocks the resorce api-reques if a rule fails.
|
- enforce # blocks the resorce api-reques if a rule fails.
|
||||||
- audit # allows resource creation and reports the failed validation rules as violations. Default
|
- audit # allows resource creation and reports the failed validation rules as violations. Default
|
||||||
background:
|
background:
|
||||||
type: boolean
|
type: boolean
|
||||||
rules:
|
rules:
|
||||||
|
@ -38,15 +38,15 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- match
|
- match
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
match:
|
match:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- resources
|
- resources
|
||||||
properties:
|
properties:
|
||||||
roles:
|
roles:
|
||||||
type: array
|
type: array
|
||||||
|
@ -61,8 +61,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -101,8 +101,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
properties:
|
properties:
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
|
@ -128,8 +128,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -167,8 +167,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
properties:
|
properties:
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
|
@ -183,9 +183,9 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key # can be of any type
|
- key # can be of any type
|
||||||
- operator # typed
|
- operator # typed
|
||||||
- value # can be of any type
|
- value # can be of any type
|
||||||
mutate:
|
mutate:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -198,17 +198,17 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- path
|
- path
|
||||||
- op
|
- op
|
||||||
properties:
|
properties:
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
op:
|
op:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- add
|
- add
|
||||||
- replace
|
- replace
|
||||||
- remove
|
- remove
|
||||||
value: {}
|
value: {}
|
||||||
validate:
|
validate:
|
||||||
type: object
|
type: object
|
||||||
|
@ -231,24 +231,24 @@ spec:
|
||||||
operator:
|
operator:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- Equal
|
- Equal
|
||||||
- Equals
|
- Equals
|
||||||
- NotEqual
|
- NotEqual
|
||||||
- NotEquals
|
- NotEquals
|
||||||
- In
|
- In
|
||||||
- NotIn
|
- NotIn
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: string
|
- type: string
|
||||||
- type: array
|
- type: array
|
||||||
items: {}
|
items: {}
|
||||||
generate:
|
generate:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
apiVersion:
|
apiVersion:
|
||||||
type: string
|
type: string
|
||||||
|
@ -260,11 +260,11 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
synchronize:
|
synchronize:
|
||||||
type: boolean
|
type: boolean
|
||||||
clone:
|
clone:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- namespace
|
- namespace
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
namespace:
|
namespace:
|
||||||
type: string
|
type: string
|
||||||
|
@ -288,7 +288,7 @@ spec:
|
||||||
plural: policies
|
plural: policies
|
||||||
singular: policy
|
singular: policy
|
||||||
shortNames:
|
shortNames:
|
||||||
- pol
|
- pol
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
validation:
|
validation:
|
||||||
|
@ -297,14 +297,14 @@ spec:
|
||||||
status: {}
|
status: {}
|
||||||
spec:
|
spec:
|
||||||
required:
|
required:
|
||||||
- rules
|
- rules
|
||||||
properties:
|
properties:
|
||||||
# default values to be handled by user
|
# default values to be handled by user
|
||||||
validationFailureAction:
|
validationFailureAction:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- enforce # blocks the resorce api-reques if a rule fails.
|
- enforce # blocks the resorce api-reques if a rule fails.
|
||||||
- audit # allows resource creation and reports the failed validation rules as violations. Default
|
- audit # allows resource creation and reports the failed validation rules as violations. Default
|
||||||
background:
|
background:
|
||||||
type: boolean
|
type: boolean
|
||||||
rules:
|
rules:
|
||||||
|
@ -312,15 +312,15 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- match
|
- match
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
match:
|
match:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- resources
|
- resources
|
||||||
properties:
|
properties:
|
||||||
roles:
|
roles:
|
||||||
type: array
|
type: array
|
||||||
|
@ -335,8 +335,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -367,8 +367,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
properties:
|
properties:
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
|
@ -394,8 +394,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -425,8 +425,8 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key
|
- key
|
||||||
- operator
|
- operator
|
||||||
properties:
|
properties:
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
|
@ -441,9 +441,9 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- key # can be of any type
|
- key # can be of any type
|
||||||
- operator # typed
|
- operator # typed
|
||||||
- value # can be of any type
|
- value # can be of any type
|
||||||
mutate:
|
mutate:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -456,17 +456,17 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- path
|
- path
|
||||||
- op
|
- op
|
||||||
properties:
|
properties:
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
op:
|
op:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- add
|
- add
|
||||||
- replace
|
- replace
|
||||||
- remove
|
- remove
|
||||||
value: {}
|
value: {}
|
||||||
validate:
|
validate:
|
||||||
type: object
|
type: object
|
||||||
|
@ -489,24 +489,24 @@ spec:
|
||||||
operator:
|
operator:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- Equal
|
- Equal
|
||||||
- Equals
|
- Equals
|
||||||
- NotEqual
|
- NotEqual
|
||||||
- NotEquals
|
- NotEquals
|
||||||
- In
|
- In
|
||||||
- NotIn
|
- NotIn
|
||||||
key:
|
key:
|
||||||
type: string
|
type: string
|
||||||
value:
|
value:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: string
|
- type: string
|
||||||
- type: array
|
- type: array
|
||||||
items: {}
|
items: {}
|
||||||
generate:
|
generate:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
apiVersion:
|
apiVersion:
|
||||||
type: string
|
type: string
|
||||||
|
@ -518,11 +518,11 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
synchronize:
|
synchronize:
|
||||||
type: boolean
|
type: boolean
|
||||||
clone:
|
clone:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- namespace
|
- namespace
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
namespace:
|
namespace:
|
||||||
type: string
|
type: string
|
||||||
|
@ -546,41 +546,41 @@ spec:
|
||||||
plural: clusterpolicyviolations
|
plural: clusterpolicyviolations
|
||||||
singular: clusterpolicyviolation
|
singular: clusterpolicyviolation
|
||||||
shortNames:
|
shortNames:
|
||||||
- cpolv
|
- cpolv
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
additionalPrinterColumns:
|
additionalPrinterColumns:
|
||||||
- name: Policy
|
- name: Policy
|
||||||
type: string
|
type: string
|
||||||
description: The policy that resulted in the violation
|
description: The policy that resulted in the violation
|
||||||
JSONPath: .spec.policy
|
JSONPath: .spec.policy
|
||||||
- name: ResourceKind
|
- name: ResourceKind
|
||||||
type: string
|
type: string
|
||||||
description: The resource kind that cause the violation
|
description: The resource kind that cause the violation
|
||||||
JSONPath: .spec.resource.kind
|
JSONPath: .spec.resource.kind
|
||||||
- name: ResourceName
|
- name: ResourceName
|
||||||
type: string
|
type: string
|
||||||
description: The resource name that caused the violation
|
description: The resource name that caused the violation
|
||||||
JSONPath: .spec.resource.name
|
JSONPath: .spec.resource.name
|
||||||
- name: Age
|
- name: Age
|
||||||
type: date
|
type: date
|
||||||
JSONPath: .metadata.creationTimestamp
|
JSONPath: .metadata.creationTimestamp
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
properties:
|
properties:
|
||||||
spec:
|
spec:
|
||||||
required:
|
required:
|
||||||
- policy
|
- policy
|
||||||
- resource
|
- resource
|
||||||
- rules
|
- rules
|
||||||
properties:
|
properties:
|
||||||
policy:
|
policy:
|
||||||
type: string
|
type: string
|
||||||
resource:
|
resource:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -591,9 +591,9 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- type
|
- type
|
||||||
- message
|
- message
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
|
@ -618,41 +618,41 @@ spec:
|
||||||
plural: policyviolations
|
plural: policyviolations
|
||||||
singular: policyviolation
|
singular: policyviolation
|
||||||
shortNames:
|
shortNames:
|
||||||
- polv
|
- polv
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
additionalPrinterColumns:
|
additionalPrinterColumns:
|
||||||
- name: Policy
|
- name: Policy
|
||||||
type: string
|
type: string
|
||||||
description: The policy that resulted in the violation
|
description: The policy that resulted in the violation
|
||||||
JSONPath: .spec.policy
|
JSONPath: .spec.policy
|
||||||
- name: ResourceKind
|
- name: ResourceKind
|
||||||
type: string
|
type: string
|
||||||
description: The resource kind that cause the violation
|
description: The resource kind that cause the violation
|
||||||
JSONPath: .spec.resource.kind
|
JSONPath: .spec.resource.kind
|
||||||
- name: ResourceName
|
- name: ResourceName
|
||||||
type: string
|
type: string
|
||||||
description: The resource name that caused the violation
|
description: The resource name that caused the violation
|
||||||
JSONPath: .spec.resource.name
|
JSONPath: .spec.resource.name
|
||||||
- name: Age
|
- name: Age
|
||||||
type: date
|
type: date
|
||||||
JSONPath: .metadata.creationTimestamp
|
JSONPath: .metadata.creationTimestamp
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
properties:
|
properties:
|
||||||
spec:
|
spec:
|
||||||
required:
|
required:
|
||||||
- policy
|
- policy
|
||||||
- resource
|
- resource
|
||||||
- rules
|
- rules
|
||||||
properties:
|
properties:
|
||||||
policy:
|
policy:
|
||||||
type: string
|
type: string
|
||||||
resource:
|
resource:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
|
@ -663,9 +663,9 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- type
|
- type
|
||||||
- message
|
- message
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
|
@ -690,52 +690,52 @@ spec:
|
||||||
plural: generaterequests
|
plural: generaterequests
|
||||||
singular: generaterequest
|
singular: generaterequest
|
||||||
shortNames:
|
shortNames:
|
||||||
- gr
|
- gr
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
additionalPrinterColumns:
|
additionalPrinterColumns:
|
||||||
- name: Policy
|
- name: Policy
|
||||||
type: string
|
type: string
|
||||||
description: The policy that resulted in the violation
|
description: The policy that resulted in the violation
|
||||||
JSONPath: .spec.policy
|
JSONPath: .spec.policy
|
||||||
- name: ResourceKind
|
- name: ResourceKind
|
||||||
type: string
|
type: string
|
||||||
description: The resource kind that cause the violation
|
description: The resource kind that cause the violation
|
||||||
JSONPath: .spec.resource.kind
|
JSONPath: .spec.resource.kind
|
||||||
- name: ResourceName
|
- name: ResourceName
|
||||||
type: string
|
type: string
|
||||||
description: The resource name that caused the violation
|
description: The resource name that caused the violation
|
||||||
JSONPath: .spec.resource.name
|
JSONPath: .spec.resource.name
|
||||||
- name: ResourceNamespace
|
- name: ResourceNamespace
|
||||||
type: string
|
type: string
|
||||||
description: The resource namespace that caused the violation
|
description: The resource namespace that caused the violation
|
||||||
JSONPath: .spec.resource.namespace
|
JSONPath: .spec.resource.namespace
|
||||||
- name: status
|
- name: status
|
||||||
type : string
|
type : string
|
||||||
description: Current state of generate request
|
description: Current state of generate request
|
||||||
JSONPath: .status.state
|
JSONPath: .status.state
|
||||||
- name: Age
|
- name: Age
|
||||||
type: date
|
type: date
|
||||||
JSONPath: .metadata.creationTimestamp
|
JSONPath: .metadata.creationTimestamp
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
properties:
|
properties:
|
||||||
spec:
|
spec:
|
||||||
required:
|
required:
|
||||||
- policy
|
- policy
|
||||||
- resource
|
- resource
|
||||||
properties:
|
properties:
|
||||||
policy:
|
policy:
|
||||||
type: string
|
type: string
|
||||||
resource:
|
resource:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- kind
|
- kind
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
namespace:
|
namespace:
|
||||||
type: string
|
type: string
|
||||||
|
|
|
@ -832,8 +832,10 @@ rules:
|
||||||
- rolebindings
|
- rolebindings
|
||||||
- clusterrolebindings
|
- clusterrolebindings
|
||||||
- configmaps
|
- configmaps
|
||||||
|
- namespaces
|
||||||
verbs:
|
verbs:
|
||||||
- watch
|
- watch
|
||||||
|
- list
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
|
|
|
@ -832,8 +832,10 @@ rules:
|
||||||
- rolebindings
|
- rolebindings
|
||||||
- clusterrolebindings
|
- clusterrolebindings
|
||||||
- configmaps
|
- configmaps
|
||||||
|
- namespaces
|
||||||
verbs:
|
verbs:
|
||||||
- watch
|
- watch
|
||||||
|
- list
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
|
|
|
@ -158,8 +158,10 @@ rules:
|
||||||
- rolebindings
|
- rolebindings
|
||||||
- clusterrolebindings
|
- clusterrolebindings
|
||||||
- configmaps
|
- configmaps
|
||||||
|
- namespaces
|
||||||
verbs:
|
verbs:
|
||||||
- watch
|
- watch
|
||||||
|
- list
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
|
|
|
@ -27,6 +27,7 @@ type PolicyResponse struct {
|
||||||
Rules []RuleResponse `json:"rules"`
|
Rules []RuleResponse `json:"rules"`
|
||||||
// ValidationFailureAction: audit(default if not set),enforce
|
// ValidationFailureAction: audit(default if not set),enforce
|
||||||
ValidationFailureAction string
|
ValidationFailureAction string
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ResourceSpec resource action applied on
|
//ResourceSpec resource action applied on
|
||||||
|
|
|
@ -175,12 +175,14 @@ func (c *Controller) deleteGR(obj interface{}) {
|
||||||
for _, resource := range gr.Status.GeneratedResources {
|
for _, resource := range gr.Status.GeneratedResources {
|
||||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
labels := r.GetLabels()
|
labels := r.GetLabels()
|
||||||
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
||||||
if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil {
|
if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil {
|
||||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package generate
|
package generate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||||
|
@ -20,6 +18,7 @@ import (
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -204,7 +203,8 @@ func (c *Controller) deleteGR(obj interface{}) {
|
||||||
for _, resource := range gr.Status.GeneratedResources {
|
for _, resource := range gr.Status.GeneratedResources {
|
||||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
labels := r.GetLabels()
|
labels := r.GetLabels()
|
||||||
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
||||||
|
|
|
@ -108,8 +108,8 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
||||||
logger.V(4).Info("policy does not apply to resource")
|
logger.V(4).Info("policy does not apply to resource")
|
||||||
return nil, fmt.Errorf("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource)
|
return nil, fmt.Errorf("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource)
|
||||||
}
|
}
|
||||||
|
var rules []response.RuleResponse
|
||||||
for i, r := range engineResponse.PolicyResponse.Rules {
|
for _, r := range engineResponse.PolicyResponse.Rules {
|
||||||
if !r.Success {
|
if !r.Success {
|
||||||
grList, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
grList, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -123,14 +123,24 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(engineResponse.PolicyResponse.Rules) > 1 {
|
} else {
|
||||||
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
|
rules = append(rules, r)
|
||||||
continue
|
}
|
||||||
} else if len(engineResponse.PolicyResponse.Rules) == 1 {
|
}
|
||||||
engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
|
engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
|
||||||
|
|
||||||
|
for _, v := range policy.Spec.Rules {
|
||||||
|
for _, r := range rules {
|
||||||
|
if policy.Name == engineResponse.PolicyResponse.Policy && r.Name == v.Name {
|
||||||
|
if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules, r)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the generate rule on resource
|
// Apply the generate rule on resource
|
||||||
return c.applyGeneratePolicy(logger, policyContext, gr)
|
return c.applyGeneratePolicy(logger, policyContext, gr)
|
||||||
}
|
}
|
||||||
|
@ -160,7 +170,23 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr)
|
|
||||||
|
processExisting := false
|
||||||
|
|
||||||
|
for _, v := range policy.Spec.Rules {
|
||||||
|
if policy.Name == gr.Spec.Policy {
|
||||||
|
if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
|
||||||
|
processExisting = func() bool {
|
||||||
|
rcreationTime := resource.GetCreationTimestamp()
|
||||||
|
pcreationTime := policy.GetCreationTimestamp()
|
||||||
|
return rcreationTime.Before(&pcreationTime)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr, processExisting)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -217,7 +243,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str
|
||||||
return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
|
return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) {
|
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest, processExisting bool) (kyverno.ResourceSpec, error) {
|
||||||
var rdata map[string]interface{}
|
var rdata map[string]interface{}
|
||||||
var err error
|
var err error
|
||||||
var mode ResourceMode
|
var mode ResourceMode
|
||||||
|
@ -227,7 +253,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return noGenResource, err
|
return noGenResource, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable substitutions
|
// Variable substitutions
|
||||||
// format : {{<variable_name}}
|
// format : {{<variable_name}}
|
||||||
// - if there is variables that are not defined the context -> results in error and rule is not applied
|
// - if there is variables that are not defined the context -> results in error and rule is not applied
|
||||||
|
@ -255,7 +280,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return noGenResource, err
|
return noGenResource, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resource to be generated
|
// Resource to be generated
|
||||||
newGenResource := kyverno.ResourceSpec{
|
newGenResource := kyverno.ResourceSpec{
|
||||||
APIVersion: genAPIVersion,
|
APIVersion: genAPIVersion,
|
||||||
|
@ -271,7 +295,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return noGenResource, err
|
return noGenResource, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if genData != nil {
|
if genData != nil {
|
||||||
rdata, mode, err = manageData(log, genAPIVersion, genKind, genNamespace, genName, genData, client, resource)
|
rdata, mode, err = manageData(log, genAPIVersion, genKind, genNamespace, genName, genData, client, resource)
|
||||||
} else {
|
} else {
|
||||||
|
@ -286,7 +309,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
// existing resource contains the configuration
|
// existing resource contains the configuration
|
||||||
return newGenResource, nil
|
return newGenResource, nil
|
||||||
}
|
}
|
||||||
|
if processExisting {
|
||||||
|
return noGenResource, nil
|
||||||
|
}
|
||||||
logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName)
|
logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName)
|
||||||
|
|
||||||
// build the resource template
|
// build the resource template
|
||||||
|
@ -297,24 +322,23 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
if newResource.GetKind() == "" {
|
if newResource.GetKind() == "" {
|
||||||
newResource.SetKind(genKind)
|
newResource.SetKind(genKind)
|
||||||
}
|
}
|
||||||
|
|
||||||
newResource.SetAPIVersion(genAPIVersion)
|
newResource.SetAPIVersion(genAPIVersion)
|
||||||
// manage labels
|
// manage labels
|
||||||
// - app.kubernetes.io/managed-by: kyverno
|
// - app.kubernetes.io/managed-by: kyverno
|
||||||
// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
|
// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
|
||||||
manageLabels(newResource, resource)
|
manageLabels(newResource, resource)
|
||||||
|
|
||||||
// Add Synchronize label
|
// Add Synchronize label
|
||||||
label := newResource.GetLabels()
|
label := newResource.GetLabels()
|
||||||
if rule.Generation.Synchronize {
|
|
||||||
label["policy.kyverno.io/synchronize"] = "enable"
|
|
||||||
} else {
|
|
||||||
label["policy.kyverno.io/synchronize"] = "disable"
|
|
||||||
}
|
|
||||||
label["policy.kyverno.io/policy-name"] = policy
|
label["policy.kyverno.io/policy-name"] = policy
|
||||||
label["policy.kyverno.io/gr-name"] = gr.Name
|
label["policy.kyverno.io/gr-name"] = gr.Name
|
||||||
newResource.SetLabels(label)
|
newResource.SetLabels(label)
|
||||||
|
|
||||||
if mode == Create {
|
if mode == Create {
|
||||||
|
if rule.Generation.Synchronize {
|
||||||
|
label["policy.kyverno.io/synchronize"] = "enable"
|
||||||
|
} else {
|
||||||
|
label["policy.kyverno.io/synchronize"] = "disable"
|
||||||
|
}
|
||||||
// Reset resource version
|
// Reset resource version
|
||||||
newResource.SetResourceVersion("")
|
newResource.SetResourceVersion("")
|
||||||
// Create the resource
|
// Create the resource
|
||||||
|
@ -327,25 +351,48 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
logger.V(4).Info("created new resource")
|
logger.V(4).Info("created new resource")
|
||||||
|
|
||||||
} else if mode == Update {
|
} else if mode == Update {
|
||||||
|
var isUpdate bool
|
||||||
label := newResource.GetLabels()
|
label := newResource.GetLabels()
|
||||||
if label != nil {
|
isUpdate = false
|
||||||
if rule.Generation.Synchronize {
|
if rule.Generation.Synchronize {
|
||||||
logger.V(4).Info("updating existing resource")
|
if label["policy.kyverno.io/synchronize"] == "enable" {
|
||||||
// Update the resource
|
isUpdate = true
|
||||||
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(err, "updating existing resource")
|
|
||||||
// Failed to update resource
|
|
||||||
return noGenResource, err
|
|
||||||
}
|
|
||||||
logger.V(4).Info("updated new resource")
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logger.V(4).Info("Synchronize resource is disabled")
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.V(4).Info("Synchronize resource is disabled")
|
if label["policy.kyverno.io/synchronize"] == "enable" {
|
||||||
|
isUpdate = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if rule.Generation.Synchronize {
|
||||||
|
label["policy.kyverno.io/synchronize"] = "enable"
|
||||||
|
} else {
|
||||||
|
label["policy.kyverno.io/synchronize"] = "disable"
|
||||||
|
}
|
||||||
|
if isUpdate {
|
||||||
|
logger.V(4).Info("updating existing resource")
|
||||||
|
// Update the resource
|
||||||
|
newResource.SetLabels(label)
|
||||||
|
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "updating existing resource")
|
||||||
|
// Failed to update resource
|
||||||
|
return noGenResource, err
|
||||||
|
}
|
||||||
|
logger.V(4).Info("updated new resource")
|
||||||
|
}else{
|
||||||
|
resource := &unstructured.Unstructured{}
|
||||||
|
resource.SetUnstructuredContent(rdata)
|
||||||
|
resource.SetLabels(label)
|
||||||
|
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, resource, false)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "updating existing resource")
|
||||||
|
// Failed to update resource
|
||||||
|
return noGenResource, err
|
||||||
|
}
|
||||||
|
logger.V(4).Info("updated new resource")
|
||||||
|
}
|
||||||
|
logger.V(4).Info("Synchronize resource is disabled")
|
||||||
|
|
||||||
}
|
}
|
||||||
return newGenResource, nil
|
return newGenResource, nil
|
||||||
}
|
}
|
||||||
|
@ -353,24 +400,19 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
||||||
func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
||||||
// check if resource to be generated exists
|
// check if resource to be generated exists
|
||||||
obj, err := client.GetResource(apiVersion, kind, namespace, name)
|
obj, err := client.GetResource(apiVersion, kind, namespace, name)
|
||||||
if apierrors.IsNotFound(err) {
|
|
||||||
log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
|
||||||
return data, Create, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if apierrors.IsNotFound(err) {
|
||||||
|
log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
||||||
|
return data, Create, nil
|
||||||
|
}
|
||||||
//something wrong while fetching resource
|
//something wrong while fetching resource
|
||||||
// client-errors
|
// client-errors
|
||||||
return nil, Skip, err
|
return nil, Skip, err
|
||||||
}
|
}
|
||||||
// Resource exists; verfiy the content of the resource
|
updateObj := &unstructured.Unstructured{}
|
||||||
err = checkResource(log, data, obj)
|
updateObj.SetUnstructuredContent(data)
|
||||||
if err == nil {
|
updateObj.SetResourceVersion(obj.GetResourceVersion())
|
||||||
// Existing resource does contain the mentioned configuration in spec, skip processing the resource as it is already in expected state
|
return updateObj.UnstructuredContent(), Update, nil
|
||||||
return nil, Skip, nil
|
|
||||||
}
|
|
||||||
log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
|
||||||
return data, Update, nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
||||||
|
@ -409,13 +451,6 @@ func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clon
|
||||||
return obj.UnstructuredContent(), Update, nil
|
return obj.UnstructuredContent(), Update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check this
|
|
||||||
if !apierrors.IsNotFound(err) {
|
|
||||||
log.Error(err, "reference/clone resource is not found", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
|
||||||
//something wrong while fetching resource
|
|
||||||
return nil, Skip, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the resource based on the reference clone
|
// create the resource based on the reference clone
|
||||||
return obj.UnstructuredContent(), Create, nil
|
return obj.UnstructuredContent(), Create, nil
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package policy
|
package policy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
informers "k8s.io/client-go/informers/core/v1"
|
informers "k8s.io/client-go/informers/core/v1"
|
||||||
|
@ -58,6 +61,9 @@ type PolicyController struct {
|
||||||
// npLister can list/get namespace policy from the shared informer's store
|
// npLister can list/get namespace policy from the shared informer's store
|
||||||
npLister kyvernolister.PolicyLister
|
npLister kyvernolister.PolicyLister
|
||||||
|
|
||||||
|
// grLister can list/get generate request from the shared informer's store
|
||||||
|
grLister kyvernolister.GenerateRequestLister
|
||||||
|
|
||||||
// pvLister can list/get policy violation from the shared informer's store
|
// pvLister can list/get policy violation from the shared informer's store
|
||||||
cpvLister kyvernolister.ClusterPolicyViolationLister
|
cpvLister kyvernolister.ClusterPolicyViolationLister
|
||||||
|
|
||||||
|
@ -82,6 +88,8 @@ type PolicyController struct {
|
||||||
// nsListerSynced returns true if the namespace store has been synced at least once
|
// nsListerSynced returns true if the namespace store has been synced at least once
|
||||||
nsListerSynced cache.InformerSynced
|
nsListerSynced cache.InformerSynced
|
||||||
|
|
||||||
|
// grListerSynced returns true if the generate request store has been synced at least once
|
||||||
|
grListerSynced cache.InformerSynced
|
||||||
// Resource manager, manages the mapping for already processed resource
|
// Resource manager, manages the mapping for already processed resource
|
||||||
rm resourceManager
|
rm resourceManager
|
||||||
|
|
||||||
|
@ -91,6 +99,7 @@ type PolicyController struct {
|
||||||
// policy violation generator
|
// policy violation generator
|
||||||
pvGenerator policyviolation.GeneratorInterface
|
pvGenerator policyviolation.GeneratorInterface
|
||||||
|
|
||||||
|
|
||||||
// resourceWebhookWatcher queues the webhook creation request, creates the webhook
|
// resourceWebhookWatcher queues the webhook creation request, creates the webhook
|
||||||
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister
|
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister
|
||||||
|
|
||||||
|
@ -104,6 +113,7 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
|
||||||
npInformer kyvernoinformer.PolicyInformer,
|
npInformer kyvernoinformer.PolicyInformer,
|
||||||
cpvInformer kyvernoinformer.ClusterPolicyViolationInformer,
|
cpvInformer kyvernoinformer.ClusterPolicyViolationInformer,
|
||||||
nspvInformer kyvernoinformer.PolicyViolationInformer,
|
nspvInformer kyvernoinformer.PolicyViolationInformer,
|
||||||
|
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||||
configHandler config.Interface, eventGen event.Interface,
|
configHandler config.Interface, eventGen event.Interface,
|
||||||
pvGenerator policyviolation.GeneratorInterface,
|
pvGenerator policyviolation.GeneratorInterface,
|
||||||
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister,
|
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister,
|
||||||
|
@ -162,12 +172,13 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
|
||||||
pc.cpvLister = cpvInformer.Lister()
|
pc.cpvLister = cpvInformer.Lister()
|
||||||
pc.nspvLister = nspvInformer.Lister()
|
pc.nspvLister = nspvInformer.Lister()
|
||||||
pc.nsLister = namespaces.Lister()
|
pc.nsLister = namespaces.Lister()
|
||||||
|
pc.grLister = grInformer.Lister()
|
||||||
pc.pListerSynced = pInformer.Informer().HasSynced
|
pc.pListerSynced = pInformer.Informer().HasSynced
|
||||||
pc.npListerSynced = npInformer.Informer().HasSynced
|
pc.npListerSynced = npInformer.Informer().HasSynced
|
||||||
pc.cpvListerSynced = cpvInformer.Informer().HasSynced
|
pc.cpvListerSynced = cpvInformer.Informer().HasSynced
|
||||||
pc.nspvListerSynced = nspvInformer.Informer().HasSynced
|
pc.nspvListerSynced = nspvInformer.Informer().HasSynced
|
||||||
pc.nsListerSynced = namespaces.Informer().HasSynced
|
pc.nsListerSynced = namespaces.Informer().HasSynced
|
||||||
|
pc.grListerSynced = grInformer.Informer().HasSynced
|
||||||
|
|
||||||
// resource manager
|
// resource manager
|
||||||
// rebuild after 300 seconds/ 5 mins
|
// rebuild after 300 seconds/ 5 mins
|
||||||
|
@ -308,7 +319,7 @@ func (pc *PolicyController) Run(workers int, stopCh <-chan struct{}) {
|
||||||
logger.Info("starting")
|
logger.Info("starting")
|
||||||
defer logger.Info("shutting down")
|
defer logger.Info("shutting down")
|
||||||
|
|
||||||
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.cpvListerSynced, pc.nspvListerSynced, pc.nsListerSynced) {
|
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.cpvListerSynced, pc.nspvListerSynced, pc.nsListerSynced,pc.grListerSynced) {
|
||||||
logger.Info("failed to sync informer cache")
|
logger.Info("failed to sync informer cache")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -373,6 +384,11 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
||||||
namespace, key, isNamespacedPolicy := getIsNamespacedPolicy(key)
|
namespace, key, isNamespacedPolicy := getIsNamespacedPolicy(key)
|
||||||
var policy *kyverno.ClusterPolicy
|
var policy *kyverno.ClusterPolicy
|
||||||
var err error
|
var err error
|
||||||
|
grList, err := pc.grLister.List(labels.Everything())
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to list generate request")
|
||||||
|
}
|
||||||
|
|
||||||
if !isNamespacedPolicy {
|
if !isNamespacedPolicy {
|
||||||
policy, err = pc.pLister.Get(key)
|
policy, err = pc.pLister.Get(key)
|
||||||
} else {
|
} else {
|
||||||
|
@ -380,9 +396,17 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
||||||
nspolicy, err = pc.npLister.Policies(namespace).Get(key)
|
nspolicy, err = pc.npLister.Policies(namespace).Get(key)
|
||||||
policy = convertPolicyToClusterPolicy(nspolicy)
|
policy = convertPolicyToClusterPolicy(nspolicy)
|
||||||
}
|
}
|
||||||
if errors.IsNotFound(err) {
|
|
||||||
go pc.deletePolicyViolations(key)
|
|
||||||
|
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
for _, v := range grList {
|
||||||
|
if key == v.Spec.Policy {
|
||||||
|
err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(),&metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to delete gr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go pc.deletePolicyViolations(key)
|
||||||
// remove webhook configurations if there are no policies
|
// remove webhook configurations if there are no policies
|
||||||
if err := pc.removeResourceWebhookConfiguration(); err != nil {
|
if err := pc.removeResourceWebhookConfiguration(); err != nil {
|
||||||
logger.Error(err, "failed to remove resource webhook configurations")
|
logger.Error(err, "failed to remove resource webhook configurations")
|
||||||
|
@ -390,11 +414,20 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
for _, v := range grList {
|
||||||
if err != nil {
|
if policy.Name == v.Spec.Policy {
|
||||||
return err
|
v.SetLabels(map[string]string{
|
||||||
|
"policy-update" :fmt.Sprintf("revision-count-%d",rand.Intn(100000)),
|
||||||
|
})
|
||||||
|
_,err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Update(v)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to update gr")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pc.resourceWebhookWatcher.RegisterResourceWebhook()
|
pc.resourceWebhookWatcher.RegisterResourceWebhook()
|
||||||
|
|
||||||
engineResponses := pc.processExistingResources(policy)
|
engineResponses := pc.processExistingResources(policy)
|
||||||
|
|
|
@ -90,6 +90,7 @@ func (g *Generator) processApply() {
|
||||||
|
|
||||||
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.Operation) error {
|
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.Operation) error {
|
||||||
// create/update a generate request
|
// create/update a generate request
|
||||||
|
|
||||||
if err := retryApplyResource(g.client, grSpec, g.log, action); err != nil {
|
if err := retryApplyResource(g.client, grSpec, g.log, action); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -125,10 +126,10 @@ func retryApplyResource(client *kyvernoclient.Clientset,
|
||||||
}
|
}
|
||||||
for i, v := range grList.Items {
|
for i, v := range grList.Items {
|
||||||
if grSpec.Policy == v.Spec.Policy && grSpec.Resource.Name == v.Spec.Resource.Name && grSpec.Resource.Kind == v.Spec.Resource.Kind && grSpec.Resource.Namespace == v.Spec.Resource.Namespace {
|
if grSpec.Policy == v.Spec.Policy && grSpec.Resource.Name == v.Spec.Resource.Name && grSpec.Resource.Kind == v.Spec.Resource.Kind && grSpec.Resource.Namespace == v.Spec.Resource.Namespace {
|
||||||
|
|
||||||
gr.SetLabels(map[string]string{
|
gr.SetLabels(map[string]string{
|
||||||
"resources-update": "true",
|
"resources-update": "true",
|
||||||
})
|
})
|
||||||
|
|
||||||
v.Spec.Context = gr.Spec.Context
|
v.Spec.Context = gr.Spec.Context
|
||||||
v.Spec.Policy = gr.Spec.Policy
|
v.Spec.Policy = gr.Spec.Policy
|
||||||
v.Spec.Resource = gr.Spec.Resource
|
v.Spec.Resource = gr.Spec.Resource
|
||||||
|
|
|
@ -47,10 +47,11 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
||||||
}
|
}
|
||||||
|
|
||||||
// engine.Generate returns a list of rules that are applicable on this resource
|
// engine.Generate returns a list of rules that are applicable on this resource
|
||||||
|
var rules []response.RuleResponse
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
policyContext.Policy = *policy
|
policyContext.Policy = *policy
|
||||||
engineResponse := engine.Generate(policyContext)
|
engineResponse := engine.Generate(policyContext)
|
||||||
for i, rule := range engineResponse.PolicyResponse.Rules {
|
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||||
if !rule.Success {
|
if !rule.Success {
|
||||||
grList, err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
grList, err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -64,15 +65,14 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(engineResponse.PolicyResponse.Rules) > 1 {
|
}else{
|
||||||
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
|
rules = append(rules,rule)
|
||||||
continue
|
|
||||||
} else if len(engineResponse.PolicyResponse.Rules) == 1 {
|
|
||||||
engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(engineResponse.PolicyResponse.Rules) > 0 {
|
|
||||||
|
|
||||||
|
if len(rules) > 0 {
|
||||||
|
engineResponse.PolicyResponse.Rules = rules
|
||||||
// some generate rules do apply to the resource
|
// some generate rules do apply to the resource
|
||||||
engineResponses = append(engineResponses, engineResponse)
|
engineResponses = append(engineResponses, engineResponse)
|
||||||
ws.statusListener.Send(generateStats{
|
ws.statusListener.Send(generateStats{
|
||||||
|
@ -81,6 +81,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds Generate Request to a channel(queue size 1000) to generators
|
// Adds Generate Request to a channel(queue size 1000) to generators
|
||||||
if failedResponse := applyGenerateRequest(ws.grGenerator, userRequestInfo, request.Operation, engineResponses...); err != nil {
|
if failedResponse := applyGenerateRequest(ws.grGenerator, userRequestInfo, request.Operation, engineResponses...); err != nil {
|
||||||
// report failure event
|
// report failure event
|
||||||
|
|
Loading…
Add table
Reference in a new issue