Skip to content

Commit d6e9553

Browse files
committed
p/o/podsecurityreadinesscontroller: add disabled syncer
1 parent acf9f46 commit d6e9553

File tree

3 files changed

+207
-17
lines changed

3 files changed

+207
-17
lines changed

pkg/operator/podsecurityreadinesscontroller/conditions.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"sort"
66
"strings"
77

8+
corev1 "k8s.io/api/core/v1"
89
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910
"k8s.io/apimachinery/pkg/util/sets"
1011

@@ -13,9 +14,12 @@ import (
1314
)
1415

1516
const (
16-
PodSecurityCustomerType = "PodSecurityCustomerEvaluationConditionsDetected"
17-
PodSecurityOpenshiftType = "PodSecurityOpenshiftEvaluationConditionsDetected"
18-
PodSecurityRunLevelZeroType = "PodSecurityRunLevelZeroEvaluationConditionsDetected"
17+
PodSecurityCustomerType = "PodSecurityCustomerEvaluationConditionsDetected"
18+
PodSecurityOpenshiftType = "PodSecurityOpenshiftEvaluationConditionsDetected"
19+
PodSecurityRunLevelZeroType = "PodSecurityRunLevelZeroEvaluationConditionsDetected"
20+
PodSecurityDisabledSyncerType = "PodSecurityDisabledSyncerEvaluationConditionsDetected"
21+
22+
labelSyncControlLabel = "security.openshift.io/scc.podSecurityLabelSync"
1923
)
2024

2125
var (
@@ -28,24 +32,31 @@ var (
2832
)
2933

3034
type podSecurityOperatorConditions struct {
31-
violatingOpenShiftNamespaces []string
32-
violatingRunLevelZeroNamespaces []string
33-
violatingCustomerNamespaces []string
35+
violatingOpenShiftNamespaces []string
36+
violatingRunLevelZeroNamespaces []string
37+
violatingCustomerNamespaces []string
38+
violatingDisabledSyncerNamespaces []string
3439
}
3540

36-
func (c *podSecurityOperatorConditions) addViolation(name string) {
37-
if runLevelZeroNamespaces.Has(name) {
38-
c.violatingRunLevelZeroNamespaces = append(c.violatingRunLevelZeroNamespaces, name)
41+
func (c *podSecurityOperatorConditions) addViolation(ns *corev1.Namespace) {
42+
if runLevelZeroNamespaces.Has(ns.Name) {
43+
c.violatingRunLevelZeroNamespaces = append(c.violatingRunLevelZeroNamespaces, ns.Name)
3944
return
4045
}
4146

42-
isOpenShift := strings.HasPrefix(name, "openshift")
47+
isOpenShift := strings.HasPrefix(ns.Name, "openshift")
4348
if isOpenShift {
44-
c.violatingOpenShiftNamespaces = append(c.violatingOpenShiftNamespaces, name)
49+
c.violatingOpenShiftNamespaces = append(c.violatingOpenShiftNamespaces, ns.Name)
50+
return
51+
}
52+
53+
if ns.Labels[labelSyncControlLabel] == "false" {
54+
// This is the only case in which the controller wouldn't enforce the pod security standards.
55+
c.violatingDisabledSyncerNamespaces = append(c.violatingDisabledSyncerNamespaces, ns.Name)
4556
return
4657
}
4758

48-
c.violatingCustomerNamespaces = append(c.violatingCustomerNamespaces, name)
59+
c.violatingCustomerNamespaces = append(c.violatingCustomerNamespaces, ns.Name)
4960
}
5061

5162
func makeCondition(conditionType string, namespaces []string) operatorv1.OperatorCondition {
@@ -76,5 +87,6 @@ func (c *podSecurityOperatorConditions) toConditionFuncs() []v1helpers.UpdateSta
7687
v1helpers.UpdateConditionFn(makeCondition(PodSecurityCustomerType, c.violatingCustomerNamespaces)),
7788
v1helpers.UpdateConditionFn(makeCondition(PodSecurityOpenshiftType, c.violatingOpenShiftNamespaces)),
7889
v1helpers.UpdateConditionFn(makeCondition(PodSecurityRunLevelZeroType, c.violatingRunLevelZeroNamespaces)),
90+
v1helpers.UpdateConditionFn(makeCondition(PodSecurityDisabledSyncerType, c.violatingDisabledSyncerNamespaces)),
7991
}
8092
}

pkg/operator/podsecurityreadinesscontroller/conditions_test.go

Lines changed: 182 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"testing"
55

66
operatorv1 "github.com/openshift/api/operator/v1"
7+
corev1 "k8s.io/api/core/v1"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
79
)
810

911
func TestCondition(t *testing.T) {
@@ -62,8 +64,184 @@ func TestCondition(t *testing.T) {
6264
}
6365
})
6466

65-
t.Run("without anything", func(t *testing.T) {
66-
cond := podSecurityOperatorConditions{}
67-
cond.addViolation("hello world")
68-
})
67+
}
68+
69+
func TestOperatorStatus(t *testing.T) {
70+
for _, tt := range []struct {
71+
name string
72+
namespace []*corev1.Namespace
73+
expected map[string]operatorv1.ConditionStatus
74+
}{
75+
{
76+
name: "with default namespace",
77+
namespace: []*corev1.Namespace{
78+
{
79+
ObjectMeta: metav1.ObjectMeta{
80+
Name: "syncer-by-default",
81+
},
82+
},
83+
},
84+
expected: map[string]operatorv1.ConditionStatus{
85+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionTrue,
86+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionFalse,
87+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionFalse,
88+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionFalse,
89+
},
90+
},
91+
{
92+
name: "with customer disabled syncer",
93+
namespace: []*corev1.Namespace{
94+
{
95+
ObjectMeta: metav1.ObjectMeta{
96+
Name: "syncer-no-thx",
97+
Labels: map[string]string{
98+
"security.openshift.io/scc.podSecurityLabelSync": "false",
99+
},
100+
},
101+
},
102+
},
103+
expected: map[string]operatorv1.ConditionStatus{
104+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionFalse,
105+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionFalse,
106+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionFalse,
107+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionTrue,
108+
},
109+
},
110+
{
111+
name: "with customer re-enabled syncer",
112+
namespace: []*corev1.Namespace{
113+
{
114+
ObjectMeta: metav1.ObjectMeta{
115+
Name: "syncer-yes-plz",
116+
Labels: map[string]string{
117+
"security.openshift.io/scc.podSecurityLabelSync": "true",
118+
},
119+
},
120+
},
121+
},
122+
expected: map[string]operatorv1.ConditionStatus{
123+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionTrue,
124+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionFalse,
125+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionFalse,
126+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionFalse,
127+
},
128+
},
129+
{
130+
name: "with openshift namespace",
131+
namespace: []*corev1.Namespace{
132+
{
133+
ObjectMeta: metav1.ObjectMeta{
134+
Name: "openshift-fail",
135+
},
136+
},
137+
},
138+
expected: map[string]operatorv1.ConditionStatus{
139+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionFalse,
140+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionTrue,
141+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionFalse,
142+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionFalse,
143+
},
144+
},
145+
{
146+
name: "with run-level 0 namespace",
147+
namespace: []*corev1.Namespace{
148+
{
149+
ObjectMeta: metav1.ObjectMeta{
150+
Name: "kube-system",
151+
},
152+
},
153+
},
154+
expected: map[string]operatorv1.ConditionStatus{
155+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionFalse,
156+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionFalse,
157+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionTrue,
158+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionFalse,
159+
},
160+
},
161+
{
162+
name: "with other customer types in combination",
163+
namespace: []*corev1.Namespace{
164+
{
165+
ObjectMeta: metav1.ObjectMeta{
166+
Name: "foobar",
167+
},
168+
},
169+
{
170+
ObjectMeta: metav1.ObjectMeta{
171+
Name: "foobar",
172+
Labels: map[string]string{
173+
"security.openshift.io/scc.podSecurityLabelSync": "false",
174+
},
175+
},
176+
},
177+
},
178+
expected: map[string]operatorv1.ConditionStatus{
179+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionTrue,
180+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionFalse,
181+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionFalse,
182+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionTrue,
183+
},
184+
},
185+
{
186+
name: "with other system types in combination",
187+
namespace: []*corev1.Namespace{
188+
{
189+
ObjectMeta: metav1.ObjectMeta{
190+
Name: "openshift-namespace",
191+
Labels: map[string]string{
192+
"pod-security.kubernetes.io/audit": "restricted",
193+
"pod-security.kubernetes.io/audit-version": "v1.24",
194+
"pod-security.kubernetes.io/warn": "restricted",
195+
"pod-security.kubernetes.io/warn-version": "v1.24",
196+
},
197+
},
198+
},
199+
{
200+
ObjectMeta: metav1.ObjectMeta{
201+
Name: "kube-system",
202+
Labels: map[string]string{},
203+
},
204+
},
205+
},
206+
expected: map[string]operatorv1.ConditionStatus{
207+
"PodSecurityCustomerEvaluationConditionsDetected": operatorv1.ConditionFalse,
208+
"PodSecurityOpenshiftEvaluationConditionsDetected": operatorv1.ConditionTrue,
209+
"PodSecurityRunLevelZeroEvaluationConditionsDetected": operatorv1.ConditionTrue,
210+
"PodSecurityDisabledSyncerEvaluationConditionsDetected": operatorv1.ConditionFalse,
211+
},
212+
},
213+
} {
214+
tt := tt
215+
t.Run(tt.name, func(t *testing.T) {
216+
cond := podSecurityOperatorConditions{}
217+
218+
for _, ns := range tt.namespace {
219+
cond.addViolation(ns)
220+
}
221+
222+
status := &operatorv1.OperatorStatus{}
223+
for _, f := range cond.toConditionFuncs() {
224+
if err := f(status); err != nil {
225+
t.Fatalf("unexpected error: %v", err)
226+
}
227+
}
228+
229+
for expectedType, expectedStatus := range tt.expected {
230+
found := false
231+
232+
for _, condition := range status.Conditions {
233+
if condition.Type == expectedType {
234+
found = true
235+
if condition.Status != expectedStatus {
236+
t.Errorf("expected %s to be %v, have %v", expectedType, expectedStatus, condition.Status)
237+
}
238+
}
239+
}
240+
241+
if !found {
242+
t.Errorf("expected condition %s not found", expectedType)
243+
}
244+
}
245+
})
246+
}
69247
}

pkg/operator/podsecurityreadinesscontroller/podsecurityreadinesscontroller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (c *PodSecurityReadinessController) sync(ctx context.Context, syncCtx facto
7979
return err
8080
}
8181
if isViolating {
82-
conditions.addViolation(ns.Name)
82+
conditions.addViolation(&ns)
8383
}
8484

8585
return nil

0 commit comments

Comments
 (0)