66 "fmt"
77 "io"
88 "net/http"
9+ "strings"
910
1011 "github.com/pkg/errors"
1112 clusterUtil "github.com/stackrox/rox/central/cluster/util"
@@ -35,24 +36,22 @@ type sbomHttpHandler struct {
3536
3637var _ http.Handler = (* sbomHttpHandler )(nil )
3738
38- // SBOMHandler returns a handler for get sbom http request
39+ // SBOMHandler returns a handler for get sbom http request.
3940func SBOMHandler (integration integration.Set , enricher enricher.ImageEnricher , clusterSACHelper sachelper.ClusterSacHelper , riskManager manager.Manager ) http.Handler {
4041 return sbomHttpHandler {
4142 integration : integration ,
4243 enricher : enricher ,
4344 clusterSACHelper : clusterSACHelper ,
4445 riskManager : riskManager ,
4546 }
46-
4747}
4848
4949func (h sbomHttpHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
50-
5150 if r .Method != http .MethodPost {
5251 w .WriteHeader (http .StatusMethodNotAllowed )
5352 return
5453 }
55- // verify scanner v4 is enabled
54+ // Verify Scanner V4 is enabled.
5655 if ! features .ScannerV4 .Enabled () {
5756 httputil .WriteGRPCStyleError (w , codes .Unimplemented , errors .New ("Scanner V4 is disabled. Enable Scanner V4 to generate SBOMs" ))
5857 return
@@ -61,20 +60,24 @@ func (h sbomHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6160 httputil .WriteGRPCStyleError (w , codes .Unimplemented , errors .New ("SBOM feature is not enabled" ))
6261 return
6362 }
64- var params apiparams.SbomRequestBody
63+
64+ var params apiparams.SBOMRequestBody
6565 sbomGenMaxReqSizeBytes := env .SBOMGenerationMaxReqSizeBytes .IntegerSetting ()
66- // timeout api after 10 minutes
6766 lr := io .LimitReader (r .Body , int64 (sbomGenMaxReqSizeBytes ))
6867 err := json .NewDecoder (lr ).Decode (& params )
6968 if err != nil {
7069 httputil .WriteGRPCStyleError (w , codes .InvalidArgument , errors .Wrap (err , "decoding json request body" ))
7170 return
7271 }
72+ params .ImageName = strings .TrimSpace (params .ImageName )
73+
7374 ctx , cancel := context .WithTimeout (r .Context (), env .ScanTimeout .DurationSetting ())
7475 defer cancel ()
75- bytes , err := h .getSbom (ctx , params )
76+ bytes , err := h .getSBOM (ctx , params )
7677 if err != nil {
77- httputil .WriteGRPCStyleError (w , codes .Internal , errors .Wrap (err , "generating SBOM" ))
78+ // Using WriteError instead of WriteGRPCStyleError so that the HTTP status
79+ // is derived from the error type.
80+ httputil .WriteError (w , errors .Wrap (err , "generating SBOM" ))
7881 return
7982 }
8083 if len (bytes ) == 0 {
@@ -89,41 +92,38 @@ func (h sbomHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
8992 _ , _ = w .Write (bytes )
9093}
9194
92- // enrichImage enriches the image with the given name and based on the given enrichment context
95+ // enrichImage enriches the image with the given name and based on the given enrichment context.
9396func (h sbomHttpHandler ) enrichImage (ctx context.Context , enrichmentCtx enricher.EnrichmentContext , imgName string ) (* storage.Image , bool , error ) {
94-
9597 // forcedEnrichment is set to true when enrichImage forces an enrichment.
96- forceEnrichment := false
98+ forcedEnrichment := false
9799 img , err := enricher .EnrichImageByName (ctx , h .enricher , enrichmentCtx , imgName )
98100 if err != nil {
99- return nil , forceEnrichment , err
101+ return nil , forcedEnrichment , err
100102 }
101- // verify that image is scanned by scanner v4 if not force enrichment using scanner v4
102- scannedByV4 := h .scannedByScannerv4 (img )
103103
104+ // SBOM generation requires an image to have been scanned by Scanner V4, if the existing image
105+ // was scanned by a different scanner we force enrichment using Scanner V4.
106+ scannedByV4 := h .scannedByScannerV4 (img )
104107 if enrichmentCtx .FetchOpt != enricher .UseImageNamesRefetchCachedValues && ! scannedByV4 {
105- // force scan by scanner v4
108+ // Force scan by Scanner V4.
106109 addForceToEnrichmentContext (& enrichmentCtx )
107- forceEnrichment = true
110+ forcedEnrichment = true
108111 img , err = enricher .EnrichImageByName (ctx , h .enricher , enrichmentCtx , imgName )
109112 if err != nil {
110- return nil , forceEnrichment , err
113+ return nil , forcedEnrichment , err
111114 }
112115 }
113116
114- // Save the image
115- img .Id = utils .GetSHA (img )
116- if img .GetId () != "" {
117- if err := h .saveImage (img ); err != nil {
118- return nil , forceEnrichment , err
119- }
117+ err = h .saveImage (img )
118+ if err != nil {
119+ return nil , forcedEnrichment , err
120120 }
121121
122- return img , forceEnrichment , nil
122+ return img , forcedEnrichment , nil
123123}
124124
125- // getSbom generates an SBOM for the specified parameters
126- func (h sbomHttpHandler ) getSbom (ctx context.Context , params apiparams.SbomRequestBody ) ([]byte , error ) {
125+ // getSBOM generates an SBOM for the specified parameters.
126+ func (h sbomHttpHandler ) getSBOM (ctx context.Context , params apiparams.SBOMRequestBody ) ([]byte , error ) {
127127 enrichmentCtx := enricher.EnrichmentContext {
128128 FetchOpt : enricher .UseCachesIfPossible ,
129129 Delegable : true ,
@@ -142,42 +142,50 @@ func (h sbomHttpHandler) getSbom(ctx context.Context, params apiparams.SbomReque
142142 }
143143 enrichmentCtx .ClusterID = clusterID
144144 }
145+
145146 img , alreadyForcedEnrichment , err := h .enrichImage (ctx , enrichmentCtx , params .ImageName )
146147 if err != nil {
147148 return nil , err
148149 }
149- // verify that index report exists. if not force image enrichment using scanner v4
150+
151+ // Verify the Index Report exists. If it doesn't, force image enrichment using Scanner V4.
150152 scannerV4 , err := h .getScannerV4SBOMIntegration ()
151153 if err != nil {
152154 return nil , err
153155 }
154- sbom , found , err := scannerV4 .GetSBOM (img )
155156
157+ sbom , found , err := scannerV4 .GetSBOM (img )
156158 if err != nil {
157159 return nil , err
158160 }
161+
159162 if ! found && ! params .Force && ! alreadyForcedEnrichment {
160- // since index report for image does not exist force scan by scanner v4
163+ // Since the Index Report for image does not exist, force scan by Scanner V4.
161164 addForceToEnrichmentContext (& enrichmentCtx )
162- _ , err = enricher .EnrichImageByName (ctx , h .enricher , enrichmentCtx , params .ImageName )
165+ img , err = enricher .EnrichImageByName (ctx , h .enricher , enrichmentCtx , params .ImageName )
163166 if err != nil {
164167 return nil , err
165168 }
166- sbom , _ , err = scannerV4 .GetSBOM (img )
167169
170+ err = h .saveImage (img )
168171 if err != nil {
169172 return nil , err
170173 }
171174
175+ sbom , _ , err = scannerV4 .GetSBOM (img )
176+ if err != nil {
177+ return nil , err
178+ }
172179 }
180+
173181 return sbom , nil
174182}
175183
176184func addForceToEnrichmentContext (enrichmentCtx * enricher.EnrichmentContext ) {
177185 enrichmentCtx .FetchOpt = enricher .UseImageNamesRefetchCachedValues
178186}
179187
180- // getScannerV4SBOMIntegration returns the SBOM interface of scanner v4
188+ // getScannerV4SBOMIntegration returns the SBOM interface of Scanner V4.
181189func (h sbomHttpHandler ) getScannerV4SBOMIntegration () (scannerTypes.SBOMer , error ) {
182190 scanners := h .integration .ScannerSet ()
183191 for _ , scanner := range scanners .GetAll () {
@@ -187,19 +195,24 @@ func (h sbomHttpHandler) getScannerV4SBOMIntegration() (scannerTypes.SBOMer, err
187195 }
188196 }
189197 }
190- return nil , errors .New ("Scanner v4 integration not found" )
198+ return nil , errors .New ("Scanner V4 integration not found" )
191199}
192200
193- // scannedByScannerv4 checks if image is scanned by scanner v4
194- func (h sbomHttpHandler ) scannedByScannerv4 (img * storage.Image ) bool {
201+ // scannedByScannerV4 checks if image is scanned by Scanner V4.
202+ func (h sbomHttpHandler ) scannedByScannerV4 (img * storage.Image ) bool {
195203 return img .GetScan ().GetDataSource ().GetId () == iiStore .DefaultScannerV4Integration .GetId ()
196204}
197205
198- // saveImage saves the image to the scanner database
206+ // saveImage saves the image to Central's database.
199207func (h sbomHttpHandler ) saveImage (img * storage.Image ) error {
208+ img .Id = utils .GetSHA (img )
209+ if img .GetId () == "" {
210+ return nil
211+ }
212+
200213 if err := h .riskManager .CalculateRiskAndUpsertImage (img ); err != nil {
201214 log .Errorw ("Error upserting image" , logging .ImageName (img .GetName ().GetFullName ()), logging .Err (err ))
202- return err
215+ return fmt . Errorf ( "saving image: %w" , err )
203216 }
204217 return nil
205218}
0 commit comments