Skip to content

Commit a2c08bc

Browse files
committed
[supervisor] Force gitpod user during Git init
1 parent 1646d5c commit a2c08bc

File tree

7 files changed

+41
-26
lines changed

7 files changed

+41
-26
lines changed

components/content-service/pkg/executor/executor.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func Prepare(req *csapi.WorkspaceInitializer, urls map[string]string) ([]byte, e
4444

4545
// Execute runs an initializer to place content in destination based on the configuration read
4646
// from the cfgin stream.
47-
func Execute(ctx context.Context, destination string, cfgin io.Reader, opts ...initializer.InitializeOpt) (src csapi.WorkspaceInitSource, err error) {
47+
func Execute(ctx context.Context, destination string, cfgin io.Reader, forceGitUser bool, opts ...initializer.InitializeOpt) (src csapi.WorkspaceInitSource, err error) {
4848
var cfg config
4949
err = json.NewDecoder(cfgin).Decode(&cfg)
5050
if err != nil {
@@ -63,7 +63,9 @@ func Execute(ctx context.Context, destination string, cfgin io.Reader, opts ...i
6363
}
6464

6565
rs = &storage.NamedURLDownloader{URLs: cfg.URLs}
66-
ilr, err = initializer.NewFromRequest(ctx, destination, rs, &req)
66+
ilr, err = initializer.NewFromRequest(ctx, destination, rs, &req, initializer.NewFromRequestOpts{
67+
ForceGitpodUserForGit: forceGitUser,
68+
})
6769
if err != nil {
6870
return "", err
6971
}

components/content-service/pkg/git/git.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -275,23 +275,6 @@ func (c *Client) Clone(ctx context.Context) (err error) {
275275
return err
276276
}
277277

278-
// TODO (aledbf): refactor to remove the need of manual chown
279-
args = []string{"-R", "-L", "gitpod", c.Location}
280-
cmd := exec.Command("chown", args...)
281-
res, err := cmd.CombinedOutput()
282-
if err != nil {
283-
if err.Error() == "wait: no child processes" || err.Error() == "waitid: no child processes" {
284-
return nil
285-
}
286-
287-
return OpFailedError{
288-
Args: args,
289-
ExecErr: err,
290-
Output: string(res),
291-
Subcommand: "chown",
292-
}
293-
}
294-
295278
return nil
296279
}
297280

components/content-service/pkg/initializer/git.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package initializer
77
import (
88
"context"
99
"os"
10+
"os/exec"
1011

1112
"github.com/opentracing/opentracing-go"
1213
"golang.org/x/xerrors"
@@ -44,6 +45,9 @@ type GitInitializer struct {
4445

4546
// The value for the clone target mode - use depends on the target mode
4647
CloneTarget string
48+
49+
// If true, the Git initializer will chown(gitpod) after the clone
50+
Chown bool
4751
}
4852

4953
// Run initializes the workspace using Git
@@ -68,6 +72,21 @@ func (ws *GitInitializer) Run(ctx context.Context, mappings []archive.IDMapping)
6872
if err := ws.Clone(ctx); err != nil {
6973
return src, xerrors.Errorf("git initializer: %w", err)
7074
}
75+
if ws.Chown {
76+
// TODO (aledbf): refactor to remove the need of manual chown
77+
args := []string{"-R", "-L", "gitpod", ws.Location}
78+
cmd := exec.Command("chown", args...)
79+
res, cerr := cmd.CombinedOutput()
80+
if cerr != nil && !(cerr.Error() == "wait: no child processes" || cerr.Error() == "waitid: no child processes") {
81+
err = git.OpFailedError{
82+
Args: args,
83+
ExecErr: cerr,
84+
Output: string(res),
85+
Subcommand: "chown",
86+
}
87+
return
88+
}
89+
}
7190
if err := ws.realizeCloneTarget(ctx); err != nil {
7291
return src, xerrors.Errorf("git initializer: %w", err)
7392
}

components/content-service/pkg/initializer/initializer.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,22 @@ func (e *EmptyInitializer) Run(ctx context.Context, mappings []archive.IDMapping
5555
return csapi.WorkspaceInitFromOther, nil
5656
}
5757

58+
// NewFromRequestOpts configures the initializer produced from a content init request
59+
type NewFromRequestOpts struct {
60+
// ForceGitpodUserForGit forces gitpod:gitpod ownership on all files produced by the Git initializer.
61+
// For FWB workspaces the content init is run from supervisor which runs as UID 0. Using this flag, the
62+
// Git content is forced to the Gitpod user. All other content (backup, prebuild, snapshot) will already
63+
// have the correct user.
64+
ForceGitpodUserForGit bool
65+
}
66+
5867
// NewFromRequest picks the initializer from the request but does not execute it.
5968
// Returns gRPC errors.
60-
func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader, req *csapi.WorkspaceInitializer) (i Initializer, err error) {
69+
func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader, req *csapi.WorkspaceInitializer, opts NewFromRequestOpts) (i Initializer, err error) {
6170
//nolint:ineffassign,staticcheck
6271
span, ctx := opentracing.StartSpanFromContext(ctx, "NewFromRequest")
6372
defer tracing.FinishSpan(span, &err)
73+
span.LogKV("opts", opts)
6474

6575
spec := req.Spec
6676
var initializer Initializer
@@ -71,7 +81,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
7181
return nil, status.Error(codes.InvalidArgument, "missing Git initializer spec")
7282
}
7383

74-
initializer, err = newGitInitializer(ctx, loc, ir.Git)
84+
initializer, err = newGitInitializer(ctx, loc, ir.Git, opts.ForceGitpodUserForGit)
7585
} else if ir, ok := spec.(*csapi.WorkspaceInitializer_Prebuild); ok {
7686
if ir.Prebuild == nil {
7787
return nil, status.Error(codes.InvalidArgument, "missing prebuild initializer spec")
@@ -80,7 +90,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
8090
return nil, status.Error(codes.InvalidArgument, "missing prebuild Git initializer spec")
8191
}
8292

83-
gitinit, err := newGitInitializer(ctx, loc, ir.Prebuild.Git)
93+
gitinit, err := newGitInitializer(ctx, loc, ir.Prebuild.Git, opts.ForceGitpodUserForGit)
8494
if err != nil {
8595
return nil, err
8696
}
@@ -110,7 +120,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
110120

111121
// newGitInitializer creates a Git initializer based on the request.
112122
// Returns gRPC errors.
113-
func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitializer) (*GitInitializer, error) {
123+
func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitializer, forceGitpodUser bool) (*GitInitializer, error) {
114124
if req.Config == nil {
115125
return nil, status.Error(codes.InvalidArgument, "Git initializer misses config")
116126
}
@@ -167,6 +177,7 @@ func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitialize
167177
},
168178
TargetMode: targetMode,
169179
CloneTarget: req.CloneTaget,
180+
Chown: forceGitpodUser,
170181
}, nil
171182
}
172183

components/image-builder/cmd/bob-init-base.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ var bobInitBase = &cobra.Command{
4848

4949
ctx := context.Background()
5050
rms := &storage.DirectNoopStorage{}
51-
ilr, err := initializer.NewFromRequest(ctx, initwd, rms, src.Source)
51+
ilr, err := initializer.NewFromRequest(ctx, initwd, rms, src.Source, initializer.NewFromRequestOpts{ForceGitpodUserForGit: false})
5252
if err != nil {
5353
log.Fatalf("cannot create initializer: %v", err)
5454
}

components/supervisor/pkg/supervisor/supervisor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ func startContentInit(ctx context.Context, cfg *Config, wg *sync.WaitGroup, cst
870870
return
871871
}
872872

873-
src, err := executor.Execute(ctx, "/workspace", f)
873+
src, err := executor.Execute(ctx, "/workspace", f, true)
874874
if err != nil {
875875
return
876876
}

components/ws-daemon/pkg/content/initializer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func RunInitializerChild() (err error) {
278278

279279
rs := &remoteContentStorage{RemoteContent: initmsg.RemoteContent}
280280

281-
initializer, err := wsinit.NewFromRequest(ctx, "/dst", rs, &req)
281+
initializer, err := wsinit.NewFromRequest(ctx, "/dst", rs, &req, wsinit.NewFromRequestOpts{ForceGitpodUserForGit: false})
282282
if err != nil {
283283
return err
284284
}

0 commit comments

Comments
 (0)