github.com/darciopacifico/docker@v1.9.0-rc1/daemon/config_experimental.go (about) 1 // +build experimental 2 3 package daemon 4 5 import ( 6 "fmt" 7 "strconv" 8 "strings" 9 10 "github.com/docker/docker/pkg/idtools" 11 flag "github.com/docker/docker/pkg/mflag" 12 "github.com/opencontainers/runc/libcontainer/user" 13 ) 14 15 func (config *Config) attachExperimentalFlags(cmd *flag.FlagSet, usageFn func(string) string) { 16 cmd.StringVar(&config.RemappedRoot, []string{"-userns-remap"}, "", usageFn("User/Group setting for user namespaces")) 17 } 18 19 const ( 20 defaultIDSpecifier string = "default" 21 defaultRemappedID string = "dockremap" 22 ) 23 24 // Parse the remapped root (user namespace) option, which can be one of: 25 // username - valid username from /etc/passwd 26 // username:groupname - valid username; valid groupname from /etc/group 27 // uid - 32-bit unsigned int valid Linux UID value 28 // uid:gid - uid value; 32-bit unsigned int Linux GID value 29 // 30 // If no groupname is specified, and a username is specified, an attempt 31 // will be made to lookup a gid for that username as a groupname 32 // 33 // If names are used, they are verified to exist in passwd/group 34 func parseRemappedRoot(usergrp string) (string, string, error) { 35 36 var ( 37 userID, groupID int 38 username, groupname string 39 ) 40 41 idparts := strings.Split(usergrp, ":") 42 if len(idparts) > 2 { 43 return "", "", fmt.Errorf("Invalid user/group specification in --userns-remap: %q", usergrp) 44 } 45 46 if uid, err := strconv.ParseInt(idparts[0], 10, 32); err == nil { 47 // must be a uid; take it as valid 48 userID = int(uid) 49 luser, err := user.LookupUid(userID) 50 if err != nil { 51 return "", "", fmt.Errorf("Uid %d has no entry in /etc/passwd: %v", userID, err) 52 } 53 username = luser.Name 54 if len(idparts) == 1 { 55 // if the uid was numeric and no gid was specified, take the uid as the gid 56 groupID = userID 57 lgrp, err := user.LookupGid(groupID) 58 if err != nil { 59 return "", "", fmt.Errorf("Gid %d has no entry in /etc/group: %v", groupID, err) 60 } 61 groupname = lgrp.Name 62 } 63 } else { 64 lookupName := idparts[0] 65 // special case: if the user specified "default", they want Docker to create or 66 // use (after creation) the "dockremap" user/group for root remapping 67 if lookupName == defaultIDSpecifier { 68 lookupName = defaultRemappedID 69 } 70 luser, err := user.LookupUser(lookupName) 71 if err != nil && idparts[0] != defaultIDSpecifier { 72 // error if the name requested isn't the special "dockremap" ID 73 return "", "", fmt.Errorf("Error during uid lookup for %q: %v", lookupName, err) 74 } else if err != nil { 75 // special case-- if the username == "default", then we have been asked 76 // to create a new entry pair in /etc/{passwd,group} for which the /etc/sub{uid,gid} 77 // ranges will be used for the user and group mappings in user namespaced containers 78 _, _, err := idtools.AddNamespaceRangesUser(defaultRemappedID) 79 if err == nil { 80 return defaultRemappedID, defaultRemappedID, nil 81 } 82 return "", "", fmt.Errorf("Error during %q user creation: %v", defaultRemappedID, err) 83 } 84 userID = luser.Uid 85 username = luser.Name 86 if len(idparts) == 1 { 87 // we only have a string username, and no group specified; look up gid from username as group 88 group, err := user.LookupGroup(lookupName) 89 if err != nil { 90 return "", "", fmt.Errorf("Error during gid lookup for %q: %v", lookupName, err) 91 } 92 groupID = group.Gid 93 groupname = group.Name 94 } 95 } 96 97 if len(idparts) == 2 { 98 // groupname or gid is separately specified and must be resolved 99 // to a unsigned 32-bit gid 100 if gid, err := strconv.ParseInt(idparts[1], 10, 32); err == nil { 101 // must be a gid, take it as valid 102 groupID = int(gid) 103 lgrp, err := user.LookupGid(groupID) 104 if err != nil { 105 return "", "", fmt.Errorf("Gid %d has no entry in /etc/passwd: %v", groupID, err) 106 } 107 groupname = lgrp.Name 108 } else { 109 // not a number; attempt a lookup 110 group, err := user.LookupGroup(idparts[1]) 111 if err != nil { 112 return "", "", fmt.Errorf("Error during gid lookup for %q: %v", idparts[1], err) 113 } 114 groupID = group.Gid 115 groupname = idparts[1] 116 } 117 } 118 return username, groupname, nil 119 }