Skip to content

Commit 9c21e15

Browse files
authored
Merge pull request #2827 from jandubois/username
Make guest username, uid, home directory configurable
2 parents 5329fd4 + c77bfa2 commit 9c21e15

File tree

27 files changed

+347
-199
lines changed

27 files changed

+347
-199
lines changed

Diff for: .golangci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ linters-settings:
121121
- name: context-keys-type
122122
- name: deep-exit
123123
- name: dot-imports
124+
arguments:
125+
- allowedPackages:
126+
- github.com/lima-vm/lima/pkg/must
124127
- name: empty-block
125128
- name: error-naming
126129
- name: error-return

Diff for: cmd/limactl/copy.go

+8-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"strings"
99

1010
"github.com/coreos/go-semver/semver"
11-
"github.com/lima-vm/lima/pkg/osutil"
1211
"github.com/lima-vm/lima/pkg/sshutil"
1312
"github.com/lima-vm/lima/pkg/store"
1413
"github.com/sirupsen/logrus"
@@ -48,11 +47,7 @@ func copyAction(cmd *cobra.Command, args []string) error {
4847
if err != nil {
4948
return err
5049
}
51-
u, err := osutil.LimaUser(false)
52-
if err != nil {
53-
return err
54-
}
55-
instDirs := make(map[string]string)
50+
instances := make(map[string]*store.Instance)
5651
scpFlags := []string{}
5752
scpArgs := []string{}
5853
debug, err := cmd.Flags().GetBool("debug")
@@ -85,28 +80,28 @@ func copyAction(cmd *cobra.Command, args []string) error {
8580
}
8681
if legacySSH {
8782
scpFlags = append(scpFlags, "-P", fmt.Sprintf("%d", inst.SSHLocalPort))
88-
scpArgs = append(scpArgs, fmt.Sprintf("%[email protected]:%s", u.Username, path[1]))
83+
scpArgs = append(scpArgs, fmt.Sprintf("%[email protected]:%s", *inst.Config.User.Name, path[1]))
8984
} else {
90-
scpArgs = append(scpArgs, fmt.Sprintf("scp://%[email protected]:%d/%s", u.Username, inst.SSHLocalPort, path[1]))
85+
scpArgs = append(scpArgs, fmt.Sprintf("scp://%[email protected]:%d/%s", *inst.Config.User.Name, inst.SSHLocalPort, path[1]))
9186
}
92-
instDirs[instName] = inst.Dir
87+
instances[instName] = inst
9388
default:
9489
return fmt.Errorf("path %q contains multiple colons", arg)
9590
}
9691
}
97-
if legacySSH && len(instDirs) > 1 {
92+
if legacySSH && len(instances) > 1 {
9893
return fmt.Errorf("more than one (instance) host is involved in this command, this is only supported for openSSH v8.0 or higher")
9994
}
10095
scpFlags = append(scpFlags, "-3", "--")
10196
scpArgs = append(scpFlags, scpArgs...)
10297

10398
var sshOpts []string
104-
if len(instDirs) == 1 {
99+
if len(instances) == 1 {
105100
// Only one (instance) host is involved; we can use the instance-specific
106101
// arguments such as ControlPath. This is preferred as we can multiplex
107102
// sessions without re-authenticating (MaxSessions permitting).
108-
for _, instDir := range instDirs {
109-
sshOpts, err = sshutil.SSHOpts(instDir, false, false, false, false)
103+
for _, inst := range instances {
104+
sshOpts, err = sshutil.SSHOpts(inst.Dir, *inst.Config.User.Name, false, false, false, false)
110105
if err != nil {
111106
return err
112107
}

Diff for: cmd/limactl/edit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func editAction(cmd *cobra.Command, args []string) error {
115115
logrus.Info("Aborting, no changes made to the instance")
116116
return nil
117117
}
118-
y, err := limayaml.Load(yBytes, filePath)
118+
y, err := limayaml.LoadWithWarnings(yBytes, filePath)
119119
if err != nil {
120120
return err
121121
}

Diff for: cmd/limactl/shell.go

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ func shellAction(cmd *cobra.Command, args []string) error {
167167

168168
sshOpts, err := sshutil.SSHOpts(
169169
inst.Dir,
170+
*inst.Config.User.Name,
170171
*inst.Config.SSH.LoadDotSSHPubKeys,
171172
*inst.Config.SSH.ForwardAgent,
172173
*inst.Config.SSH.ForwardX11,

Diff for: cmd/limactl/show-ssh.go

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ func showSSHAction(cmd *cobra.Command, args []string) error {
9090
filepath.Join(inst.Dir, filenames.SSHConfig), inst.Hostname)
9191
opts, err := sshutil.SSHOpts(
9292
inst.Dir,
93+
*inst.Config.User.Name,
9394
*inst.Config.SSH.LoadDotSSHPubKeys,
9495
*inst.Config.SSH.ForwardAgent,
9596
*inst.Config.SSH.ForwardX11,

Diff for: cmd/limactl/tunnel.go

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func tunnelAction(cmd *cobra.Command, args []string) error {
107107

108108
sshOpts, err := sshutil.SSHOpts(
109109
inst.Dir,
110+
*inst.Config.User.Name,
110111
*inst.Config.SSH.LoadDotSSHPubKeys,
111112
*inst.Config.SSH.ForwardAgent,
112113
*inst.Config.SSH.ForwardX11,

Diff for: hack/test-templates.sh

+7
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ declare -A CHECKS=(
3737
["mount-path-with-spaces"]=""
3838
["provision-ansible"]=""
3939
["param-env-variables"]=""
40+
["set-user"]=""
4041
)
4142

4243
case "$NAME" in
@@ -63,6 +64,7 @@ case "$NAME" in
6364
CHECKS["mount-path-with-spaces"]="1"
6465
CHECKS["provision-ansible"]="1"
6566
CHECKS["param-env-variables"]="1"
67+
CHECKS["set-user"]="1"
6668
;;
6769
"docker")
6870
CONTAINER_ENGINE="docker"
@@ -172,6 +174,11 @@ if [[ -n ${CHECKS["param-env-variables"]} ]]; then
172174
limactl shell "$NAME" test -e /tmp/param-user
173175
fi
174176

177+
if [[ -n ${CHECKS["set-user"]} ]]; then
178+
INFO 'Testing that user settings can be provided by lima.yaml'
179+
limactl shell "$NAME" grep "^john:x:4711:4711:John Doe:/home/john-john" /etc/passwd
180+
fi
181+
175182
INFO "Testing proxy settings are imported"
176183
got=$(limactl shell "$NAME" env | grep FTP_PROXY)
177184
# Expected: FTP_PROXY is set in addition to ftp_proxy, localhost is replaced

Diff for: hack/test-templates/test-misc.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,9 @@ probes:
5858
# $ limactl disk create data --size 10G
5959
additionalDisks:
6060
- "data"
61+
62+
user:
63+
name: john
64+
comment: John Doe
65+
home: "/home/{{.User}}-{{.User}}"
66+
uid: 4711

Diff for: pkg/cidata/cidata.TEMPLATE.d/boot/02-wsl2-setup.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[ "$LIMA_CIDATA_VMTYPE" = "wsl2" ] || exit 0
55

66
# create user
7-
sudo useradd -u "${LIMA_CIDATA_UID}" "${LIMA_CIDATA_USER}" -c "${LIMA_CIDATA_GECOS}" -d "${LIMA_CIDATA_HOME}"
7+
sudo useradd -u "${LIMA_CIDATA_UID}" "${LIMA_CIDATA_USER}" -c "${LIMA_CIDATA_COMMENT}" -d "${LIMA_CIDATA_HOME}"
88
sudo mkdir "${LIMA_CIDATA_HOME}"/.ssh/
99
sudo cp "${LIMA_CIDATA_MNT}"/ssh_authorized_keys "${LIMA_CIDATA_HOME}"/.ssh/authorized_keys
1010
sudo chown "${LIMA_CIDATA_USER}" "${LIMA_CIDATA_HOME}"/.ssh/authorized_keys

Diff for: pkg/cidata/cidata.TEMPLATE.d/lima.env

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ LIMA_CIDATA_DEBUG={{ .Debug }}
22
LIMA_CIDATA_NAME={{ .Name }}
33
LIMA_CIDATA_USER={{ .User }}
44
LIMA_CIDATA_UID={{ .UID }}
5-
LIMA_CIDATA_GECOS={{ .GECOS }}
5+
LIMA_CIDATA_COMMENT={{ .Comment }}
66
LIMA_CIDATA_HOME={{ .Home}}
77
LIMA_CIDATA_HOSTHOME_MOUNTPOINT={{ .HostHomeMountPoint }}
88
LIMA_CIDATA_MOUNTS={{ len .Mounts }}

Diff for: pkg/cidata/cidata.TEMPLATE.d/user-data

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ timezone: {{.TimeZone}}
3030
users:
3131
- name: "{{.User}}"
3232
uid: "{{.UID}}"
33-
{{- if .GECOS }}
34-
gecos: {{ printf "%q" .GECOS }}
33+
{{- if .Comment }}
34+
gecos: {{ printf "%q" .Comment }}
3535
{{- end }}
3636
homedir: "{{.Home}}"
3737
shell: /bin/bash

Diff for: pkg/cidata/cidata.go

+5-13
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"path"
1212
"path/filepath"
1313
"slices"
14-
"strconv"
1514
"strings"
1615
"time"
1716

@@ -117,23 +116,15 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
117116
if err := limayaml.Validate(instConfig, false); err != nil {
118117
return nil, err
119118
}
120-
u, err := osutil.LimaUser(true)
121-
if err != nil {
122-
return nil, err
123-
}
124-
uid, err := strconv.Atoi(u.Uid)
125-
if err != nil {
126-
return nil, err
127-
}
128119
args := TemplateArgs{
129120
Debug: debugutil.Debug,
130121
BootScripts: bootScripts,
131122
Name: name,
132123
Hostname: identifierutil.HostnameFromInstName(name), // TODO: support customization
133-
User: u.Username,
134-
UID: uid,
135-
GECOS: u.Name,
136-
Home: fmt.Sprintf("/home/%s.linux", u.Username),
124+
User: *instConfig.User.Name,
125+
Comment: *instConfig.User.Comment,
126+
Home: *instConfig.User.Home,
127+
UID: *instConfig.User.UID,
137128
GuestInstallPrefix: *instConfig.GuestInstallPrefix,
138129
UpgradePackages: *instConfig.UpgradePackages,
139130
Containerd: Containerd{System: *instConfig.Containerd.System, User: *instConfig.Containerd.User},
@@ -151,6 +142,7 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
151142

152143
firstUsernetIndex := limayaml.FirstUsernetIndex(instConfig)
153144
var subnet net.IP
145+
var err error
154146

155147
if firstUsernetIndex != -1 {
156148
usernetName := instConfig.Networks[firstUsernetIndex].Lima

Diff for: pkg/cidata/template.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/lima-vm/lima/pkg/iso9660util"
1212

1313
"github.com/containerd/containerd/identifiers"
14-
"github.com/lima-vm/lima/pkg/osutil"
1514
"github.com/lima-vm/lima/pkg/textutil"
1615
)
1716

@@ -59,9 +58,9 @@ type TemplateArgs struct {
5958
Hostname string // instance hostname
6059
IID string // instance id
6160
User string // user name
62-
GECOS string // user information
61+
Comment string // user information
6362
Home string // home directory
64-
UID int
63+
UID uint32
6564
SSHPubKeys []string
6665
Mounts []Mount
6766
MountType string
@@ -97,9 +96,8 @@ func ValidateTemplateArgs(args *TemplateArgs) error {
9796
if err := identifiers.Validate(args.Name); err != nil {
9897
return err
9998
}
100-
if !osutil.ValidateUsername(args.User) {
101-
return errors.New("field User must be valid linux username")
102-
}
99+
// args.User is intentionally not validated here; the user can override with any name they want
100+
// limayaml.FillDefault will validate the default (local) username, but not an explicit setting
103101
if args.User == "root" {
104102
return errors.New("field User must not be \"root\"")
105103
}

Diff for: pkg/cidata/template_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ var defaultRemoveDefaults = false
1212

1313
func TestConfig(t *testing.T) {
1414
args := &TemplateArgs{
15-
Name: "default",
16-
User: "foo",
17-
UID: 501,
18-
GECOS: "Foo",
19-
Home: "/home/foo.linux",
15+
Name: "default",
16+
User: "foo",
17+
UID: 501,
18+
Comment: "Foo",
19+
Home: "/home/foo.linux",
2020
SSHPubKeys: []string{
2121
"ssh-rsa dummy [email protected]",
2222
},
@@ -30,11 +30,11 @@ func TestConfig(t *testing.T) {
3030

3131
func TestConfigCACerts(t *testing.T) {
3232
args := &TemplateArgs{
33-
Name: "default",
34-
User: "foo",
35-
UID: 501,
36-
GECOS: "Foo",
37-
Home: "/home/foo.linux",
33+
Name: "default",
34+
User: "foo",
35+
UID: 501,
36+
Comment: "Foo",
37+
Home: "/home/foo.linux",
3838
SSHPubKeys: []string{
3939
"ssh-rsa dummy [email protected]",
4040
},

Diff for: pkg/hostagent/hostagent.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt
144144

145145
sshOpts, err := sshutil.SSHOpts(
146146
inst.Dir,
147+
*inst.Config.User.Name,
147148
*inst.Config.SSH.LoadDotSSHPubKeys,
148149
*inst.Config.SSH.ForwardAgent,
149150
*inst.Config.SSH.ForwardX11,
@@ -182,13 +183,13 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt
182183
// Block ports 22 and sshLocalPort on all IPs
183184
for _, port := range []int{sshGuestPort, sshLocalPort} {
184185
rule := limayaml.PortForward{GuestIP: net.IPv4zero, GuestPort: port, Ignore: true}
185-
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Param)
186+
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Config.User, inst.Param)
186187
rules = append(rules, rule)
187188
}
188189
rules = append(rules, inst.Config.PortForwards...)
189190
// Default forwards for all non-privileged ports from "127.0.0.1" and "::1"
190191
rule := limayaml.PortForward{}
191-
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Param)
192+
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Config.User, inst.Param)
192193
rules = append(rules, rule)
193194

194195
limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{

Diff for: pkg/instance/create.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY
4141
}
4242
// limayaml.Load() needs to pass the store file path to limayaml.FillDefault() to calculate default MAC addresses
4343
filePath := filepath.Join(instDir, filenames.LimaYAML)
44-
loadedInstConfig, err := limayaml.Load(instConfig, filePath)
44+
loadedInstConfig, err := limayaml.LoadWithWarnings(instConfig, filePath)
4545
if err != nil {
4646
return nil, err
4747
}

0 commit comments

Comments
 (0)