mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-06 18:00:18 +09:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e28e79a648 | |||
| 6a0e125018 | |||
| 1c19e2ba43 |
+21
-1
@@ -21,8 +21,19 @@ import (
|
|||||||
"gitea.dev/modules/util"
|
"gitea.dev/modules/util"
|
||||||
|
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
|
"github.com/mholt/acmez/v3/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func acmeExternalAccountBinding() (acme.EAB, bool, error) {
|
||||||
|
if setting.AcmeEABKID == "" && setting.AcmeEABHMAC == "" {
|
||||||
|
return acme.EAB{}, false, nil
|
||||||
|
}
|
||||||
|
if setting.AcmeEABKID == "" || setting.AcmeEABHMAC == "" {
|
||||||
|
return acme.EAB{}, false, errors.New("both ACME_EAB_KID and ACME_EAB_HMAC must be set")
|
||||||
|
}
|
||||||
|
return acme.EAB{KeyID: setting.AcmeEABKID, MACKey: setting.AcmeEABHMAC}, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getCARoot(path string) (*x509.CertPool, error) {
|
func getCARoot(path string) (*x509.CertPool, error) {
|
||||||
r, err := os.ReadFile(path)
|
r, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -66,6 +77,14 @@ func runACME(listenAddr string, m http.Handler) error {
|
|||||||
log.Warn("Failed to parse CA Root certificate, using default CA trust: %v", err)
|
log.Warn("Failed to parse CA Root certificate, using default CA trust: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
externalAccountBinding, hasExternalAccount, err := acmeExternalAccountBinding()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var externalAccount *acme.EAB
|
||||||
|
if hasExternalAccount {
|
||||||
|
externalAccount = &externalAccountBinding
|
||||||
|
}
|
||||||
// FIXME: this path is not right, it uses "AppWorkPath" incorrectly, and writes the data into "AppWorkPath/https"
|
// FIXME: this path is not right, it uses "AppWorkPath" incorrectly, and writes the data into "AppWorkPath/https"
|
||||||
// Ideally it should migrate to AppDataPath write to "AppDataPath/https"
|
// Ideally it should migrate to AppDataPath write to "AppDataPath/https"
|
||||||
// And one more thing, no idea why we should set the global default variables here
|
// And one more thing, no idea why we should set the global default variables here
|
||||||
@@ -84,6 +103,7 @@ func runACME(listenAddr string, m http.Handler) error {
|
|||||||
Email: setting.AcmeEmail,
|
Email: setting.AcmeEmail,
|
||||||
Agreed: setting.AcmeTOS,
|
Agreed: setting.AcmeTOS,
|
||||||
Profile: setting.AcmeProfile,
|
Profile: setting.AcmeProfile,
|
||||||
|
ExternalAccount: externalAccount,
|
||||||
DisableHTTPChallenge: !enableHTTPChallenge,
|
DisableHTTPChallenge: !enableHTTPChallenge,
|
||||||
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
|
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
|
||||||
ListenHost: setting.HTTPAddr,
|
ListenHost: setting.HTTPAddr,
|
||||||
@@ -100,7 +120,7 @@ func runACME(listenAddr string, m http.Handler) error {
|
|||||||
// takes HTTPS down on restart (https://github.com/go-gitea/gitea/issues/38519).
|
// takes HTTPS down on restart (https://github.com/go-gitea/gitea/issues/38519).
|
||||||
// Prefer keeping the existing cert and retrying renewals asynchronously.
|
// Prefer keeping the existing cert and retrying renewals asynchronously.
|
||||||
ctx := graceful.GetManager().ShutdownContext()
|
ctx := graceful.GetManager().ShutdownContext()
|
||||||
err := magic.ManageSync(ctx, []string{setting.AppDomain})
|
err = magic.ManageSync(ctx, []string{setting.AppDomain})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cert, cacheErr := magic.CacheManagedCertificate(ctx, setting.AppDomain)
|
cert, cacheErr := magic.CacheManagedCertificate(ctx, setting.AppDomain)
|
||||||
if cacheErr != nil || cert.Expired() {
|
if cacheErr != nil || cert.Expired() {
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.dev/modules/setting"
|
||||||
|
"gitea.dev/modules/test"
|
||||||
|
|
||||||
|
"github.com/mholt/acmez/v3/acme"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAcmeExternalAccountBinding(t *testing.T) {
|
||||||
|
t.Cleanup(test.MockVariableValue(&setting.AcmeEABKID, ""))
|
||||||
|
t.Cleanup(test.MockVariableValue(&setting.AcmeEABHMAC, ""))
|
||||||
|
|
||||||
|
binding, configured, err := acmeExternalAccountBinding()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, configured)
|
||||||
|
assert.Empty(t, binding)
|
||||||
|
|
||||||
|
setting.AcmeEABKID = "kid"
|
||||||
|
_, _, err = acmeExternalAccountBinding()
|
||||||
|
assert.ErrorContains(t, err, "both ACME_EAB_KID and ACME_EAB_HMAC must be set")
|
||||||
|
|
||||||
|
setting.AcmeEABHMAC = "hmac"
|
||||||
|
binding, configured, err = acmeExternalAccountBinding()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, configured)
|
||||||
|
assert.Equal(t, acme.EAB{KeyID: "kid", MACKey: "hmac"}, binding)
|
||||||
|
}
|
||||||
@@ -264,6 +264,11 @@
|
|||||||
;; ACME profile to request from the CA (e.g. "shortlived" for raw-IP certificates)
|
;; ACME profile to request from the CA (e.g. "shortlived" for raw-IP certificates)
|
||||||
;ACME_PROFILE =
|
;ACME_PROFILE =
|
||||||
;;
|
;;
|
||||||
|
;; External account binding credentials; set both to enable EAB
|
||||||
|
;; ACME_EAB_HMAC should be a base64url-encoded MAC key
|
||||||
|
;ACME_EAB_KID =
|
||||||
|
;ACME_EAB_HMAC =
|
||||||
|
;;
|
||||||
;; ACME live directory (not to be confused with ACME directory URL: ACME_URL)
|
;; ACME live directory (not to be confused with ACME directory URL: ACME_URL)
|
||||||
;; (Refer to caddy's ACME manager https://github.com/caddyserver/certmagic)
|
;; (Refer to caddy's ACME manager https://github.com/caddyserver/certmagic)
|
||||||
;ACME_DIRECTORY = https
|
;ACME_DIRECTORY = https
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.24
|
github.com/mattn/go-isatty v0.0.24
|
||||||
github.com/mattn/go-sqlite3 v1.14.52
|
github.com/mattn/go-sqlite3 v1.14.52
|
||||||
github.com/meilisearch/meilisearch-go v0.36.3
|
github.com/meilisearch/meilisearch-go v0.36.3
|
||||||
|
github.com/mholt/acmez/v3 v3.1.6
|
||||||
github.com/mholt/archives v0.1.5
|
github.com/mholt/archives v0.1.5
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/microsoft/go-mssqldb v1.11.2
|
github.com/microsoft/go-mssqldb v1.11.2
|
||||||
@@ -199,7 +200,6 @@ require (
|
|||||||
github.com/markbates/going v1.0.3 // indirect
|
github.com/markbates/going v1.0.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||||
github.com/mholt/acmez/v3 v3.1.6 // indirect
|
|
||||||
github.com/miekg/dns v1.1.72 // indirect
|
github.com/miekg/dns v1.1.72 // indirect
|
||||||
github.com/mikelolasagasti/xz v1.0.1 // indirect
|
github.com/mikelolasagasti/xz v1.0.1 // indirect
|
||||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ var (
|
|||||||
AcmeEmail string
|
AcmeEmail string
|
||||||
AcmeURL string
|
AcmeURL string
|
||||||
AcmeProfile string
|
AcmeProfile string
|
||||||
|
AcmeEABKID string
|
||||||
|
AcmeEABHMAC string
|
||||||
AcmeCARoot string
|
AcmeCARoot string
|
||||||
SSLMinimumVersion string
|
SSLMinimumVersion string
|
||||||
SSLMaximumVersion string
|
SSLMaximumVersion string
|
||||||
@@ -144,6 +146,11 @@ func loadServerDomainAndURL(sec ConfigSection, protocol string) {
|
|||||||
AppDomain = appURL.Hostname()
|
AppDomain = appURL.Hostname()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadAcmeEABFrom(sec ConfigSection) {
|
||||||
|
AcmeEABKID = sec.Key("ACME_EAB_KID").MustString("")
|
||||||
|
AcmeEABHMAC = sec.Key("ACME_EAB_HMAC").MustString("")
|
||||||
|
}
|
||||||
|
|
||||||
func loadServerFrom(rootCfg ConfigProvider) {
|
func loadServerFrom(rootCfg ConfigProvider) {
|
||||||
sec := rootCfg.Section("server")
|
sec := rootCfg.Section("server")
|
||||||
AppName = rootCfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea")
|
AppName = rootCfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea")
|
||||||
@@ -173,6 +180,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
|||||||
if EnableAcme {
|
if EnableAcme {
|
||||||
AcmeURL = sec.Key("ACME_URL").MustString("")
|
AcmeURL = sec.Key("ACME_URL").MustString("")
|
||||||
AcmeProfile = sec.Key("ACME_PROFILE").MustString("")
|
AcmeProfile = sec.Key("ACME_PROFILE").MustString("")
|
||||||
|
loadAcmeEABFrom(sec)
|
||||||
AcmeCARoot = sec.Key("ACME_CA_ROOT").MustString("")
|
AcmeCARoot = sec.Key("ACME_CA_ROOT").MustString("")
|
||||||
|
|
||||||
if sec.HasKey("ACME_ACCEPTTOS") {
|
if sec.HasKey("ACME_ACCEPTTOS") {
|
||||||
@@ -208,6 +216,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
|||||||
KeyFile = filepath.Join(CustomPath, KeyFile)
|
KeyFile = filepath.Join(CustomPath, KeyFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SSLMinimumVersion = sec.Key("SSL_MIN_VERSION").MustString("")
|
SSLMinimumVersion = sec.Key("SSL_MIN_VERSION").MustString("")
|
||||||
SSLMaximumVersion = sec.Key("SSL_MAX_VERSION").MustString("")
|
SSLMaximumVersion = sec.Key("SSL_MAX_VERSION").MustString("")
|
||||||
SSLCurvePreferences = sec.Key("SSL_CURVE_PREFERENCES").Strings(",")
|
SSLCurvePreferences = sec.Key("SSL_CURVE_PREFERENCES").Strings(",")
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.dev/modules/test"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadAcmeEABFrom(t *testing.T) {
|
||||||
|
t.Cleanup(test.MockVariableValue(&AcmeEABKID, ""))
|
||||||
|
t.Cleanup(test.MockVariableValue(&AcmeEABHMAC, ""))
|
||||||
|
|
||||||
|
cfg, err := NewConfigProviderFromData(`
|
||||||
|
[server]
|
||||||
|
ACME_EAB_KID = kid
|
||||||
|
ACME_EAB_HMAC = hmac
|
||||||
|
`)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
loadAcmeEABFrom(cfg.Section("server"))
|
||||||
|
|
||||||
|
assert.Equal(t, "kid", AcmeEABKID)
|
||||||
|
assert.Equal(t, "hmac", AcmeEABHMAC)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user