consul: Deny delete anonymous or update of root policies

This commit is contained in:
Armon Dadgar 2014-08-22 14:55:09 -07:00
parent 3e4bd6a2ec
commit 9622e99861
2 changed files with 66 additions and 1 deletions

View File

@ -27,7 +27,7 @@ func (a *ACL) Apply(args *structs.ACLRequest, reply *string) error {
return fmt.Errorf(aclDisabled) return fmt.Errorf(aclDisabled)
} }
// Verify token is permitted to list ACLs // Verify token is permitted to modify ACLs
if acl, err := a.srv.resolveToken(args.Token); err != nil { if acl, err := a.srv.resolveToken(args.Token); err != nil {
return err return err
} else if acl == nil || !acl.ACLModify() { } else if acl == nil || !acl.ACLModify() {
@ -44,6 +44,11 @@ func (a *ACL) Apply(args *structs.ACLRequest, reply *string) error {
return fmt.Errorf("Invalid ACL Type") return fmt.Errorf("Invalid ACL Type")
} }
// Verify this is not a root ACL
if acl.RootACL(args.ACL.ID) != nil {
return fmt.Errorf("%s: Cannot modify root ACL", permissionDenied)
}
// Validate the rules compile // Validate the rules compile
_, err := acl.Parse(args.ACL.Rules) _, err := acl.Parse(args.ACL.Rules)
if err != nil { if err != nil {
@ -53,6 +58,8 @@ func (a *ACL) Apply(args *structs.ACLRequest, reply *string) error {
case structs.ACLDelete: case structs.ACLDelete:
if args.ACL.ID == "" { if args.ACL.ID == "" {
return fmt.Errorf("Missing ACL ID") return fmt.Errorf("Missing ACL ID")
} else if args.ACL.ID == anonymousToken {
return fmt.Errorf("%s: Cannot delete anonymous token", permissionDenied)
} }
default: default:

View File

@ -174,6 +174,64 @@ func TestACLEndpoint_Apply_Denied(t *testing.T) {
} }
} }
func TestACLEndpoint_Apply_DeleteAnon(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.ACLDatacenter = "dc1"
c.ACLMasterToken = "root"
})
defer os.RemoveAll(dir1)
defer s1.Shutdown()
client := rpcClient(t, s1)
defer client.Close()
testutil.WaitForLeader(t, client.Call, "dc1")
arg := structs.ACLRequest{
Datacenter: "dc1",
Op: structs.ACLDelete,
ACL: structs.ACL{
ID: anonymousToken,
Name: "User token",
Type: structs.ACLTypeClient,
},
WriteRequest: structs.WriteRequest{Token: "root"},
}
var out string
err := client.Call("ACL.Apply", &arg, &out)
if err == nil || !strings.Contains(err.Error(), "delete anonymous") {
t.Fatalf("err: %v", err)
}
}
func TestACLEndpoint_Apply_RootChange(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.ACLDatacenter = "dc1"
c.ACLMasterToken = "root"
})
defer os.RemoveAll(dir1)
defer s1.Shutdown()
client := rpcClient(t, s1)
defer client.Close()
testutil.WaitForLeader(t, client.Call, "dc1")
arg := structs.ACLRequest{
Datacenter: "dc1",
Op: structs.ACLSet,
ACL: structs.ACL{
ID: "manage",
Name: "User token",
Type: structs.ACLTypeClient,
},
WriteRequest: structs.WriteRequest{Token: "root"},
}
var out string
err := client.Call("ACL.Apply", &arg, &out)
if err == nil || !strings.Contains(err.Error(), "root ACL") {
t.Fatalf("err: %v", err)
}
}
func TestACLEndpoint_Get(t *testing.T) { func TestACLEndpoint_Get(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) { dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.ACLDatacenter = "dc1" c.ACLDatacenter = "dc1"