package cloudinitexecute import ( "io/ioutil" "os" "path" "strconv" "strings" "github.com/rancher/os/pkg/log" "github.com/rancher/os/pkg/util" ) const ( sshDirName = ".ssh" authorizedKeysFileName = "authorized_keys" ) func authorizeSSHKeys(username string, authorizedKeys []string, name string) error { var uid int var gid int var homeDir string bytes, err := ioutil.ReadFile("/etc/passwd") if err != nil { return err } for _, line := range strings.Split(string(bytes), "\n") { if strings.HasPrefix(line, username) { split := strings.Split(line, ":") if len(split) < 6 { break } uid, err = strconv.Atoi(split[2]) if err != nil { return err } gid, err = strconv.Atoi(split[3]) if err != nil { return err } homeDir = split[5] } } sshDir := path.Join(homeDir, sshDirName) authorizedKeysFile := path.Join(sshDir, authorizedKeysFileName) if _, err := os.Stat(sshDir); os.IsNotExist(err) { if err = os.Mkdir(sshDir, 0700); err != nil { return err } } else if err != nil { return err } if err = os.Chown(sshDir, uid, gid); err != nil { return err } for _, authorizedKey := range authorizedKeys { if err = authorizeSSHKey(authorizedKey, authorizedKeysFile, uid, gid); err != nil { log.Errorf("Failed to authorize SSH key %s: %v", authorizedKey, err) } } return nil } func authorizeSSHKey(authorizedKey, authorizedKeysFile string, uid, gid int) error { authorizedKeysFileInfo, err := os.Stat(authorizedKeysFile) if os.IsNotExist(err) { keysFile, err := os.Create(authorizedKeysFile) if err != nil { return err } if err = keysFile.Chmod(0600); err != nil { return err } if err = keysFile.Close(); err != nil { return err } authorizedKeysFileInfo, err = os.Stat(authorizedKeysFile) if err != nil { return err } } else if err != nil { return err } bytes, err := ioutil.ReadFile(authorizedKeysFile) if err != nil { return err } if !strings.Contains(string(bytes), authorizedKey) { bytes = append(bytes, []byte(authorizedKey)...) bytes = append(bytes, '\n') } perm := authorizedKeysFileInfo.Mode().Perm() if err = util.WriteFileAtomic(authorizedKeysFile, bytes, perm); err != nil { return err } return os.Chown(authorizedKeysFile, uid, gid) }