Skip to content

Commit

Permalink
Make guest username, uid, home directory configurable
Browse files Browse the repository at this point in the history
Also disallows the "admin" username by default (because it is a builtin
user in Ubuntu), but can be overridden by setting it explicitly in lima.yaml.

Signed-off-by: Jan Dubois <[email protected]>
  • Loading branch information
jandubois committed Nov 1, 2024
1 parent 361fe23 commit 6279d7a
Show file tree
Hide file tree
Showing 19 changed files with 303 additions and 166 deletions.
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ linters-settings:
- name: context-keys-type
- name: deep-exit
- name: dot-imports
arguments:
- allowedPackages:
- github.com/lima-vm/lima/pkg/must
- name: empty-block
- name: error-naming
- name: error-return
Expand Down
21 changes: 8 additions & 13 deletions cmd/limactl/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"strings"

"github.com/coreos/go-semver/semver"
"github.com/lima-vm/lima/pkg/osutil"
"github.com/lima-vm/lima/pkg/sshutil"
"github.com/lima-vm/lima/pkg/store"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -48,11 +47,7 @@ func copyAction(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
u, err := osutil.LimaUser(false)
if err != nil {
return err
}
instDirs := make(map[string]string)
instances := make(map[string]*store.Instance)
scpFlags := []string{}
scpArgs := []string{}
debug, err := cmd.Flags().GetBool("debug")
Expand Down Expand Up @@ -85,28 +80,28 @@ func copyAction(cmd *cobra.Command, args []string) error {
}
if legacySSH {
scpFlags = append(scpFlags, "-P", fmt.Sprintf("%d", inst.SSHLocalPort))
scpArgs = append(scpArgs, fmt.Sprintf("%[email protected]:%s", u.Username, path[1]))
scpArgs = append(scpArgs, fmt.Sprintf("%[email protected]:%s", *inst.Config.User.Username, path[1]))
} else {
scpArgs = append(scpArgs, fmt.Sprintf("scp://%[email protected]:%d/%s", u.Username, inst.SSHLocalPort, path[1]))
scpArgs = append(scpArgs, fmt.Sprintf("scp://%[email protected]:%d/%s", *inst.Config.User.Username, inst.SSHLocalPort, path[1]))
}
instDirs[instName] = inst.Dir
instances[instName] = inst
default:
return fmt.Errorf("path %q contains multiple colons", arg)
}
}
if legacySSH && len(instDirs) > 1 {
if legacySSH && len(instances) > 1 {
return fmt.Errorf("more than one (instance) host is involved in this command, this is only supported for openSSH v8.0 or higher")
}
scpFlags = append(scpFlags, "-3", "--")
scpArgs = append(scpFlags, scpArgs...)

var sshOpts []string
if len(instDirs) == 1 {
if len(instances) == 1 {
// Only one (instance) host is involved; we can use the instance-specific
// arguments such as ControlPath. This is preferred as we can multiplex
// sessions without re-authenticating (MaxSessions permitting).
for _, instDir := range instDirs {
sshOpts, err = sshutil.SSHOpts(instDir, false, false, false, false)
for _, inst := range instances {
sshOpts, err = sshutil.SSHOpts(inst.Dir, *inst.Config.User.Username, false, false, false, false)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions cmd/limactl/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ func shellAction(cmd *cobra.Command, args []string) error {

sshOpts, err := sshutil.SSHOpts(
inst.Dir,
*inst.Config.User.Username,
*inst.Config.SSH.LoadDotSSHPubKeys,
*inst.Config.SSH.ForwardAgent,
*inst.Config.SSH.ForwardX11,
Expand Down
1 change: 1 addition & 0 deletions cmd/limactl/show-ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func showSSHAction(cmd *cobra.Command, args []string) error {
filepath.Join(inst.Dir, filenames.SSHConfig), inst.Hostname)
opts, err := sshutil.SSHOpts(
inst.Dir,
*inst.Config.User.Username,
*inst.Config.SSH.LoadDotSSHPubKeys,
*inst.Config.SSH.ForwardAgent,
*inst.Config.SSH.ForwardX11,
Expand Down
1 change: 1 addition & 0 deletions cmd/limactl/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func tunnelAction(cmd *cobra.Command, args []string) error {

sshOpts, err := sshutil.SSHOpts(
inst.Dir,
*inst.Config.User.Username,
*inst.Config.SSH.LoadDotSSHPubKeys,
*inst.Config.SSH.ForwardAgent,
*inst.Config.SSH.ForwardX11,
Expand Down
9 changes: 5 additions & 4 deletions pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
if err := limayaml.Validate(instConfig, false); err != nil {
return nil, err
}
u, err := osutil.LimaUser(true)
uid, err := strconv.Atoi(*instConfig.User.UID)
if err != nil {
return nil, err
}
uid, err := strconv.Atoi(u.Uid)
gid, err := strconv.Atoi(*instConfig.User.GID)
if err != nil {
return nil, err
}
Expand All @@ -130,9 +130,10 @@ func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.L
BootScripts: bootScripts,
Name: name,
Hostname: identifierutil.HostnameFromInstName(name), // TODO: support customization
User: u.Username,
UID: uid,
Home: fmt.Sprintf("/home/%s.linux", u.Username),
GID: gid,
User: *instConfig.User.Username,
Home: *instConfig.User.HomeDir,
GuestInstallPrefix: *instConfig.GuestInstallPrefix,
UpgradePackages: *instConfig.UpgradePackages,
Containerd: Containerd{System: *instConfig.Containerd.System, User: *instConfig.Containerd.User},
Expand Down
7 changes: 3 additions & 4 deletions pkg/cidata/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/lima-vm/lima/pkg/iso9660util"

"github.com/containerd/containerd/identifiers"
"github.com/lima-vm/lima/pkg/osutil"
"github.com/lima-vm/lima/pkg/textutil"
)

Expand Down Expand Up @@ -61,6 +60,7 @@ type TemplateArgs struct {
User string // user name
Home string // home directory
UID int
GID int
SSHPubKeys []string
Mounts []Mount
MountType string
Expand Down Expand Up @@ -96,9 +96,8 @@ func ValidateTemplateArgs(args *TemplateArgs) error {
if err := identifiers.Validate(args.Name); err != nil {
return err
}
if !osutil.ValidateUsername(args.User) {
return errors.New("field User must be valid linux username")
}
// args.User is intentionally not validated here; the user can override with any name they want
// limayaml.FillDefault will validate the default (local) username, but not an explicit setting
if args.User == "root" {
return errors.New("field User must not be \"root\"")
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/hostagent/hostagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt

sshOpts, err := sshutil.SSHOpts(
inst.Dir,
*inst.Config.User.Username,
*inst.Config.SSH.LoadDotSSHPubKeys,
*inst.Config.SSH.ForwardAgent,
*inst.Config.SSH.ForwardX11,
Expand Down Expand Up @@ -182,13 +183,13 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt
// Block ports 22 and sshLocalPort on all IPs
for _, port := range []int{sshGuestPort, sshLocalPort} {
rule := limayaml.PortForward{GuestIP: net.IPv4zero, GuestPort: port, Ignore: true}
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Param)
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Config.User, inst.Param)
rules = append(rules, rule)
}
rules = append(rules, inst.Config.PortForwards...)
// Default forwards for all non-privileged ports from "127.0.0.1" and "::1"
rule := limayaml.PortForward{}
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Param)
limayaml.FillPortForwardDefaults(&rule, inst.Dir, inst.Config.User, inst.Param)
rules = append(rules, rule)

limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{
Expand Down
2 changes: 1 addition & 1 deletion pkg/instance/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY
}
// limayaml.Load() needs to pass the store file path to limayaml.FillDefault() to calculate default MAC addresses
filePath := filepath.Join(instDir, filenames.LimaYAML)
loadedInstConfig, err := limayaml.Load(instConfig, filePath)
loadedInstConfig, err := limayaml.LoadWithWarnings(instConfig, filePath)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 6279d7a

Please sign in to comment.