@@ -8,9 +8,11 @@ import (
88 "io/ioutil"
99 "net/http"
1010 "os"
11+ "strconv"
1112 "strings"
1213 "time"
1314
15+ dockerapi "github.com/fsouza/go-dockerclient"
1416 log "github.com/sirupsen/logrus"
1517 corev1 "k8s.io/api/core/v1"
1618 apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -24,6 +26,7 @@ import (
2426
2527 "github.com/mintoolkit/mint/pkg/app"
2628 "github.com/mintoolkit/mint/pkg/app/master/command"
29+ "github.com/mintoolkit/mint/pkg/app/master/inspectors/image"
2730 "github.com/mintoolkit/mint/pkg/util/jsonutil"
2831)
2932
@@ -33,6 +36,7 @@ func HandleKubernetesRuntime(
3336 xc * app.ExecutionContext ,
3437 gparams * command.GenericParams ,
3538 commandParams * CommandParams ,
39+ dockerClient * dockerapi.Client ,
3640 sid string ,
3741 debugContainerName string ) {
3842 logger = logger .WithFields (
@@ -484,17 +488,121 @@ func HandleKubernetesRuntime(
484488 }
485489
486490 targetIsNonRoot := runAsNonRoot ()
487- runAsUserVal := runAsUser (targetIsNonRoot )
488- if targetIsNonRoot && runAsUserVal == nil {
489- //TODO: first, try getting the user identity from the target's container image
490- runAsUserVal = & defaultNonRootUser
491- }
491+
492492 runAsGroupVal := runAsGroup (targetIsNonRoot )
493493 if targetIsNonRoot && runAsGroupVal == nil && commandParams .UID < 0 {
494494 //don't use the default group if UID is set
495495 runAsGroupVal = & defaultNonRootGroup
496496 }
497497
498+ runAsUserVal := runAsUser (targetIsNonRoot )
499+ if targetIsNonRoot && runAsUserVal == nil {
500+ //first, try getting the user identity from the target's container image
501+ var userFromImage string
502+ if targetContainer .Image != "" && dockerClient != nil {
503+ //TODO: improve
504+ //v1 version is very hacky:
505+ //* it expects the Docker container runtime locally
506+ //* it expects the target container image to be available locally
507+ //* it expects the target container images to be pullable (with no auth)
508+ imageInspector , err := image .NewInspector (dockerClient , targetContainer .Image )
509+ if err == nil {
510+ noImage , err := imageInspector .NoImage ()
511+ if err == nil {
512+ var foundImage bool
513+ if noImage {
514+ if err := imageInspector .Pull (true , "" , "" , "" ); err != nil {
515+ logger .WithError (err ).Trace ("imageInspector.Pull" )
516+ }
517+
518+ imageInspector , err = image .NewInspector (dockerClient , targetContainer .Image )
519+ if err == nil {
520+ noImage , err = imageInspector .NoImage ()
521+ if err == nil {
522+ if ! noImage {
523+ foundImage = true
524+ }
525+ } else {
526+ logger .WithError (err ).Trace ("imageInspector.NoImage" )
527+ }
528+ } else {
529+ logger .WithError (err ).Trace ("image.NewInspector" )
530+ }
531+ } else {
532+ foundImage = true
533+ }
534+
535+ if foundImage {
536+ if err := imageInspector .Inspect (); err == nil {
537+ userFromImage = imageInspector .ImageInfo .Config .User
538+ } else {
539+ logger .WithError (err ).Trace ("imageInspector.Inspect" )
540+ }
541+ }
542+
543+ } else {
544+ logger .WithError (err ).Trace ("imageInspector.NoImage" )
545+ }
546+ } else {
547+ logger .WithError (err ).Trace ("image.NewInspector" )
548+ }
549+ }
550+
551+ uid := int64 (- 1 )
552+ gid := int64 (- 1 )
553+ if userFromImage != "" {
554+ var uidStr string
555+ var gidStr string
556+ if strings .Contains (userFromImage , ":" ) {
557+ parts := strings .SplitN (userFromImage , ":" , 2 )
558+ uidStr = parts [0 ]
559+ gidStr = parts [1 ]
560+ } else {
561+ uidStr = userFromImage
562+ }
563+
564+ uid , err = strconv .ParseInt (uidStr , 10 , 64 )
565+ if err != nil {
566+ logger .WithError (err ).Tracef ("strconv.ParseUint(uidStr=%s)" , uidStr )
567+ uid = - 1
568+ }
569+
570+ if gidStr != "" {
571+ gid , err = strconv .ParseInt (gidStr , 10 , 64 )
572+ if err != nil {
573+ logger .WithError (err ).Tracef ("strconv.ParseUint(gidStr=%s)" , gidStr )
574+ gid = - 1
575+ }
576+ }
577+
578+ logger .WithFields (
579+ log.Fields {
580+ "data" : userFromImage ,
581+ "image" : targetContainer .Image ,
582+ "uid.str" : uidStr ,
583+ "gid.str" : gidStr ,
584+ "uid" : uid ,
585+ "gid" : gid ,
586+ }).Trace ("user.from.target.image" )
587+ }
588+
589+ if uid > - 1 {
590+ runAsUserVal = & uid
591+ logger .Debugf ("using.target.image.user=%v" , uid )
592+ } else {
593+ runAsUserVal = & defaultNonRootUser
594+ }
595+
596+ if gid == - 1 {
597+ gid = uid
598+ }
599+
600+ if runAsGroupVal == & defaultNonRootGroup && gid > - 1 {
601+ runAsGroupVal = & gid
602+ logger .Debugf ("using.target.image.user.group=%v" , gid )
603+ }
604+ }
605+
498606 var doRunAsNonRoot bool
499607 if targetIsNonRoot && commandParams .DoFallbackToTargetUser {
500608 doRunAsNonRoot = true
0 commit comments