From dabe592d46069dac7af57a9bbca26832b2c7fa60 Mon Sep 17 00:00:00 2001
From: Shivkumar Dudhani <shivkumar@nirmata.com>
Date: Mon, 13 Jan 2020 11:21:14 -0800
Subject: [PATCH] fix the bugs and add pre-condition checks (#606)

* fix the bugs and add pre-condition checks

* add precondition documentation
---
 documentation/writing-policies.md  | 20 ++++++++++++++++++-
 pkg/webhooks/generation.go         |  2 +-
 test/policy/generate/variable.yaml | 31 ++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/documentation/writing-policies.md b/documentation/writing-policies.md
index 60ccf5beb2..1c0d2bcc4f 100644
--- a/documentation/writing-policies.md
+++ b/documentation/writing-policies.md
@@ -98,7 +98,6 @@ Example  userName=`system:serviceaccount:nirmata:user1` will store variable valu
 - `serviceAccountNamespace` : extracts the `namespace` of the serviceAccount. 
 Example  userName=`system:serviceaccount:nirmata:user1` will store variable value as `nirmata`.
 
-
 Examples:
 
 1. Refer to resource name(type string)
@@ -113,5 +112,24 @@ Examples:
 
 `{{request.object.metadata}}`
 
+# PreConditions:
+Apart from using `match` & `exclude` conditions on resource to filter which resources to apply the rule on, `preconditions` can be used to define custom filters.
+```yaml
+  - name: generate-owner-role
+    match:
+      resources:
+        kinds:
+        - Namespace
+    preconditions:
+    - key: "{{request.userInfo.username}}"
+      operator: NotEqual
+      value: ""
+```
+In the above example, if the variable `{{request.userInfo.username}}` is blank then we dont apply the rule on resource.
+
+Operators supported:
+- Equal
+- NotEqual
+
 ---
 <small>*Read Next >> [Validate](/documentation/writing-policies-validate.md)*</small>
\ No newline at end of file
diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go
index 3929f6e330..9c9e1fa586 100644
--- a/pkg/webhooks/generation.go
+++ b/pkg/webhooks/generation.go
@@ -33,7 +33,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
 	// build context
 	ctx := context.NewContext()
 	// load incoming resource into the context
-	// ctx.AddResource(request.Object.Raw)
+	ctx.AddResource(request.Object.Raw)
 	ctx.AddUserInfo(userRequestInfo)
 	// load service account in context
 	ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
diff --git a/test/policy/generate/variable.yaml b/test/policy/generate/variable.yaml
index 41255b0a10..d35597121b 100644
--- a/test/policy/generate/variable.yaml
+++ b/test/policy/generate/variable.yaml
@@ -6,12 +6,23 @@ metadata:
     policies.kyverno.io/category: Workload Isolation
     policies.kyverno.io/description: Create roles and role bindings for a new namespace
 spec:
+  background: false
   rules:
   - name: generate-owner-role
     match:
       resources:
         kinds:
         - Namespace
+    preconditions:
+    - key: "{{request.userInfo.username}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountName}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountNamespace}}"
+      operator: NotEqual
+      value: ""
     generate:
       kind: ClusterRole
       name: "ns-owner-{{request.object.metadata.name}}-{{request.userInfo.username}}"
@@ -30,6 +41,16 @@ spec:
       resources:
         kinds:
         - Namespace
+    preconditions:
+    - key: "{{request.userInfo.username}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountName}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountNamespace}}"
+      operator: NotEqual
+      value: ""
     generate:
       kind: ClusterRoleBinding
       name: "ns-owner-{{request.object.metadata.name}}-{{request.userInfo.username}}-binding"
@@ -51,6 +72,16 @@ spec:
       resources:
         kinds:
         - Namespace
+    preconditions:
+    - key: "{{request.userInfo.username}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountName}}"
+      operator: NotEqual
+      value: ""
+    - key: "{{serviceAccountNamespace}}"
+      operator: NotEqual
+      value: ""
     generate:
       kind: RoleBinding
       name: "ns-admin-{{request.object.metadata.name}}-{{request.userInfo.username}}-binding"