authorize_ssh_keys.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package cloudinitexecute
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path"
  6. "strconv"
  7. "strings"
  8. "github.com/rancher/os/log"
  9. "github.com/rancher/os/util"
  10. )
  11. const (
  12. sshDirName = ".ssh"
  13. authorizedKeysFileName = "authorized_keys"
  14. )
  15. func authorizeSSHKeys(username string, authorizedKeys []string, name string) error {
  16. var uid int
  17. var gid int
  18. var homeDir string
  19. bytes, err := ioutil.ReadFile("/etc/passwd")
  20. if err != nil {
  21. return err
  22. }
  23. for _, line := range strings.Split(string(bytes), "\n") {
  24. if strings.HasPrefix(line, username) {
  25. split := strings.Split(line, ":")
  26. if len(split) < 6 {
  27. break
  28. }
  29. uid, err = strconv.Atoi(split[2])
  30. if err != nil {
  31. return err
  32. }
  33. gid, err = strconv.Atoi(split[3])
  34. if err != nil {
  35. return err
  36. }
  37. homeDir = split[5]
  38. }
  39. }
  40. sshDir := path.Join(homeDir, sshDirName)
  41. authorizedKeysFile := path.Join(sshDir, authorizedKeysFileName)
  42. if _, err := os.Stat(sshDir); os.IsNotExist(err) {
  43. if err = os.Mkdir(sshDir, 0700); err != nil {
  44. return err
  45. }
  46. } else if err != nil {
  47. return err
  48. }
  49. if err = os.Chown(sshDir, uid, gid); err != nil {
  50. return err
  51. }
  52. for _, authorizedKey := range authorizedKeys {
  53. if err = authorizeSSHKey(authorizedKey, authorizedKeysFile, uid, gid); err != nil {
  54. log.Errorf("Failed to authorize SSH key %s: %v", authorizedKey, err)
  55. }
  56. }
  57. return nil
  58. }
  59. func authorizeSSHKey(authorizedKey, authorizedKeysFile string, uid, gid int) error {
  60. authorizedKeysFileInfo, err := os.Stat(authorizedKeysFile)
  61. if os.IsNotExist(err) {
  62. keysFile, err := os.Create(authorizedKeysFile)
  63. if err != nil {
  64. return err
  65. }
  66. if err = keysFile.Chmod(0600); err != nil {
  67. return err
  68. }
  69. if err = keysFile.Close(); err != nil {
  70. return err
  71. }
  72. authorizedKeysFileInfo, err = os.Stat(authorizedKeysFile)
  73. if err != nil {
  74. return err
  75. }
  76. } else if err != nil {
  77. return err
  78. }
  79. bytes, err := ioutil.ReadFile(authorizedKeysFile)
  80. if err != nil {
  81. return err
  82. }
  83. if !strings.Contains(string(bytes), authorizedKey) {
  84. bytes = append(bytes, []byte(authorizedKey)...)
  85. bytes = append(bytes, '\n')
  86. }
  87. perm := authorizedKeysFileInfo.Mode().Perm()
  88. if err = util.WriteFileAtomic(authorizedKeysFile, bytes, perm); err != nil {
  89. return err
  90. }
  91. return os.Chown(authorizedKeysFile, uid, gid)
  92. }