nomad: ACL endpoints enforce permissions

This commit is contained in:
Armon Dadgar
2017-08-20 20:38:22 -07:00
parent 0fcf618dfc
commit b64d7d184a
2 changed files with 160 additions and 45 deletions

View File

@@ -33,6 +33,13 @@ func (a *ACL) UpsertPolicies(args *structs.ACLPolicyUpsertRequest, reply *struct
}
defer metrics.MeasureSince([]string{"nomad", "acl", "upsert_policies"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate non-zero set of policies
if len(args.Policies) == 0 {
return fmt.Errorf("must specify as least one policy")
@@ -69,6 +76,13 @@ func (a *ACL) DeletePolicies(args *structs.ACLPolicyDeleteRequest, reply *struct
}
defer metrics.MeasureSince([]string{"nomad", "acl", "delete_policies"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate non-zero set of policies
if len(args.Names) == 0 {
return fmt.Errorf("must specify as least one policy")
@@ -95,6 +109,13 @@ func (a *ACL) ListPolicies(args *structs.ACLPolicyListRequest, reply *structs.AC
}
defer metrics.MeasureSince([]string{"nomad", "acl", "list_policies"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,
@@ -150,6 +171,13 @@ func (a *ACL) GetPolicy(args *structs.ACLPolicySpecificRequest, reply *structs.S
}
defer metrics.MeasureSince([]string{"nomad", "acl", "get_policy"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,
@@ -188,6 +216,13 @@ func (a *ACL) GetPolicies(args *structs.ACLPolicySetRequest, reply *structs.ACLP
}
defer metrics.MeasureSince([]string{"nomad", "acl", "get_policies"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,
@@ -293,6 +328,13 @@ func (a *ACL) UpsertTokens(args *structs.ACLTokenUpsertRequest, reply *structs.A
}
defer metrics.MeasureSince([]string{"nomad", "acl", "upsert_tokens"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate non-zero set of tokens
if len(args.Tokens) == 0 {
return fmt.Errorf("must specify as least one token")
@@ -371,6 +413,13 @@ func (a *ACL) DeleteTokens(args *structs.ACLTokenDeleteRequest, reply *structs.G
}
defer metrics.MeasureSince([]string{"nomad", "acl", "delete_tokens"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate non-zero set of tokens
if len(args.AccessorIDs) == 0 {
return fmt.Errorf("must specify as least one token")
@@ -397,6 +446,13 @@ func (a *ACL) ListTokens(args *structs.ACLTokenListRequest, reply *structs.ACLTo
}
defer metrics.MeasureSince([]string{"nomad", "acl", "list_tokens"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,
@@ -448,6 +504,13 @@ func (a *ACL) GetToken(args *structs.ACLTokenSpecificRequest, reply *structs.Sin
}
defer metrics.MeasureSince([]string{"nomad", "acl", "get_token"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,
@@ -486,6 +549,13 @@ func (a *ACL) GetTokens(args *structs.ACLTokenSetRequest, reply *structs.ACLToke
}
defer metrics.MeasureSince([]string{"nomad", "acl", "get_tokens"}, time.Now())
// Check management level permissions
if acl, err := a.srv.resolveToken(args.SecretID); err != nil {
return err
} else if acl == nil || !acl.IsManagement() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,

View File

@@ -14,7 +14,7 @@ import (
func TestACLEndpoint_GetPolicy(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -25,8 +25,11 @@ func TestACLEndpoint_GetPolicy(t *testing.T) {
// Lookup the policy
get := &structs.ACLPolicySpecificRequest{
Name: policy.Name,
QueryOptions: structs.QueryOptions{Region: "global"},
Name: policy.Name,
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.SingleACLPolicyResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp); err != nil {
@@ -46,7 +49,7 @@ func TestACLEndpoint_GetPolicy(t *testing.T) {
func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -78,6 +81,7 @@ func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 150,
SecretID: root.SecretID,
},
}
var resp structs.SingleACLPolicyResponse
@@ -124,7 +128,7 @@ func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) {
func TestACLEndpoint_GetPolicies(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -136,8 +140,11 @@ func TestACLEndpoint_GetPolicies(t *testing.T) {
// Lookup the policy
get := &structs.ACLPolicySetRequest{
Names: []string{policy.Name, policy2.Name},
QueryOptions: structs.QueryOptions{Region: "global"},
Names: []string{policy.Name, policy2.Name},
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.ACLPolicySetResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil {
@@ -160,7 +167,7 @@ func TestACLEndpoint_GetPolicies(t *testing.T) {
func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -192,6 +199,7 @@ func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 150,
SecretID: root.SecretID,
},
}
var resp structs.ACLPolicySetResponse
@@ -238,7 +246,7 @@ func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) {
func TestACLEndpoint_ListPolicies(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -253,7 +261,10 @@ func TestACLEndpoint_ListPolicies(t *testing.T) {
// Lookup the policies
get := &structs.ACLPolicyListRequest{
QueryOptions: structs.QueryOptions{Region: "global"},
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.ACLPolicyListResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp); err != nil {
@@ -265,8 +276,9 @@ func TestACLEndpoint_ListPolicies(t *testing.T) {
// Lookup the policies by prefix
get = &structs.ACLPolicyListRequest{
QueryOptions: structs.QueryOptions{
Region: "global",
Prefix: "aaaabb",
Region: "global",
Prefix: "aaaabb",
SecretID: root.SecretID,
},
}
var resp2 structs.ACLPolicyListResponse
@@ -279,7 +291,7 @@ func TestACLEndpoint_ListPolicies(t *testing.T) {
func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -299,6 +311,7 @@ func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 1,
SecretID: root.SecretID,
},
}
start := time.Now()
@@ -338,7 +351,7 @@ func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) {
func TestACLEndpoint_DeletePolicies(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -349,8 +362,11 @@ func TestACLEndpoint_DeletePolicies(t *testing.T) {
// Lookup the policies
req := &structs.ACLPolicyDeleteRequest{
Names: []string{p1.Name},
WriteRequest: structs.WriteRequest{Region: "global"},
Names: []string{p1.Name},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.GenericResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.DeletePolicies", req, &resp); err != nil {
@@ -361,7 +377,7 @@ func TestACLEndpoint_DeletePolicies(t *testing.T) {
func TestACLEndpoint_UpsertPolicies(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -371,8 +387,11 @@ func TestACLEndpoint_UpsertPolicies(t *testing.T) {
// Lookup the policies
req := &structs.ACLPolicyUpsertRequest{
Policies: []*structs.ACLPolicy{p1},
WriteRequest: structs.WriteRequest{Region: "global"},
Policies: []*structs.ACLPolicy{p1},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.GenericResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp); err != nil {
@@ -388,7 +407,7 @@ func TestACLEndpoint_UpsertPolicies(t *testing.T) {
func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -399,8 +418,11 @@ func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) {
// Lookup the policies
req := &structs.ACLPolicyUpsertRequest{
Policies: []*structs.ACLPolicy{p1},
WriteRequest: structs.WriteRequest{Region: "global"},
Policies: []*structs.ACLPolicy{p1},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.GenericResponse
err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp)
@@ -412,7 +434,7 @@ func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) {
func TestACLEndpoint_GetToken(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -423,8 +445,11 @@ func TestACLEndpoint_GetToken(t *testing.T) {
// Lookup the token
get := &structs.ACLTokenSpecificRequest{
AccessorID: token.AccessorID,
QueryOptions: structs.QueryOptions{Region: "global"},
AccessorID: token.AccessorID,
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.SingleACLTokenResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp); err != nil {
@@ -444,7 +469,7 @@ func TestACLEndpoint_GetToken(t *testing.T) {
func TestACLEndpoint_GetToken_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -476,6 +501,7 @@ func TestACLEndpoint_GetToken_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 150,
SecretID: root.SecretID,
},
}
var resp structs.SingleACLTokenResponse
@@ -522,7 +548,7 @@ func TestACLEndpoint_GetToken_Blocking(t *testing.T) {
func TestACLEndpoint_GetTokens(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -534,8 +560,11 @@ func TestACLEndpoint_GetTokens(t *testing.T) {
// Lookup the token
get := &structs.ACLTokenSetRequest{
AccessorIDS: []string{token.AccessorID, token2.AccessorID},
QueryOptions: structs.QueryOptions{Region: "global"},
AccessorIDS: []string{token.AccessorID, token2.AccessorID},
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.ACLTokenSetResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", get, &resp); err != nil {
@@ -557,7 +586,7 @@ func TestACLEndpoint_GetTokens(t *testing.T) {
func TestACLEndpoint_GetTokens_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -589,6 +618,7 @@ func TestACLEndpoint_GetTokens_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 150,
SecretID: root.SecretID,
},
}
var resp structs.ACLTokenSetResponse
@@ -635,7 +665,7 @@ func TestACLEndpoint_GetTokens_Blocking(t *testing.T) {
func TestACLEndpoint_ListTokens(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -651,7 +681,10 @@ func TestACLEndpoint_ListTokens(t *testing.T) {
// Lookup the tokens
get := &structs.ACLTokenListRequest{
QueryOptions: structs.QueryOptions{Region: "global"},
QueryOptions: structs.QueryOptions{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.ACLTokenListResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp); err != nil {
@@ -663,8 +696,9 @@ func TestACLEndpoint_ListTokens(t *testing.T) {
// Lookup the tokens by prefix
get = &structs.ACLTokenListRequest{
QueryOptions: structs.QueryOptions{
Region: "global",
Prefix: "aaaabb",
Region: "global",
Prefix: "aaaabb",
SecretID: root.SecretID,
},
}
var resp2 structs.ACLTokenListResponse
@@ -678,7 +712,8 @@ func TestACLEndpoint_ListTokens(t *testing.T) {
get = &structs.ACLTokenListRequest{
GlobalOnly: true,
QueryOptions: structs.QueryOptions{
Region: "global",
Region: "global",
SecretID: root.SecretID,
},
}
var resp3 structs.ACLTokenListResponse
@@ -691,7 +726,7 @@ func TestACLEndpoint_ListTokens(t *testing.T) {
func TestACLEndpoint_ListTokens_Blocking(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
state := s1.fsm.State()
codec := rpcClient(t, s1)
@@ -711,6 +746,7 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) {
QueryOptions: structs.QueryOptions{
Region: "global",
MinQueryIndex: 2,
SecretID: root.SecretID,
},
}
start := time.Now()
@@ -750,7 +786,7 @@ func TestACLEndpoint_ListTokens_Blocking(t *testing.T) {
func TestACLEndpoint_DeleteTokens(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -761,8 +797,11 @@ func TestACLEndpoint_DeleteTokens(t *testing.T) {
// Lookup the tokens
req := &structs.ACLTokenDeleteRequest{
AccessorIDs: []string{p1.AccessorID},
WriteRequest: structs.WriteRequest{Region: "global"},
AccessorIDs: []string{p1.AccessorID},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.GenericResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.DeleteTokens", req, &resp); err != nil {
@@ -808,7 +847,7 @@ func TestACLEndpoint_Bootstrap(t *testing.T) {
func TestACLEndpoint_UpsertTokens(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -819,8 +858,11 @@ func TestACLEndpoint_UpsertTokens(t *testing.T) {
// Lookup the tokens
req := &structs.ACLTokenUpsertRequest{
Tokens: []*structs.ACLToken{p1},
WriteRequest: structs.WriteRequest{Region: "global"},
Tokens: []*structs.ACLToken{p1},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.ACLTokenUpsertResponse
if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp); err != nil {
@@ -861,7 +903,7 @@ func TestACLEndpoint_UpsertTokens(t *testing.T) {
func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) {
t.Parallel()
s1, _ := testACLServer(t, nil)
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
@@ -872,8 +914,11 @@ func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) {
// Lookup the tokens
req := &structs.ACLTokenUpsertRequest{
Tokens: []*structs.ACLToken{p1},
WriteRequest: structs.WriteRequest{Region: "global"},
Tokens: []*structs.ACLToken{p1},
WriteRequest: structs.WriteRequest{
Region: "global",
SecretID: root.SecretID,
},
}
var resp structs.GenericResponse
err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp)