diff --git a/agent/consul/state/acl_oss.go b/agent/consul/state/acl_oss.go index 36e907b1a..ea4e47343 100644 --- a/agent/consul/state/acl_oss.go +++ b/agent/consul/state/acl_oss.go @@ -5,207 +5,11 @@ package state import ( "fmt" - "github.com/hashicorp/consul/agent/structs" memdb "github.com/hashicorp/go-memdb" + + "github.com/hashicorp/consul/agent/structs" ) -/////////////////////////////////////////////////////////////////////////////// -///// ACL Table Schemas ///// -/////////////////////////////////////////////////////////////////////////////// - -func tokensTableSchema() *memdb.TableSchema { - return &memdb.TableSchema{ - Name: "acl-tokens", - Indexes: map[string]*memdb.IndexSchema{ - "accessor": { - Name: "accessor", - // DEPRECATED (ACL-Legacy-Compat) - we should not AllowMissing here once legacy compat is removed - AllowMissing: true, - Unique: true, - Indexer: &memdb.UUIDFieldIndex{ - Field: "AccessorID", - }, - }, - "id": { - Name: "id", - AllowMissing: false, - Unique: true, - Indexer: &memdb.StringFieldIndex{ - Field: "SecretID", - Lowercase: false, - }, - }, - "policies": { - Name: "policies", - // Need to allow missing for the anonymous token - AllowMissing: true, - Unique: false, - Indexer: &TokenPoliciesIndex{}, - }, - "roles": { - Name: "roles", - AllowMissing: true, - Unique: false, - Indexer: &TokenRolesIndex{}, - }, - "authmethod": { - Name: "authmethod", - AllowMissing: true, - Unique: false, - Indexer: &memdb.StringFieldIndex{ - Field: "AuthMethod", - Lowercase: false, - }, - }, - "local": { - Name: "local", - AllowMissing: false, - Unique: false, - Indexer: &memdb.ConditionalIndex{ - Conditional: func(obj interface{}) (bool, error) { - if token, ok := obj.(*structs.ACLToken); ok { - return token.Local, nil - } - return false, nil - }, - }, - }, - "expires-global": { - Name: "expires-global", - AllowMissing: true, - Unique: false, - Indexer: &TokenExpirationIndex{LocalFilter: false}, - }, - "expires-local": { - Name: "expires-local", - AllowMissing: true, - Unique: false, - Indexer: &TokenExpirationIndex{LocalFilter: true}, - }, - - //DEPRECATED (ACL-Legacy-Compat) - This index is only needed while we support upgrading v1 to v2 acls - // This table indexes all the ACL tokens that do not have an AccessorID - "needs-upgrade": { - Name: "needs-upgrade", - AllowMissing: false, - Unique: false, - Indexer: &memdb.ConditionalIndex{ - Conditional: func(obj interface{}) (bool, error) { - if token, ok := obj.(*structs.ACLToken); ok { - return token.AccessorID == "", nil - } - return false, nil - }, - }, - }, - }, - } -} - -func policiesTableSchema() *memdb.TableSchema { - return &memdb.TableSchema{ - Name: "acl-policies", - Indexes: map[string]*memdb.IndexSchema{ - "id": { - Name: "id", - AllowMissing: false, - Unique: true, - Indexer: &memdb.UUIDFieldIndex{ - Field: "ID", - }, - }, - "name": { - Name: "name", - AllowMissing: false, - Unique: true, - Indexer: &memdb.StringFieldIndex{ - Field: "Name", - // TODO (ACL-V2) - should we coerce to lowercase? - Lowercase: true, - }, - }, - }, - } -} - -func rolesTableSchema() *memdb.TableSchema { - return &memdb.TableSchema{ - Name: "acl-roles", - Indexes: map[string]*memdb.IndexSchema{ - "id": { - Name: "id", - AllowMissing: false, - Unique: true, - Indexer: &memdb.UUIDFieldIndex{ - Field: "ID", - }, - }, - "name": { - Name: "name", - AllowMissing: false, - Unique: true, - Indexer: &memdb.StringFieldIndex{ - Field: "Name", - Lowercase: true, - }, - }, - "policies": { - Name: "policies", - // Need to allow missing for the anonymous token - AllowMissing: true, - Unique: false, - Indexer: &RolePoliciesIndex{}, - }, - }, - } -} - -func bindingRulesTableSchema() *memdb.TableSchema { - return &memdb.TableSchema{ - Name: "acl-binding-rules", - Indexes: map[string]*memdb.IndexSchema{ - "id": { - Name: "id", - AllowMissing: false, - Unique: true, - Indexer: &memdb.UUIDFieldIndex{ - Field: "ID", - }, - }, - "authmethod": { - Name: "authmethod", - AllowMissing: false, - Unique: false, - Indexer: &memdb.StringFieldIndex{ - Field: "AuthMethod", - Lowercase: true, - }, - }, - }, - } -} - -func authMethodsTableSchema() *memdb.TableSchema { - return &memdb.TableSchema{ - Name: "acl-auth-methods", - Indexes: map[string]*memdb.IndexSchema{ - "id": { - Name: "id", - AllowMissing: false, - Unique: true, - Indexer: &memdb.StringFieldIndex{ - Field: "Name", - Lowercase: true, - }, - }, - }, - } -} - -/////////////////////////////////////////////////////////////////////////////// -///// ACL Policy Functions ///// -/////////////////////////////////////////////////////////////////////////////// - func aclPolicyInsert(tx *txn, policy *structs.ACLPolicy) error { if err := tx.Insert("acl-policies", policy); err != nil { return fmt.Errorf("failed inserting acl policy: %v", err) diff --git a/agent/consul/state/acl_schema.go b/agent/consul/state/acl_schema.go new file mode 100644 index 000000000..88cd1b4d6 --- /dev/null +++ b/agent/consul/state/acl_schema.go @@ -0,0 +1,210 @@ +package state + +import ( + "github.com/hashicorp/go-memdb" + + "github.com/hashicorp/consul/agent/structs" +) + +const ( + tableACLTokens = "acl-tokens" + tableACLPolicies = "acl-policies" + tableACLRoles = "acl-roles" + tableACLBindingRules = "acl-binding-rules" + tableACLAuthMethods = "acl-auth-methods" + + indexPolicies = "policies" + indexRoles = "roles" + indexAuthMethod = "authmethod" + indexLocal = "local" + indexName = "name" +) + +func tokensTableSchema() *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tableACLTokens, + Indexes: map[string]*memdb.IndexSchema{ + "accessor": { + Name: "accessor", + // DEPRECATED (ACL-Legacy-Compat) - we should not AllowMissing here once legacy compat is removed + AllowMissing: true, + Unique: true, + Indexer: &memdb.UUIDFieldIndex{ + Field: "AccessorID", + }, + }, + indexID: { + Name: indexID, + AllowMissing: false, + Unique: true, + Indexer: &memdb.StringFieldIndex{ + Field: "SecretID", + Lowercase: false, + }, + }, + indexPolicies: { + Name: indexPolicies, + // Need to allow missing for the anonymous token + AllowMissing: true, + Unique: false, + Indexer: &TokenPoliciesIndex{}, + }, + indexRoles: { + Name: indexRoles, + AllowMissing: true, + Unique: false, + Indexer: &TokenRolesIndex{}, + }, + indexAuthMethod: { + Name: indexAuthMethod, + AllowMissing: true, + Unique: false, + Indexer: &memdb.StringFieldIndex{ + Field: "AuthMethod", + Lowercase: false, + }, + }, + indexLocal: { + Name: indexLocal, + AllowMissing: false, + Unique: false, + Indexer: &memdb.ConditionalIndex{ + Conditional: func(obj interface{}) (bool, error) { + if token, ok := obj.(*structs.ACLToken); ok { + return token.Local, nil + } + return false, nil + }, + }, + }, + "expires-global": { + Name: "expires-global", + AllowMissing: true, + Unique: false, + Indexer: &TokenExpirationIndex{LocalFilter: false}, + }, + "expires-local": { + Name: "expires-local", + AllowMissing: true, + Unique: false, + Indexer: &TokenExpirationIndex{LocalFilter: true}, + }, + + //DEPRECATED (ACL-Legacy-Compat) - This index is only needed while we support upgrading v1 to v2 acls + // This table indexes all the ACL tokens that do not have an AccessorID + "needs-upgrade": { + Name: "needs-upgrade", + AllowMissing: false, + Unique: false, + Indexer: &memdb.ConditionalIndex{ + Conditional: func(obj interface{}) (bool, error) { + if token, ok := obj.(*structs.ACLToken); ok { + return token.AccessorID == "", nil + } + return false, nil + }, + }, + }, + }, + } +} + +func policiesTableSchema() *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tableACLPolicies, + Indexes: map[string]*memdb.IndexSchema{ + indexID: { + Name: indexID, + AllowMissing: false, + Unique: true, + Indexer: &memdb.UUIDFieldIndex{ + Field: "ID", + }, + }, + indexName: { + Name: indexName, + AllowMissing: false, + Unique: true, + Indexer: &memdb.StringFieldIndex{ + Field: "Name", + // TODO (ACL-V2) - should we coerce to lowercase? + Lowercase: true, + }, + }, + }, + } +} + +func rolesTableSchema() *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tableACLRoles, + Indexes: map[string]*memdb.IndexSchema{ + indexID: { + Name: indexID, + AllowMissing: false, + Unique: true, + Indexer: &memdb.UUIDFieldIndex{ + Field: "ID", + }, + }, + indexName: { + Name: indexName, + AllowMissing: false, + Unique: true, + Indexer: &memdb.StringFieldIndex{ + Field: "Name", + Lowercase: true, + }, + }, + indexPolicies: { + Name: indexPolicies, + // Need to allow missing for the anonymous token + AllowMissing: true, + Unique: false, + Indexer: &RolePoliciesIndex{}, + }, + }, + } +} + +func bindingRulesTableSchema() *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tableACLBindingRules, + Indexes: map[string]*memdb.IndexSchema{ + indexID: { + Name: indexID, + AllowMissing: false, + Unique: true, + Indexer: &memdb.UUIDFieldIndex{ + Field: "ID", + }, + }, + indexAuthMethod: { + Name: indexAuthMethod, + AllowMissing: false, + Unique: false, + Indexer: &memdb.StringFieldIndex{ + Field: "AuthMethod", + Lowercase: true, + }, + }, + }, + } +} + +func authMethodsTableSchema() *memdb.TableSchema { + return &memdb.TableSchema{ + Name: tableACLAuthMethods, + Indexes: map[string]*memdb.IndexSchema{ + indexID: { + Name: indexID, + AllowMissing: false, + Unique: true, + Indexer: &memdb.StringFieldIndex{ + Field: "Name", + Lowercase: true, + }, + }, + }, + } +}