Exemple #1
0
// createSecretIDAccessorEntry creates an identifier for the SecretID. A storage index,
// mapping the accessor to the SecretID is also created. This method should
// be called when the lock for the corresponding SecretID is held.
func (b *backend) createSecretIDAccessorEntry(s logical.Storage, entry *secretIDStorageEntry, secretIDHMAC string) error {
	// Create a random accessor
	accessorUUID, err := uuid.GenerateUUID()
	if err != nil {
		return err
	}
	entry.SecretIDAccessor = accessorUUID

	// Create index entry, mapping the accessor to the token ID
	entryIndex := "accessor/" + b.salt.SaltID(entry.SecretIDAccessor)

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

	if entry, err := logical.StorageEntryJSON(entryIndex, &secretIDAccessorStorageEntry{
		SecretIDHMAC: secretIDHMAC,
	}); err != nil {
		return err
	} else if err = s.Put(entry); err != nil {
		return fmt.Errorf("failed to persist accessor index entry: %s", err)
	}

	return nil
}
Exemple #2
0
func (b *backend) setUser(s logical.Storage, username string, userEntry *UserEntry) error {
	entry, err := logical.StorageEntryJSON("user/"+username, userEntry)
	if err != nil {
		return err
	}

	return s.Put(entry)
}
Exemple #3
0
// NewSalt creates a new salt based on the configuration
func NewSalt(view logical.Storage, config *Config) (*Salt, error) {
	// Setup the configuration
	if config == nil {
		config = &Config{}
	}
	if config.Location == "" {
		config.Location = DefaultLocation
	}
	if config.HashFunc == nil {
		config.HashFunc = SHA256Hash
	}

	// Create the salt
	s := &Salt{
		config: config,
	}

	// Look for the salt
	raw, err := view.Get(config.Location)
	if err != nil {
		return nil, fmt.Errorf("failed to read salt: %v", err)
	}

	// Restore the salt if it exists
	if raw != nil {
		s.salt = string(raw.Value)
	}

	// Generate a new salt if necessary
	if s.salt == "" {
		s.salt, err = uuid.GenerateUUID()
		if err != nil {
			return nil, fmt.Errorf("failed to generate uuid: %v", err)
		}
		s.generated = true
		if view != nil {
			raw := &logical.StorageEntry{
				Key:   config.Location,
				Value: []byte(s.salt),
			}
			if err := view.Put(raw); err != nil {
				return nil, fmt.Errorf("failed to persist salt: %v", err)
			}
		}
	}

	if config.HMAC != nil {
		if len(config.HMACType) == 0 {
			return nil, fmt.Errorf("HMACType must be defined")
		}
		s.hmacType = config.HMACType
	}

	return s, nil
}
// Stores an instance ID and the information required to validate further login/renewal attempts from
// the same instance ID.
func setWhitelistIdentityEntry(s logical.Storage, instanceID string, identity *whitelistIdentity) error {
	entry, err := logical.StorageEntryJSON("whitelist/identity/"+instanceID, identity)
	if err != nil {
		return err
	}

	if err := s.Put(entry); err != nil {
		return err
	}
	return nil
}
Exemple #5
0
// Put writes the structure.
func (p *PathStruct) Put(s logical.Storage, v map[string]interface{}) error {
	bytes, err := json.Marshal(v)
	if err != nil {
		return err
	}

	return s.Put(&logical.StorageEntry{
		Key:   fmt.Sprintf("struct/%s", p.Name),
		Value: bytes,
	})
}
// Stores the given list of roles at zeroaddress endpoint
func (b *backend) putZeroAddressRoles(s logical.Storage, roles []string) error {
	entry, err := logical.StorageEntryJSON("config/zeroaddress", &zeroAddressRoles{
		Roles: roles,
	})
	if err != nil {
		return err
	}
	if err := s.Put(entry); err != nil {
		return err
	}
	return nil
}
Exemple #7
0
func (p *policy) storeArchive(archive *archivedKeys, storage logical.Storage) error {
	// Encode the policy
	buf, err := json.Marshal(archive)
	if err != nil {
		return err
	}

	// Write the policy into storage
	err = storage.Put(&logical.StorageEntry{
		Key:   "archive/" + p.Name,
		Value: buf,
	})
	if err != nil {
		return err
	}

	return nil
}
Exemple #8
0
func (p *Policy) Persist(storage logical.Storage, name string) error {
	// Encode the policy
	buf, err := p.Serialize()
	if err != nil {
		return err
	}

	// Write the policy into storage
	err = storage.Put(&logical.StorageEntry{
		Key:   "policy/" + name,
		Value: buf,
	})
	if err != nil {
		return err
	}

	return nil
}
// nonLockedSetAWSPublicCertificateEntry is used to store the AWS public key in
// the storage. This method does not acquire lock before reading the storage.
// If locking is desired, use lockedSetAWSPublicCertificateEntry instead.
func (b *backend) nonLockedSetAWSPublicCertificateEntry(s logical.Storage, certName string, certEntry *awsPublicCert) error {
	if certName == "" {
		return fmt.Errorf("missing certificate name")
	}

	if certEntry == nil {
		return fmt.Errorf("nil AWS public key certificate")
	}

	entry, err := logical.StorageEntryJSON("config/certificate/"+certName, certEntry)
	if err != nil {
		return err
	}
	if entry == nil {
		return fmt.Errorf("failed to create storage entry for AWS public key certificate")
	}

	return s.Put(entry)
}
Exemple #10
0
// PutWAL writes some data to the WAL.
//
// The kind parameter is used by the framework to allow users to store
// multiple kinds of WAL data and to easily disambiguate what data they're
// expecting.
//
// Data within the WAL that is uncommitted (CommitWAL hasn't be called)
// will be given to the rollback callback when an rollback operation is
// received, allowing the backend to clean up some partial states.
//
// The data must be JSON encodable.
//
// This returns a unique ID that can be used to reference this WAL data.
// WAL data cannot be modified. You can only add to the WAL and commit existing
// WAL entries.
func PutWAL(s logical.Storage, kind string, data interface{}) (string, error) {
	value, err := json.Marshal(&WALEntry{
		Kind:      kind,
		Data:      data,
		CreatedAt: time.Now().UTC().Unix(),
	})
	if err != nil {
		return "", err
	}

	id, err := logical.UUID()
	if err != nil {
		return "", err
	}

	return id, s.Put(&logical.StorageEntry{
		Key:   WALPrefix + id,
		Value: value,
	})
}
Exemple #11
0
// nonLockedSetAWSRole creates or updates a role in the storage. This method
// does not acquire the write lock before reading the role from the storage. If
// locking is desired, use lockedSetAWSRole instead.
func (b *backend) nonLockedSetAWSRole(s logical.Storage, roleName string,
	roleEntry *awsRoleEntry) error {
	if roleName == "" {
		return fmt.Errorf("missing role name")
	}

	if roleEntry == nil {
		return fmt.Errorf("nil role entry")
	}

	entry, err := logical.StorageEntryJSON("role/"+strings.ToLower(roleName), roleEntry)
	if err != nil {
		return err
	}

	if err := s.Put(entry); err != nil {
		return err
	}

	return nil
}
Exemple #12
0
func (b *backend) getRole(s logical.Storage, n string) (*roleEntry, error) {
	entry, err := s.Get("role/" + n)
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	var result roleEntry
	if err := entry.DecodeJSON(&result); err != nil {
		return nil, err
	}

	// Migrate existing saved entries and save back if changed
	modified := false
	if len(result.TTL) == 0 && len(result.Lease) != 0 {
		result.TTL = result.Lease
		result.Lease = ""
		modified = true
	}
	if len(result.MaxTTL) == 0 && len(result.LeaseMax) != 0 {
		result.MaxTTL = result.LeaseMax
		result.LeaseMax = ""
		modified = true
	}
	if modified {
		jsonEntry, err := logical.StorageEntryJSON("role/"+n, &result)
		if err != nil {
			return nil, err
		}
		if err := s.Put(jsonEntry); err != nil {
			return nil, err
		}
	}

	return &result, nil
}
Exemple #13
0
// nonLockedSetSecretIDStorageEntry creates or updates a secret ID entry at the
// physical storage. The entry will be indexed based on the given HMACs of both
// role name and the secret ID. This method will not acquire secret ID lock to
// create/update the storage entry. Locks need to be acquired before calling
// this method.
func (b *backend) nonLockedSetSecretIDStorageEntry(s logical.Storage, roleNameHMAC, secretIDHMAC string, secretEntry *secretIDStorageEntry) error {
	if secretIDHMAC == "" {
		return fmt.Errorf("missing secret ID HMAC")
	}

	if roleNameHMAC == "" {
		return fmt.Errorf("missing role name HMAC")
	}

	if secretEntry == nil {
		return fmt.Errorf("nil secret entry")
	}

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

	if entry, err := logical.StorageEntryJSON(entryIndex, secretEntry); err != nil {
		return err
	} else if err = s.Put(entry); err != nil {
		return err
	}

	return nil
}
Exemple #14
0
func (p *policy) Persist(storage logical.Storage) error {
	err := p.handleArchiving(storage)
	if err != nil {
		return err
	}

	// Encode the policy
	buf, err := p.Serialize()
	if err != nil {
		return err
	}

	// Write the policy into storage
	err = storage.Put(&logical.StorageEntry{
		Key:   "policy/" + p.Name,
		Value: buf,
	})
	if err != nil {
		return err
	}

	return nil
}
Exemple #15
0
// generatePolicy is used to create a new named policy with
// a randomly generated key
func generatePolicy(storage logical.Storage, name string, derived bool) (*Policy, error) {
	// Create the policy object
	p := &Policy{
		Name:       name,
		CipherMode: "aes-gcm",
		Derived:    derived,
	}
	if derived {
		p.KDFMode = kdfMode
	}

	// Generate a 256bit key
	p.Key = make([]byte, 32)
	_, err := rand.Read(p.Key)
	if err != nil {
		return nil, err
	}

	// Encode the policy
	buf, err := p.Serialize()
	if err != nil {
		return nil, err
	}

	// Write the policy into storage
	err = storage.Put(&logical.StorageEntry{
		Key:   "policy/" + name,
		Value: buf,
	})
	if err != nil {
		return nil, err
	}

	// Return the policy
	return p, nil
}
Exemple #16
0
// registerSecretIDEntry creates a new storage entry for the given SecretID.
func (b *backend) registerSecretIDEntry(s logical.Storage, roleName, secretID, hmacKey string, secretEntry *secretIDStorageEntry) (*secretIDStorageEntry, error) {
	secretIDHMAC, err := createHMAC(hmacKey, secretID)
	if err != nil {
		return nil, fmt.Errorf("failed to create HMAC of secret_id: %s", err)
	}
	roleNameHMAC, err := createHMAC(hmacKey, roleName)
	if err != nil {
		return nil, fmt.Errorf("failed to create HMAC of role_name: %s", err)
	}

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

	lock := b.secretIDLock(secretIDHMAC)
	lock.RLock()

	entry, err := s.Get(entryIndex)
	if err != nil {
		lock.RUnlock()
		return nil, err
	}
	if entry != nil {
		lock.RUnlock()
		return nil, fmt.Errorf("SecretID is already registered")
	}

	// If there isn't an entry for the secretID already, switch the read lock
	// with a write lock and create an entry.
	lock.RUnlock()
	lock.Lock()
	defer lock.Unlock()

	// But before saving a new entry, check if the secretID entry was created during the lock switch.
	entry, err = s.Get(entryIndex)
	if err != nil {
		return nil, err
	}
	if entry != nil {
		return nil, fmt.Errorf("SecretID is already registered")
	}

	// Create a new entry for the SecretID

	// Set the creation time for the SecretID
	currentTime := time.Now()
	secretEntry.CreationTime = currentTime
	secretEntry.LastUpdatedTime = currentTime

	// If SecretIDTTL is not specified or if it crosses the backend mount's limit,
	// cap the expiration to backend's max. Otherwise, use it to determine the
	// expiration time.
	if secretEntry.SecretIDTTL < time.Duration(0) || secretEntry.SecretIDTTL > b.System().MaxLeaseTTL() {
		secretEntry.ExpirationTime = currentTime.Add(b.System().MaxLeaseTTL())
	} else if secretEntry.SecretIDTTL != time.Duration(0) {
		// Set the ExpirationTime only if SecretIDTTL was set. SecretIDs should not
		// expire by default.
		secretEntry.ExpirationTime = currentTime.Add(secretEntry.SecretIDTTL)
	}

	// Before storing the SecretID, store its accessor.
	if err := b.createSecretIDAccessorEntry(s, secretEntry, secretIDHMAC); err != nil {
		return nil, err
	}

	if entry, err := logical.StorageEntryJSON(entryIndex, secretEntry); err != nil {
		return nil, err
	} else if err = s.Put(entry); err != nil {
		return nil, err
	}

	return secretEntry, nil
}
Exemple #17
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
}
Exemple #18
0
func (b *backend) getRole(s logical.Storage, n string) (*roleEntry, error) {
	entry, err := s.Get("role/" + n)
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, nil
	}

	var result roleEntry
	if err := entry.DecodeJSON(&result); err != nil {
		return nil, err
	}

	// Migrate existing saved entries and save back if changed
	modified := false
	if len(result.TTL) == 0 && len(result.Lease) != 0 {
		result.TTL = result.Lease
		result.Lease = ""
		modified = true
	}
	if len(result.MaxTTL) == 0 && len(result.LeaseMax) != 0 {
		result.MaxTTL = result.LeaseMax
		result.LeaseMax = ""
		modified = true
	}
	if result.AllowBaseDomain {
		result.AllowBaseDomain = false
		result.AllowBareDomains = true
		modified = true
	}
	if result.AllowedBaseDomain != "" {
		found := false
		allowedDomains := strings.Split(result.AllowedDomains, ",")
		if len(allowedDomains) != 0 {
			for _, v := range allowedDomains {
				if v == result.AllowedBaseDomain {
					found = true
					break
				}
			}
		}
		if !found {
			if result.AllowedDomains == "" {
				result.AllowedDomains = result.AllowedBaseDomain
			} else {
				result.AllowedDomains += "," + result.AllowedBaseDomain
			}
		}
		result.AllowedBaseDomain = ""
		modified = true
	}

	if modified {
		jsonEntry, err := logical.StorageEntryJSON("role/"+n, &result)
		if err != nil {
			return nil, err
		}
		if err := s.Put(jsonEntry); err != nil {
			return nil, err
		}
	}

	return &result, nil
}