// 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 }
// 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 }
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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }