9
9
"strings"
10
10
"time"
11
11
12
+ "github.com/distribution/reference"
12
13
dockerregistry "github.com/docker/docker/api/types/registry"
13
14
"github.com/kubescape/backend/pkg/server/v1/systemreports"
14
15
"github.com/kubescape/go-logger"
@@ -27,6 +28,7 @@ import (
27
28
"github.com/armosec/armoapi-go/apis"
28
29
apitypes "github.com/armosec/armoapi-go/armotypes"
29
30
"github.com/armosec/armoapi-go/identifiers"
31
+ "github.com/armosec/utils-k8s-go/armometadata"
30
32
31
33
"github.com/armosec/utils-go/httputils"
32
34
"github.com/kubescape/k8s-interface/cloudsupport"
@@ -318,13 +320,13 @@ func (actionHandler *ActionHandler) scanImage(ctx context.Context, sessionObj *u
318
320
return fmt .Errorf ("failed to get container for image %s" , actionHandler .command .Args [utils .ArgsContainerData ])
319
321
}
320
322
321
- authConfig , err := actionHandler .getAuthConfig ( pod , containerData .ImageTag )
323
+ imageScanConfig , err := getImageScanConfig ( actionHandler .k8sAPI , actionHandler . config . Namespace (), pod , containerData .ImageTag )
322
324
if err != nil {
323
325
return fmt .Errorf ("failed to get auth config for image %s" , containerData .ImageTag )
324
326
}
325
327
326
328
span .AddEvent ("scanning" , trace .WithAttributes (attribute .String ("wlid" , actionHandler .wlid )))
327
- cmd := actionHandler .getImageScanCommand (containerData , sessionObj , authConfig )
329
+ cmd := actionHandler .getImageScanCommand (containerData , sessionObj , imageScanConfig )
328
330
329
331
if err := sendCommandToScanner (ctx , actionHandler .config , cmd , sessionObj .Command .CommandName ); err != nil {
330
332
return fmt .Errorf ("failed to send command to scanner with err %v" , err )
@@ -345,31 +347,44 @@ func (actionHandler *ActionHandler) scanFilteredSBOM(ctx context.Context, sessio
345
347
return fmt .Errorf ("failed to get container for image %s" , actionHandler .command .Args [utils .ArgsContainerData ])
346
348
}
347
349
350
+ // scanning a filtered SBOM (SBOM already downloaded) so AuthConfig can be empty
348
351
span .AddEvent ("scanning" , trace .WithAttributes (attribute .String ("wlid" , actionHandler .wlid )))
349
- cmd := actionHandler .getImageScanCommand (containerData , sessionObj , []dockerregistry. AuthConfig {})
352
+ cmd := actionHandler .getImageScanCommand (containerData , sessionObj , & ImageScanConfig {})
350
353
351
354
if err := sendCommandToScanner (ctx , actionHandler .config , cmd , apis .TypeScanImages ); err != nil {
352
355
return fmt .Errorf ("failed to send command to scanner with err %v" , err )
353
356
}
354
357
return nil
355
358
}
356
- func (actionHandler * ActionHandler ) getImageScanCommand (containerData * utils.ContainerData , sessionObj * utils.SessionObj , authConfig []dockerregistry.AuthConfig ) * apis.WebsocketScanCommand {
359
+ func (actionHandler * ActionHandler ) getImageScanCommand (containerData * utils.ContainerData , sessionObj * utils.SessionObj , imageScanConfig * ImageScanConfig ) * apis.WebsocketScanCommand {
360
+
357
361
cmd := & apis.WebsocketScanCommand {
358
362
ImageScanParams : apis.ImageScanParams {
359
363
Session : apis.SessionChain {
360
364
ActionTitle : string (sessionObj .Command .CommandName ),
361
365
JobIDs : make ([]string , 0 ),
362
366
Timestamp : sessionObj .Reporter .GetTimestamp (),
363
367
},
368
+ Args : map [string ]interface {}{},
364
369
ImageTag : containerData .ImageTag ,
365
- Credentialslist : authConfig ,
370
+ Credentialslist : imageScanConfig . authConfigs ,
366
371
JobID : sessionObj .Reporter .GetJobID (),
367
372
},
368
373
Wlid : containerData .Wlid ,
369
374
ContainerName : containerData .ContainerName ,
370
375
ImageHash : containerData .ImageID ,
371
376
}
372
377
378
+ if imageScanConfig .skipTLSVerify != nil && * imageScanConfig .skipTLSVerify {
379
+ logger .L ().Debug ("setting skipTLSVerify (true) in image scan command" , helpers .String ("imageTag" , containerData .ImageTag ))
380
+ cmd .Args [identifiers .AttributeSkipTLSVerify ] = true
381
+ }
382
+
383
+ if imageScanConfig .insecure != nil && * imageScanConfig .insecure {
384
+ logger .L ().Debug ("setting insecure (true) in image scan command" , helpers .String ("imageTag" , containerData .ImageTag ))
385
+ cmd .Args [identifiers .AttributeUseHTTP ] = true
386
+ }
387
+
373
388
// Add instanceID only if container is not empty
374
389
if containerData .Slug != "" {
375
390
cmd .InstanceID = & containerData .Slug
@@ -381,15 +396,29 @@ func (actionHandler *ActionHandler) getImageScanCommand(containerData *utils.Con
381
396
return cmd
382
397
}
383
398
384
- func (actionHandler * ActionHandler ) getAuthConfig (pod * corev1.Pod , imageTag string ) ([]dockerregistry.AuthConfig , error ) {
385
- registryAuth := []dockerregistry.AuthConfig {}
399
+ type ImageScanConfig struct {
400
+ skipTLSVerify * bool
401
+ insecure * bool
402
+ authConfigs []dockerregistry.AuthConfig
403
+ }
404
+
405
+ func getImageScanConfig (k8sAPI IWorkloadsGetter , namespace string , pod * corev1.Pod , imageTag string ) (* ImageScanConfig , error ) {
406
+ imageScanConfig := ImageScanConfig {}
407
+ registryName := getRegistryNameFromImageTag (imageTag )
408
+ logger .L ().Debug ("parsed registry name from image tag" , helpers .String ("registryName" , registryName ), helpers .String ("imageTag" , imageTag ))
386
409
387
410
// build a list of secrets from the ImagePullSecrets
388
- if secrets , err := getRegistryScanSecrets (actionHandler . k8sAPI , actionHandler . config . Namespace () , "" ); err == nil && len (secrets ) > 0 {
411
+ if secrets , err := getRegistryScanSecrets (k8sAPI , namespace , "" ); err == nil && len (secrets ) > 0 {
389
412
for i := range secrets {
390
413
if auth , err := parseRegistryAuthSecret (secrets [i ]); err == nil {
391
414
for _ , authConfig := range auth {
392
- registryAuth = append (registryAuth , dockerregistry.AuthConfig {
415
+ // if we have a registry name and it matches the current registry, check if we need to skip TLS verification
416
+ if registryName != "" && containsIgnoreCase (authConfig .Registry , registryName ) {
417
+ imageScanConfig .skipTLSVerify = authConfig .SkipTLSVerify
418
+ imageScanConfig .insecure = authConfig .Insecure
419
+ }
420
+
421
+ imageScanConfig .authConfigs = append (imageScanConfig .authConfigs , dockerregistry.AuthConfig {
393
422
Username : authConfig .Username ,
394
423
Password : authConfig .Password ,
395
424
ServerAddress : authConfig .Registry ,
@@ -399,17 +428,19 @@ func (actionHandler *ActionHandler) getAuthConfig(pod *corev1.Pod, imageTag stri
399
428
}
400
429
}
401
430
402
- // TODO: this should not happen every scan
403
- // build a list of secrets from the the registry secrets
404
- secrets , err := cloudsupport .GetImageRegistryCredentials (imageTag , pod )
405
- if err != nil {
406
- return nil , err
407
- }
408
- for i := range secrets {
409
- registryAuth = append (registryAuth , secrets [i ])
431
+ if pod != nil {
432
+ // TODO: this should not happen every scan
433
+ // build a list of secrets from the the registry secrets
434
+ secrets , err := cloudsupport .GetImageRegistryCredentials (imageTag , pod )
435
+ if err != nil {
436
+ return nil , err
437
+ }
438
+ for i := range secrets {
439
+ imageScanConfig .authConfigs = append (imageScanConfig .authConfigs , secrets [i ])
440
+ }
410
441
}
411
442
412
- return registryAuth , nil
443
+ return & imageScanConfig , nil
413
444
}
414
445
415
446
func prepareSessionChain (sessionObj * utils.SessionObj , websocketScanCommand * apis.WebsocketScanCommand , actionHandler * ActionHandler ) {
@@ -505,3 +536,25 @@ func sendCommandToScanner(ctx context.Context, config config.IConfig, webSocketS
505
536
}
506
537
return err
507
538
}
539
+
540
+ func normalizeReference (ref string ) string {
541
+ n , err := reference .ParseNormalizedNamed (ref )
542
+ if err != nil {
543
+ return ref
544
+ }
545
+ return n .String ()
546
+ }
547
+
548
+ func getRegistryNameFromImageTag (imageTag string ) string {
549
+ imageTagNormalized := normalizeReference (imageTag )
550
+ imageInfo , err := armometadata .ImageTagToImageInfo (imageTagNormalized )
551
+ if err != nil {
552
+ return ""
553
+ }
554
+ return imageInfo .Registry
555
+ }
556
+
557
+ // containsIgnoreCase reports whether substr is within s (ignoring case)
558
+ func containsIgnoreCase (s , substr string ) bool {
559
+ return strings .Contains (strings .ToLower (s ), strings .ToLower (substr ))
560
+ }
0 commit comments