container_create: correctly set user
We had a bug in ImageStatus where we weren't returning the default image user if set, thus running all containers as root despite a user being set in the image config. We weren't populating the Username field of ImageStatus. This patch fixes that along with the handling of multiple images based on the registry patch for multiple images. It also fixes ListImages to return Username as well. Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
9128ffc226
commit
96fb47213e
4 changed files with 103 additions and 28 deletions
|
@ -39,6 +39,7 @@ type ImageResult struct {
|
||||||
Size *uint64
|
Size *uint64
|
||||||
Digest digest.Digest
|
Digest digest.Digest
|
||||||
ConfigDigest digest.Digest
|
ConfigDigest digest.Digest
|
||||||
|
User string
|
||||||
}
|
}
|
||||||
|
|
||||||
type indexInfo struct {
|
type indexInfo struct {
|
||||||
|
@ -181,6 +182,16 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
imageFull, err := ref.NewImage(systemContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer imageFull.Close()
|
||||||
|
|
||||||
|
imageConfig, err := imageFull.OCIConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
name, tags, digests := sortNamesByType(image.Names)
|
name, tags, digests := sortNamesByType(image.Names)
|
||||||
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
|
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
|
||||||
results = append(results, ImageResult{
|
results = append(results, ImageResult{
|
||||||
|
@ -191,6 +202,7 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
|
||||||
Size: size,
|
Size: size,
|
||||||
Digest: imageDigest,
|
Digest: imageDigest,
|
||||||
ConfigDigest: configDigest,
|
ConfigDigest: configDigest,
|
||||||
|
User: imageConfig.Config.User,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -213,6 +225,16 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
imageFull, err := ref.NewImage(systemContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer imageFull.Close()
|
||||||
|
|
||||||
|
imageConfig, err := imageFull.OCIConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
name, tags, digests := sortNamesByType(image.Names)
|
name, tags, digests := sortNamesByType(image.Names)
|
||||||
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
|
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
|
||||||
results = append(results, ImageResult{
|
results = append(results, ImageResult{
|
||||||
|
@ -223,6 +245,7 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
|
||||||
Size: size,
|
Size: size,
|
||||||
Digest: imageDigest,
|
Digest: imageDigest,
|
||||||
ConfigDigest: configDigest,
|
ConfigDigest: configDigest,
|
||||||
|
User: imageConfig.Config.User,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,6 +269,16 @@ func (svc *imageService) ImageStatus(systemContext *types.SystemContext, nameOrI
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
imageFull, err := ref.NewImage(systemContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer imageFull.Close()
|
||||||
|
|
||||||
|
imageConfig, err := imageFull.OCIConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
img, err := ref.NewImageSource(systemContext)
|
img, err := ref.NewImageSource(systemContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -268,6 +301,7 @@ func (svc *imageService) ImageStatus(systemContext *types.SystemContext, nameOrI
|
||||||
Size: size,
|
Size: size,
|
||||||
Digest: imageDigest,
|
Digest: imageDigest,
|
||||||
ConfigDigest: configDigest,
|
ConfigDigest: configDigest,
|
||||||
|
User: imageConfig.Config.User,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result, nil
|
return &result, nil
|
||||||
|
|
|
@ -449,7 +449,7 @@ func setupContainerUser(specgen *generate.Generator, rootfs string, sc *pb.Linux
|
||||||
containerUser := ""
|
containerUser := ""
|
||||||
// Case 1: run as user is set by kubelet
|
// Case 1: run as user is set by kubelet
|
||||||
if sc.GetRunAsUser() != nil {
|
if sc.GetRunAsUser() != nil {
|
||||||
containerUser = strconv.FormatInt(sc.GetRunAsUser().Value, 10)
|
containerUser = strconv.FormatInt(sc.GetRunAsUser().GetValue(), 10)
|
||||||
} else {
|
} else {
|
||||||
// Case 2: run as username is set by kubelet
|
// Case 2: run as username is set by kubelet
|
||||||
userName := sc.GetRunAsUsername()
|
userName := sc.GetRunAsUsername()
|
||||||
|
|
|
@ -31,20 +31,20 @@ func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (res
|
||||||
}
|
}
|
||||||
resp = &pb.ListImagesResponse{}
|
resp = &pb.ListImagesResponse{}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
if result.Size != nil {
|
resImg := &pb.Image{
|
||||||
resp.Images = append(resp.Images, &pb.Image{
|
|
||||||
Id: result.ID,
|
Id: result.ID,
|
||||||
RepoTags: result.RepoTags,
|
RepoTags: result.RepoTags,
|
||||||
RepoDigests: result.RepoDigests,
|
RepoDigests: result.RepoDigests,
|
||||||
Size_: *result.Size,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
resp.Images = append(resp.Images, &pb.Image{
|
|
||||||
Id: result.ID,
|
|
||||||
RepoTags: result.RepoTags,
|
|
||||||
RepoDigests: result.RepoDigests,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
uid, username := getUserFromImage(result.User)
|
||||||
|
if uid != nil {
|
||||||
|
resImg.Uid = &pb.Int64Value{Value: *uid}
|
||||||
|
}
|
||||||
|
resImg.Username = username
|
||||||
|
if result.Size != nil {
|
||||||
|
resImg.Size_ = *result.Size
|
||||||
|
}
|
||||||
|
resp.Images = append(resp.Images, resImg)
|
||||||
}
|
}
|
||||||
logrus.Debugf("ListImagesResponse: %+v", resp)
|
logrus.Debugf("ListImagesResponse: %+v", resp)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
|
|
@ -2,6 +2,8 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
|
@ -37,14 +39,21 @@ func (s *Server) ImageStatus(ctx context.Context, req *pb.ImageStatusRequest) (r
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// match just the first registry as that's what kube meant
|
var (
|
||||||
image = images[0]
|
notfound bool
|
||||||
|
lastErr error
|
||||||
|
)
|
||||||
|
for _, image := range images {
|
||||||
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image)
|
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == storage.ErrImageUnknown {
|
if errors.Cause(err) == storage.ErrImageUnknown {
|
||||||
return &pb.ImageStatusResponse{}, nil
|
logrus.Warnf("imageStatus: can't find %s", image)
|
||||||
|
notfound = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
return nil, err
|
logrus.Warnf("imageStatus: error getting status from %s: %v", image, err)
|
||||||
|
lastErr = err
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
resp = &pb.ImageStatusResponse{
|
resp = &pb.ImageStatusResponse{
|
||||||
Image: &pb.Image{
|
Image: &pb.Image{
|
||||||
|
@ -54,6 +63,38 @@ func (s *Server) ImageStatus(ctx context.Context, req *pb.ImageStatusRequest) (r
|
||||||
Size_: *status.Size,
|
Size_: *status.Size,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
uid, username := getUserFromImage(status.User)
|
||||||
|
if uid != nil {
|
||||||
|
resp.Image.Uid = &pb.Int64Value{Value: *uid}
|
||||||
|
}
|
||||||
|
resp.Image.Username = username
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if lastErr != nil && resp == nil {
|
||||||
|
return nil, lastErr
|
||||||
|
}
|
||||||
|
if notfound && resp == nil {
|
||||||
|
return &pb.ImageStatusResponse{}, nil
|
||||||
|
}
|
||||||
logrus.Debugf("ImageStatusResponse: %+v", resp)
|
logrus.Debugf("ImageStatusResponse: %+v", resp)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUserFromImage gets uid or user name of the image user.
|
||||||
|
// If user is numeric, it will be treated as uid; or else, it is treated as user name.
|
||||||
|
func getUserFromImage(user string) (*int64, string) {
|
||||||
|
// return both empty if user is not specified in the image.
|
||||||
|
if user == "" {
|
||||||
|
return nil, ""
|
||||||
|
}
|
||||||
|
// split instances where the id may contain user:group
|
||||||
|
user = strings.Split(user, ":")[0]
|
||||||
|
// user could be either uid or user name. Try to interpret as numeric uid.
|
||||||
|
uid, err := strconv.ParseInt(user, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
// If user is non numeric, assume it's user name.
|
||||||
|
return nil, user
|
||||||
|
}
|
||||||
|
// If user is a numeric uid.
|
||||||
|
return &uid, ""
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue