@@ -10,6 +10,7 @@ import (
1010
1111 "github.com/stackrox/roxie/internal/k8s"
1212 "gopkg.in/yaml.v3"
13+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1314)
1415
1516const (
@@ -107,11 +108,21 @@ func (d *Deployer) getOperatorIndexImage() string {
107108func (d * Deployer ) createCatalogSource (ctx context.Context , indexImage string ) error {
108109 d .logger .Info ("Creating CatalogSource..." )
109110
110- // Check if CatalogSource CRD supports securityContextConfig (OCP 4.14+).
111- hasSecurityContextConfig , err := d .catalogSourceSupportsSecurityContextConfig (ctx )
111+ securityContextConfigSupported , err := d .catalogSourceSupportsSecurityContextConfig (ctx )
112112 if err != nil {
113113 d .logger .Warning ("Could not check CatalogSource CRD capabilities, proceeding without securityContextConfig" )
114- hasSecurityContextConfig = false
114+ securityContextConfigSupported = false
115+ }
116+
117+ catalogSourceSpec := map [string ]interface {}{
118+ "sourceType" : "grpc" ,
119+ "image" : indexImage ,
120+ "displayName" : "StackRox Operator Index" ,
121+ }
122+ if securityContextConfigSupported {
123+ catalogSourceSpec ["grpcPodConfig" ] = map [string ]interface {}{
124+ "securityContextConfig" : "restricted" ,
125+ }
115126 }
116127
117128 catalogSource := map [string ]interface {}{
@@ -121,19 +132,7 @@ func (d *Deployer) createCatalogSource(ctx context.Context, indexImage string) e
121132 "name" : catalogSourceName ,
122133 "namespace" : operatorNamespace ,
123134 },
124- "spec" : map [string ]interface {}{
125- "sourceType" : "grpc" ,
126- "image" : indexImage ,
127- "displayName" : "StackRox Operator Index" ,
128- },
129- }
130-
131- // TODO(ROX-34499): Add security context config if supported.
132- if hasSecurityContextConfig {
133- spec := catalogSource ["spec" ].(map [string ]interface {})
134- spec ["grpcPodConfig" ] = map [string ]interface {}{
135- "securityContextConfig" : "restricted" ,
136- }
135+ "spec" : catalogSourceSpec ,
137136 }
138137
139138 yamlData , err := yaml .Marshal (catalogSource )
@@ -153,18 +152,49 @@ func (d *Deployer) createCatalogSource(ctx context.Context, indexImage string) e
153152 return nil
154153}
155154
156- // catalogSourceSupportsSecurityContextConfig checks if the CatalogSource CRD supports securityContextConfig.
155+ // catalogSourceSupportsSecurityContextConfig checks if any served CatalogSource CRD version
156+ // includes securityContextConfig in its schema.
157157func (d * Deployer ) catalogSourceSupportsSecurityContextConfig (ctx context.Context ) (bool , error ) {
158+ crdName := "catalogsources.operators.coreos.com"
158159 result , err := d .runKubectl (ctx , k8s.KubectlOptions {
159- Args : []string {"get" , "crd" , "catalogsources.operators.coreos.com" , "-o" , "yaml" },
160+ Args : []string {"get" , "crd" , crdName , "-o" , "yaml" },
160161 })
161162 if err != nil {
162163 return false , err
163164 }
164165
165- // TODO(ROX-34499): this is overly optimistic and would incorrectly succeed if an api version
166- // that contains this had "serving: false"
167- return strings .Contains (result .Stdout , "securityContextConfig" ), nil
166+ obj := & unstructured.Unstructured {}
167+ if err := yaml .Unmarshal ([]byte (result .Stdout ), & obj .Object ); err != nil {
168+ return false , fmt .Errorf ("failed to parse CatalogSource CRD: %w" , err )
169+ }
170+
171+ // Note, we cannot use NestedSlice, because that does an implicit runtime.DeepCopyJSONValue, which fail,
172+ // because the versions slice YAML also contains unsupported types (int).
173+ versions , _ , _ := unstructured .NestedFieldNoCopy (obj .Object , "spec" , "versions" )
174+ versionsSlice , ok := versions .([]interface {})
175+ if ! ok {
176+ return false , fmt .Errorf ("failed to extract spec.versions from crd %s" , crdName )
177+ }
178+
179+ for _ , v := range versionsSlice {
180+ version , ok := v .(map [string ]interface {})
181+ if ! ok {
182+ continue
183+ }
184+ served , _ , _ := unstructured .NestedBool (version , "served" )
185+ if ! served {
186+ continue
187+ }
188+ _ , found , _ := unstructured .NestedMap (version ,
189+ "schema" , "openAPIV3Schema" , "properties" , "spec" ,
190+ "properties" , "grpcPodConfig" , "properties" , "securityContextConfig" ,
191+ )
192+ if found {
193+ return true , nil
194+ }
195+ }
196+
197+ return false , nil
168198}
169199
170200// createOperatorGroup creates the OperatorGroup.
0 commit comments