1- package v1alpha1_test
1+ package v1alpha1
22
33import (
44 "testing"
5+ "time"
56
6- "github.com/rancher-sandbox/runtime-enforcer/api/v1alpha1 "
7+ "github.com/rancher-sandbox/runtime-enforcer/internal/types/policymode "
78 "github.com/stretchr/testify/require"
89 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910)
1011
1112func TestWorkloadPolicyNamespacedName (t * testing.T ) {
12- wp := & v1alpha1. WorkloadPolicy {
13+ wp := & WorkloadPolicy {
1314 ObjectMeta : metav1.ObjectMeta {
1415 Namespace : "test-namespace" ,
1516 Name : "test-name" ,
@@ -18,3 +19,169 @@ func TestWorkloadPolicyNamespacedName(t *testing.T) {
1819 expected := "test-namespace/test-name"
1920 require .Equal (t , expected , wp .NamespacedName ())
2021}
22+
23+ func TestRecomputeStatus (t * testing.T ) {
24+ // This test should simulate a real flow
25+ const (
26+ forgottenBinary = "/usr/bin/cat"
27+ containerName = "example"
28+ workloadName = "example-workload"
29+ workloadKind = "Deployment"
30+ podA = "pod-a"
31+ nodeA = "node-a"
32+ podB = "pod-b"
33+ nodeB = "node-b"
34+ )
35+ baseViolation := ViolationRecord {
36+ ContainerName : containerName ,
37+ ExecutablePath : forgottenBinary ,
38+ Action : policymode .ProtectString ,
39+ WorkloadName : workloadName ,
40+ WorkloadKind : workloadKind ,
41+ }
42+ podAViolation := baseViolation .withPodName (podA ).withNodeName (nodeA )
43+ podBViolation := baseViolation .withPodName (podB ).withNodeName (nodeB )
44+ baseTS := time .Date (2026 , 3 , 1 , 9 , 0 , 0 , 0 , time .UTC )
45+ ts := func (sec int ) time.Time {
46+ return baseTS .Add (time .Duration (sec ) * time .Second )
47+ }
48+
49+ policy := & WorkloadPolicy {
50+ ObjectMeta : metav1.ObjectMeta {
51+ Generation : 7 ,
52+ Annotations : map [string ]string {},
53+ },
54+ Spec : WorkloadPolicySpec {
55+ RulesByContainer : map [string ]* WorkloadPolicyRules {
56+ containerName : {Executables : WorkloadPolicyExecutables {Allowed : []string {
57+ "/usr/bin/sh" ,
58+ "/usr/bin/ls" ,
59+ }}},
60+ },
61+ },
62+ Status : WorkloadPolicyStatus {
63+ ViolationCount : 0 ,
64+ ActiveViolationCount : 0 ,
65+ },
66+ }
67+
68+ ///////////////////////////
69+ // the user forgot a binary "/usr/bin/cat"
70+ ///////////////////////////
71+
72+ // If the application is a deployment we expect multiple violations from different nodes
73+ violations := []ViolationRecord {
74+ // The agent should send newest records first
75+ podAViolation .withTimestamp (ts (1 )),
76+ podAViolation .withTimestamp (ts (2 )),
77+ podBViolation .withTimestamp (ts (3 )),
78+ podAViolation .withTimestamp (ts (4 )),
79+ }
80+
81+ policy .RecomputeStatus (nil , violations , ts (5 ))
82+ expectedPolicyStatus := WorkloadPolicyStatus {
83+ ViolationCount : 4 ,
84+ ActiveViolationCount : 2 ,
85+ Violations : []ViolationRecord {
86+ podAViolation .withID (0 ).withTimestamp (ts (4 )),
87+ // This has ID 2 because we first face 2 violation for pod-a
88+ podBViolation .withID (2 ).withTimestamp (ts (3 )),
89+ },
90+ ObservedGeneration : 7 ,
91+ Phase : Ready ,
92+ }
93+ require .Equal (t , expectedPolicyStatus , policy .Status )
94+
95+ ///////////////////////////
96+ // the user set the policy to monitor
97+ ///////////////////////////
98+
99+ // we should receive new violation in monitor mode so we convert them
100+ podAViolationMonitor := podAViolation .withAction (policymode .MonitorString )
101+ podBViolationMonitor := podBViolation .withAction (policymode .MonitorString )
102+ violations = []ViolationRecord {
103+ // The agent should send newest records first
104+ podAViolationMonitor .withTimestamp (ts (20 )),
105+ podBViolationMonitor .withTimestamp (ts (21 )),
106+ podAViolationMonitor .withTimestamp (ts (22 )),
107+ }
108+ policy .RecomputeStatus (nil , violations , ts (24 ))
109+ expectedPolicyStatus = WorkloadPolicyStatus {
110+ ViolationCount : 7 ,
111+ ActiveViolationCount : 4 ,
112+ Violations : []ViolationRecord {
113+ podAViolationMonitor .withID (4 ).withTimestamp (ts (22 )),
114+ podBViolationMonitor .withID (5 ).withTimestamp (ts (21 )),
115+ podAViolation .withID (0 ).withTimestamp (ts (4 )),
116+ podBViolation .withID (2 ).withTimestamp (ts (3 )),
117+ },
118+ ObservedGeneration : 7 ,
119+ Phase : Ready ,
120+ }
121+ require .Equal (t , expectedPolicyStatus , policy .Status )
122+
123+ ///////////////////////////
124+ // the user adds the binary into the spec
125+ ///////////////////////////
126+
127+ policy .Spec .RulesByContainer [containerName ].Executables .Allowed =
128+ append (policy .Spec .RulesByContainer [containerName ].Executables .Allowed , forgottenBinary )
129+ policy .Generation = 8
130+
131+ // Some new violations comes in the meantime
132+ violations = []ViolationRecord {
133+ podAViolationMonitor .withTimestamp (ts (40 )),
134+ podBViolationMonitor .withTimestamp (ts (41 )),
135+ }
136+ policy .RecomputeStatus (nil , violations , ts (42 ))
137+ expectedPolicyStatus = WorkloadPolicyStatus {
138+ ViolationCount : 9 ,
139+ ActiveViolationCount : 0 ,
140+ Violations : []ViolationRecord {},
141+ ObservedGeneration : 8 ,
142+ Phase : Ready ,
143+ }
144+ require .Equal (t , expectedPolicyStatus , policy .Status )
145+
146+ ///////////////////////////
147+ // A real violation comes
148+ ///////////////////////////
149+
150+ violations = []ViolationRecord {
151+ podAViolation .withTimestamp (ts (100 )).withExecutable ("/usr/bin/malware" ),
152+ }
153+ policy .RecomputeStatus (nil , violations , ts (101 ))
154+ expectedPolicyStatus = WorkloadPolicyStatus {
155+ ViolationCount : 10 ,
156+ ActiveViolationCount : 1 ,
157+ Violations : []ViolationRecord {
158+ podAViolation .withID (9 ).withTimestamp (ts (100 )).withExecutable ("/usr/bin/malware" ),
159+ },
160+ ObservedGeneration : 8 ,
161+ Phase : Ready ,
162+ }
163+ require .Equal (t , expectedPolicyStatus , policy .Status )
164+
165+ ///////////////////////////
166+ // The user acknowledges it
167+ ///////////////////////////
168+
169+ policy .Annotations [ViolationAcknowledgePrefix + "9" ] = "acknowledged by the user"
170+ acknowledgeTime := ts (120 )
171+ policy .RecomputeStatus (nil , nil , acknowledgeTime )
172+ expectedPolicyStatus = WorkloadPolicyStatus {
173+ ViolationCount : 10 ,
174+ ActiveViolationCount : 0 ,
175+ Violations : []ViolationRecord {},
176+ AcknowledgedViolations : []AcknowledgedViolationRecord {
177+ {
178+ Violation : podAViolation .withID (9 ).withTimestamp (ts (100 )).withExecutable ("/usr/bin/malware" ),
179+ Reason : "acknowledged by the user" ,
180+ AcknowledgedAt : metav1.Time {Time : acknowledgeTime },
181+ },
182+ },
183+ ObservedGeneration : 8 ,
184+ Phase : Ready ,
185+ }
186+ require .Equal (t , expectedPolicyStatus , policy .Status )
187+ }
0 commit comments