Merge pull request #10824 from hashicorp/dnephin/acl-token-bug

proxycfg: Use acl.tokens.default token as a default when there is no token in the registration
This commit is contained in:
Daniel Nephin 2021-08-12 17:00:35 -04:00 committed by GitHub
commit b85987ae5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 3 deletions

3
.changelog/10824.txt Normal file
View File

@ -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.
```

View File

@ -559,6 +559,7 @@ func (a *Agent) Start(ctx context.Context) error {
Health: a.rpcClientHealth, Health: a.rpcClientHealth,
Logger: a.logger.Named(logging.ProxyConfig), Logger: a.logger.Named(logging.ProxyConfig),
State: a.State, State: a.State,
Tokens: a.baseDeps.Tokens,
Source: &structs.QuerySource{ Source: &structs.QuerySource{
Datacenter: a.config.Datacenter, Datacenter: a.config.Datacenter,
Segment: a.config.SegmentName, Segment: a.config.SegmentName,

View File

@ -9,6 +9,7 @@ import (
"github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/cache"
"github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/local"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/agent/token"
"github.com/hashicorp/consul/tlsutil" "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 is the agent's logger to be used for logging logs.
Logger hclog.Logger Logger hclog.Logger
TLSConfigurator *tlsutil.Configurator 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 // IntentionDefaultAllow is set by the agent so that we can pass this
// information to proxies that need to make intention decisions on their // 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 // 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 // proxy service. Sidecar Service in the interim can do that, but we should
// validate more generally that that is always true. // validate more generally that that is always true.
err := m.ensureProxyServiceLocked(svc, m.State.ServiceToken(sid)) err := m.ensureProxyServiceLocked(svc)
if err != nil { if err != nil {
m.Logger.Error("failed to watch proxy service", m.Logger.Error("failed to watch proxy service",
"service", sid.String(), "service", sid.String(),
@ -175,10 +179,18 @@ func (m *Manager) syncState() {
} }
// ensureProxyServiceLocked adds or changes the proxy to our state. // 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() 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 ok {
if !state.Changed(ns, token) { if !state.Changed(ns, token) {
// No change // No change

View File

@ -557,3 +557,48 @@ func testGenCacheKey(req cache.Request) string {
info := req.CacheInfo() info := req.CacheInfo()
return path.Join(info.Key, info.Datacenter) 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)
}