diff --git a/cmd/buildkitd/config/config.go b/cmd/buildkitd/config/config.go index 9af4156f68de..58dd2f8a047b 100644 --- a/cmd/buildkitd/config/config.go +++ b/cmd/buildkitd/config/config.go @@ -40,10 +40,11 @@ type LogConfig struct { } type GRPCConfig struct { - Address []string `toml:"address"` - DebugAddress string `toml:"debugAddress"` - UID *int `toml:"uid"` - GID *int `toml:"gid"` + Address []string `toml:"address"` + DebugAddress string `toml:"debugAddress"` + UID *int `toml:"uid"` + GID *int `toml:"gid"` + SecurityDescriptor string `toml:"securityDescriptor"` TLS TLSConfig `toml:"tls"` // MaxRecvMsgSize int `toml:"max_recv_message_size"` diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index 3a3ff16f2b1e..a62e913bd295 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -9,6 +9,7 @@ import ( "os" "os/user" "path/filepath" + "runtime" "sort" "strconv" "strings" @@ -397,9 +398,18 @@ func newGRPCListeners(cfg config.GRPCConfig) ([]net.Listener, error) { if err != nil { return nil, err } + + sd := cfg.SecurityDescriptor + if sd == "" { + sd, err = groupToSecurityDescriptor("") + if err != nil { + return nil, err + } + } + listeners := make([]net.Listener, 0, len(addrs)) for _, addr := range addrs { - l, err := getListener(addr, *cfg.UID, *cfg.GID, tlsConfig) + l, err := getListener(addr, *cfg.UID, *cfg.GID, sd, tlsConfig) if err != nil { for _, l := range listeners { l.Close() @@ -569,11 +579,19 @@ func applyMainFlags(c *cli.Context, cfg *config.Config) error { } if group := c.String("group"); group != "" { - gid, err := groupToGid(group) - if err != nil { - return err + if runtime.GOOS == "windows" { + secDescriptor, err := groupToSecurityDescriptor(group) + if err != nil { + return err + } + cfg.GRPC.SecurityDescriptor = secDescriptor + } else { + gid, err := groupToGid(group) + if err != nil { + return err + } + cfg.GRPC.GID = &gid } - cfg.GRPC.GID = &gid } if tlscert := c.String("tlscert"); tlscert != "" { @@ -628,7 +646,7 @@ func groupToGid(group string) (int, error) { return id, nil } -func getListener(addr string, uid, gid int, tlsConfig *tls.Config) (net.Listener, error) { +func getListener(addr string, uid, gid int, secDescriptor string, tlsConfig *tls.Config) (net.Listener, error) { addrSlice := strings.SplitN(addr, "://", 2) if len(addrSlice) < 2 { return nil, errors.Errorf("address %s does not contain proto, you meant unix://%s ?", @@ -641,6 +659,9 @@ func getListener(addr string, uid, gid int, tlsConfig *tls.Config) (net.Listener if tlsConfig != nil { bklog.L.Warnf("TLS is disabled for %s", addr) } + if proto == "npipe" { + return getLocalListener(listenAddr, secDescriptor) + } return sys.GetLocalListener(listenAddr, uid, gid) case "fd": return listenFD(listenAddr, tlsConfig) @@ -928,7 +949,7 @@ func parseBoolOrAuto(s string) (*bool, error) { func runTraceController(p string, exp sdktrace.SpanExporter) error { server := grpc.NewServer() tracev1.RegisterTraceServiceServer(server, &traceCollector{exporter: exp}) - l, err := getLocalListener(p) + l, err := getLocalListener(p, "") if err != nil { return errors.Wrap(err, "creating trace controller listener") } diff --git a/cmd/buildkitd/main_unix.go b/cmd/buildkitd/main_unix.go index d819d1187f59..1dc3a2ed35c9 100644 --- a/cmd/buildkitd/main_unix.go +++ b/cmd/buildkitd/main_unix.go @@ -48,7 +48,7 @@ func listenFD(addr string, tlsConfig *tls.Config) (net.Listener, error) { return nil, errors.New("not supported yet") } -func getLocalListener(listenerPath string) (net.Listener, error) { +func getLocalListener(listenerPath, _ string) (net.Listener, error) { uid := os.Getuid() l, err := sys.GetLocalListener(listenerPath, uid, uid) if err != nil { @@ -60,3 +60,7 @@ func getLocalListener(listenerPath string) (net.Listener, error) { } return l, nil } + +func groupToSecurityDescriptor(_ string) (string, error) { + return "", nil +} diff --git a/cmd/buildkitd/main_windows.go b/cmd/buildkitd/main_windows.go index 5ca20a689534..fdde4a821e5b 100644 --- a/cmd/buildkitd/main_windows.go +++ b/cmd/buildkitd/main_windows.go @@ -5,7 +5,9 @@ package main import ( "crypto/tls" + "fmt" "net" + "strings" "github.com/Microsoft/go-winio" _ "github.com/moby/buildkit/solver/llbsolver/ops" @@ -19,14 +21,18 @@ func listenFD(addr string, tlsConfig *tls.Config) (net.Listener, error) { return nil, errors.New("listening server on fd not supported on windows") } -func getLocalListener(listenerPath string) (net.Listener, error) { - pc := &winio.PipeConfig{ +func getLocalListener(listenerPath, secDescriptor string) (net.Listener, error) { + if secDescriptor == "" { // Allow generic read and generic write access to authenticated users // and system users. On Linux, this pipe seems to be given rw access to // user, group and others (666). // TODO(gabriel-samfira): should we restrict access to this pipe to just // authenticated users? Or Administrators group? - SecurityDescriptor: "D:P(A;;GRGW;;;AU)(A;;GRGW;;;SY)", + secDescriptor = "D:P(A;;GRGW;;;AU)(A;;GRGW;;;SY)" + } + + pc := &winio.PipeConfig{ + SecurityDescriptor: secDescriptor, } listener, err := winio.ListenPipe(listenerPath, pc) @@ -35,3 +41,17 @@ func getLocalListener(listenerPath string) (net.Listener, error) { } return listener, nil } + +func groupToSecurityDescriptor(group string) (string, error) { + sddl := "D:P(A;;GA;;;BA)(A;;GA;;;SY)" + if group != "" { + for _, g := range strings.Split(group, ",") { + sid, err := winio.LookupSidByName(g) + if err != nil { + return "", errors.Wrapf(err, "failed to lookup sid for group %s", g) + } + sddl += fmt.Sprintf("(A;;GRGW;;;%s)", sid) + } + } + return sddl, nil +}