mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
* [docker-up] Minor fixes and add tests Tool: gitpod/catfood.gitpod.cloud * [image-builder-bob] Tests&fixes from an experimental PR Tool: gitpod/catfood.gitpod.cloud * [supervisor, ws-manager] Write docker credentials into client config file if passed into workspace Tool: gitpod/catfood.gitpod.cloud * [server] Introduce project.settings.enableDockerdAuthentication and expose it on the API Tool: gitpod/catfood.gitpod.cloud * [dashboard] Add "Docker registry authentication" toggle under projects/env vars Tool: gitpod/catfood.gitpod.cloud * [server] Guard project.settings.enableDockerdAuthentication by org write_settings permission Tool: gitpod/catfood.gitpod.cloud * review comments with cleanup + small fixes Tool: gitpod/catfood.gitpod.cloud
149 lines
3.6 KiB
Go
149 lines
3.6 KiB
Go
// Copyright (c) 2025 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package dockerd
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
const (
|
|
gitpodUserId = 33333
|
|
)
|
|
|
|
type ConvertUserArg func(arg string, value interface{}) ([]string, error)
|
|
|
|
var allowedDockerArgs = map[string]ConvertUserArg{
|
|
"remap-user": convertRemapUser,
|
|
// TODO(gpl): Why this allow-list instead of a converter lookup only?
|
|
"proxies": nil,
|
|
"http-proxy": nil,
|
|
"https-proxy": nil,
|
|
}
|
|
|
|
func ParseUserArgs(log *logrus.Entry, userArgs string) ([]string, error) {
|
|
if userArgs == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
var providedDockerArgs map[string]interface{}
|
|
if err := json.Unmarshal([]byte(userArgs), &providedDockerArgs); err != nil {
|
|
return nil, xerrors.Errorf("unable to deserialize docker args: %w", err)
|
|
}
|
|
|
|
return mapUserArgs(log, providedDockerArgs)
|
|
}
|
|
|
|
func mapUserArgs(log *logrus.Entry, jsonObj map[string]interface{}) ([]string, error) {
|
|
args := []string{}
|
|
for userArg, userValue := range jsonObj {
|
|
converter, exists := allowedDockerArgs[userArg]
|
|
if !exists {
|
|
// TODO(gpl): Why this allow-list instead of a converter lookup only?
|
|
continue
|
|
}
|
|
|
|
if converter != nil {
|
|
cargs, err := converter(userArg, userValue)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("could not convert %v - %v: %w", userArg, userValue, err)
|
|
}
|
|
args = append(args, cargs...)
|
|
continue
|
|
}
|
|
|
|
strValue, ok := (userValue).(string)
|
|
if ok {
|
|
args = append(args, fmt.Sprintf("--%s=%s", userArg, strValue))
|
|
continue
|
|
}
|
|
|
|
bValue, ok := (userValue).(bool)
|
|
if ok {
|
|
args = append(args, fmt.Sprintf("--%s=%t", userArg, bValue))
|
|
continue
|
|
}
|
|
|
|
obj, ok := (userValue).(map[string]interface{})
|
|
if ok {
|
|
nestedArgs, err := mapUserArgs(log, obj)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("could not convert nested arg %v - %v: %w", userArg, userValue, err)
|
|
}
|
|
args = append(args, nestedArgs...)
|
|
continue
|
|
}
|
|
|
|
log.WithField("arg", userArg).WithField("value", userValue).Warn("could not map userArg to dockerd argument, skipping.")
|
|
}
|
|
|
|
return args, nil
|
|
}
|
|
|
|
func convertRemapUser(arg string, value interface{}) ([]string, error) {
|
|
v, ok := (value).(string)
|
|
if !ok {
|
|
return nil, xerrors.Errorf("userns-remap expects a string argument")
|
|
}
|
|
|
|
id, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, f := range []string{"/etc/subuid", "/etc/subgid"} {
|
|
err := adaptSubid(f, id)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("could not adapt subid files: %w", err)
|
|
}
|
|
}
|
|
|
|
return []string{"--userns-remap", "gitpod"}, nil
|
|
}
|
|
|
|
func adaptSubid(oldfile string, id int) error {
|
|
uid, err := os.Open(oldfile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newfile, err := os.Create(oldfile + ".new")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
mappingFmt := func(username string, id int, size int) string { return fmt.Sprintf("%s:%d:%d\n", username, id, size) }
|
|
|
|
if id != 0 {
|
|
newfile.WriteString(mappingFmt("gitpod", 1, id))
|
|
newfile.WriteString(mappingFmt("gitpod", gitpodUserId, 1))
|
|
} else {
|
|
newfile.WriteString(mappingFmt("gitpod", gitpodUserId, 1))
|
|
newfile.WriteString(mappingFmt("gitpod", 1, gitpodUserId-1))
|
|
newfile.WriteString(mappingFmt("gitpod", gitpodUserId+1, 32200)) // map rest of user ids in the user namespace
|
|
}
|
|
|
|
uidScanner := bufio.NewScanner(uid)
|
|
for uidScanner.Scan() {
|
|
l := uidScanner.Text()
|
|
if !strings.HasPrefix(l, "gitpod") {
|
|
newfile.WriteString(l + "\n")
|
|
}
|
|
}
|
|
|
|
if err = os.Rename(newfile.Name(), oldfile); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|