Skip to content

Commit c806d02

Browse files
committed
Raise a violation when given invalid metadata
Previously, if labels or annotations inside an objectTemplate used values that were not strings, the ConfigurationPolicy might try to remove all labels or annotations on that object. That behavior was potentially destructive, and it was easy for a policy author to accidentally trigger by getting some quotes wrong in their template, or by using `yes` as a value (which is interpreted by some parsers as a boolean `true`). Now, the ConfigurationPolicy will emit a special error if the input object template has invalid labels or annotations. Refs: - https://issues.redhat.com/browse/ACM-26186 Signed-off-by: Justin Kulikauskas <[email protected]>
1 parent e95b23e commit c806d02

File tree

10 files changed

+127
-8
lines changed

10 files changed

+127
-8
lines changed

controllers/configurationpolicy_controller.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,17 +3553,34 @@ func handleKeys(
35533553
continue
35543554
}
35553555

3556-
// only look at labels and annotations for metadata - configurationPolicies do not update other metadata fields
35573556
if key == "metadata" {
3558-
// if it's not the right type, the map will be empty
3559-
mdMap, _ := mergedObj.(map[string]interface{})
3557+
if mdMap, ok := mergedObj.(map[string]any); ok {
3558+
// ConfigurationPolicies should not affect metadata fields other than labels and
3559+
// annotations, and if the desired state is invalid, a violation should be raised.
3560+
mergedAnnos, found, err := unstructured.NestedStringMap(mdMap, "annotations")
3561+
if err != nil {
3562+
// A test verifies that this error text is stable
3563+
errMsg, _ := strings.CutPrefix(err.Error(), ".annotations accessor error: ")
3564+
3565+
return true, fmt.Sprintf("invalid annotation, error: %v", errMsg), true, statusMismatch, missingKey
3566+
}
3567+
3568+
if found {
3569+
existingObj.SetAnnotations(mergedAnnos)
3570+
}
35603571

3561-
// if either isn't found, they'll just be empty
3562-
mergedAnnotations, _, _ := unstructured.NestedStringMap(mdMap, "annotations")
3563-
mergedLabels, _, _ := unstructured.NestedStringMap(mdMap, "labels")
3572+
mergedLabels, found, err := unstructured.NestedStringMap(mdMap, "labels")
3573+
if err != nil {
3574+
// A test verifies that this error text is stable
3575+
errMsg, _ := strings.CutPrefix(err.Error(), ".labels accessor error: ")
3576+
3577+
return true, fmt.Sprintf("invalid label, error: %v", errMsg), true, statusMismatch, missingKey
3578+
}
35643579

3565-
existingObj.SetAnnotations(mergedAnnotations)
3566-
existingObj.SetLabels(mergedLabels)
3580+
if found {
3581+
existingObj.SetLabels(mergedLabels)
3582+
}
3583+
}
35673584
} else {
35683585
existingObj.UnstructuredContent()[key] = mergedObj
35693586
}

test/dryrun/kind_field/kind_field_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,17 @@ var podAnnotationMismatch embed.FS
2323
func TestPodAnnotationMisMatch(t *testing.T) {
2424
t.Run("Test pod annotation mismatch", dryrun.Run(podAnnotationMismatch))
2525
}
26+
27+
//go:embed pod_label_invalid/*
28+
var podLabelInvalid embed.FS
29+
30+
func TestPodLabelInvalid(t *testing.T) {
31+
t.Run("Test invalid pod label in policy", dryrun.Run(podLabelInvalid))
32+
}
33+
34+
//go:embed pod_annotation_invalid/*
35+
var podAnnotationInvalid embed.FS
36+
37+
func TestPodAnnotationInvalid(t *testing.T) {
38+
t.Run("Test invalid pod annotation in policy", dryrun.Run(podAnnotationInvalid))
39+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: nginx-pod-e2e-10
5+
namespace: managed
6+
annotations:
7+
test: e2e10
8+
labels:
9+
test: e2e10
10+
spec:
11+
containers:
12+
- image: nginx:1.7.9
13+
name: nginx
14+
ports:
15+
- containerPort: 80
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: managed
5+
spec: {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Diffs:
2+
v1 Pod managed/nginx-pod-e2e-10:
3+
4+
# Compliance messages:
5+
NonCompliant; violation - pods [nginx-pod-e2e-10] found but not as specified in namespace managed
6+
NonCompliant; violation - invalid annotation, error: contains non-string value in the map under key "case": 10 is of the type int64, expected string
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: policy.open-cluster-management.io/v1
2+
kind: ConfigurationPolicy
3+
metadata:
4+
name: policy-kind-labels-fail
5+
spec:
6+
remediationAction: inform # will be overridden by remediationAction in parent policy
7+
severity: low
8+
object-templates:
9+
- complianceType: musthave
10+
objectDefinition:
11+
apiVersion: v1
12+
kind: Pod
13+
metadata:
14+
namespace: managed
15+
name: nginx-pod-e2e-10
16+
annotations:
17+
case: 10
18+
test: fail
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: nginx-pod-e2e-10
5+
namespace: managed
6+
annotations:
7+
test: e2e10
8+
labels:
9+
test: e2e10
10+
spec:
11+
containers:
12+
- image: nginx:1.7.9
13+
name: nginx
14+
ports:
15+
- containerPort: 80
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: managed
5+
spec: {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Diffs:
2+
v1 Pod managed/nginx-pod-e2e-10:
3+
4+
# Compliance messages:
5+
NonCompliant; violation - pods [nginx-pod-e2e-10] found but not as specified in namespace managed
6+
NonCompliant; violation - invalid label, error: contains non-string value in the map under key "problem": true is of the type bool, expected string
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: policy.open-cluster-management.io/v1
2+
kind: ConfigurationPolicy
3+
metadata:
4+
name: policy-kind-labels-fail
5+
spec:
6+
remediationAction: inform # will be overridden by remediationAction in parent policy
7+
severity: low
8+
object-templates:
9+
- complianceType: musthave
10+
objectDefinition:
11+
apiVersion: v1
12+
kind: Pod
13+
metadata:
14+
namespace: managed
15+
name: nginx-pod-e2e-10
16+
labels:
17+
problem: yes
18+
test: fail

0 commit comments

Comments
 (0)