Skip to content

Commit 8cb6e2a

Browse files
authored
Revert "Relax assumptions in supervisor (#18782)"
This reverts commit 9a38b60.
1 parent 9179f65 commit 8cb6e2a

File tree

14 files changed

+123
-235
lines changed

14 files changed

+123
-235
lines changed

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

Lines changed: 2 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, runAs *initializer.User, 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 {
@@ -64,7 +64,7 @@ func Execute(ctx context.Context, destination string, cfgin io.Reader, runAs *in
6464

6565
rs = &storage.NamedURLDownloader{URLs: cfg.URLs}
6666
ilr, err = initializer.NewFromRequest(ctx, destination, rs, &req, initializer.NewFromRequestOpts{
67-
RunAs: runAs,
67+
ForceGitpodUserForGit: forceGitUser,
6868
})
6969
if err != nil {
7070
return "", err

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

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"os/exec"
1414
"path/filepath"
1515
"strings"
16-
"syscall"
1716

1817
"github.com/opentracing/opentracing-go"
1918
"golang.org/x/xerrors"
@@ -94,12 +93,8 @@ type Client struct {
9493
// UpstreamCloneURI is the fork upstream of a repository
9594
UpstreamRemoteURI string
9695

97-
// RunAs runs the Git commands as a particular user - if not nil
98-
RunAs *User
99-
}
100-
101-
type User struct {
102-
UID, GID uint32
96+
// if true will run git command as gitpod user (should be executed as root that has access to sudo in this case)
97+
RunAsGitpodUser bool
10398
}
10499

105100
// Status describes the status of a Git repo/working copy akin to "git status"
@@ -183,6 +178,8 @@ func (c *Client) GitWithOutput(ctx context.Context, ignoreErr *string, subcomman
183178
env = append(env, fmt.Sprintf("GIT_AUTH_PASSWORD=%s", pwd))
184179
}
185180

181+
env = append(env, "HOME=/home/gitpod")
182+
186183
fullArgs = append(fullArgs, subcommand)
187184
fullArgs = append(fullArgs, args...)
188185

@@ -204,19 +201,13 @@ func (c *Client) GitWithOutput(ctx context.Context, ignoreErr *string, subcomman
204201
span.LogKV("args", fullArgs)
205202

206203
cmdName := "git"
204+
if c.RunAsGitpodUser {
205+
cmdName = "sudo"
206+
fullArgs = append([]string{"-u", "gitpod", "git"}, fullArgs...)
207+
}
207208
cmd := exec.Command(cmdName, fullArgs...)
208209
cmd.Dir = c.Location
209210
cmd.Env = env
210-
if c.RunAs != nil {
211-
if cmd.SysProcAttr == nil {
212-
cmd.SysProcAttr = &syscall.SysProcAttr{}
213-
}
214-
if cmd.SysProcAttr.Credential == nil {
215-
cmd.SysProcAttr.Credential = &syscall.Credential{}
216-
}
217-
cmd.SysProcAttr.Credential.Uid = c.RunAs.UID
218-
cmd.SysProcAttr.Credential.Gid = c.RunAs.UID
219-
}
220211

221212
res, err := cmd.CombinedOutput()
222213
if err != nil {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ func (ws *GitInitializer) Run(ctx context.Context, mappings []archive.IDMapping)
9595

9696
// make sure that folder itself is owned by gitpod user prior to doing git clone
9797
// this is needed as otherwise git clone will fail if the folder is owned by root
98-
if ws.RunAs != nil {
99-
args := []string{fmt.Sprintf("%d:%d", ws.RunAs.UID, ws.RunAs.GID), ws.Location}
98+
if ws.RunAsGitpodUser {
99+
args := []string{"gitpod", ws.Location}
100100
cmd := exec.Command("chown", args...)
101101
res, cerr := cmd.CombinedOutput()
102102
if cerr != nil && !process.IsNotChildProcess(cerr) {

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

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,11 @@ func (e CompositeInitializer) Run(ctx context.Context, mappings []archive.IDMapp
9999

100100
// NewFromRequestOpts configures the initializer produced from a content init request
101101
type NewFromRequestOpts struct {
102-
// RunAs - if not nil - decides the user with which the initiallisation will be executed
103-
RunAs *User
104-
}
105-
106-
type User struct {
107-
UID uint32
108-
GID uint32
102+
// ForceGitpodUserForGit forces gitpod:gitpod ownership on all files produced by the Git initializer.
103+
// For FWB workspaces the content init is run from supervisor which runs as UID 0. Using this flag, the
104+
// Git content is forced to the Gitpod user. All other content (backup, prebuild, snapshot) will already
105+
// have the correct user.
106+
ForceGitpodUserForGit bool
109107
}
110108

111109
// NewFromRequest picks the initializer from the request but does not execute it.
@@ -134,7 +132,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
134132
return nil, status.Error(codes.InvalidArgument, "missing Git initializer spec")
135133
}
136134

137-
initializer, err = newGitInitializer(ctx, loc, ir.Git, opts.RunAs)
135+
initializer, err = newGitInitializer(ctx, loc, ir.Git, opts.ForceGitpodUserForGit)
138136
} else if ir, ok := spec.(*csapi.WorkspaceInitializer_Prebuild); ok {
139137
if ir.Prebuild == nil {
140138
return nil, status.Error(codes.InvalidArgument, "missing prebuild initializer spec")
@@ -148,7 +146,7 @@ func NewFromRequest(ctx context.Context, loc string, rs storage.DirectDownloader
148146
}
149147
var gits []*GitInitializer
150148
for _, gi := range ir.Prebuild.Git {
151-
gitinit, err := newGitInitializer(ctx, loc, gi, opts.RunAs)
149+
gitinit, err := newGitInitializer(ctx, loc, gi, opts.ForceGitpodUserForGit)
152150
if err != nil {
153151
return nil, err
154152
}
@@ -251,7 +249,7 @@ func (bi *fromBackupInitializer) Run(ctx context.Context, mappings []archive.IDM
251249

252250
// newGitInitializer creates a Git initializer based on the request.
253251
// Returns gRPC errors.
254-
func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitializer, runAs *User) (*GitInitializer, error) {
252+
func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitializer, forceGitpodUser bool) (*GitInitializer, error) {
255253
if req.Config == nil {
256254
return nil, status.Error(codes.InvalidArgument, "Git initializer misses config")
257255
}
@@ -296,11 +294,6 @@ func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitialize
296294
return
297295
})
298296

299-
var user *git.User
300-
if runAs != nil {
301-
user = &git.User{UID: runAs.UID, GID: runAs.GID}
302-
}
303-
304297
log.WithField("location", loc).Debug("using Git initializer")
305298
return &GitInitializer{
306299
Client: git.Client{
@@ -310,7 +303,7 @@ func newGitInitializer(ctx context.Context, loc string, req *csapi.GitInitialize
310303
Config: req.Config.CustomConfig,
311304
AuthMethod: authMethod,
312305
AuthProvider: authProvider,
313-
RunAs: user,
306+
RunAsGitpodUser: forceGitpodUser,
314307
},
315308
TargetMode: targetMode,
316309
CloneTarget: req.CloneTaget,

components/supervisor/cmd/dump-initializer.go

Lines changed: 0 additions & 38 deletions
This file was deleted.

components/supervisor/pkg/supervisor/config.go

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/json"
99
"fmt"
1010
"io"
11+
"io/ioutil"
1112
"math"
1213
"net/http"
1314
"net/url"
@@ -328,35 +329,6 @@ type WorkspaceConfig struct {
328329

329330
// ConfigcatEnabled controls whether configcat is enabled
330331
ConfigcatEnabled bool `env:"GITPOD_CONFIGCAT_ENABLED"`
331-
332-
WorkspaceLinuxUID uint32 `env:"GITPOD_WORKSPACE_LINUX_UID,default=33333"`
333-
WorkspaceLinuxGID uint32 `env:"GITPOD_WORKSPACE_LINUX_GID,default=33333"`
334-
335-
// ContentInitializer - if set - will run the content initializer instead of waiting for the ready file
336-
ContentInitializer string `env:"SUPERVISOR_CONTENT_INITIALIZER"`
337-
338-
// WorkspaceRuntime configures the runtime supervisor is running in
339-
WorkspaceRuntime WorkspaceRuntime `env:"SUPERVISOR_WORKSPACE_RUNTIME,default=container"`
340-
}
341-
342-
type WorkspaceRuntime string
343-
344-
const (
345-
WorkspaceRuntimeContainer WorkspaceRuntime = "container"
346-
WorkspaceRuntimeNextgen WorkspaceRuntime = "nextgen"
347-
WorkspaceRuntimeRunGP WorkspaceRuntime = "rungp"
348-
)
349-
350-
func (rt *WorkspaceRuntime) UnmarshalEnvironmentValue(data string) error {
351-
switch WorkspaceRuntime(data) {
352-
case WorkspaceRuntimeContainer, WorkspaceRuntimeNextgen, WorkspaceRuntimeRunGP:
353-
// everything's fine
354-
default:
355-
return fmt.Errorf("unknown workspace runtime: %s", data)
356-
}
357-
358-
*rt = WorkspaceRuntime(data)
359-
return nil
360332
}
361333

362334
// WorkspaceGitpodToken is a list of tokens that should be added to supervisor's token service.
@@ -615,7 +587,7 @@ func loadDesktopIDEs(static *StaticConfig) ([]*IDEConfig, error) {
615587
uniqueDesktopIDEs[desktopIDE.Name] = struct{}{}
616588
}
617589

618-
files, err := os.ReadDir(static.DesktopIDERoot)
590+
files, err := ioutil.ReadDir(static.DesktopIDERoot)
619591
if err != nil {
620592
return nil, err
621593
}

components/supervisor/pkg/supervisor/docker.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func socketActivationForDocker(parentCtx context.Context, wg *sync.WaitGroup, te
5757
return
5858
}
5959

60-
logFile, err := openDockerUpLogFile(int(cfg.WorkspaceLinuxUID), int(cfg.WorkspaceLinuxGID))
60+
logFile, err := openDockerUpLogFile()
6161
if err != nil {
6262
log.WithError(err).Error("docker-up: cannot open log file")
6363
} else {
@@ -164,7 +164,7 @@ func listenToDockerSocket(parentCtx context.Context, term *terminal.Mux, cfg *Co
164164
l.Close()
165165
}()
166166

167-
_ = os.Chown(fn, int(cfg.WorkspaceLinuxUID), int(cfg.WorkspaceLinuxGID))
167+
_ = os.Chown(fn, gitpodUID, gitpodGID)
168168

169169
var lastExitErrorTime time.Time
170170
burstAttempts := 0
@@ -267,19 +267,19 @@ func listenToDockerSocket(parentCtx context.Context, term *terminal.Mux, cfg *Co
267267
return ctx.Err()
268268
}
269269

270-
func openDockerUpLogFile(uid, gid int) (*os.File, error) {
270+
func openDockerUpLogFile() (*os.File, error) {
271271
if err := os.MkdirAll(logsDir, 0755); err != nil {
272272
return nil, xerrors.Errorf("cannot create logs dir: %w", err)
273273
}
274-
if err := os.Chown(logsDir, uid, gid); err != nil {
274+
if err := os.Chown(logsDir, gitpodUID, gitpodGID); err != nil {
275275
return nil, xerrors.Errorf("cannot chown logs dir: %w", err)
276276
}
277277
logFile, err := os.OpenFile(dockerUpLogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
278278
if err != nil {
279279
return nil, xerrors.Errorf("cannot open docker-up log file: %w", err)
280280
}
281281

282-
if err := os.Chown(dockerUpLogFilePath, uid, gid); err != nil {
282+
if err := os.Chown(dockerUpLogFilePath, gitpodUID, gitpodGID); err != nil {
283283
_ = logFile.Close()
284284
return nil, xerrors.Errorf("cannot chown docker-up log file: %w", err)
285285
}

components/supervisor/pkg/supervisor/git.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (p *GitTokenProvider) openAccessControl() error {
9292
return err
9393
}
9494
gpCmd := exec.Command(gpPath, "preview", "--external", p.workspaceConfig.GitpodHost+"/access-control")
95-
runAsUser(gpCmd, p.workspaceConfig.WorkspaceLinuxUID, p.workspaceConfig.WorkspaceLinuxGID)
95+
runAsGitpodUser(gpCmd)
9696
if b, err := gpCmd.CombinedOutput(); err != nil {
9797
log.WithField("Stdout", string(b)).WithError(err).Error("failed to exec gp preview to open access control")
9898
return err

components/supervisor/pkg/supervisor/services.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ func (is *InfoService) WorkspaceInfo(ctx context.Context, req *api.WorkspaceInfo
741741
}
742742
}
743743

744-
resp.UserHome = os.Getenv("HOME")
744+
resp.UserHome = "/home/gitpod"
745745

746746
endpoint, host, err := is.cfg.GitpodAPIEndpoint()
747747
if err != nil {
@@ -763,8 +763,6 @@ type ControlService struct {
763763
publicKey string
764764
hostKey *api.SSHPublicKey
765765

766-
uid, gid int
767-
768766
api.UnimplementedControlServiceServer
769767
}
770768

@@ -785,24 +783,24 @@ func (c *ControlService) ExposePort(ctx context.Context, req *api.ExposePortRequ
785783
}
786784

787785
// CreateSSHKeyPair create a ssh key pair for the workspace.
788-
func (c *ControlService) CreateSSHKeyPair(ctx context.Context, req *api.CreateSSHKeyPairRequest) (response *api.CreateSSHKeyPairResponse, err error) {
789-
home := os.Getenv("HOME")
790-
if c.privateKey != "" && c.publicKey != "" {
786+
func (ss *ControlService) CreateSSHKeyPair(ctx context.Context, req *api.CreateSSHKeyPairRequest) (response *api.CreateSSHKeyPairResponse, err error) {
787+
home := "/home/gitpod/"
788+
if ss.privateKey != "" && ss.publicKey != "" {
791789
checkKey := func() error {
792790
data, err := os.ReadFile(filepath.Join(home, ".ssh/authorized_keys"))
793791
if err != nil {
794792
return xerrors.Errorf("cannot read file ~/.ssh/authorized_keys: %w", err)
795793
}
796-
if !bytes.Contains(data, []byte(c.publicKey)) {
794+
if !bytes.Contains(data, []byte(ss.publicKey)) {
797795
return xerrors.Errorf("not found special publickey")
798796
}
799797
return nil
800798
}
801799
err := checkKey()
802800
if err == nil {
803801
return &api.CreateSSHKeyPairResponse{
804-
PrivateKey: c.privateKey,
805-
HostKey: c.hostKey,
802+
PrivateKey: ss.privateKey,
803+
HostKey: ss.hostKey,
806804
}, nil
807805
}
808806
log.WithError(err).Error("check authorized_keys failed, will recreate")
@@ -813,7 +811,7 @@ func (c *ControlService) CreateSSHKeyPair(ctx context.Context, req *api.CreateSS
813811
if err != nil {
814812
return nil, xerrors.Errorf("cannot create tmpfile: %w", err)
815813
}
816-
err = prepareSSHKey(ctx, filepath.Join(dir, "ssh"), c.uid, c.gid)
814+
err = prepareSSHKey(ctx, filepath.Join(dir, "ssh"))
817815
if err != nil {
818816
return nil, xerrors.Errorf("cannot create ssh key pair: %w", err)
819817
}
@@ -837,7 +835,7 @@ func (c *ControlService) CreateSSHKeyPair(ctx context.Context, req *api.CreateSS
837835
if err != nil {
838836
return nil, xerrors.Errorf("cannot write file ~.ssh/authorized_keys: %w", err)
839837
}
840-
err = os.Chown(filepath.Join(home, ".ssh/authorized_keys"), c.uid, c.gid)
838+
err = os.Chown(filepath.Join(home, ".ssh/authorized_keys"), gitpodUID, gitpodGID)
841839
if err != nil {
842840
return nil, xerrors.Errorf("cannot chown SSH authorized_keys file: %w", err)
843841
}
@@ -847,25 +845,25 @@ func (c *ControlService) CreateSSHKeyPair(ctx context.Context, req *api.CreateSS
847845
if err != nil {
848846
return nil, status.Errorf(codes.Internal, "cannot create ssh key pair: %v", err)
849847
}
850-
c.privateKey = string(generated.PrivateKey)
851-
c.publicKey = string(generated.PublicKey)
848+
ss.privateKey = string(generated.PrivateKey)
849+
ss.publicKey = string(generated.PublicKey)
852850

853851
hostKey, err := os.ReadFile("/.supervisor/ssh/sshkey.pub")
854852
if err != nil {
855853
log.WithError(err).Error("faled to read host key")
856854
} else {
857855
hostKeyParts := strings.Split(string(hostKey), " ")
858856
if len(hostKeyParts) >= 2 {
859-
c.hostKey = &api.SSHPublicKey{
857+
ss.hostKey = &api.SSHPublicKey{
860858
Type: hostKeyParts[0],
861859
Value: hostKeyParts[1],
862860
}
863861
}
864862
}
865863

866864
return &api.CreateSSHKeyPairResponse{
867-
PrivateKey: c.privateKey,
868-
HostKey: c.hostKey,
865+
PrivateKey: ss.privateKey,
866+
HostKey: ss.hostKey,
869867
}, err
870868
}
871869

0 commit comments

Comments
 (0)