示例#1
0
文件: acl.go 项目: hashicorp/consul
// aclSetTxn is the inner method used to insert an ACL rule with the
// proper indexes into the state store.
func (s *StateStore) aclSetTxn(tx *memdb.Txn, idx uint64, acl *structs.ACL) error {
	// Check that the ID is set
	if acl.ID == "" {
		return ErrMissingACLID
	}

	// Check for an existing ACL
	existing, err := tx.First("acls", "id", acl.ID)
	if err != nil {
		return fmt.Errorf("failed acl lookup: %s", err)
	}

	// Set the indexes
	if existing != nil {
		acl.CreateIndex = existing.(*structs.ACL).CreateIndex
		acl.ModifyIndex = idx
	} else {
		acl.CreateIndex = idx
		acl.ModifyIndex = idx
	}

	// Insert the ACL
	if err := tx.Insert("acls", acl); err != nil {
		return fmt.Errorf("failed inserting acl: %s", err)
	}
	if err := tx.Insert("index", &IndexEntry{"acls", idx}); err != nil {
		return fmt.Errorf("failed updating index: %s", err)
	}

	tx.Defer(func() { s.tableWatches["acls"].Notify() })
	return nil
}
示例#2
0
// ACLSet is used to create or update an ACL entry
// allowCreate is used for initialization of the anonymous and master tokens,
// since it permits them to be created with a specified ID that does not exist.
func (s *StateStore) ACLSet(index uint64, acl *structs.ACL, allowCreate bool) error {
	// Start a new txn
	tx, err := s.tables.StartTxn(false)
	if err != nil {
		return err
	}
	defer tx.Abort()

	// Generate a new session ID
	if acl.ID == "" {
		for {
			acl.ID = generateUUID()
			res, err := s.aclTable.GetTxn(tx, "id", acl.ID)
			if err != nil {
				return err
			}
			// Quit if this ID is unique
			if len(res) == 0 {
				break
			}
		}
		acl.CreateIndex = index
		acl.ModifyIndex = index

	} else {
		// Look for the existing node
		res, err := s.aclTable.GetTxn(tx, "id", acl.ID)
		if err != nil {
			return err
		}

		switch len(res) {
		case 0:
			if !allowCreate {
				return fmt.Errorf("Invalid ACL")
			}
			acl.CreateIndex = index
			acl.ModifyIndex = index
		case 1:
			exist := res[0].(*structs.ACL)
			acl.CreateIndex = exist.CreateIndex
			acl.ModifyIndex = index
		default:
			panic(fmt.Errorf("Duplicate ACL definition. Internal error"))
		}
	}

	// Insert the ACL
	if err := s.aclTable.InsertTxn(tx, acl); err != nil {
		return err
	}

	// Trigger the update notifications
	if err := s.aclTable.SetLastIndexTxn(tx, index); err != nil {
		return err
	}
	tx.Defer(func() { s.watch[s.aclTable].Notify() })
	return tx.Commit()
}