@@ -21,6 +21,7 @@ import (
2121 "fmt"
2222 "log"
2323 "os"
24+ "strings"
2425 "time"
2526
2627 policyduckv1beta1 "github.com/sigstore/policy-controller/pkg/apis/duck/v1beta1"
@@ -60,7 +61,13 @@ import (
6061 cwebhook "github.com/sigstore/policy-controller/pkg/webhook"
6162)
6263
64+ const (
65+ defaultResourceNames = "pods,replicasets,deployments,statefulsets,daemonsets,jobs,cronjobs"
66+ )
67+
6368var (
69+ validResourceTypes = []string {"pods" , "replicasets" , "deployments" , "statefulsets" , "daemonsets" , "jobs" , "cronjobs" }
70+
6471 // webhookName holds the name of the validating and mutating webhook
6572 // configuration resources dispatching admission requests to policy-controller.
6673 // It is also the name of the webhook which is injected by the controller
@@ -103,6 +110,10 @@ var (
103110 // trustrootResyncPeriod holds the interval which the TrustRoot will resync
104111 // This is essential for triggering a reconcile update for potentially stale TUF metadata.
105112 trustrootResyncPeriod = flag .Duration ("trustroot-resync-period" , 24 * time .Hour , "The resync period for ClusterImagePolicies. The default is 24h." )
113+
114+ // resourceNames holds the comma-separated list of Kubernetes resources to monitor.
115+ // https://github.com/sigstore/policy-controller/issues/1388
116+ resourceNames = flag .String ("resource-names" , defaultResourceNames , "Comma-separated list of Kubernetes resources to monitor. WARNING: If parent resources (e.g., Deployments, ReplicaSets) are not monitored, users will not receive policy violation feedback when creating them, even though the Pods they create may violate policies." )
106117)
107118
108119func main () {
@@ -118,6 +129,13 @@ func main() {
118129
119130 flag .Parse ()
120131
132+ // Parse and validate resource names
133+ resourceList := parseResourceNames (* resourceNames )
134+ types = buildTypesMap (resourceList , * resourceNames != defaultResourceNames )
135+
136+ // Update ValidResourceNames to match the configured resources
137+ common .ValidResourceNames = sets .NewString (resourceList ... )
138+
121139 // If TUF has been disabled do not try to set it up.
122140 if ! * disableTUF {
123141 // If they provided an alternate TUF root file to use, read it here.
@@ -139,11 +157,6 @@ func main() {
139157 ctx = clusterimagepolicy .ToContext (ctx , * policyResyncPeriod )
140158 ctx = pctuf .ToContext (ctx , * trustrootResyncPeriod )
141159
142- // This must match the set of resources we configure in
143- // cmd/webhook/main.go in the "types" map.
144- common .ValidResourceNames = sets .NewString ("replicasets" , "deployments" ,
145- "pods" , "cronjobs" , "jobs" , "statefulsets" , "daemonsets" )
146-
147160 v := version .GetVersionInfo ()
148161 vJSON , _ := v .JSONString ()
149162 log .Printf ("%v" , vJSON )
@@ -199,17 +212,77 @@ func (c *crdEphemeralContainers) SupportedVerbs() []admissionregistrationv1.Oper
199212 }
200213}
201214
202- var types = map [schema.GroupVersionKind ]resourcesemantics.GenericCRD {
203- corev1 .SchemeGroupVersion .WithKind ("Pod" ): & crdEphemeralContainers {GenericCRD : & duckv1.Pod {}},
215+ // types holds the mapping of Kubernetes resource types to their CRD handlers.
216+ // This is initialized in main() based on the --resource-names flag.
217+ var types map [schema.GroupVersionKind ]resourcesemantics.GenericCRD
218+
219+ // parseResourceNames parses a comma-separated list of resource names and returns a cleaned slice.
220+ func parseResourceNames (input string ) []string {
221+ parts := strings .Split (input , "," )
222+ result := make ([]string , 0 , len (parts ))
223+ for _ , part := range parts {
224+ trimmed := strings .TrimSpace (strings .ToLower (part ))
225+ if trimmed != "" {
226+ result = append (result , trimmed )
227+ }
228+ }
229+ return result
230+ }
231+
232+ // buildTypesMap constructs the types map based on the provided resource names.
233+ // Resource names must be in lowercase plural form (e.g., "pods", "deployments").
234+ func buildTypesMap (resourceNames []string , isCustom bool ) map [schema.GroupVersionKind ]resourcesemantics.GenericCRD {
235+ typesMap := make (map [schema.GroupVersionKind ]resourcesemantics.GenericCRD )
236+ var validResources , invalidResources []string
237+
238+ for _ , name := range resourceNames {
239+ switch name {
240+ case "pods" :
241+ typesMap [corev1 .SchemeGroupVersion .WithKind ("Pod" )] = & crdEphemeralContainers {GenericCRD : & duckv1.Pod {}}
242+ validResources = append (validResources , name )
243+ case "replicasets" :
244+ typesMap [appsv1 .SchemeGroupVersion .WithKind ("ReplicaSet" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}}
245+ validResources = append (validResources , name )
246+ case "deployments" :
247+ typesMap [appsv1 .SchemeGroupVersion .WithKind ("Deployment" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}}
248+ validResources = append (validResources , name )
249+ case "statefulsets" :
250+ typesMap [appsv1 .SchemeGroupVersion .WithKind ("StatefulSet" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}}
251+ validResources = append (validResources , name )
252+ case "daemonsets" :
253+ typesMap [appsv1 .SchemeGroupVersion .WithKind ("DaemonSet" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.WithPod {}}
254+ validResources = append (validResources , name )
255+ case "jobs" :
256+ typesMap [batchv1 .SchemeGroupVersion .WithKind ("Job" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.WithPod {}}
257+ validResources = append (validResources , name )
258+ case "cronjobs" :
259+ typesMap [batchv1 .SchemeGroupVersion .WithKind ("CronJob" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.CronJob {}}
260+ typesMap [batchv1beta1 .SchemeGroupVersion .WithKind ("CronJob" )] = & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.CronJob {}}
261+ validResources = append (validResources , name )
262+ default :
263+ invalidResources = append (invalidResources , name )
264+ }
265+ }
204266
205- appsv1 .SchemeGroupVersion .WithKind ("ReplicaSet" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}},
206- appsv1 .SchemeGroupVersion .WithKind ("Deployment" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}},
207- appsv1 .SchemeGroupVersion .WithKind ("StatefulSet" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & policyduckv1beta1.PodScalable {}},
208- appsv1 .SchemeGroupVersion .WithKind ("DaemonSet" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.WithPod {}},
209- batchv1 .SchemeGroupVersion .WithKind ("Job" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.WithPod {}},
267+ if len (invalidResources ) > 0 {
268+ log .Printf ("WARNING: Invalid resource names will be ignored: %v. Valid options: %v" , invalidResources , validResourceTypes )
269+ }
270+
271+ if len (validResources ) == 0 {
272+ log .Fatalf ("No valid resources specified. At least one resource type must be monitored. Valid options: %v" , validResourceTypes )
273+ }
274+
275+ if isCustom {
276+ log .Printf ("WARNING: Using custom resource names may result in poor user experience. " +
277+ "If parent resources (e.g., Deployments, ReplicaSets) are not monitored, users will not receive policy violation feedback " +
278+ "when creating those resources, even though the Pods they create may violate policies. " +
279+ "It is recommended to monitor all resource types unless you have a specific reason to exclude some. " +
280+ "Current monitored resources: %v" , validResources )
281+ } else {
282+ log .Printf ("Monitoring resources: %v" , validResources )
283+ }
210284
211- batchv1 .SchemeGroupVersion .WithKind ("CronJob" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.CronJob {}},
212- batchv1beta1 .SchemeGroupVersion .WithKind ("CronJob" ): & crdNoStatusUpdatesOrDeletes {GenericCRD : & duckv1.CronJob {}},
285+ return typesMap
213286}
214287
215288var typesCIP = map [schema.GroupVersionKind ]resourcesemantics.GenericCRD {
0 commit comments