예제 #1
0
// flushRoleSecrets deletes all the SecretIDs that belong to the given
// RoleID.
func (b *backend) flushRoleSecrets(s logical.Storage, roleName, hmacKey string) error {
	roleNameHMAC, err := createHMAC(hmacKey, roleName)
	if err != nil {
		return fmt.Errorf("failed to create HMAC of role_name: %s", err)
	}

	// Acquire the custom lock to perform listing of SecretIDs
	customLock := b.secretIDLock("")
	customLock.RLock()
	defer customLock.RUnlock()

	secretIDHMACs, err := s.List(fmt.Sprintf("secret_id/%s/", roleNameHMAC))
	if err != nil {
		return err
	}
	for _, secretIDHMAC := range secretIDHMACs {
		// Acquire the lock belonging to the SecretID
		lock := b.secretIDLock(secretIDHMAC)
		lock.Lock()
		entryIndex := fmt.Sprintf("secret_id/%s/%s", roleNameHMAC, secretIDHMAC)
		if err := s.Delete(entryIndex); err != nil {
			lock.Unlock()
			return fmt.Errorf("error deleting SecretID %s from storage: %s", secretIDHMAC, err)
		}
		lock.Unlock()
	}
	return nil
}
예제 #2
0
// deleteSecretIDAccessorEntry deletes the storage index mapping the accessor to a SecretID.
func (b *backend) deleteSecretIDAccessorEntry(s logical.Storage, secretIDAccessor string) error {
	accessorEntryIndex := "accessor/" + b.salt.SaltID(secretIDAccessor)

	accessorLock := b.secretIDAccessorLock(secretIDAccessor)
	accessorLock.Lock()
	defer accessorLock.Unlock()

	// Delete the accessor of the SecretID first
	if err := s.Delete(accessorEntryIndex); err != nil {
		return fmt.Errorf("failed to delete accessor storage entry: %s", err)
	}

	return nil
}
예제 #3
0
// deletePolicy deletes a policy
func (p *policyCache) deletePolicy(storage logical.Storage, name string) error {
	// Ensure one with this name exists
	lp, err := p.getPolicy(&logical.Request{
		Storage: storage,
	}, name)
	if err != nil {
		return fmt.Errorf("error checking if policy already exists: %s", err)
	}
	if lp == nil {
		return fmt.Errorf("policy %s does not exist", name)
	}

	p.Lock()
	defer p.Unlock()

	lp = p.cache[name]
	if lp == nil {
		return fmt.Errorf("policy %s not found", name)
	}

	// We need to ensure all other access has stopped
	lp.Lock()
	defer lp.Unlock()

	// Verify this hasn't changed
	if !lp.policy.DeletionAllowed {
		return fmt.Errorf("deletion not allowed for policy %s", name)
	}

	err = storage.Delete("policy/" + name)
	if err != nil {
		return fmt.Errorf("error deleting policy %s: %s", name, err)
	}

	err = storage.Delete("archive/" + name)
	if err != nil {
		return fmt.Errorf("error deleting archive %s: %s", name, err)
	}

	lp.policy = nil
	delete(p.cache, name)

	return nil
}
// tidyWhitelistIdentity is used to delete entries in the whitelist that are expired.
func (b *backend) tidyWhitelistIdentity(s logical.Storage, safety_buffer int) error {
	grabbed := atomic.CompareAndSwapUint32(&b.tidyWhitelistCASGuard, 0, 1)
	if grabbed {
		defer atomic.StoreUint32(&b.tidyWhitelistCASGuard, 0)
	} else {
		return fmt.Errorf("identity whitelist tidy operation already running")
	}

	bufferDuration := time.Duration(safety_buffer) * time.Second

	identities, err := s.List("whitelist/identity/")
	if err != nil {
		return err
	}

	for _, instanceID := range identities {
		identityEntry, err := s.Get("whitelist/identity/" + instanceID)
		if err != nil {
			return fmt.Errorf("error fetching identity of instanceID %s: %s", instanceID, err)
		}

		if identityEntry == nil {
			return fmt.Errorf("identity entry for instanceID %s is nil", instanceID)
		}

		if identityEntry.Value == nil || len(identityEntry.Value) == 0 {
			return fmt.Errorf("found identity entry for instanceID %s but actual identity is empty", instanceID)
		}

		var result whitelistIdentity
		if err := identityEntry.DecodeJSON(&result); err != nil {
			return err
		}

		if time.Now().UTC().After(result.ExpirationTime.Add(bufferDuration)) {
			if err := s.Delete("whitelist/identity" + instanceID); err != nil {
				return fmt.Errorf("error deleting identity of instanceID %s from storage: %s", instanceID, err)
			}
		}
	}

	return nil
}
예제 #5
0
func (lm *lockManager) DeletePolicy(storage logical.Storage, name string) error {
	lm.cacheMutex.Lock()
	lock := lm.policyLock(name, exclusive)
	defer lock.Unlock()
	defer lm.cacheMutex.Unlock()

	var p *policy
	var err error

	if lm.CacheActive() {
		p = lm.cache[name]
	}
	if p == nil {
		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			return err
		}
		if p == nil {
			return fmt.Errorf("could not delete policy; not found")
		}
	}

	if !p.DeletionAllowed {
		return fmt.Errorf("deletion is not allowed for this policy")
	}

	err = storage.Delete("policy/" + name)
	if err != nil {
		return fmt.Errorf("error deleting policy %s: %s", name, err)
	}

	err = storage.Delete("archive/" + name)
	if err != nil {
		return fmt.Errorf("error deleting archive %s: %s", name, err)
	}

	if lm.CacheActive() {
		delete(lm.cache, name)
	}

	return nil
}
예제 #6
0
// tidyBlacklistRoleTag is used to clean-up the entries in the role tag blacklist.
func (b *backend) tidyBlacklistRoleTag(s logical.Storage, safety_buffer int) error {
	grabbed := atomic.CompareAndSwapUint32(&b.tidyBlacklistCASGuard, 0, 1)
	if grabbed {
		defer atomic.StoreUint32(&b.tidyBlacklistCASGuard, 0)
	} else {
		return fmt.Errorf("roletag blacklist tidy operation already running")
	}

	bufferDuration := time.Duration(safety_buffer) * time.Second
	tags, err := s.List("blacklist/roletag/")
	if err != nil {
		return err
	}

	for _, tag := range tags {
		tagEntry, err := s.Get("blacklist/roletag/" + tag)
		if err != nil {
			return fmt.Errorf("error fetching tag %s: %s", tag, err)
		}

		if tagEntry == nil {
			return fmt.Errorf("tag entry for tag %s is nil", tag)
		}

		if tagEntry.Value == nil || len(tagEntry.Value) == 0 {
			return fmt.Errorf("found entry for tag %s but actual tag is empty", tag)
		}

		var result roleTagBlacklistEntry
		if err := tagEntry.DecodeJSON(&result); err != nil {
			return err
		}

		if time.Now().After(result.ExpirationTime.Add(bufferDuration)) {
			if err := s.Delete("blacklist/roletag" + tag); err != nil {
				return fmt.Errorf("error deleting tag %s from storage: %s", tag, err)
			}
		}
	}

	return nil
}
예제 #7
0
// validateBindSecretID is used to determine if the given SecretID is a valid one.
func (b *backend) validateBindSecretID(s logical.Storage, roleName, secretID, hmacKey string) (bool, map[string]string, error) {
	secretIDHMAC, err := createHMAC(hmacKey, secretID)
	if err != nil {
		return false, nil, fmt.Errorf("failed to create HMAC of secret_id: %s", err)
	}

	roleNameHMAC, err := createHMAC(hmacKey, roleName)
	if err != nil {
		return false, nil, fmt.Errorf("failed to create HMAC of role_name: %s", err)
	}

	entryIndex := fmt.Sprintf("secret_id/%s/%s", roleNameHMAC, secretIDHMAC)

	// SecretID locks are always index based on secretIDHMACs. This helps
	// acquiring the locks when the SecretIDs are listed. This allows grabbing
	// the correct locks even if the SecretIDs are not known in plaintext.
	lock := b.secretIDLock(secretIDHMAC)
	lock.RLock()

	result := secretIDStorageEntry{}
	if entry, err := s.Get(entryIndex); err != nil {
		lock.RUnlock()
		return false, nil, err
	} else if entry == nil {
		lock.RUnlock()
		return false, nil, nil
	} else if err := entry.DecodeJSON(&result); err != nil {
		lock.RUnlock()
		return false, nil, err
	}

	// SecretIDNumUses will be zero only if the usage limit was not set at all,
	// in which case, the SecretID will remain to be valid as long as it is not
	// expired.
	if result.SecretIDNumUses == 0 {
		lock.RUnlock()
		return true, result.Metadata, nil
	}

	// If the SecretIDNumUses is non-zero, it means that its use-count should be updated
	// in the storage. Switch the lock from a `read` to a `write` and update
	// the storage entry.
	lock.RUnlock()

	lock.Lock()
	defer lock.Unlock()

	// Lock switching may change the data. Refresh the contents.
	result = secretIDStorageEntry{}
	if entry, err := s.Get(entryIndex); err != nil {
		return false, nil, err
	} else if entry == nil {
		return false, nil, nil
	} else if err := entry.DecodeJSON(&result); err != nil {
		return false, nil, err
	}

	// If there exists a single use left, delete the SecretID entry from
	// the storage but do not fail the validation request. Subsequest
	// requests to use the same SecretID will fail.
	if result.SecretIDNumUses == 1 {
		// Delete the secret IDs accessor first
		if err := b.deleteSecretIDAccessorEntry(s, result.SecretIDAccessor); err != nil {
			return false, nil, err
		}
		if err := s.Delete(entryIndex); err != nil {
			return false, nil, fmt.Errorf("failed to delete SecretID: %s", err)
		}
	} else {
		// If the use count is greater than one, decrement it and update the last updated time.
		result.SecretIDNumUses -= 1
		result.LastUpdatedTime = time.Now()
		if entry, err := logical.StorageEntryJSON(entryIndex, &result); err != nil {
			return false, nil, fmt.Errorf("failed to decrement the use count for SecretID:%s", secretID)
		} else if err = s.Put(entry); err != nil {
			return false, nil, fmt.Errorf("failed to decrement the use count for SecretID:%s", secretID)
		}
	}

	return true, result.Metadata, nil
}
예제 #8
0
// Delete removes the structure.
func (p *PathStruct) Delete(s logical.Storage) error {
	return s.Delete(fmt.Sprintf("struct/%s", p.Name))
}
예제 #9
0
파일: wal.go 프로젝트: citywander/vault
// DeleteWAL commits the WAL entry with the given ID. Once committed,
// it is assumed that the operation was a success and doesn't need to
// be rolled back.
func DeleteWAL(s logical.Storage, id string) error {
	return s.Delete(WALPrefix + id)
}
예제 #10
0
// tidySecretID is used to delete entries in the whitelist that are expired.
func (b *backend) tidySecretID(s logical.Storage) error {
	grabbed := atomic.CompareAndSwapUint32(&b.tidySecretIDCASGuard, 0, 1)
	if grabbed {
		defer atomic.StoreUint32(&b.tidySecretIDCASGuard, 0)
	} else {
		return fmt.Errorf("SecretID tidy operation already running")
	}

	roleNameHMACs, err := s.List("secret_id/")
	if err != nil {
		return err
	}

	var result error
	for _, roleNameHMAC := range roleNameHMACs {
		// roleNameHMAC will already have a '/' suffix. Don't append another one.
		secretIDHMACs, err := s.List(fmt.Sprintf("secret_id/%s", roleNameHMAC))
		if err != nil {
			return err
		}
		for _, secretIDHMAC := range secretIDHMACs {
			// In order to avoid lock swroleing in case there is need to delete,
			// grab the write lock.
			lock := b.secretIDLock(secretIDHMAC)
			lock.Lock()
			// roleNameHMAC will already have a '/' suffix. Don't append another one.
			entryIndex := fmt.Sprintf("secret_id/%s%s", roleNameHMAC, secretIDHMAC)
			secretIDEntry, err := s.Get(entryIndex)
			if err != nil {
				lock.Unlock()
				return fmt.Errorf("error fetching SecretID %s: %s", secretIDHMAC, err)
			}

			if secretIDEntry == nil {
				result = multierror.Append(result, fmt.Errorf("entry for SecretID %s is nil", secretIDHMAC))
				lock.Unlock()
				continue
			}

			if secretIDEntry.Value == nil || len(secretIDEntry.Value) == 0 {
				lock.Unlock()
				return fmt.Errorf("found entry for SecretID %s but actual SecretID is empty", secretIDHMAC)
			}

			var result secretIDStorageEntry
			if err := secretIDEntry.DecodeJSON(&result); err != nil {
				lock.Unlock()
				return err
			}

			// ExpirationTime not being set indicates non-expiring SecretIDs
			if !result.ExpirationTime.IsZero() && time.Now().After(result.ExpirationTime) {
				if err := s.Delete(entryIndex); err != nil {
					lock.Unlock()
					return fmt.Errorf("error deleting SecretID %s from storage: %s", secretIDHMAC, err)
				}
			}
			lock.Unlock()
		}
	}
	return result
}