diff --git a/consul/state/state_store.go b/consul/state/state_store.go index 79150aaf4..0eb1689eb 100644 --- a/consul/state/state_store.go +++ b/consul/state/state_store.go @@ -1283,3 +1283,29 @@ func (s *StateStore) aclDeleteTxn(idx uint64, aclID string, tx *memdb.Txn) error } return nil } + +// ACLList is used to list out all of the ACLs in the state store. +func (s *StateStore) ACLList() (uint64, []*structs.ACL, error) { + tx := s.db.Txn(false) + defer tx.Abort() + + // Query all of the ACLs in the state store + acls, err := tx.Get("acls", "id") + if err != nil { + return 0, nil, fmt.Errorf("failed acl lookup: %s", err) + } + + // Go over all of the ACLs and build the response + var result []*structs.ACL + var lindex uint64 + for acl := acls.Next(); acl != nil; acl = acls.Next() { + a := acl.(*structs.ACL) + result = append(result, a) + + // Accumulate the highest index + if a.ModifyIndex > lindex { + lindex = a.ModifyIndex + } + } + return lindex, result, nil +} diff --git a/consul/state/state_store_test.go b/consul/state/state_store_test.go index 5a9369dbc..1d69d835e 100644 --- a/consul/state/state_store_test.go +++ b/consul/state/state_store_test.go @@ -1604,3 +1604,51 @@ func TestStateStore_ACLDelete(t *testing.T) { t.Fatalf("expected nil, got: %#v", result) } } + +func TestStateStore_ACLList(t *testing.T) { + s := testStateStore(t) + + // Listing when no ACLs exist returns nil + idx, res, err := s.ACLList() + if idx != 0 || res != nil || err != nil { + t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) + } + + // Insert some ACLs + acls := []*structs.ACL{ + &structs.ACL{ + ID: "acl1", + Type: structs.ACLTypeClient, + Rules: "rules1", + RaftIndex: structs.RaftIndex{ + CreateIndex: 1, + ModifyIndex: 1, + }, + }, + &structs.ACL{ + ID: "acl2", + Type: structs.ACLTypeClient, + Rules: "rules2", + RaftIndex: structs.RaftIndex{ + CreateIndex: 2, + ModifyIndex: 2, + }, + }, + } + for _, acl := range acls { + if err := s.ACLSet(acl.ModifyIndex, acl); err != nil { + t.Fatalf("err: %s", err) + } + } + + // Query the ACLs + idx, res, err = s.ACLList() + if idx != 2 { + t.Fatalf("bad index: %d", idx) + } + + // Check that the result matches + if !reflect.DeepEqual(res, acls) { + t.Fatalf("bad: %#v", res) + } +}