You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ssh_key_authorized_keys.go 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package asymkey
  4. import (
  5. "context"
  6. "fmt"
  7. "os"
  8. "path/filepath"
  9. "time"
  10. asymkey_model "code.gitea.io/gitea/models/asymkey"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/util"
  14. )
  15. // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
  16. // Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function
  17. // outside any session scope independently.
  18. func RewriteAllPublicKeys(ctx context.Context) error {
  19. // Don't rewrite key if internal server
  20. if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile {
  21. return nil
  22. }
  23. return asymkey_model.WithSSHOpLocker(func() error {
  24. return rewriteAllPublicKeys(ctx)
  25. })
  26. }
  27. func rewriteAllPublicKeys(ctx context.Context) error {
  28. if setting.SSH.RootPath != "" {
  29. // First of ensure that the RootPath is present, and if not make it with 0700 permissions
  30. // This of course doesn't guarantee that this is the right directory for authorized_keys
  31. // but at least if it's supposed to be this directory and it doesn't exist and we're the
  32. // right user it will at least be created properly.
  33. err := os.MkdirAll(setting.SSH.RootPath, 0o700)
  34. if err != nil {
  35. log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
  36. return err
  37. }
  38. }
  39. fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
  40. tmpPath := fPath + ".tmp"
  41. t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
  42. if err != nil {
  43. return err
  44. }
  45. defer func() {
  46. t.Close()
  47. if err := util.Remove(tmpPath); err != nil {
  48. log.Warn("Unable to remove temporary authorized keys file: %s: Error: %v", tmpPath, err)
  49. }
  50. }()
  51. if setting.SSH.AuthorizedKeysBackup {
  52. isExist, err := util.IsExist(fPath)
  53. if err != nil {
  54. log.Error("Unable to check if %s exists. Error: %v", fPath, err)
  55. return err
  56. }
  57. if isExist {
  58. bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix())
  59. if err = util.CopyFile(fPath, bakPath); err != nil {
  60. return err
  61. }
  62. }
  63. }
  64. if err := asymkey_model.RegeneratePublicKeys(ctx, t); err != nil {
  65. return err
  66. }
  67. t.Close()
  68. return util.Rename(tmpPath, fPath)
  69. }