diff --git a/Makefile b/Makefile
index 732a1facce..506f4fb2a1 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,7 @@ REGISTRY=index.docker.io
 REPO=$(REGISTRY)/nirmata/kyverno
 IMAGE_TAG=$(GIT_VERSION)
 GOOS ?= $(shell go env GOOS)
+PACKAGE ?=github.com/nirmata/kyverno
 LD_FLAGS="-s -w -X $(PACKAGE)/pkg/version.BuildVersion=$(GIT_VERSION) -X $(PACKAGE)/pkg/version.BuildHash=$(GIT_HASH) -X $(PACKAGE)/pkg/version.BuildTime=$(TIMESTAMP)"
 
 ##################################
diff --git a/definitions/install.yaml b/definitions/install.yaml
index fd7fc1a58b..8e5b660096 100644
--- a/definitions/install.yaml
+++ b/definitions/install.yaml
@@ -520,10 +520,10 @@ spec:
       serviceAccountName: kyverno-service-account
       initContainers:
         - name: kyverno-pre
-          image: nirmata/kyvernopre:v1.1.0
+          image: nirmata/kyvernopre:v1.1.1
       containers:
         - name: kyverno
-          image: nirmata/kyverno:v1.1.0
+          image: nirmata/kyverno:v1.1.1
           args:
           - "--filterK8Resources=[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][*,kyverno,*]"
           # customize webhook timout
diff --git a/definitions/rolebinding.yaml b/definitions/rolebinding.yaml
deleted file mode 100644
index b8240c0014..0000000000
--- a/definitions/rolebinding.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: rbac.authorization.k8s.io/v1beta1
-kind: RoleBinding
-metadata:
-  name: policyviolation
-  # change namespace below to create rolebinding for the namespace admin
-  namespace: default
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: ClusterRole
-  name: policyviolation
-subjects:
-# configure below to access policy violation for the namespace admin
-- kind: ServiceAccount
-  name: default
-  namespace: default
-# - apiGroup: rbac.authorization.k8s.io
-#   kind: User
-#   name: 
-# - apiGroup: rbac.authorization.k8s.io
-#   kind: Group
-#   name: 
\ No newline at end of file
diff --git a/documentation/installation.md b/documentation/installation.md
index 5c609f283f..702c6bc94d 100644
--- a/documentation/installation.md
+++ b/documentation/installation.md
@@ -116,12 +116,34 @@ Here is a script that generates a self-signed CA, a TLS certificate-key pair, an
 
 # Configure a namespace admin to access policy violations
 
-During Kyverno installation, it creates a ClusterRole `policyviolation` which has the `list,get,watch` operation on resource `policyviolations`. To grant access to a namespace admin, configure [definitions/rolebinding.yaml](../definitions/rolebinding.yaml) then apply to the cluster.
+During Kyverno installation, it creates a ClusterRole `policyviolation` which has the `list,get,watch` operation on resource `policyviolations`. To grant access to a namespace admin, configure the following YAML file then apply to the cluster.
 
 - Replace `metadata.namespace` with namespace of the admin
 - Configure `subjects` field to bind admin's role to the ClusterRole `policyviolation`
 
-
+````yaml
+apiVersion: rbac.authorization.k8s.io/v1beta1
+kind: RoleBinding
+metadata:
+  name: policyviolation
+  # change namespace below to create rolebinding for the namespace admin
+  namespace: default
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: policyviolation
+subjects:
+# configure below to access policy violation for the namespace admin
+- kind: ServiceAccount
+  name: default
+  namespace: default
+# - apiGroup: rbac.authorization.k8s.io
+#   kind: User
+#   name: 
+# - apiGroup: rbac.authorization.k8s.io
+#   kind: Group
+#   name: 
+````
 # Installing outside of the cluster (debug mode)
 
 To build Kyverno in a development environment see: https://github.com/nirmata/kyverno/wiki/Building
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/engine/mutate/overlay.go b/pkg/engine/mutate/overlay.go
index 51b0640b25..59d1f50865 100644
--- a/pkg/engine/mutate/overlay.go
+++ b/pkg/engine/mutate/overlay.go
@@ -387,11 +387,11 @@ func preparePath(path string) string {
 	}
 
 	annPath := "/metadata/annotations/"
-	idx := strings.Index(path, annPath)
 	// escape slash in annotation patch
 	if strings.Contains(path, annPath) {
+		idx := strings.Index(path, annPath)
 		p := path[idx+len(annPath):]
-		path = annPath + strings.ReplaceAll(p, "/", "~1")
+		path = path[:idx+len(annPath)] + strings.ReplaceAll(p, "/", "~1")
 	}
 	return path
 }
diff --git a/pkg/engine/policy/background.go b/pkg/engine/policy/background.go
index 636d4f7666..e027d7c6c7 100644
--- a/pkg/engine/policy/background.go
+++ b/pkg/engine/policy/background.go
@@ -26,8 +26,10 @@ func ContainsUserInfo(policy kyverno.ClusterPolicy) error {
 		// - validate.pattern
 		// - validate.anyPattern[*]
 		// variables to filter
-		// - request.userInfo
-		filterVars := []string{"request.userInfo*"}
+		// - request.userInfo*
+		// - serviceAccountName
+		// - serviceAccountNamespace
+		filterVars := []string{"request.userInfo*", "serviceAccountName", "serviceAccountNamespace"}
 		for condIdx, condition := range rule.Conditions {
 			if err := variables.CheckVariables(condition.Key, filterVars, "/"); err != nil {
 				return fmt.Errorf("path: spec/rules[%d]/condition[%d]/key%s", idx, condIdx, err)
diff --git a/pkg/engine/policy/validate_test.go b/pkg/engine/policy/validate_test.go
index bd791e84a8..bce81bcab9 100644
--- a/pkg/engine/policy/validate_test.go
+++ b/pkg/engine/policy/validate_test.go
@@ -1434,3 +1434,81 @@ func Test_BackGroundUserInfo_validate_anyPattern(t *testing.T) {
 		t.Error("Incorrect Path")
 	}
 }
+
+func Test_BackGroundUserInfo_validate_anyPattern_multiple_var(t *testing.T) {
+	var err error
+	rawPolicy := []byte(`
+	{
+		"apiVersion": "kyverno.io/v1",
+		"kind": "ClusterPolicy",
+		"metadata": {
+		  "name": "disallow-root-user"
+		},
+		"spec": {
+		  "rules": [
+			{
+			  "name": "validate.anyPattern",
+			  "validate": {
+				"anyPattern": [
+				  {
+					"var1": "temp"
+				  },
+				  {
+					"var1": "{{request.userInfo}}-{{temp}}"
+				  }
+				]
+			  }
+			}
+		  ]
+		}
+	  }	`)
+	var policy *kyverno.ClusterPolicy
+	err = json.Unmarshal(rawPolicy, &policy)
+	assert.NilError(t, err)
+
+	err = ContainsUserInfo(*policy)
+
+	if err.Error() != "path: spec/rules[0]/validate/anyPattern[1]/var1/{{request.userInfo}}-{{temp}}" {
+		t.Log(err)
+		t.Error("Incorrect Path")
+	}
+}
+
+func Test_BackGroundUserInfo_validate_anyPattern_serviceAccount(t *testing.T) {
+	var err error
+	rawPolicy := []byte(`
+	{
+		"apiVersion": "kyverno.io/v1",
+		"kind": "ClusterPolicy",
+		"metadata": {
+		  "name": "disallow-root-user"
+		},
+		"spec": {
+		  "rules": [
+			{
+			  "name": "validate.anyPattern",
+			  "validate": {
+				"anyPattern": [
+				  {
+					"var1": "temp"
+				  },
+				  {
+					"var1": "{{serviceAccountName}}"
+				  }
+				]
+			  }
+			}
+		  ]
+		}
+	  }	`)
+	var policy *kyverno.ClusterPolicy
+	err = json.Unmarshal(rawPolicy, &policy)
+	assert.NilError(t, err)
+
+	err = ContainsUserInfo(*policy)
+
+	if err.Error() != "path: spec/rules[0]/validate/anyPattern[1]/var1/{{serviceAccountName}}" {
+		t.Log(err)
+		t.Error("Incorrect Path")
+	}
+}
diff --git a/pkg/engine/variables/validatevariables.go b/pkg/engine/variables/validatevariables.go
index 78e9d687d6..23e3edf2bb 100644
--- a/pkg/engine/variables/validatevariables.go
+++ b/pkg/engine/variables/validatevariables.go
@@ -13,25 +13,27 @@ import (
 func ValidateVariables(ctx context.EvalInterface, pattern interface{}) string {
 	var pathsNotPresent []string
 	variableList := extractVariables(pattern)
-	for i := 0; i < len(variableList)-1; i = i + 2 {
-		p := variableList[i+1]
-		glog.V(3).Infof("validating variables %s", p)
-		val, err := ctx.Query(p)
-		// reference path is not present
-		if err == nil && val == nil {
-			pathsNotPresent = append(pathsNotPresent, p)
+	for _, variable := range variableList {
+		if len(variable) == 2 {
+			varName := variable[0]
+			varValue := variable[1]
+			glog.V(3).Infof("validating variable %s", varName)
+			val, err := ctx.Query(varValue)
+			if err == nil && val == nil {
+				// path is not present, returns nil interface
+				pathsNotPresent = append(pathsNotPresent, varValue)
+			}
 		}
 	}
 
-	if len(variableList) != 0 && len(pathsNotPresent) != 0 {
+	if len(pathsNotPresent) != 0 {
 		return strings.Join(pathsNotPresent, ";")
 	}
-
 	return ""
 }
 
 // extractVariables extracts variables in the pattern
-func extractVariables(pattern interface{}) []string {
+func extractVariables(pattern interface{}) [][]string {
 	switch typedPattern := pattern.(type) {
 	case map[string]interface{}:
 		return extractMap(typedPattern)
@@ -44,8 +46,8 @@ func extractVariables(pattern interface{}) []string {
 	}
 }
 
-func extractMap(patternMap map[string]interface{}) []string {
-	var variableList []string
+func extractMap(patternMap map[string]interface{}) [][]string {
+	var variableList [][]string
 
 	for _, patternElement := range patternMap {
 		if vars := extractVariables(patternElement); vars != nil {
@@ -55,8 +57,8 @@ func extractMap(patternMap map[string]interface{}) []string {
 	return variableList
 }
 
-func extractArray(patternList []interface{}) []string {
-	var variableList []string
+func extractArray(patternList []interface{}) [][]string {
+	var variableList [][]string
 
 	for _, patternElement := range patternList {
 		if vars := extractVariables(patternElement); vars != nil {
@@ -66,17 +68,22 @@ func extractArray(patternList []interface{}) []string {
 	return variableList
 }
 
-func extractValue(valuePattern string) []string {
+func extractValue(valuePattern string) [][]string {
 	operatorVariable := getOperator(valuePattern)
 	variable := valuePattern[len(operatorVariable):]
 	return extractValueVariable(variable)
 }
 
-func extractValueVariable(valuePattern string) []string {
+// returns multiple variable match groups
+func extractValueVariable(valuePattern string) [][]string {
 	variableRegex := regexp.MustCompile(variableRegex)
-	groups := variableRegex.FindStringSubmatch(valuePattern)
-	if len(groups)%2 != 0 {
+	groups := variableRegex.FindAllStringSubmatch(valuePattern, -1)
+	if len(groups) == 0 {
+		// no variables
 		return nil
 	}
+	// group[*] <- all the matches
+	// group[*][0] <- group match
+	// group[*][1] <- group capture value
 	return groups
 }
diff --git a/pkg/engine/variables/validatevariables_test.go b/pkg/engine/variables/validatevariables_test.go
index c71a966bdd..a6e5154f1a 100644
--- a/pkg/engine/variables/validatevariables_test.go
+++ b/pkg/engine/variables/validatevariables_test.go
@@ -40,7 +40,9 @@ func Test_ExtractVariables(t *testing.T) {
 	json.Unmarshal(patternRaw, &pattern)
 
 	vars := extractVariables(pattern)
-	result := []string{"{{request.userInfo.username}}", "request.userInfo.username", "{{request.object.metadata.name}}", "request.object.metadata.name"}
+
+	result := [][]string{[]string{"{{request.userInfo.username}}", "request.userInfo.username"},
+		[]string{"{{request.object.metadata.name}}", "request.object.metadata.name"}}
 
 	assert.Assert(t, len(vars) == len(result), fmt.Sprintf("result does not match, var: %s", vars))
 }
diff --git a/pkg/engine/variables/variables.go b/pkg/engine/variables/variables.go
index 7d9b352e4e..1f71c16aaf 100644
--- a/pkg/engine/variables/variables.go
+++ b/pkg/engine/variables/variables.go
@@ -110,17 +110,18 @@ func getValues(ctx context.EvalInterface, groups [][]string) map[string]interfac
 	for _, group := range groups {
 		if len(group) == 2 {
 			// 0th is string
-			// 1st is the capture group
-			variable, err := ctx.Query(group[1])
+			varName := group[0]
+			varValue := group[1]
+			variable, err := ctx.Query(varValue)
 			if err != nil {
-				glog.V(4).Infof("variable substitution failed for query %s: %v", group[0], err)
-				subs[group[0]] = emptyInterface
+				glog.V(4).Infof("variable substitution failed for query %s: %v", varName, err)
+				subs[varName] = emptyInterface
 				continue
 			}
 			if variable == nil {
-				subs[group[0]] = emptyInterface
+				subs[varName] = emptyInterface
 			} else {
-				subs[group[0]] = variable
+				subs[varName] = variable
 			}
 		}
 	}
diff --git a/pkg/engine/variables/variables_check.go b/pkg/engine/variables/variables_check.go
index 46aa56b0fe..19ee50172e 100644
--- a/pkg/engine/variables/variables_check.go
+++ b/pkg/engine/variables/variables_check.go
@@ -50,11 +50,22 @@ func checkValue(valuePattern string, variables []string, path string) error {
 
 func checkValueVariable(valuePattern string, variables []string) bool {
 	variableRegex := regexp.MustCompile(variableRegex)
-	groups := variableRegex.FindStringSubmatch(valuePattern)
-	if len(groups) < 2 {
+	groups := variableRegex.FindAllStringSubmatch(valuePattern, -1)
+	if len(groups) == 0 {
+		// no variables
 		return false
 	}
-	return variablePatternSearch(groups[1], variables)
+	// if variables are defined, check against the list of variables to be filtered
+	for _, group := range groups {
+		if len(group) == 2 {
+			// group[0] -> {{variable}}
+			// group[1] -> variable
+			if variablePatternSearch(group[1], variables) {
+				return true
+			}
+		}
+	}
+	return false
 }
 
 func variablePatternSearch(pattern string, regexs []string) bool {
diff --git a/pkg/webhooks/common.go b/pkg/webhooks/common.go
index 611e81cd2e..16b0843d6c 100644
--- a/pkg/webhooks/common.go
+++ b/pkg/webhooks/common.go
@@ -92,7 +92,7 @@ const (
 
 func processResourceWithPatches(patch []byte, resource []byte) []byte {
 	if patch == nil {
-		return nil
+		return resource
 	}
 
 	resource, err := engineutils.ApplyPatchNew(resource, patch)
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 03850b09dd..79ca2f42bc 100644
--- a/test/policy/generate/variable.yaml
+++ b/test/policy/generate/variable.yaml
@@ -6,16 +6,40 @@ 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: add-sa-annotation
+    match:
+      resources:
+        kinds:
+        - Namespace
+    mutate:
+      overlay:
+        metadata:
+          annotations:
+            nirmata.io/ns-creator: "{{serviceAccountName}}"
   - 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}}"
       data:
+        metadata:
+          annotations:
+            nirmata.io/ns-creator: "{{serviceAccountName}}"
         rules:
         - apiGroups: [""]
           resources: ["namespaces"]
@@ -27,10 +51,23 @@ 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"
       data:
+        metadata:
+          annotations:
+            nirmata.io/ns-creator: "{{serviceAccountName}}"
         roleRef:
           apiGroup: rbac.authorization.k8s.io
           kind: ClusterRole
@@ -45,11 +82,24 @@ 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"
       namespace: "{{request.object.metadata.name}}"
       data:
+        metadata:
+          annotations:
+            nirmata.io/ns-creator: "{{serviceAccountName}}"
         roleRef:
           apiGroup: rbac.authorization.k8s.io
           kind: ClusterRole
@@ -57,4 +107,4 @@ spec:
         subjects:
         - kind: ServiceAccount
           name: "{{serviceAccountName}}"
-          namespace: "{{serviceAccountNamespace}}"
+          namespace: "{{serviceAccountNamespace}}"
\ No newline at end of file