mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	| @@ -126,16 +126,15 @@ func loadOAuth2From(rootCfg ConfigProvider) { | |||||||
| 		OAuth2.Enabled = sec.Key("ENABLE").MustBool(OAuth2.Enabled) | 		OAuth2.Enabled = sec.Key("ENABLE").MustBool(OAuth2.Enabled) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !OAuth2.Enabled { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET") |  | ||||||
|  |  | ||||||
| 	if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) { | 	if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) { | ||||||
| 		OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile) | 		OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// FIXME: at the moment, no matter oauth2 is enabled or not, it must generate a "oauth2 JWT_SECRET" | ||||||
|  | 	// Because this secret is also used as GeneralTokenSigningSecret (as a quick not-that-breaking fix for some legacy problems). | ||||||
|  | 	// Including: CSRF token, account validation token, etc ... | ||||||
|  | 	// In main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...) | ||||||
|  | 	jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET") | ||||||
| 	if InstallLock { | 	if InstallLock { | ||||||
| 		jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64) | 		jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @@ -157,8 +156,6 @@ func loadOAuth2From(rootCfg ConfigProvider) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // generalSigningSecret is used as container for a []byte value |  | ||||||
| // instead of an additional mutex, we use CompareAndSwap func to change the value thread save |  | ||||||
| var generalSigningSecret atomic.Pointer[[]byte] | var generalSigningSecret atomic.Pointer[[]byte] | ||||||
|  |  | ||||||
| func GetGeneralTokenSigningSecret() []byte { | func GetGeneralTokenSigningSecret() []byte { | ||||||
| @@ -166,11 +163,9 @@ func GetGeneralTokenSigningSecret() []byte { | |||||||
| 	if old == nil || len(*old) == 0 { | 	if old == nil || len(*old) == 0 { | ||||||
| 		jwtSecret, _, err := generate.NewJwtSecretWithBase64() | 		jwtSecret, _, err := generate.NewJwtSecretWithBase64() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Fatal("Unable to generate general JWT secret: %s", err.Error()) | 			log.Fatal("Unable to generate general JWT secret: %v", err) | ||||||
| 		} | 		} | ||||||
| 		if generalSigningSecret.CompareAndSwap(old, &jwtSecret) { | 		if generalSigningSecret.CompareAndSwap(old, &jwtSecret) { | ||||||
| 			// FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...) |  | ||||||
| 			LogStartupProblem(1, 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") |  | ||||||
| 			return jwtSecret | 			return jwtSecret | ||||||
| 		} | 		} | ||||||
| 		return *generalSigningSecret.Load() | 		return *generalSigningSecret.Load() | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| package setting | package setting | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"os" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"code.gitea.io/gitea/modules/generate" | 	"code.gitea.io/gitea/modules/generate" | ||||||
| @@ -14,7 +15,7 @@ import ( | |||||||
|  |  | ||||||
| func TestGetGeneralSigningSecret(t *testing.T) { | func TestGetGeneralSigningSecret(t *testing.T) { | ||||||
| 	// when there is no general signing secret, it should be generated, and keep the same value | 	// when there is no general signing secret, it should be generated, and keep the same value | ||||||
| 	assert.Nil(t, generalSigningSecret.Load()) | 	generalSigningSecret.Store(nil) | ||||||
| 	s1 := GetGeneralTokenSigningSecret() | 	s1 := GetGeneralTokenSigningSecret() | ||||||
| 	assert.NotNil(t, s1) | 	assert.NotNil(t, s1) | ||||||
| 	s2 := GetGeneralTokenSigningSecret() | 	s2 := GetGeneralTokenSigningSecret() | ||||||
| @@ -33,6 +34,31 @@ JWT_SECRET = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB | |||||||
| 	assert.EqualValues(t, expected, actual) | 	assert.EqualValues(t, expected, actual) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestGetGeneralSigningSecretSave(t *testing.T) { | ||||||
|  | 	defer test.MockVariableValue(&InstallLock, true)() | ||||||
|  |  | ||||||
|  | 	old := GetGeneralTokenSigningSecret() | ||||||
|  | 	assert.Len(t, old, 32) | ||||||
|  |  | ||||||
|  | 	tmpFile := t.TempDir() + "/app.ini" | ||||||
|  | 	_ = os.WriteFile(tmpFile, nil, 0o644) | ||||||
|  | 	cfg, _ := NewConfigProviderFromFile(tmpFile) | ||||||
|  | 	loadOAuth2From(cfg) | ||||||
|  | 	generated := GetGeneralTokenSigningSecret() | ||||||
|  | 	assert.Len(t, generated, 32) | ||||||
|  | 	assert.NotEqual(t, old, generated) | ||||||
|  |  | ||||||
|  | 	generalSigningSecret.Store(nil) | ||||||
|  | 	cfg, _ = NewConfigProviderFromFile(tmpFile) | ||||||
|  | 	loadOAuth2From(cfg) | ||||||
|  | 	again := GetGeneralTokenSigningSecret() | ||||||
|  | 	assert.Equal(t, generated, again) | ||||||
|  |  | ||||||
|  | 	iniContent, err := os.ReadFile(tmpFile) | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	assert.Contains(t, string(iniContent), "JWT_SECRET = ") | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestOauth2DefaultApplications(t *testing.T) { | func TestOauth2DefaultApplications(t *testing.T) { | ||||||
| 	cfg, _ := NewConfigProviderFromData(``) | 	cfg, _ := NewConfigProviderFromData(``) | ||||||
| 	loadOAuth2From(cfg) | 	loadOAuth2From(cfg) | ||||||
|   | |||||||
| @@ -481,6 +481,17 @@ func SubmitInstall(ctx *context.Context) { | |||||||
| 		cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(internalToken) | 		cfg.Section("security").Key("INTERNAL_TOKEN").SetValue(internalToken) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// FIXME: at the moment, no matter oauth2 is enabled or not, it must generate a "oauth2 JWT_SECRET" | ||||||
|  | 	// see the "loadOAuth2From" in "setting/oauth2.go" | ||||||
|  | 	if !cfg.Section("oauth2").HasKey("JWT_SECRET") && !cfg.Section("oauth2").HasKey("JWT_SECRET_URI") { | ||||||
|  | 		_, jwtSecretBase64, err := generate.NewJwtSecretWithBase64() | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), tplInstall, &form) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		cfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// if there is already a SECRET_KEY, we should not overwrite it, otherwise the encrypted data will not be able to be decrypted | 	// if there is already a SECRET_KEY, we should not overwrite it, otherwise the encrypted data will not be able to be decrypted | ||||||
| 	if setting.SecretKey == "" { | 	if setting.SecretKey == "" { | ||||||
| 		var secretKey string | 		var secretKey string | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user