@@ -10,6 +10,7 @@ import (
1010 "github.com/openshift/origin/pkg/monitor/monitorapi"
1111 "github.com/openshift/origin/pkg/monitortestframework"
1212 "github.com/openshift/origin/pkg/test/ginkgo/junitapi"
13+ exutil "github.com/openshift/origin/test/extended/util"
1314 v1 "k8s.io/api/core/v1"
1415 "k8s.io/apimachinery/pkg/util/sets"
1516
@@ -31,6 +32,56 @@ var defaultSCCs = sets.NewString(
3132 "restricted-v2" ,
3233)
3334
35+ var nonStandardSCCNamespaces = map [string ]sets.Set [string ]{
36+ "node-exporter" : sets .New ("openshift-monitoring" ),
37+ "machine-api-termination-handler" : sets .New ("openshift-machine-api" ),
38+ }
39+
40+ // namespacesWithPendingSCCPinning includes namespaces with workloads that have pending SCC pinning.
41+ var namespacesWithPendingSCCPinning = sets .NewString (
42+ "openshift-cluster-csi-drivers" ,
43+ "openshift-cluster-version" ,
44+ "openshift-image-registry" ,
45+ "openshift-ingress" ,
46+ "openshift-ingress-canary" ,
47+ "openshift-ingress-operator" ,
48+ "openshift-insights" ,
49+ "openshift-machine-api" ,
50+ "openshift-monitoring" ,
51+ // run-level namespaces
52+ "openshift-cloud-controller-manager" ,
53+ "openshift-cloud-controller-manager-operator" ,
54+ "openshift-cluster-api" ,
55+ "openshift-cluster-machine-approver" ,
56+ "openshift-dns" ,
57+ "openshift-dns-operator" ,
58+ "openshift-etcd" ,
59+ "openshift-etcd-operator" ,
60+ "openshift-kube-apiserver" ,
61+ "openshift-kube-apiserver-operator" ,
62+ "openshift-kube-controller-manager" ,
63+ "openshift-kube-controller-manager-operator" ,
64+ "openshift-kube-proxy" ,
65+ "openshift-kube-scheduler" ,
66+ "openshift-kube-scheduler-operator" ,
67+ "openshift-multus" ,
68+ "openshift-network-operator" ,
69+ "openshift-ovn-kubernetes" ,
70+ "openshift-sdn" ,
71+ "openshift-storage" ,
72+ )
73+
74+ // systemNamespaces includes namespaces that should be treated as flaking.
75+ // these namespaces are included because we don't control their creation or labeling on their creation.
76+ var systemNamespaces = sets .NewString (
77+ "default" ,
78+ "kube-system" ,
79+ "kube-public" ,
80+ "openshift-node" ,
81+ "openshift-infra" ,
82+ "openshift" ,
83+ )
84+
3485type requiredSCCAnnotationChecker struct {
3586 kubeClient kubernetes.Interface
3687}
@@ -61,7 +112,12 @@ func (w *requiredSCCAnnotationChecker) CollectData(ctx context.Context, storageD
61112
62113 junits := []* junitapi.JUnitTestCase {}
63114 for _ , ns := range namespaces .Items {
64- // require that all workloads in openshift, kube-* or default namespaces must have the required-scc annotation
115+ // skip managed service namespaces
116+ if exutil .ManagedServiceNamespaces .Has (ns .Name ) {
117+ continue
118+ }
119+
120+ // require that all workloads in openshift, kube-*, or default namespaces must have the required-scc annotation
65121 // ignore openshift-must-gather-* namespaces which are generated dynamically
66122 isPermanentOpenShiftNamespace := (ns .Name == "openshift" || strings .HasPrefix (ns .Name , "openshift-" )) && ! strings .HasPrefix (ns .Name , "openshift-must-gather-" )
67123 if ! strings .HasPrefix (ns .Name , "kube-" ) && ns .Name != "default" && ! isPermanentOpenShiftNamespace {
@@ -75,13 +131,47 @@ func (w *requiredSCCAnnotationChecker) CollectData(ctx context.Context, storageD
75131
76132 failures := make ([]string , 0 )
77133 for _ , pod := range pods .Items {
134+ validatedSCC := pod .Annotations [securityv1 .ValidatedSCCAnnotation ]
135+ allowedNamespaces , isNonStandard := nonStandardSCCNamespaces [validatedSCC ]
136+
78137 if _ , exists := pod .Annotations [securityv1 .RequiredSCCAnnotation ]; exists {
138+ if isNonStandard && ! allowedNamespaces .Has (ns .Name ) {
139+ failures = append (failures , fmt .Sprintf (
140+ "pod '%s' has a non-standard SCC '%s' not allowed in namespace '%s'; allowed namespaces are: %s" ,
141+ pod .Name , validatedSCC , ns .Name , strings .Join (allowedNamespaces .UnsortedList (), ", " )))
142+ }
79143 continue
80144 }
81145
82- suggestedSCC := suggestSCC (& pod )
83146 owners := ownerReferences (& pod )
84- failures = append (failures , fmt .Sprintf ("annotation missing from pod '%s'%s; %s" , pod .Name , owners , suggestedSCC ))
147+
148+ switch {
149+ case len (validatedSCC ) == 0 :
150+ failures = append (failures , fmt .Sprintf (
151+ "annotation missing from pod '%s'%s; cannot suggest required-scc, no validated SCC on pod" ,
152+ pod .Name , owners ))
153+
154+ case defaultSCCs .Has (validatedSCC ):
155+ failures = append (failures , fmt .Sprintf (
156+ "annotation missing from pod '%s'%s; suggested required-scc: '%s'" ,
157+ pod .Name , owners , validatedSCC ))
158+
159+ case isNonStandard :
160+ if allowedNamespaces .Has (ns .Name ) {
161+ failures = append (failures , fmt .Sprintf (
162+ "annotation missing from pod '%s'%s; suggested required-scc: '%s', this is a non-standard SCC" ,
163+ pod .Name , owners , validatedSCC ))
164+ } else {
165+ failures = append (failures , fmt .Sprintf (
166+ "annotation missing from pod '%s'%s; pod is using non-standard SCC '%s' not allowed in namespace '%s'; allowed namespaces are: %s" ,
167+ pod .Name , owners , validatedSCC , ns .Name , strings .Join (allowedNamespaces .UnsortedList (), ", " )))
168+ }
169+
170+ default :
171+ failures = append (failures , fmt .Sprintf (
172+ "annotation missing from pod '%s'%s; cannot suggest required-scc, validated SCC '%s' is a custom SCC" ,
173+ pod .Name , owners , validatedSCC ))
174+ }
85175 }
86176
87177 testName := fmt .Sprintf ("[sig-auth] all workloads in ns/%s must set the '%s' annotation" , ns .Name , securityv1 .RequiredSCCAnnotation )
@@ -91,18 +181,21 @@ func (w *requiredSCCAnnotationChecker) CollectData(ctx context.Context, storageD
91181 }
92182
93183 failureMsg := strings .Join (failures , "\n " )
184+
94185 junits = append (junits ,
95186 & junitapi.JUnitTestCase {
96187 Name : testName ,
97188 SystemOut : failureMsg ,
98189 FailureOutput : & junitapi.FailureOutput {Output : failureMsg },
99- },
100-
101- // add a successful test with the same name to cause a flake
102- & junitapi.JUnitTestCase {
103- Name : testName ,
104- },
105- )
190+ })
191+
192+ // add a successful test with the same name to cause a flake if the namespace should be flaking
193+ if namespacesWithPendingSCCPinning .Has (ns .Name ) || systemNamespaces .Has (ns .Name ) {
194+ junits = append (junits ,
195+ & junitapi.JUnitTestCase {
196+ Name : testName ,
197+ })
198+ }
106199 }
107200
108201 return nil , junits , nil
@@ -124,20 +217,6 @@ func (w *requiredSCCAnnotationChecker) Cleanup(ctx context.Context) error {
124217 return nil
125218}
126219
127- // suggestSCC suggests the assigned SCC only if it belongs to the default set of SCCs
128- // pods in runlevel 0/1 namespaces won't have any assigned SCC as SCC admission is disabled
129- func suggestSCC (pod * v1.Pod ) string {
130- if len (pod .Annotations [securityv1 .ValidatedSCCAnnotation ]) == 0 {
131- return "cannot suggest required-scc, no validated SCC on pod"
132- }
133-
134- if defaultSCCs .Has (pod .Annotations [securityv1 .ValidatedSCCAnnotation ]) {
135- return fmt .Sprintf ("suggested required-scc: '%s'" , pod .Annotations [securityv1 .ValidatedSCCAnnotation ])
136- }
137-
138- return "cannot suggest required-scc, validated SCC is custom"
139- }
140-
141220func ownerReferences (pod * v1.Pod ) string {
142221 ownerRefs := make ([]string , len (pod .OwnerReferences ))
143222 for i , or := range pod .OwnerReferences {
0 commit comments