diff --git a/builder/oracle/oci/config.go b/builder/oracle/oci/config.go index 85de3b2cc..dd2beaaba 100644 --- a/builder/oracle/oci/config.go +++ b/builder/oracle/oci/config.go @@ -94,21 +94,11 @@ func NewConfig(raws ...interface{}) (*Config, error) { var keyContent []byte if c.KeyFile != "" { - u, err := user.Current() + path, err := common.ExpandUser(c.KeyFile) if err != nil { return nil, err } - if u.HomeDir == "" { - return nil, fmt.Errorf("Unable to determine the home directory for the current user.") - } - - // If c.KeyFile is not an absolute path, then it's relative so prefix it relative to the home directory - path := c.KeyFile - if !filepath.IsAbs(c.KeyFile) { - path = filepath.Join(u.HomeDir, c.KeyFile) - } - // Read API signing key keyContent, err = ioutil.ReadFile(path) if err != nil { diff --git a/common/config.go b/common/config.go index 70ebc8452..9dffab23c 100644 --- a/common/config.go +++ b/common/config.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" "os" + "os/user" "path/filepath" "regexp" "runtime" @@ -206,3 +207,44 @@ func FileExistsLocally(original string) bool { } return true } + +func ExpandUser(path string) (string, error) { + var ( + u *user.User + err error + ) + + // refuse to do anything with a zero-length path + if len(path) == 0 { + return path + } + + // If no expansion was specified, then refuse that too + if path[0] != "~" { + return path, nil + } + + // Grab everything up to the first filepath.Separator + idx := strings.IndexAny(path, `/\`) + if idx == -1 { + idx = len(path) + } + + // Now we should be able to extract the username + username := path[:idx] + + // Check if the current user was requested + if username == "~" { + u, err = user.Current() + } else { + u, err = user.Lookup(username[1:]) + } + + // If we couldn't figure that out, then fail here + if err != nil { + return "", err + } + + // Now we can replace the path with u.HomeDir + return filepath.Join(u.HomeDir, path[idx:]) +} diff --git a/helper/communicator/config.go b/helper/communicator/config.go index 0bd54a134..6c0477bf5 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -6,10 +6,9 @@ import ( "io/ioutil" "net" "os" - "os/user" - "path/filepath" "time" + "github.com/hashicorp/packer/common" packerssh "github.com/hashicorp/packer/communicator/ssh" "github.com/hashicorp/packer/helper/multistep" helperssh "github.com/hashicorp/packer/helper/ssh" @@ -74,19 +73,9 @@ func (c *Config) ReadSSHPrivateKeyFile() ([]byte, error) { var privateKey []byte if c.SSHPrivateKeyFile != "" { - u, err := user.Current() + keyPath, err := common.ExpandUser(c.SSHPrivateKeyFile) if err != nil { - return []byte{}, fmt.Errorf("Error trying to determine the current user for the SSH private key: %s", err) - } - - if u.HomeDir == "" { - return []byte{}, fmt.Errorf("Error locating home directory for the SSH private key") - } - - // If c.SSHPrivateKeyFile is not an absolute path, then it's relative and should be prefixed with u.HomeDir - keyPath := c.SSHPrivateKeyFile - if !filepath.IsAbs(c.SSHPrivateKeyFile) { - keyPath = filepath.Join(u.HomeDir, c.SSHPrivateKeyFile) + return []byte{}, fmt.Errorf("Error expanding path for SSH private key: %s", err) } privateKey, err = ioutil.ReadFile(keyPath) @@ -272,24 +261,8 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error { errs = append(errs, errors.New("An ssh_username must be specified\n Note: some builders used to default ssh_username to \"root\".")) } - // Figure out the current user's home directory - u, err := user.Current() - if err != nil { - errs = append(errs, fmt.Errorf("Unable to determine the current user from : %s", err)) - } else if u.HomeDir == "" { - // If the home directory is empty, then set `err` so that later a failure will happen - err = fmt.Errorf("Unable to determine the home directory for the current user.") - } - if c.SSHPrivateKeyFile != "" { - path := c.SSHPrivateKeyFile - - // If c.SSHPrivateKeyFile is not an absolute path, then it's relative and should be prefixed with u.HomeDir - if err == nil && !filepath.IsAbs(c.SSHPrivateKeyFile) { - path = filepath.Join(u.HomeDir, c.SSHPrivateKeyFile) - } - - // The `err` variable here comes from the empty home directory above + path, err := common.ExpandUser(c.SSHPrivateKeyFile) if err != nil { errs = append(errs, fmt.Errorf( "ssh_private_key_file is invalid: %s", err)) @@ -307,9 +280,7 @@ func (c *Config) prepareSSH(ctx *interpolate.Context) []error { errs = append(errs, errors.New( "ssh_bastion_password or ssh_bastion_private_key_file must be specified")) } else if c.SSHBastionPrivateKeyFile != "" { - path := filepath.Join(u.HomeDir, c.SSHBastionPrivateKeyFile) - - // The `err` variable here comes from an empty home directory + path, err := common.ExpandUser(c.SSHBastionPrivateKeyFile) if err != nil { errs = append(errs, fmt.Errorf( "ssh_bastion_private_key_file is invalid: %s", err)) diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index b8b5ee3ce..121a7c307 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -7,8 +7,6 @@ import ( "log" "net" "os" - "os/user" - "path/filepath" "strings" "time" @@ -228,17 +226,12 @@ func sshBastionConfig(config *Config) (*gossh.ClientConfig, error) { } if config.SSHBastionPrivateKeyFile != "" { - u, err := user.Current() + path, err := common.ExpandUser(config.SSHBastionPrivateKeyFile) if err != nil { - return nil, fmt.Errorf("Unable to determine the current user for the SSH bastion private key: %s", err) + return nil, fmt.Errorf( + "Error expanding path for SSH bastion private key: %s", err) } - if u.HomeDir == "" { - return nil, fmt.Errorf("Unable to determine the current user's home directory for the SSH bastion private key.") - } - - path := filepath.Join(u.HomeDir, config.SSHBastionPrivateKeyFile) - signer, err := helperssh.FileSigner(path) if err != nil { return nil, err