From aedc03b7ae21ac55b0de91804882f7c55a10ef1b Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Mon, 25 Sep 2023 11:24:30 -0400 Subject: [PATCH] api: add Token field to ServiceRegisterOpts (#18983) Ongoing work to support Nomad Workload Identity for authenticating with Consul will mean that Nomad's service registration sync with Consul will want to use Consul tokens scoped to individual workloads for registering services and checks. The `ServiceRegisterOpts` type in the API doesn't have an option to pass the token in, which prevent us from sharing the same Consul connection for all workloads. Add a `Token` field to match the behavior of `ServiceDeregisterOpts`. --- .changelog/18983.txt | 3 +++ api/agent.go | 7 +++++++ api/agent_test.go | 15 +++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 .changelog/18983.txt diff --git a/.changelog/18983.txt b/.changelog/18983.txt new file mode 100644 index 000000000000..8a49a850eb35 --- /dev/null +++ b/.changelog/18983.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api: added `Token` field to `ServiceRegisterOpts` type in Agent API +``` diff --git a/api/agent.go b/api/agent.go index 3c0934f675c7..8c2bf6b455c8 100644 --- a/api/agent.go +++ b/api/agent.go @@ -307,6 +307,10 @@ type ServiceRegisterOpts struct { // having to manually deregister checks. ReplaceExistingChecks bool + // Token is used to provide a per-request ACL token + // which overrides the agent's default token. + Token string + // ctx is an optional context pass through to the underlying HTTP // request layer. Use WithContext() to set the context. ctx context.Context @@ -835,6 +839,9 @@ func (a *Agent) serviceRegister(service *AgentServiceRegistration, opts ServiceR if opts.ReplaceExistingChecks { r.params.Set("replace-existing-checks", "true") } + if opts.Token != "" { + r.header.Set("X-Consul-Token", opts.Token) + } _, resp, err := a.c.doRequest(r) if err != nil { return err diff --git a/api/agent_test.go b/api/agent_test.go index 133cbd968f5e..2c359fe86e3d 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -297,6 +297,21 @@ func TestAgent_ServiceRegisterOpts_WithContextTimeout(t *testing.T) { require.True(t, errors.Is(err, context.DeadlineExceeded), "expected timeout") } +func TestAgent_ServiceRegisterOpts_Token(t *testing.T) { + c, s := makeACLClient(t) + defer s.Stop() + + reg := &AgentServiceRegistration{Name: "example"} + opts := &ServiceRegisterOpts{} + opts.Token = "invalid" + err := c.Agent().ServiceRegisterOpts(reg, *opts) + require.EqualError(t, err, "Unexpected response code: 403 (ACL not found)") + + opts.Token = "root" + err = c.Agent().ServiceRegisterOpts(reg, *opts) + require.NoError(t, err) +} + func TestAPI_NewClient_TokenFileCLIFirstPriority(t *testing.T) { os.Setenv("CONSUL_HTTP_TOKEN_FILE", "httpTokenFile.txt") os.Setenv("CONSUL_HTTP_TOKEN", "httpToken")