mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-19 23:22:57 +02:00
fix: package registry keypair creation race (#39319)
Alpine, arch, debian, and rpm package types have a race in key creation. --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
co-authored by
Lunny Xiao
silverwind
parent
b27e7d0289
commit
fce7b9d531
@@ -44,32 +44,9 @@ func GetOrCreateRepositoryVersion(ctx context.Context, ownerID int64) (*packages
|
||||
|
||||
// GetOrCreateKeyPair gets or creates the RSA keys used to sign repository files
|
||||
func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, error) {
|
||||
priv, err := user_model.GetSetting(ctx, ownerID, alpine_module.SettingKeyPrivate)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pub, err := user_model.GetSetting(ctx, ownerID, alpine_module.SettingKeyPublic)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if priv == "" || pub == "" {
|
||||
priv, pub, err = util.GenerateKeyPair(4096)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, alpine_module.SettingKeyPrivate, priv); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, alpine_module.SettingKeyPublic, pub); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
return priv, pub, nil
|
||||
return packages_service.GetOrCreateKeyPair(ctx, ownerID, alpine_module.SettingKeyPrivate, alpine_module.SettingKeyPublic, func() (string, string, error) {
|
||||
return util.GenerateKeyPair(4096)
|
||||
})
|
||||
}
|
||||
|
||||
// BuildAllRepositoryFiles (re)builds all repository files for every available branches, repositories and architectures
|
||||
|
||||
@@ -49,32 +49,7 @@ func GetOrCreateRepositoryVersion(ctx context.Context, ownerID int64) (*packages
|
||||
|
||||
// GetOrCreateKeyPair gets or creates the PGP keys used to sign repository files
|
||||
func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, error) {
|
||||
priv, err := user_model.GetSetting(ctx, ownerID, arch_module.SettingKeyPrivate)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pub, err := user_model.GetSetting(ctx, ownerID, arch_module.SettingKeyPublic)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if priv == "" || pub == "" {
|
||||
priv, pub, err = generateKeypair()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, arch_module.SettingKeyPrivate, priv); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, arch_module.SettingKeyPublic, pub); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
return priv, pub, nil
|
||||
return packages_service.GetOrCreateKeyPair(ctx, ownerID, arch_module.SettingKeyPrivate, arch_module.SettingKeyPublic, generateKeypair)
|
||||
}
|
||||
|
||||
func generateKeypair() (string, string, error) {
|
||||
|
||||
@@ -39,32 +39,7 @@ func GetOrCreateRepositoryVersion(ctx context.Context, ownerID int64) (*packages
|
||||
|
||||
// GetOrCreateKeyPair gets or creates the PGP keys used to sign repository files
|
||||
func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, error) {
|
||||
priv, err := user_model.GetSetting(ctx, ownerID, debian_module.SettingKeyPrivate)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pub, err := user_model.GetSetting(ctx, ownerID, debian_module.SettingKeyPublic)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if priv == "" || pub == "" {
|
||||
priv, pub, err = generateKeypair()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPrivate, priv); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, debian_module.SettingKeyPublic, pub); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
return priv, pub, nil
|
||||
return packages_service.GetOrCreateKeyPair(ctx, ownerID, debian_module.SettingKeyPrivate, debian_module.SettingKeyPublic, generateKeypair)
|
||||
}
|
||||
|
||||
func generateKeypair() (string, string, error) {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/globallock"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// GetOrCreateKeyPair gets the owner's key pair used to sign repository files,
|
||||
// generating and storing it if it does not exist yet.
|
||||
func GetOrCreateKeyPair(ctx context.Context, ownerID int64, settingKeyPriv, settingKeyPub string, generate func() (priv, pub string, err error)) (string, string, error) {
|
||||
priv, pub, err := getKeyPair(ctx, ownerID, settingKeyPriv, settingKeyPub)
|
||||
if err != nil || (priv != "" && pub != "") {
|
||||
return priv, pub, err
|
||||
}
|
||||
|
||||
err = globallock.LockAndDo(ctx, fmt.Sprintf("pkg-keypair-%s-%d", settingKeyPriv, ownerID), func(ctx context.Context) error {
|
||||
priv, pub, err = getKeyPair(ctx, ownerID, settingKeyPriv, settingKeyPub) // re-read inside the lock, another request may have created it
|
||||
if err != nil || (priv != "" && pub != "") {
|
||||
return err
|
||||
}
|
||||
|
||||
if priv, pub, err = generate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, settingKeyPriv, priv); err != nil {
|
||||
return err
|
||||
}
|
||||
return user_model.SetUserSetting(ctx, ownerID, settingKeyPub, pub)
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return priv, pub, nil
|
||||
}
|
||||
|
||||
func getKeyPair(ctx context.Context, ownerID int64, settingKeyPriv, settingKeyPub string) (string, string, error) {
|
||||
priv, err := user_model.GetSetting(ctx, ownerID, settingKeyPriv)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pub, err := user_model.GetSetting(ctx, ownerID, settingKeyPub)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return priv, pub, nil
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
@@ -23,7 +22,6 @@ import (
|
||||
"gitea.dev/modules/json"
|
||||
packages_module "gitea.dev/modules/packages"
|
||||
rpm_module "gitea.dev/modules/packages/rpm"
|
||||
"gitea.dev/modules/util"
|
||||
packages_service "gitea.dev/services/packages"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
@@ -39,32 +37,7 @@ func GetOrCreateRepositoryVersion(ctx context.Context, ownerID int64) (*packages
|
||||
|
||||
// GetOrCreateKeyPair gets or creates the PGP keys used to sign repository metadata files
|
||||
func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, error) {
|
||||
priv, err := user_model.GetSetting(ctx, ownerID, rpm_module.SettingKeyPrivate)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
pub, err := user_model.GetSetting(ctx, ownerID, rpm_module.SettingKeyPublic)
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if priv == "" || pub == "" {
|
||||
priv, pub, err = generateKeypair()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, rpm_module.SettingKeyPrivate, priv); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if err := user_model.SetUserSetting(ctx, ownerID, rpm_module.SettingKeyPublic, pub); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
return priv, pub, nil
|
||||
return packages_service.GetOrCreateKeyPair(ctx, ownerID, rpm_module.SettingKeyPrivate, rpm_module.SettingKeyPublic, generateKeypair)
|
||||
}
|
||||
|
||||
func generateKeypair() (string, string, error) {
|
||||
|
||||
Reference in New Issue
Block a user