Skip to content

Commit 6123c44

Browse files
committed
refactor
1 parent e936d2b commit 6123c44

File tree

9 files changed

+77
-33
lines changed

9 files changed

+77
-33
lines changed

modules/base/tool.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf any) string {
115115

116116
// create sha1 encode string
117117
sh := sha1.New()
118-
_, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, setting.SecretKey, startStr, endStr, minutes)))
118+
_, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, endStr, minutes)))
119119
encoded := hex.EncodeToString(sh.Sum(nil))
120120

121121
code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)

modules/context/context.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package context
66

77
import (
88
"context"
9+
"encoding/hex"
910
"fmt"
1011
"html/template"
1112
"io"
@@ -124,7 +125,7 @@ func NewWebContext(base *Base, render Render, session session.Store) *Context {
124125
func Contexter() func(next http.Handler) http.Handler {
125126
rnd := templates.HTMLRenderer()
126127
csrfOpts := CsrfOptions{
127-
Secret: setting.SecretKey,
128+
Secret: hex.EncodeToString(setting.GetGeneralTokenSigningSecret()),
128129
Cookie: setting.CSRFCookieName,
129130
SetCookie: true,
130131
Secure: setting.SessionConfig.Secure,

modules/setting/lfs.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import (
1212

1313
// LFS represents the configuration for Git LFS
1414
var LFS = struct {
15-
StartServer bool `ini:"LFS_START_SERVER"`
16-
JWTSecretBase64 string `ini:"LFS_JWT_SECRET"`
17-
JWTSecretBytes []byte `ini:"-"`
18-
HTTPAuthExpiry time.Duration `ini:"LFS_HTTP_AUTH_EXPIRY"`
19-
MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
20-
LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
15+
StartServer bool `ini:"LFS_START_SERVER"`
16+
JWTSecretBytes []byte `ini:"-"`
17+
HTTPAuthExpiry time.Duration `ini:"LFS_HTTP_AUTH_EXPIRY"`
18+
MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
19+
LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
2120

2221
Storage *Storage
2322
}{}
@@ -59,10 +58,10 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
5958
return nil
6059
}
6160

62-
LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
63-
LFS.JWTSecretBytes, err = generate.DecodeJwtSecretBase64(LFS.JWTSecretBase64)
61+
jwtSecretBase64 := loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
62+
LFS.JWTSecretBytes, err = generate.DecodeJwtSecretBase64(jwtSecretBase64)
6463
if err != nil {
65-
LFS.JWTSecretBytes, LFS.JWTSecretBase64, err = generate.NewJwtSecretWithBase64()
64+
LFS.JWTSecretBytes, jwtSecretBase64, err = generate.NewJwtSecretWithBase64()
6665
if err != nil {
6766
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)
6867
}
@@ -72,8 +71,8 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
7271
if err != nil {
7372
return fmt.Errorf("error saving JWT Secret for custom config: %v", err)
7473
}
75-
rootCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
76-
saveCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
74+
rootCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(jwtSecretBase64)
75+
saveCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(jwtSecretBase64)
7776
if err := saveCfg.Save(); err != nil {
7877
return fmt.Errorf("error saving JWT Secret for custom config: %v", err)
7978
}

modules/setting/oauth2.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
package setting
55

66
import (
7+
"fmt"
78
"math"
89
"path/filepath"
10+
"sync/atomic"
911

1012
"code.gitea.io/gitea/modules/generate"
1113
"code.gitea.io/gitea/modules/log"
@@ -96,7 +98,6 @@ var OAuth2 = struct {
9698
RefreshTokenExpirationTime int64
9799
InvalidateRefreshTokens bool
98100
JWTSigningAlgorithm string `ini:"JWT_SIGNING_ALGORITHM"`
99-
JWTSecretBase64 string `ini:"JWT_SECRET"`
100101
JWTSigningPrivateKeyFile string `ini:"JWT_SIGNING_PRIVATE_KEY_FILE"`
101102
MaxTokenLength int
102103
DefaultApplications []string
@@ -128,28 +129,45 @@ func loadOAuth2From(rootCfg ConfigProvider) {
128129
return
129130
}
130131

131-
OAuth2.JWTSecretBase64 = loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
132+
jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
132133

133134
if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) {
134135
OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile)
135136
}
136137

137138
if InstallLock {
138-
if _, err := generate.DecodeJwtSecretBase64(OAuth2.JWTSecretBase64); err != nil {
139-
_, OAuth2.JWTSecretBase64, err = generate.NewJwtSecretWithBase64()
139+
jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64)
140+
if err != nil {
141+
jwtSecretBytes, jwtSecretBase64, err = generate.NewJwtSecretWithBase64()
140142
if err != nil {
141143
log.Fatal("error generating JWT secret: %v", err)
142144
}
143-
144145
saveCfg, err := rootCfg.PrepareSaving()
145146
if err != nil {
146147
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
147148
}
148-
rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
149-
saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
149+
rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64)
150+
saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64)
150151
if err := saveCfg.Save(); err != nil {
151152
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
152153
}
153154
}
155+
generalSigningSecret.Store(&jwtSecretBytes)
156+
}
157+
}
158+
159+
var generalSigningSecret atomic.Pointer[[]byte]
160+
161+
func GetGeneralTokenSigningSecret() []byte {
162+
ptr := generalSigningSecret.Load()
163+
if ptr == nil {
164+
if jwtSecret, _, err := generate.NewJwtSecretWithBase64(); err != nil {
165+
panic(fmt.Errorf("unable to generate general JWT secret: %w", err))
166+
} else {
167+
if generalSigningSecret.CompareAndSwap(nil, &jwtSecret) {
168+
log.Warn("OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes")
169+
}
170+
}
154171
}
172+
return *generalSigningSecret.Load()
155173
}

modules/setting/oauth2_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package setting
5+
6+
import (
7+
"code.gitea.io/gitea/modules/generate"
8+
"code.gitea.io/gitea/modules/test"
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestGetGeneralSigningSecret(t *testing.T) {
15+
// when there is no general signing secret, it should be generated, and keep the same value
16+
assert.Nil(t, generalSigningSecret.Load())
17+
s1 := GetGeneralTokenSigningSecret()
18+
assert.NotNil(t, s1)
19+
s2 := GetGeneralTokenSigningSecret()
20+
assert.Equal(t, s1, s2)
21+
22+
// the config value should always override any pre-generated value
23+
cfg, _ := NewConfigProviderFromData(`
24+
[oauth2]
25+
JWT_SECRET = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
26+
`)
27+
defer test.MockVariableValue(&InstallLock, true)()
28+
loadOAuth2From(cfg)
29+
actual := GetGeneralTokenSigningSecret()
30+
expected, _ := generate.DecodeJwtSecretBase64("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB")
31+
assert.Len(t, actual, 32)
32+
assert.EqualValues(t, expected, actual)
33+
}

services/actions/auth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func CreateAuthorizationToken(taskID, runID, jobID int64) (string, error) {
3838
}
3939
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
4040

41-
tokenString, err := token.SignedString([]byte(setting.SecretKey))
41+
tokenString, err := token.SignedString(setting.GetGeneralTokenSigningSecret())
4242
if err != nil {
4343
return "", err
4444
}
@@ -62,7 +62,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
6262
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
6363
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
6464
}
65-
return []byte(setting.SecretKey), nil
65+
return setting.GetGeneralTokenSigningSecret(), nil
6666
})
6767
if err != nil {
6868
return 0, err

services/actions/auth_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestCreateAuthorizationToken(t *testing.T) {
2020
assert.NotEqual(t, "", token)
2121
claims := jwt.MapClaims{}
2222
_, err = jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (interface{}, error) {
23-
return []byte(setting.SecretKey), nil
23+
return setting.GetGeneralTokenSigningSecret(), nil
2424
})
2525
assert.Nil(t, err)
2626
scp, ok := claims["scp"]

services/auth/source/oauth2/jwtsigningkey.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"path/filepath"
1919
"strings"
2020

21-
"code.gitea.io/gitea/modules/generate"
2221
"code.gitea.io/gitea/modules/log"
2322
"code.gitea.io/gitea/modules/setting"
2423
"code.gitea.io/gitea/modules/util"
@@ -301,7 +300,7 @@ func InitSigningKey() error {
301300
case "HS384":
302301
fallthrough
303302
case "HS512":
304-
key, err = loadSymmetricKey()
303+
key = setting.GetGeneralTokenSigningSecret()
305304
case "RS256":
306305
fallthrough
307306
case "RS384":
@@ -334,12 +333,6 @@ func InitSigningKey() error {
334333
return nil
335334
}
336335

337-
// loadSymmetricKey checks if the configured secret is valid.
338-
// If it is not valid, it will return an error.
339-
func loadSymmetricKey() (any, error) {
340-
return generate.DecodeJwtSecretBase64(setting.OAuth2.JWTSecretBase64)
341-
}
342-
343336
// loadOrCreateAsymmetricKey checks if the configured private key exists.
344337
// If it does not exist a new random key gets generated and saved on the configured path.
345338
func loadOrCreateAsymmetricKey() (any, error) {

services/packages/auth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func CreateAuthorizationToken(u *user_model.User) (string, error) {
3333
}
3434
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
3535

36-
tokenString, err := token.SignedString([]byte(setting.SecretKey))
36+
tokenString, err := token.SignedString(setting.GetGeneralTokenSigningSecret())
3737
if err != nil {
3838
return "", err
3939
}
@@ -57,7 +57,7 @@ func ParseAuthorizationToken(req *http.Request) (int64, error) {
5757
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
5858
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
5959
}
60-
return []byte(setting.SecretKey), nil
60+
return setting.GetGeneralTokenSigningSecret(), nil
6161
})
6262
if err != nil {
6363
return 0, err

0 commit comments

Comments
 (0)