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