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`.
This commit is contained in:
Tim Gross 2023-09-25 11:24:30 -04:00 committed by GitHub
parent 58d06175ab
commit aedc03b7ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 0 deletions

3
.changelog/18983.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
api: added `Token` field to `ServiceRegisterOpts` type in Agent API
```

View File

@ -307,6 +307,10 @@ type ServiceRegisterOpts struct {
// having to manually deregister checks. // having to manually deregister checks.
ReplaceExistingChecks bool 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 // ctx is an optional context pass through to the underlying HTTP
// request layer. Use WithContext() to set the context. // request layer. Use WithContext() to set the context.
ctx context.Context ctx context.Context
@ -835,6 +839,9 @@ func (a *Agent) serviceRegister(service *AgentServiceRegistration, opts ServiceR
if opts.ReplaceExistingChecks { if opts.ReplaceExistingChecks {
r.params.Set("replace-existing-checks", "true") r.params.Set("replace-existing-checks", "true")
} }
if opts.Token != "" {
r.header.Set("X-Consul-Token", opts.Token)
}
_, resp, err := a.c.doRequest(r) _, resp, err := a.c.doRequest(r)
if err != nil { if err != nil {
return err return err

View File

@ -297,6 +297,21 @@ func TestAgent_ServiceRegisterOpts_WithContextTimeout(t *testing.T) {
require.True(t, errors.Is(err, context.DeadlineExceeded), "expected timeout") 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) { func TestAPI_NewClient_TokenFileCLIFirstPriority(t *testing.T) {
os.Setenv("CONSUL_HTTP_TOKEN_FILE", "httpTokenFile.txt") os.Setenv("CONSUL_HTTP_TOKEN_FILE", "httpTokenFile.txt")
os.Setenv("CONSUL_HTTP_TOKEN", "httpToken") os.Setenv("CONSUL_HTTP_TOKEN", "httpToken")