internals_windows.go 3.4 KB

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