diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2024-03-04 16:57:39 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-04 08:57:39 +0000 |
commit | e2277d07ca5112a797f8c86f825060027ff1c2da (patch) | |
tree | 77dc35194eaf4afb0f94265b46ec3c0faf312826 /models | |
parent | c337ff0ec70618ef2ead7850f90ab2a8458db192 (diff) | |
download | gitea-e2277d07ca5112a797f8c86f825060027ff1c2da.tar.gz gitea-e2277d07ca5112a797f8c86f825060027ff1c2da.zip |
Move some asymkey functions to service layer (#28894)
After the moving, all models will not depend on `util.Rename` so that I
can do next step refactoring.
Diffstat (limited to 'models')
-rw-r--r-- | models/asymkey/ssh_key_authorized_keys.go | 66 | ||||
-rw-r--r-- | models/asymkey/ssh_key_authorized_principals.go | 134 | ||||
-rw-r--r-- | models/asymkey/ssh_key_principals.go | 40 |
3 files changed, 6 insertions, 234 deletions
diff --git a/models/asymkey/ssh_key_authorized_keys.go b/models/asymkey/ssh_key_authorized_keys.go index 267ab252c8..9279db2020 100644 --- a/models/asymkey/ssh_key_authorized_keys.go +++ b/models/asymkey/ssh_key_authorized_keys.go @@ -12,7 +12,6 @@ import ( "path/filepath" "strings" "sync" - "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/log" @@ -44,6 +43,12 @@ const ( var sshOpLocker sync.Mutex +func WithSSHOpLocker(f func() error) error { + sshOpLocker.Lock() + defer sshOpLocker.Unlock() + return f() +} + // AuthorizedStringForKey creates the authorized keys string appropriate for the provided key func AuthorizedStringForKey(key *PublicKey) string { sb := &strings.Builder{} @@ -114,65 +119,6 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error { return nil } -// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. -// Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function -// outside any session scope independently. -func RewriteAllPublicKeys(ctx context.Context) error { - // Don't rewrite key if internal server - if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { - return nil - } - - sshOpLocker.Lock() - defer sshOpLocker.Unlock() - - if setting.SSH.RootPath != "" { - // First of ensure that the RootPath is present, and if not make it with 0700 permissions - // This of course doesn't guarantee that this is the right directory for authorized_keys - // but at least if it's supposed to be this directory and it doesn't exist and we're the - // right user it will at least be created properly. - err := os.MkdirAll(setting.SSH.RootPath, 0o700) - if err != nil { - log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err) - return err - } - } - - fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys") - tmpPath := fPath + ".tmp" - t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600) - if err != nil { - return err - } - defer func() { - t.Close() - if err := util.Remove(tmpPath); err != nil { - log.Warn("Unable to remove temporary authorized keys file: %s: Error: %v", tmpPath, err) - } - }() - - if setting.SSH.AuthorizedKeysBackup { - isExist, err := util.IsExist(fPath) - if err != nil { - log.Error("Unable to check if %s exists. Error: %v", fPath, err) - return err - } - if isExist { - bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix()) - if err = util.CopyFile(fPath, bakPath); err != nil { - return err - } - } - } - - if err := RegeneratePublicKeys(ctx, t); err != nil { - return err - } - - t.Close() - return util.Rename(tmpPath, fPath) -} - // RegeneratePublicKeys regenerates the authorized_keys file func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) { diff --git a/models/asymkey/ssh_key_authorized_principals.go b/models/asymkey/ssh_key_authorized_principals.go deleted file mode 100644 index 107d70c766..0000000000 --- a/models/asymkey/ssh_key_authorized_principals.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2021 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package asymkey - -import ( - "bufio" - "context" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" -) - -// _____ __ .__ .__ .___ -// / _ \ __ ___/ |_| |__ ___________|__|_______ ____ __| _/ -// / /_\ \| | \ __\ | \ / _ \_ __ \ \___ // __ \ / __ | -// / | \ | /| | | Y ( <_> ) | \/ |/ /\ ___// /_/ | -// \____|__ /____/ |__| |___| /\____/|__| |__/_____ \\___ >____ | -// \/ \/ \/ \/ \/ -// __________ .__ .__ .__ -// \______ _______|__| ____ ____ |_____________ | | ______ -// | ___\_ __ | |/ \_/ ___\| \____ \__ \ | | / ___/ -// | | | | \| | | \ \___| | |_> / __ \| |__\___ \ -// |____| |__| |__|___| /\___ |__| __(____ |____/____ > -// \/ \/ |__| \/ \/ -// -// This file contains functions for creating authorized_principals files -// -// There is a dependence on the database within RewriteAllPrincipalKeys & RegeneratePrincipalKeys -// The sshOpLocker is used from ssh_key_authorized_keys.go - -const authorizedPrincipalsFile = "authorized_principals" - -// RewriteAllPrincipalKeys removes any authorized principal and rewrite all keys from database again. -// Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function -// outside any session scope independently. -func RewriteAllPrincipalKeys(ctx context.Context) error { - // Don't rewrite key if internal server - if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedPrincipalsFile { - return nil - } - - sshOpLocker.Lock() - defer sshOpLocker.Unlock() - - if setting.SSH.RootPath != "" { - // First of ensure that the RootPath is present, and if not make it with 0700 permissions - // This of course doesn't guarantee that this is the right directory for authorized_keys - // but at least if it's supposed to be this directory and it doesn't exist and we're the - // right user it will at least be created properly. - err := os.MkdirAll(setting.SSH.RootPath, 0o700) - if err != nil { - log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err) - return err - } - } - - fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile) - tmpPath := fPath + ".tmp" - t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600) - if err != nil { - return err - } - defer func() { - t.Close() - os.Remove(tmpPath) - }() - - if setting.SSH.AuthorizedPrincipalsBackup { - isExist, err := util.IsExist(fPath) - if err != nil { - log.Error("Unable to check if %s exists. Error: %v", fPath, err) - return err - } - if isExist { - bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix()) - if err = util.CopyFile(fPath, bakPath); err != nil { - return err - } - } - } - - if err := regeneratePrincipalKeys(ctx, t); err != nil { - return err - } - - t.Close() - return util.Rename(tmpPath, fPath) -} - -func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error { - if err := db.GetEngine(ctx).Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) { - _, err = t.WriteString((bean.(*PublicKey)).AuthorizedString()) - return err - }); err != nil { - return err - } - - fPath := filepath.Join(setting.SSH.RootPath, authorizedPrincipalsFile) - isExist, err := util.IsExist(fPath) - if err != nil { - log.Error("Unable to check if %s exists. Error: %v", fPath, err) - return err - } - if isExist { - f, err := os.Open(fPath) - if err != nil { - return err - } - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, tplCommentPrefix) { - scanner.Scan() - continue - } - _, err = t.WriteString(line + "\n") - if err != nil { - f.Close() - return err - } - } - f.Close() - } - return nil -} diff --git a/models/asymkey/ssh_key_principals.go b/models/asymkey/ssh_key_principals.go index 4e7dee2c91..e8b97d306e 100644 --- a/models/asymkey/ssh_key_principals.go +++ b/models/asymkey/ssh_key_principals.go @@ -9,51 +9,11 @@ import ( "strings" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" ) -// AddPrincipalKey adds new principal to database and authorized_principals file. -func AddPrincipalKey(ctx context.Context, ownerID int64, content string, authSourceID int64) (*PublicKey, error) { - dbCtx, committer, err := db.TxContext(ctx) - if err != nil { - return nil, err - } - defer committer.Close() - - // Principals cannot be duplicated. - has, err := db.GetEngine(dbCtx). - Where("content = ? AND type = ?", content, KeyTypePrincipal). - Get(new(PublicKey)) - if err != nil { - return nil, err - } else if has { - return nil, ErrKeyAlreadyExist{0, "", content} - } - - key := &PublicKey{ - OwnerID: ownerID, - Name: content, - Content: content, - Mode: perm.AccessModeWrite, - Type: KeyTypePrincipal, - LoginSourceID: authSourceID, - } - if err = db.Insert(dbCtx, key); err != nil { - return nil, fmt.Errorf("addKey: %w", err) - } - - if err = committer.Commit(); err != nil { - return nil, err - } - - committer.Close() - - return key, RewriteAllPrincipalKeys(ctx) -} - // CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines func CheckPrincipalKeyString(ctx context.Context, user *user_model.User, content string) (_ string, err error) { if setting.SSH.Disabled { |