mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-01 20:59:45 +09:00
feat(acme): support EAB credentials
Co-authored-by: techknowlogick <164197+techknowlogick@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
1c19e2ba43
commit
6a0e125018
+17
-1
@@ -21,8 +21,19 @@ import (
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/mholt/acmez/v3/acme"
|
||||
)
|
||||
|
||||
func acmeExternalAccountBinding() (*acme.EAB, error) {
|
||||
if setting.AcmeEABKID == "" && setting.AcmeEABHMAC == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if setting.AcmeEABKID == "" || setting.AcmeEABHMAC == "" {
|
||||
return nil, errors.New("both ACME_EAB_KID and ACME_EAB_HMAC must be set")
|
||||
}
|
||||
return &acme.EAB{KeyID: setting.AcmeEABKID, MACKey: setting.AcmeEABHMAC}, nil
|
||||
}
|
||||
|
||||
func getCARoot(path string) (*x509.CertPool, error) {
|
||||
r, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
@@ -66,6 +77,10 @@ func runACME(listenAddr string, m http.Handler) error {
|
||||
log.Warn("Failed to parse CA Root certificate, using default CA trust: %v", err)
|
||||
}
|
||||
}
|
||||
externalAccount, err := acmeExternalAccountBinding()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 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"
|
||||
// And one more thing, no idea why we should set the global default variables here
|
||||
@@ -84,6 +99,7 @@ func runACME(listenAddr string, m http.Handler) error {
|
||||
Email: setting.AcmeEmail,
|
||||
Agreed: setting.AcmeTOS,
|
||||
Profile: setting.AcmeProfile,
|
||||
ExternalAccount: externalAccount,
|
||||
DisableHTTPChallenge: !enableHTTPChallenge,
|
||||
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
|
||||
ListenHost: setting.HTTPAddr,
|
||||
@@ -100,7 +116,7 @@ func runACME(listenAddr string, m http.Handler) error {
|
||||
// takes HTTPS down on restart (https://github.com/go-gitea/gitea/issues/38519).
|
||||
// Prefer keeping the existing cert and retrying renewals asynchronously.
|
||||
ctx := graceful.GetManager().ShutdownContext()
|
||||
err := magic.ManageSync(ctx, []string{setting.AppDomain})
|
||||
err = magic.ManageSync(ctx, []string{setting.AppDomain})
|
||||
if err != nil {
|
||||
cert, cacheErr := magic.CacheManagedCertificate(ctx, setting.AppDomain)
|
||||
if cacheErr != nil || cert.Expired() {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// 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, err := acmeExternalAccountBinding()
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(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, err = acmeExternalAccountBinding()
|
||||
assert.NoError(t, err)
|
||||
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 =
|
||||
;;
|
||||
;; 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)
|
||||
;; (Refer to caddy's ACME manager https://github.com/caddyserver/certmagic)
|
||||
;ACME_DIRECTORY = https
|
||||
|
||||
@@ -68,6 +68,7 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.24
|
||||
github.com/mattn/go-sqlite3 v1.14.52
|
||||
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/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/microsoft/go-mssqldb v1.11.2
|
||||
@@ -199,7 +200,6 @@ require (
|
||||
github.com/markbates/going v1.0.3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // 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/mikelolasagasti/xz v1.0.1 // indirect
|
||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||
|
||||
@@ -102,6 +102,8 @@ var (
|
||||
AcmeEmail string
|
||||
AcmeURL string
|
||||
AcmeProfile string
|
||||
AcmeEABKID string
|
||||
AcmeEABHMAC string
|
||||
AcmeCARoot string
|
||||
SSLMinimumVersion string
|
||||
SSLMaximumVersion string
|
||||
@@ -144,6 +146,11 @@ func loadServerDomainAndURL(sec ConfigSection, protocol string) {
|
||||
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) {
|
||||
sec := rootCfg.Section("server")
|
||||
AppName = rootCfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea")
|
||||
@@ -173,6 +180,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
||||
if EnableAcme {
|
||||
AcmeURL = sec.Key("ACME_URL").MustString("")
|
||||
AcmeProfile = sec.Key("ACME_PROFILE").MustString("")
|
||||
loadAcmeEABFrom(sec)
|
||||
AcmeCARoot = sec.Key("ACME_CA_ROOT").MustString("")
|
||||
|
||||
if sec.HasKey("ACME_ACCEPTTOS") {
|
||||
@@ -208,6 +216,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
||||
KeyFile = filepath.Join(CustomPath, KeyFile)
|
||||
}
|
||||
}
|
||||
|
||||
SSLMinimumVersion = sec.Key("SSL_MIN_VERSION").MustString("")
|
||||
SSLMaximumVersion = sec.Key("SSL_MAX_VERSION").MustString("")
|
||||
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