From ab5ce9b1a70fb4fa85789c5390bcb1763c24ac0d Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Sun, 20 Aug 2017 19:59:25 -0700 Subject: [PATCH] nomad: ACL endpoints check support enabled and redirect to authority --- command/agent/acl_endpoint_test.go | 26 +++++++------ command/agent/http_test.go | 12 ++++++ command/agent/testagent.go | 15 ++++++++ nomad/acl_endpoint.go | 56 +++++++++++++++++++++++++++ nomad/acl_endpoint_test.go | 62 +++++++++++++++--------------- nomad/mock/mock.go | 13 +++++++ nomad/server_test.go | 16 ++++++++ 7 files changed, 159 insertions(+), 41 deletions(-) diff --git a/command/agent/acl_endpoint_test.go b/command/agent/acl_endpoint_test.go index 6bb66a753..980648c21 100644 --- a/command/agent/acl_endpoint_test.go +++ b/command/agent/acl_endpoint_test.go @@ -12,7 +12,7 @@ import ( func TestHTTP_ACLPolicyList(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLPolicy() p2 := mock.ACLPolicy() p3 := mock.ACLPolicy() @@ -59,7 +59,7 @@ func TestHTTP_ACLPolicyList(t *testing.T) { func TestHTTP_ACLPolicyQuery(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLPolicy() args := structs.ACLPolicyUpsertRequest{ Policies: []*structs.ACLPolicy{p1}, @@ -104,7 +104,7 @@ func TestHTTP_ACLPolicyQuery(t *testing.T) { func TestHTTP_ACLPolicyCreate(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { // Make the HTTP request p1 := mock.ACLPolicy() buf := encodeReq(p1) @@ -138,7 +138,7 @@ func TestHTTP_ACLPolicyCreate(t *testing.T) { func TestHTTP_ACLPolicyDelete(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLPolicy() args := structs.ACLPolicyUpsertRequest{ Policies: []*structs.ACLPolicy{p1}, @@ -176,7 +176,11 @@ func TestHTTP_ACLPolicyDelete(t *testing.T) { func TestHTTP_ACLTokenBootstrap(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + conf := func(c *Config) { + c.ACL.Enabled = true + c.ACL.PolicyTTL = 0 // Special flag to disable auto-bootstrap + } + httpTest(t, conf, func(s *TestAgent) { // Make the HTTP request req, err := http.NewRequest("PUT", "/v1/acl/bootstrap", nil) if err != nil { @@ -204,7 +208,7 @@ func TestHTTP_ACLTokenBootstrap(t *testing.T) { func TestHTTP_ACLTokenList(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLToken() p1.AccessorID = "" p2 := mock.ACLToken() @@ -244,9 +248,9 @@ func TestHTTP_ACLTokenList(t *testing.T) { t.Fatalf("missing last contact") } - // Check the output + // Check the output (includes boostrap token) n := obj.([]*structs.ACLTokenListStub) - if len(n) != 3 { + if len(n) != 4 { t.Fatalf("bad: %#v", n) } }) @@ -254,7 +258,7 @@ func TestHTTP_ACLTokenList(t *testing.T) { func TestHTTP_ACLTokenQuery(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLToken() p1.AccessorID = "" args := structs.ACLTokenUpsertRequest{ @@ -299,7 +303,7 @@ func TestHTTP_ACLTokenQuery(t *testing.T) { func TestHTTP_ACLTokenCreate(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { // Make the HTTP request p1 := mock.ACLToken() p1.AccessorID = "" @@ -332,7 +336,7 @@ func TestHTTP_ACLTokenCreate(t *testing.T) { func TestHTTP_ACLTokenDelete(t *testing.T) { t.Parallel() - httpTest(t, nil, func(s *TestAgent) { + httpACLTest(t, nil, func(s *TestAgent) { p1 := mock.ACLToken() p1.AccessorID = "" args := structs.ACLTokenUpsertRequest{ diff --git a/command/agent/http_test.go b/command/agent/http_test.go index dd4e69c1e..faecc93f2 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -496,6 +496,18 @@ func httpTest(t testing.TB, cb func(c *Config), f func(srv *TestAgent)) { f(s) } +func httpACLTest(t testing.TB, cb func(c *Config), f func(srv *TestAgent)) { + s := makeHTTPServer(t, func(c *Config) { + c.ACL.Enabled = true + if cb != nil { + cb(c) + } + }) + defer s.Shutdown() + testutil.WaitForLeader(t, s.Agent.RPC) + f(s) +} + func encodeReq(obj interface{}) io.ReadCloser { buf := bytes.NewBuffer(nil) enc := json.NewEncoder(buf) diff --git a/command/agent/testagent.go b/command/agent/testagent.go index 0cb04bc70..2396a4cf4 100644 --- a/command/agent/testagent.go +++ b/command/agent/testagent.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/client/fingerprint" "github.com/hashicorp/nomad/nomad" + "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" sconfig "github.com/hashicorp/nomad/nomad/structs/config" "github.com/hashicorp/nomad/testutil" @@ -66,6 +67,9 @@ type TestAgent struct { // Agent is the embedded Nomad agent. // It is valid after Start(). *Agent + + // Token is auto-bootstrapped if ACLs are enabled + Token *structs.ACLToken } // NewTestAgent returns a started agent with the given name and @@ -164,6 +168,17 @@ func (a *TestAgent) Start() *TestAgent { panic(fmt.Sprintf("failed OK response: %v", err)) }) } + + // Check if ACLs enabled. Use special value of PolicyTTL 0s + // to do a bypass of this step. This is so we can test bootstrap + // without having to pass down a special flag. + if a.Config.ACL.Enabled && a.Config.Server.Enabled && a.Config.ACL.PolicyTTL != 0 { + a.Token = mock.ACLManagementToken() + state := a.Agent.server.State() + if err := state.BootstrapACLTokens(1, a.Token); err != nil { + panic(fmt.Sprintf("token bootstrap failed: %v", err)) + } + } return a } diff --git a/nomad/acl_endpoint.go b/nomad/acl_endpoint.go index 9b1180ab3..9b7bbdaa7 100644 --- a/nomad/acl_endpoint.go +++ b/nomad/acl_endpoint.go @@ -10,6 +10,11 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) +var ( + // aclDisabled is returned when an ACL endpoint is hit but ACLs are not enabled + aclDisabled = fmt.Errorf("ACL support disabled") +) + // ACL endpoint is used for manipulating ACL tokens and policies type ACL struct { srv *Server @@ -17,6 +22,12 @@ type ACL struct { // UpsertPolicies is used to create or update a set of policies func (a *ACL) UpsertPolicies(args *structs.ACLPolicyUpsertRequest, reply *structs.GenericResponse) error { + // Ensure ACLs are enabled, and always flow modification requests to the authoritative region + if !a.srv.config.ACLEnabled { + return aclDisabled + } + args.Region = a.srv.config.AuthoritativeRegion + if done, err := a.srv.forward("ACL.UpsertPolicies", args, args, reply); done { return err } @@ -47,6 +58,12 @@ func (a *ACL) UpsertPolicies(args *structs.ACLPolicyUpsertRequest, reply *struct // DeletePolicies is used to delete policies func (a *ACL) DeletePolicies(args *structs.ACLPolicyDeleteRequest, reply *structs.GenericResponse) error { + // Ensure ACLs are enabled, and always flow modification requests to the authoritative region + if !a.srv.config.ACLEnabled { + return aclDisabled + } + args.Region = a.srv.config.AuthoritativeRegion + if done, err := a.srv.forward("ACL.DeletePolicies", args, args, reply); done { return err } @@ -70,6 +87,9 @@ func (a *ACL) DeletePolicies(args *structs.ACLPolicyDeleteRequest, reply *struct // ListPolicies is used to list the policies func (a *ACL) ListPolicies(args *structs.ACLPolicyListRequest, reply *structs.ACLPolicyListResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.ListPolicies", args, args, reply); done { return err } @@ -122,6 +142,9 @@ func (a *ACL) ListPolicies(args *structs.ACLPolicyListRequest, reply *structs.AC // GetPolicy is used to get a specific policy func (a *ACL) GetPolicy(args *structs.ACLPolicySpecificRequest, reply *structs.SingleACLPolicyResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.GetPolicy", args, args, reply); done { return err } @@ -157,6 +180,9 @@ func (a *ACL) GetPolicy(args *structs.ACLPolicySpecificRequest, reply *structs.S // GetPolicies is used to get a set of policies func (a *ACL) GetPolicies(args *structs.ACLPolicySetRequest, reply *structs.ACLPolicySetResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.GetPolicies", args, args, reply); done { return err } @@ -194,6 +220,12 @@ func (a *ACL) GetPolicies(args *structs.ACLPolicySetRequest, reply *structs.ACLP // Bootstrap is used to bootstrap the initial token func (a *ACL) Bootstrap(args *structs.ACLTokenBootstrapRequest, reply *structs.ACLTokenUpsertResponse) error { + // Ensure ACLs are enabled, and always flow modification requests to the authoritative region + if !a.srv.config.ACLEnabled { + return aclDisabled + } + args.Region = a.srv.config.AuthoritativeRegion + if done, err := a.srv.forward("ACL.Bootstrap", args, args, reply); done { return err } @@ -250,6 +282,12 @@ func (a *ACL) Bootstrap(args *structs.ACLTokenBootstrapRequest, reply *structs.A // UpsertTokens is used to create or update a set of tokens func (a *ACL) UpsertTokens(args *structs.ACLTokenUpsertRequest, reply *structs.ACLTokenUpsertResponse) error { + // Ensure ACLs are enabled, and always flow modification requests to the authoritative region + if !a.srv.config.ACLEnabled { + return aclDisabled + } + args.Region = a.srv.config.AuthoritativeRegion + if done, err := a.srv.forward("ACL.UpsertTokens", args, args, reply); done { return err } @@ -322,6 +360,12 @@ func (a *ACL) UpsertTokens(args *structs.ACLTokenUpsertRequest, reply *structs.A // DeleteTokens is used to delete tokens func (a *ACL) DeleteTokens(args *structs.ACLTokenDeleteRequest, reply *structs.GenericResponse) error { + // Ensure ACLs are enabled, and always flow modification requests to the authoritative region + if !a.srv.config.ACLEnabled { + return aclDisabled + } + args.Region = a.srv.config.AuthoritativeRegion + if done, err := a.srv.forward("ACL.DeleteTokens", args, args, reply); done { return err } @@ -345,6 +389,9 @@ func (a *ACL) DeleteTokens(args *structs.ACLTokenDeleteRequest, reply *structs.G // ListTokens is used to list the tokens func (a *ACL) ListTokens(args *structs.ACLTokenListRequest, reply *structs.ACLTokenListResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.ListTokens", args, args, reply); done { return err } @@ -393,6 +440,9 @@ func (a *ACL) ListTokens(args *structs.ACLTokenListRequest, reply *structs.ACLTo // GetToken is used to get a specific token func (a *ACL) GetToken(args *structs.ACLTokenSpecificRequest, reply *structs.SingleACLTokenResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.GetToken", args, args, reply); done { return err } @@ -428,6 +478,9 @@ func (a *ACL) GetToken(args *structs.ACLTokenSpecificRequest, reply *structs.Sin // GetTokens is used to get a set of token func (a *ACL) GetTokens(args *structs.ACLTokenSetRequest, reply *structs.ACLTokenSetResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.GetTokens", args, args, reply); done { return err } @@ -465,6 +518,9 @@ func (a *ACL) GetTokens(args *structs.ACLTokenSetRequest, reply *structs.ACLToke // ResolveToken is used to lookup a specific token by a secret ID. This is used for enforcing ACLs by clients. func (a *ACL) ResolveToken(args *structs.ResolveACLTokenRequest, reply *structs.ResolveACLTokenResponse) error { + if !a.srv.config.ACLEnabled { + return aclDisabled + } if done, err := a.srv.forward("ACL.ResolveToken", args, args, reply); done { return err } diff --git a/nomad/acl_endpoint_test.go b/nomad/acl_endpoint_test.go index 077d95de5..51832246b 100644 --- a/nomad/acl_endpoint_test.go +++ b/nomad/acl_endpoint_test.go @@ -14,7 +14,7 @@ import ( func TestACLEndpoint_GetPolicy(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -46,7 +46,7 @@ func TestACLEndpoint_GetPolicy(t *testing.T) { func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -124,7 +124,7 @@ func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) { func TestACLEndpoint_GetPolicies(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -160,7 +160,7 @@ func TestACLEndpoint_GetPolicies(t *testing.T) { func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -238,7 +238,7 @@ func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) { func TestACLEndpoint_ListPolicies(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -279,7 +279,7 @@ func TestACLEndpoint_ListPolicies(t *testing.T) { func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -338,7 +338,7 @@ func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) { func TestACLEndpoint_DeletePolicies(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -361,7 +361,7 @@ func TestACLEndpoint_DeletePolicies(t *testing.T) { func TestACLEndpoint_UpsertPolicies(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -388,7 +388,7 @@ func TestACLEndpoint_UpsertPolicies(t *testing.T) { func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -412,7 +412,7 @@ func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) { func TestACLEndpoint_GetToken(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -444,7 +444,7 @@ func TestACLEndpoint_GetToken(t *testing.T) { func TestACLEndpoint_GetToken_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -522,7 +522,7 @@ func TestACLEndpoint_GetToken_Blocking(t *testing.T) { func TestACLEndpoint_GetTokens(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -557,7 +557,7 @@ func TestACLEndpoint_GetTokens(t *testing.T) { func TestACLEndpoint_GetTokens_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -635,7 +635,7 @@ func TestACLEndpoint_GetTokens_Blocking(t *testing.T) { func TestACLEndpoint_ListTokens(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -658,7 +658,7 @@ func TestACLEndpoint_ListTokens(t *testing.T) { t.Fatalf("err: %v", err) } assert.Equal(t, uint64(1000), resp.Index) - assert.Equal(t, 2, len(resp.Tokens)) + assert.Equal(t, 3, len(resp.Tokens)) // Lookup the tokens by prefix get = &structs.ACLTokenListRequest{ @@ -686,12 +686,12 @@ func TestACLEndpoint_ListTokens(t *testing.T) { t.Fatalf("err: %v", err) } assert.Equal(t, uint64(1000), resp3.Index) - assert.Equal(t, 1, len(resp3.Tokens)) + assert.Equal(t, 2, len(resp3.Tokens)) } func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() state := s1.fsm.State() codec := rpcClient(t, s1) @@ -702,7 +702,7 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { // Upsert eval triggers watches time.AfterFunc(100*time.Millisecond, func() { - if err := state.UpsertACLTokens(2, []*structs.ACLToken{token}); err != nil { + if err := state.UpsertACLTokens(3, []*structs.ACLToken{token}); err != nil { t.Fatalf("err: %v", err) } }) @@ -710,7 +710,7 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { req := &structs.ACLTokenListRequest{ QueryOptions: structs.QueryOptions{ Region: "global", - MinQueryIndex: 1, + MinQueryIndex: 2, }, } start := time.Now() @@ -722,19 +722,19 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { if elapsed := time.Since(start); elapsed < 100*time.Millisecond { t.Fatalf("should block (returned in %s) %#v", elapsed, resp) } - assert.Equal(t, uint64(2), resp.Index) - if len(resp.Tokens) != 1 || resp.Tokens[0].AccessorID != token.AccessorID { + assert.Equal(t, uint64(3), resp.Index) + if len(resp.Tokens) != 2 { t.Fatalf("bad: %#v", resp.Tokens) } // Eval deletion triggers watches time.AfterFunc(100*time.Millisecond, func() { - if err := state.DeleteACLTokens(3, []string{token.AccessorID}); err != nil { + if err := state.DeleteACLTokens(4, []string{token.AccessorID}); err != nil { t.Fatalf("err: %v", err) } }) - req.MinQueryIndex = 2 + req.MinQueryIndex = 3 start = time.Now() var resp2 structs.ACLTokenListResponse if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", req, &resp2); err != nil { @@ -744,13 +744,13 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) { if elapsed := time.Since(start); elapsed < 100*time.Millisecond { t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) } - assert.Equal(t, uint64(3), resp2.Index) - assert.Equal(t, 0, len(resp2.Tokens)) + assert.Equal(t, uint64(4), resp2.Index) + assert.Equal(t, 1, len(resp2.Tokens)) } func TestACLEndpoint_DeleteTokens(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -773,7 +773,9 @@ func TestACLEndpoint_DeleteTokens(t *testing.T) { func TestACLEndpoint_Bootstrap(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1 := testServer(t, func(c *Config) { + c.ACLEnabled = true + }) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -806,7 +808,7 @@ func TestACLEndpoint_Bootstrap(t *testing.T) { func TestACLEndpoint_UpsertTokens(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -859,7 +861,7 @@ func TestACLEndpoint_UpsertTokens(t *testing.T) { func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) @@ -883,7 +885,7 @@ func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) { func TestACLEndpoint_ResolveToken(t *testing.T) { t.Parallel() - s1 := testServer(t, nil) + s1, _ := testACLServer(t, nil) defer s1.Shutdown() codec := rpcClient(t, s1) testutil.WaitForLeader(t, s1.RPC) diff --git a/nomad/mock/mock.go b/nomad/mock/mock.go index 8f2a53b71..ca22302f2 100644 --- a/nomad/mock/mock.go +++ b/nomad/mock/mock.go @@ -371,3 +371,16 @@ func ACLToken() *structs.ACLToken { ModifyIndex: 20, } } + +func ACLManagementToken() *structs.ACLToken { + return &structs.ACLToken{ + AccessorID: structs.GenerateUUID(), + SecretID: structs.GenerateUUID(), + Name: "management " + structs.GenerateUUID(), + Type: "management", + Global: true, + CreateTime: time.Now().UTC(), + CreateIndex: 10, + ModifyIndex: 20, + } +} diff --git a/nomad/server_test.go b/nomad/server_test.go index 56726e2a4..70f809260 100644 --- a/nomad/server_test.go +++ b/nomad/server_test.go @@ -13,6 +13,7 @@ import ( "time" "github.com/hashicorp/nomad/command/agent/consul" + "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" "github.com/hashicorp/nomad/testutil" @@ -38,6 +39,21 @@ func tmpDir(t *testing.T) string { return dir } +func testACLServer(t *testing.T, cb func(*Config)) (*Server, *structs.ACLToken) { + server := testServer(t, func(c *Config) { + c.ACLEnabled = true + if cb != nil { + cb(c) + } + }) + token := mock.ACLManagementToken() + err := server.State().BootstrapACLTokens(1, token) + if err != nil { + t.Fatalf("failed to bootstrap ACL token: %v", err) + } + return server, token +} + func testServer(t *testing.T, cb func(*Config)) *Server { // Setup the default settings config := DefaultConfig()