diff --git a/.changelog/10824.txt b/.changelog/10824.txt new file mode 100644 index 000000000..53da4296b --- /dev/null +++ b/.changelog/10824.txt @@ -0,0 +1,3 @@ +```release-note:bug +acl: fixes a bug that prevented the default user token from being used to authorize service registration for connect proxies. +``` diff --git a/agent/agent.go b/agent/agent.go index 8dc6c1f0a..87c6d3a22 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -559,6 +559,7 @@ func (a *Agent) Start(ctx context.Context) error { Health: a.rpcClientHealth, Logger: a.logger.Named(logging.ProxyConfig), State: a.State, + Tokens: a.baseDeps.Tokens, Source: &structs.QuerySource{ Datacenter: a.config.Datacenter, Segment: a.config.SegmentName, diff --git a/agent/proxycfg/manager.go b/agent/proxycfg/manager.go index 922e73ed5..aca122b0c 100644 --- a/agent/proxycfg/manager.go +++ b/agent/proxycfg/manager.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/tlsutil" ) @@ -73,6 +74,9 @@ type ManagerConfig struct { // logger is the agent's logger to be used for logging logs. Logger hclog.Logger TLSConfigurator *tlsutil.Configurator + // Tokens configured on the local agent. Used to look up the agent token if + // a service is registered without a token. + Tokens *token.Store // IntentionDefaultAllow is set by the agent so that we can pass this // information to proxies that need to make intention decisions on their @@ -156,7 +160,7 @@ func (m *Manager) syncState() { // know that so we'd need to set it here if not during registration of the // proxy service. Sidecar Service in the interim can do that, but we should // validate more generally that that is always true. - err := m.ensureProxyServiceLocked(svc, m.State.ServiceToken(sid)) + err := m.ensureProxyServiceLocked(svc) if err != nil { m.Logger.Error("failed to watch proxy service", "service", sid.String(), @@ -175,10 +179,18 @@ func (m *Manager) syncState() { } // ensureProxyServiceLocked adds or changes the proxy to our state. -func (m *Manager) ensureProxyServiceLocked(ns *structs.NodeService, token string) error { +func (m *Manager) ensureProxyServiceLocked(ns *structs.NodeService) error { sid := ns.CompoundServiceID() - state, ok := m.proxies[sid] + // Retrieve the token used to register the service, or fallback to the + // default user token. This token is expected to match the token used in + // the xDS request for this data. + token := m.State.ServiceToken(sid) + if token == "" { + token = m.Tokens.UserToken() + } + + state, ok := m.proxies[sid] if ok { if !state.Changed(ns, token) { // No change diff --git a/agent/proxycfg/manager_test.go b/agent/proxycfg/manager_test.go index 658bad43b..8cd19a513 100644 --- a/agent/proxycfg/manager_test.go +++ b/agent/proxycfg/manager_test.go @@ -557,3 +557,48 @@ func testGenCacheKey(req cache.Request) string { info := req.CacheInfo() return path.Join(info.Key, info.Datacenter) } + +func TestManager_SyncState_DefaultToken(t *testing.T) { + types := NewTestCacheTypes(t) + c := TestCacheWithTypes(t, types) + logger := testutil.Logger(t) + tokens := new(token.Store) + tokens.UpdateUserToken("default-token", token.TokenSourceConfig) + + state := local.NewState(local.Config{}, logger, tokens) + state.TriggerSyncChanges = func() {} + + m, err := NewManager(ManagerConfig{ + Cache: c, + Health: &health.Client{Cache: c, CacheName: cachetype.HealthServicesName}, + State: state, + Tokens: tokens, + Source: &structs.QuerySource{Datacenter: "dc1"}, + Logger: logger, + }) + require.NoError(t, err) + defer m.Close() + + srv := &structs.NodeService{ + Kind: structs.ServiceKindConnectProxy, + ID: "web-sidecar-proxy", + Service: "web-sidecar-proxy", + Port: 9999, + Meta: map[string]string{}, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceID: "web", + DestinationServiceName: "web", + LocalServiceAddress: "127.0.0.1", + LocalServicePort: 8080, + Config: map[string]interface{}{ + "foo": "bar", + }, + }, + } + + err = state.AddServiceWithChecks(srv, nil, "") + require.NoError(t, err) + m.syncState() + + require.Equal(t, "default-token", m.proxies[srv.CompoundServiceID()].serviceInstance.token) +}