Пример #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
// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(store logical.Storage) (pool *x509.CertPool, trusted []*ParsedCert) {
	pool = x509.NewCertPool()
	names, err := store.List("cert/")
	if err != nil {
		b.Logger().Printf("[ERR] cert: failed to list trusted certs: %v", err)
		return
	}
	for _, name := range names {
		entry, err := b.Cert(store, strings.TrimPrefix(name, "cert/"))
		if err != nil {
			b.Logger().Printf("[ERR] cert: failed to load trusted certs '%s': %v", name, err)
			continue
		}
		parsed := parsePEM([]byte(entry.Certificate))
		if len(parsed) == 0 {
			b.Logger().Printf("[ERR] cert: failed to parse certificate for '%s'", name)
			continue
		}
		for _, p := range parsed {
			pool.AddCert(p)
		}

		// Create a ParsedCert entry
		trusted = append(trusted, &ParsedCert{
			Entry:        entry,
			Certificates: parsed,
		})
	}
	return
}
Пример #3
0
func (b *backend) populateCRLs(storage logical.Storage) error {
	b.crlUpdateMutex.Lock()
	defer b.crlUpdateMutex.Unlock()

	keys, err := storage.List("crls/")
	if err != nil {
		return fmt.Errorf("error listing CRLs: %v", err)
	}
	if keys == nil || len(keys) == 0 {
		return nil
	}

	for _, key := range keys {
		entry, err := storage.Get("crls/" + key)
		if err != nil {
			return fmt.Errorf("error loading CRL %s: %v", key, err)
		}
		if entry == nil {
			continue
		}
		var crlInfo CRLInfo
		err = entry.DecodeJSON(&crlInfo)
		if err != nil {
			return fmt.Errorf("error decoding CRL %s: %v", key, err)
		}
		b.crls[key] = crlInfo
	}

	return nil
}
Пример #4
0
// ListWAL lists all the entries in the WAL.
func ListWAL(s logical.Storage) ([]string, error) {
	keys, err := s.List(WALPrefix)
	if err != nil {
		return nil, err
	}

	for i, k := range keys {
		keys[i] = strings.TrimPrefix(k, WALPrefix)
	}

	return keys, nil
}
Пример #5
0
// List reads the keys under a given path
func (p *PathMap) List(s logical.Storage, prefix string) ([]string, error) {
	stripPrefix := fmt.Sprintf("struct/map/%s/", p.Name)
	fullPrefix := fmt.Sprintf("%s%s", stripPrefix, prefix)
	out, err := s.List(fullPrefix)
	if err != nil {
		return nil, err
	}
	stripped := make([]string, len(out))
	for idx, k := range out {
		stripped[idx] = strings.TrimPrefix(k, stripPrefix)
	}
	return stripped, nil
}
Пример #6
0
// awsPublicCertificates returns a slice of all the parsed AWS public
// certificates, which are used to verify either the SHA256 RSA signature, or
// the PKCS7 signatures of the instance identity documents. This method will
// append the certificates registered using `config/certificate/<cert_name>`
// endpoint, along with the default certificate in the backend.
func (b *backend) awsPublicCertificates(s logical.Storage, isPkcs bool) ([]*x509.Certificate, error) {
	// Lock at beginning and use internal method so that we are consistent as
	// we iterate through
	b.configMutex.RLock()
	defer b.configMutex.RUnlock()

	var certs []*x509.Certificate

	defaultCert := genericAWSPublicCertificateIdentity
	if isPkcs {
		defaultCert = genericAWSPublicCertificatePkcs7
	}

	// Append the generic certificate provided in the AWS EC2 instance metadata documentation
	decodedCert, err := decodePEMAndParseCertificate(defaultCert)
	if err != nil {
		return nil, err
	}
	certs = append(certs, decodedCert)

	// Get the list of all the registered certificates
	registeredCerts, err := s.List("config/certificate/")
	if err != nil {
		return nil, err
	}

	// Iterate through each certificate, parse and append it to a slice
	for _, cert := range registeredCerts {
		certEntry, err := b.nonLockedAWSPublicCertificateEntry(s, cert)
		if err != nil {
			return nil, err
		}
		if certEntry == nil {
			return nil, fmt.Errorf("certificate storage has a nil entry under the name:%s\n", cert)
		}
		// Append relevant certificates only
		if (isPkcs && certEntry.Type == "pkcs7") ||
			(!isPkcs && certEntry.Type == "identity") {
			decodedCert, err := decodePEMAndParseCertificate(certEntry.AWSPublicCert)
			if err != nil {
				return nil, err
			}
			certs = append(certs, decodedCert)
		}
	}

	return certs, 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
}
Пример #8
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
}
// awsPublicCertificates returns a slice of all the parsed AWS public
// certificates, that were registered using `config/certificate/<cert_name>` endpoint.
// This method will also append default certificate in the backend, to the slice.
func (b *backend) awsPublicCertificates(s logical.Storage) ([]*x509.Certificate, error) {
	// Lock at beginning and use internal method so that we are consistent as
	// we iterate through
	b.configMutex.RLock()
	defer b.configMutex.RUnlock()

	var certs []*x509.Certificate

	// Append the generic certificate provided in the AWS EC2 instance metadata documentation.
	decodedCert, err := decodePEMAndParseCertificate(genericAWSPublicCertificate)
	if err != nil {
		return nil, err
	}
	certs = append(certs, decodedCert)

	// Get the list of all the registered certificates.
	registeredCerts, err := s.List("config/certificate/")
	if err != nil {
		return nil, err
	}

	// Iterate through each certificate, parse and append it to a slice.
	for _, cert := range registeredCerts {
		certEntry, err := b.nonLockedAWSPublicCertificateEntry(s, cert)
		if err != nil {
			return nil, err
		}
		if certEntry == nil {
			return nil, fmt.Errorf("certificate storage has a nil entry under the name:%s\n", cert)
		}
		decodedCert, err := decodePEMAndParseCertificate(certEntry.AWSPublicCert)
		if err != nil {
			return nil, err
		}
		certs = append(certs, decodedCert)
	}

	return certs, nil
}
Пример #10
0
// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(store logical.Storage) (pool *x509.CertPool, trusted []*ParsedCert, trustedNonCAs []*ParsedCert) {
	pool = x509.NewCertPool()
	trusted = make([]*ParsedCert, 0)
	trustedNonCAs = make([]*ParsedCert, 0)
	names, err := store.List("cert/")
	if err != nil {
		b.Logger().Error("cert: failed to list trusted certs", "error", err)
		return
	}
	for _, name := range names {
		entry, err := b.Cert(store, strings.TrimPrefix(name, "cert/"))
		if err != nil {
			b.Logger().Error("cert: failed to load trusted cert", "name", name, "error", err)
			continue
		}
		parsed := parsePEM([]byte(entry.Certificate))
		if len(parsed) == 0 {
			b.Logger().Error("cert: failed to parse certificate", "name", name)
			continue
		}
		if !parsed[0].IsCA {
			trustedNonCAs = append(trustedNonCAs, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		} else {
			for _, p := range parsed {
				pool.AddCert(p)
			}

			// Create a ParsedCert entry
			trusted = append(trusted, &ParsedCert{
				Entry:        entry,
				Certificates: parsed,
			})
		}
	}
	return
}
Пример #11
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
}