github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/builder/dockerfile/internals_windows.go (about) 1 package dockerfile // import "github.com/docker/docker/builder/dockerfile" 2 3 import ( 4 "bytes" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/containerd/containerd/platforms" 10 "github.com/docker/docker/api/types/container" 11 "github.com/docker/docker/api/types/mount" 12 "github.com/docker/docker/pkg/idtools" 13 "github.com/docker/docker/pkg/jsonmessage" 14 "github.com/docker/docker/pkg/system" 15 "github.com/pkg/errors" 16 "golang.org/x/sys/windows" 17 ) 18 19 func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping *idtools.IdentityMapping) (idtools.Identity, error) { 20 if builder.options.Platform == "windows" { 21 return getAccountIdentity(builder, chown, ctrRootPath, state) 22 } 23 24 return identityMapping.RootPair(), nil 25 } 26 27 func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) { 28 // If this is potentially a string SID then attempt to convert it to verify 29 // this, otherwise continue looking for the account. 30 if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") { 31 sid, err := windows.StringToSid(accountName) 32 33 if err == nil { 34 accountSid, err := sid.String() 35 36 if err != nil { 37 return idtools.Identity{SID: ""}, errors.Wrapf(err, "error converting SID to string") 38 } 39 40 return idtools.Identity{SID: accountSid}, nil 41 } 42 } 43 44 // Attempt to obtain the SID using the name. 45 sid, _, accType, err := windows.LookupSID("", accountName) 46 47 // If this is a SID that is built-in and hence the same across all systems then use that. 48 if err == nil && (accType == windows.SidTypeAlias || accType == windows.SidTypeWellKnownGroup) { 49 accountSid, err := sid.String() 50 51 if err != nil { 52 return idtools.Identity{SID: ""}, errors.Wrapf(err, "error converting SID to string") 53 } 54 55 return idtools.Identity{SID: accountSid}, nil 56 } 57 58 // Check if the account name is one unique to containers. 59 if strings.EqualFold(accountName, "ContainerAdministrator") { 60 return idtools.Identity{SID: system.ContainerAdministratorSidString}, nil 61 62 } else if strings.EqualFold(accountName, "ContainerUser") { 63 return idtools.Identity{SID: system.ContainerUserSidString}, nil 64 } 65 66 // All other lookups failed, so therefore determine if the account in 67 // question exists in the container and if so, obtain its SID. 68 return lookupNTAccount(builder, accountName, state) 69 } 70 71 func lookupNTAccount(builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) { 72 73 source, _ := filepath.Split(os.Args[0]) 74 75 target := "C:\\Docker" 76 targetExecutable := target + "\\containerutility.exe" 77 78 optionsPlatform, err := platforms.Parse(builder.options.Platform) 79 if err != nil { 80 return idtools.Identity{}, err 81 } 82 83 runConfig := copyRunConfig(state.runConfig, 84 withCmdCommentString("internal run to obtain NT account information.", optionsPlatform.OS)) 85 86 runConfig.ArgsEscaped = true 87 runConfig.Cmd = []string{targetExecutable, "getaccountsid", accountName} 88 89 hostConfig := &container.HostConfig{Mounts: []mount.Mount{ 90 { 91 Type: mount.TypeBind, 92 Source: source, 93 Target: target, 94 ReadOnly: true, 95 }, 96 }, 97 } 98 99 container, err := builder.containerManager.Create(runConfig, hostConfig) 100 if err != nil { 101 return idtools.Identity{}, err 102 } 103 104 stdout := new(bytes.Buffer) 105 stderr := new(bytes.Buffer) 106 107 if err := builder.containerManager.Run(builder.clientCtx, container.ID, stdout, stderr); err != nil { 108 if err, ok := err.(*statusCodeError); ok { 109 return idtools.Identity{}, &jsonmessage.JSONError{ 110 Message: stderr.String(), 111 Code: err.StatusCode(), 112 } 113 } 114 return idtools.Identity{}, err 115 } 116 117 accountSid := stdout.String() 118 119 return idtools.Identity{SID: accountSid}, nil 120 }