Skip to content

Commit

Permalink
sids_hook: read tokens from consul_hook when available (#18594)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tgross authored Oct 3, 2023
1 parent df16c96 commit 52ef476
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 17 deletions.
57 changes: 45 additions & 12 deletions client/allocrunner/taskrunner/sids_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 6 additions & 5 deletions client/allocrunner/taskrunner/task_runner_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}))
}

Expand Down
2 changes: 2 additions & 0 deletions client/allocrunner/taskrunner/task_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down

1 comment on commit 52ef476

@vercel
Copy link

@vercel vercel bot commented on 52ef476 Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.