sids_hook: read tokens from consul_hook when available (#18594)

The `sids_hook` runs for Connect sidecar/gateway tasks and gets Consul Service
Identity (SI) tokens for use by the Envoy bootstrap hook. When Workload Identity
is being used with Consul, the `consul_hook` will have already added these
tokens to the alloc hook resources. Update the `sids_hook` to use those tokens
instead and write them to the expected area of the taskdir.
This commit is contained in:
Tim Gross
2023-10-03 09:12:13 -04:00
committed by GitHub
parent df16c96a9f
commit 52ef476a72
3 changed files with 53 additions and 17 deletions

View File

@@ -16,6 +16,7 @@ import (
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
ti "github.com/hashicorp/nomad/client/allocrunner/taskrunner/interfaces"
"github.com/hashicorp/nomad/client/consul"
cstructs "github.com/hashicorp/nomad/client/structs"
"github.com/hashicorp/nomad/nomad/structs"
)
@@ -46,11 +47,12 @@ const (
)
type sidsHookConfig struct {
alloc *structs.Allocation
task *structs.Task
sidsClient consul.ServiceIdentityAPI
lifecycle ti.TaskLifecycle
logger hclog.Logger
alloc *structs.Allocation
task *structs.Task
sidsClient consul.ServiceIdentityAPI
lifecycle ti.TaskLifecycle
logger hclog.Logger
allocHookResources *cstructs.AllocHookResources
}
// Service Identities hook for managing SI tokens of connect enabled tasks.
@@ -80,17 +82,22 @@ type sidsHook struct {
// firstRun keeps track of whether the hook is being called for the first
// time (for this task) during the lifespan of the Nomad Client process.
firstRun bool
// allocHookResources gives us access to Consul tokens that may have been
// set by the consul_hook
allocHookResources *cstructs.AllocHookResources
}
func newSIDSHook(c sidsHookConfig) *sidsHook {
return &sidsHook{
alloc: c.alloc,
task: c.task,
sidsClient: c.sidsClient,
lifecycle: c.lifecycle,
derivationTimeout: sidsDerivationTimeout,
logger: c.logger.Named(sidsHookName),
firstRun: true,
alloc: c.alloc,
task: c.task,
sidsClient: c.sidsClient,
lifecycle: c.lifecycle,
derivationTimeout: sidsDerivationTimeout,
logger: c.logger.Named(sidsHookName),
firstRun: true,
allocHookResources: c.allocHookResources,
}
}
@@ -118,6 +125,32 @@ func (h *sidsHook) Prestart(
return err
}
// if we're using Workload Identities then this Connect task should already
// have a token stored under the cluster + service ID.
tokens := h.allocHookResources.GetConsulTokens()
// Find the group-level service that this task belongs to
tg := h.alloc.Job.LookupTaskGroup(h.alloc.TaskGroup)
serviceName := h.task.Kind.Value()
var serviceIdentityName string
var cluster string
for _, service := range tg.Services {
if service.Name == serviceName {
serviceIdentityName = service.MakeUniqueIdentityName()
cluster = service.Cluster
break
}
}
if cluster != "" && serviceIdentityName != "" {
if token, ok := tokens[cluster][serviceIdentityName]; ok {
if err := h.writeToken(req.TaskDir.SecretsDir, token); err != nil {
return err
}
resp.Done = true
return nil
}
}
// need to ask for a new SI token & persist it to disk
if token == "" {
if token, err = h.deriveSIToken(ctx); err != nil {

View File

@@ -142,11 +142,12 @@ func (tr *TaskRunner) initHooks() {
// with a consul token, indicating that Consul ACLs are enabled
if tr.clientConfig.ConsulConfig.Token != "" {
tr.runnerHooks = append(tr.runnerHooks, newSIDSHook(sidsHookConfig{
alloc: tr.Alloc(),
task: tr.Task(),
sidsClient: tr.siClient,
lifecycle: tr,
logger: hookLogger,
alloc: tr.Alloc(),
task: tr.Task(),
sidsClient: tr.siClient,
lifecycle: tr,
logger: hookLogger,
allocHookResources: tr.allocHookResources,
}))
}

View File

@@ -28,6 +28,7 @@ import (
regMock "github.com/hashicorp/nomad/client/serviceregistration/mock"
"github.com/hashicorp/nomad/client/serviceregistration/wrapper"
cstate "github.com/hashicorp/nomad/client/state"
cstructs "github.com/hashicorp/nomad/client/structs"
ctestutil "github.com/hashicorp/nomad/client/testutil"
"github.com/hashicorp/nomad/client/vaultclient"
"github.com/hashicorp/nomad/client/widmgr"
@@ -146,6 +147,7 @@ func testTaskRunnerConfig(t *testing.T, alloc *structs.Allocation, taskName stri
Getter: getter.TestSandbox(t),
Wranglers: proclib.MockWranglers(t),
WIDMgr: widmgr.NewWIDMgr(widsigner, alloc, logger),
AllocHookResources: cstructs.NewAllocHookResources(),
}
return conf, trCleanup