feature/acme, ipn/ipnlocal: start moving ACME/cert state into an extension
The ACME serialization mutex (acmeMu) was a package-level global, and
several ACME-related fields lived on LocalBackend even though the
cert code is conditional and not linked into every binary. With
multiple tsnet.Servers in one process (each its own LocalBackend),
a process-wide acmeMu also serialized unrelated backends.
Introduce a new feature/acme extension that owns the per-LocalBackend
ACME/cert state in an ipnlocal.CertState value:
- acmeMu, renewMu, renewCertAt (previously package globals)
- pendingACMETLSALPNCerts, pendingCertDomains{,Mu},
getCertForTest, certRefreshCancel (previously LocalBackend
fields, only meaningful when ACME was compiled in)
ipnlocal/cert.go now reaches the state through b.certState(), which
is routed by a feature.Hook installed at init by feature/acme. The
CertState type lives in ipnlocal so cert.go can access its fields
directly without a method explosion; the extension in feature/acme
constructs and owns it.
This is a baby step. The end goal is for the entire cert/ACME code
to live in feature/acme, with ipnlocal only retaining whatever thin
hooks the rest of LocalBackend needs to call into it. The current
split (CertState and most of cert.go in ipnlocal, extension wrapper
in feature/acme) is a deliberately temporary middle ground that
keeps this PR small while making the next moves mechanical.
The package is named feature/acme to match the existing HasACME /
ts_omit_acme naming. condregister/maybe_acme.go wires it in for
non-js builds.
Updates #12614
Updates #20248
Updates #20249
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I520909f24ad11a9622ef33c2290fe36ad44d6f71
This commit is contained in:
committed by
Brad Fitzpatrick
parent
8379d5955f
commit
f5eac39ea7
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !js && !ts_omit_acme
|
||||
|
||||
package ipnlocal
|
||||
|
||||
import "sync"
|
||||
|
||||
// In tests we can't import feature/acme (it would import this package
|
||||
// and form a cycle), so the real cert extension is never registered.
|
||||
// Install a default [hookCertState] provider here that lazily creates
|
||||
// a [CertState] per [LocalBackend].
|
||||
//
|
||||
// Tests that want different behavior can use
|
||||
// [feature.Hook.SetForTest] to override this hook for the duration
|
||||
// of the test.
|
||||
func init() {
|
||||
if hookCertState.IsSet() {
|
||||
return
|
||||
}
|
||||
var (
|
||||
mu sync.Mutex
|
||||
states = map[*LocalBackend]*CertState{}
|
||||
)
|
||||
hookCertState.Set(func(b *LocalBackend) *CertState {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if s, ok := states[b]; ok {
|
||||
return s
|
||||
}
|
||||
s := new(CertState)
|
||||
states[b] = s
|
||||
return s
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user