feat: NATS mTLS pubsub implementation (#26902)

This commit is contained in:
Callum Styan
2026-07-13 11:00:02 -07:00
committed by GitHub
parent 010d96c3cd
commit ad29777cb2
22 changed files with 1776 additions and 57 deletions
+7 -1
View File
@@ -29,6 +29,7 @@ import (
agplaudit "github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/boundaryusage"
agplconnectionlog "github.com/coder/coder/v2/coderd/connectionlog"
"github.com/coder/coder/v2/coderd/cryptokeys"
"github.com/coder/coder/v2/coderd/database"
agpldbauthz "github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbtime"
@@ -806,7 +807,6 @@ type Options struct {
// Used for high availability.
ReplicaSyncUpdateInterval time.Duration
ReplicaErrorGracePeriod time.Duration
ClusterHost string // IP or hostname to reach this specific replica
DERPServerRelayAddress string
DERPServerRegionID int
@@ -1013,6 +1013,9 @@ func (api *API) updateEntitlements(ctx context.Context) error {
}
if natsPubsub, ok := api.Pubsub.(*nats.Pubsub); ok {
// Swap the real nats_ca CA cache and the replica peer fetcher
// in so the first route handshake can negotiate mTLS.
natsPubsub.SetCACache(api.AGPL.NATSCACache)
natsPubsub.SetPeerFetcher(api.replicaManager)
api.replicaManager.SetCallback("nats", natsPubsub.RefreshPeers)
}
@@ -1045,6 +1048,9 @@ func (api *API) updateEntitlements(ctx context.Context) error {
if natsPubsub, ok := api.Pubsub.(*nats.Pubsub); ok {
natsPubsub.SetPeerFetcher(nats.NopPeerFetcher{})
// Revert to the noop CA cache: new route handshakes can no
// longer mint a leaf, so the cluster mesh stops forming.
natsPubsub.SetCACache(cryptokeys.NoopSigningKeycache{})
api.replicaManager.SetCallback("nats", nil)
}
}
+6
View File
@@ -1092,6 +1092,12 @@ func TestGetCryptoKeys(t *testing.T) {
require.Error(t, err)
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode())
// The NATS cluster CA bundle contains a private key and must never be
// served to workspace proxies.
_, err = proxy.SDKClient.CryptoKeys(ctx, codersdk.CryptoKeyFeature(database.CryptoKeyFeatureNATSCA))
require.Error(t, err)
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode())
_, err = proxy.SDKClient.CryptoKeys(ctx, "invalid")
require.Error(t, err)
require.ErrorAs(t, err, &sdkErr)