Steven Clark 789f9b7821
Add missing revocation storage lock on RevokeCert refactoring (#28259)
* Add missing revocation storage lock on RevokeCert refactoring

* Refactor internal PKI revocation API

 - Process the odd logical.Response/error returns internally to make
   the returns better consumable from other users.
 - Leverage the GetConfigWithUpdate to fetch the current CRL config, otherwise we can use older or nil configs.
2024-09-03 17:18:30 -04:00

101 lines
3.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package revocation
import (
"bytes"
"context"
"crypto/x509"
"fmt"
"time"
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
"github.com/hashicorp/vault/builtin/logical/pki/pki_backend"
"github.com/hashicorp/vault/sdk/helper/errutil"
"github.com/hashicorp/vault/sdk/logical"
)
const (
RevokedPath = "revoked/"
)
type RevokerFactory interface {
GetRevoker(context.Context, logical.Storage) (Revoker, error)
}
type RevokeCertInfo struct {
RevocationTime time.Time
Warnings []string
}
type Revoker interface {
RevokeCert(cert *x509.Certificate) (RevokeCertInfo, error)
RevokeCertBySerial(serial string) (RevokeCertInfo, error)
}
type RevocationInfo struct {
CertificateBytes []byte `json:"certificate_bytes"`
RevocationTime int64 `json:"revocation_time"`
RevocationTimeUTC time.Time `json:"revocation_time_utc"`
CertificateIssuer issuing.IssuerID `json:"issuer_id"`
}
func (ri *RevocationInfo) AssociateRevokedCertWithIsssuer(revokedCert *x509.Certificate, issuerIDCertMap map[issuing.IssuerID]*x509.Certificate) bool {
for issuerId, issuerCert := range issuerIDCertMap {
if bytes.Equal(revokedCert.RawIssuer, issuerCert.RawSubject) {
if err := revokedCert.CheckSignatureFrom(issuerCert); err == nil {
// Valid mapping. Add it to the specified entry.
ri.CertificateIssuer = issuerId
return true
}
}
}
return false
}
// FetchIssuerMapForRevocationChecking fetches a map of IssuerID->parsed cert for revocation
// usage. Unlike other paths, this needs to handle the legacy bundle
// more gracefully than rejecting it outright.
func FetchIssuerMapForRevocationChecking(sc pki_backend.StorageContext) (map[issuing.IssuerID]*x509.Certificate, error) {
var err error
var issuers []issuing.IssuerID
if !sc.UseLegacyBundleCaStorage() {
issuers, err = issuing.ListIssuers(sc.GetContext(), sc.GetStorage())
if err != nil {
return nil, fmt.Errorf("could not fetch issuers list: %w", err)
}
} else {
// Hack: this isn't a real IssuerID, but it works for fetchCAInfo
// since it resolves the reference.
issuers = []issuing.IssuerID{issuing.LegacyBundleShimID}
}
issuerIDCertMap := make(map[issuing.IssuerID]*x509.Certificate, len(issuers))
for _, issuer := range issuers {
_, bundle, caErr := issuing.FetchCertBundleByIssuerId(sc.GetContext(), sc.GetStorage(), issuer, false)
if caErr != nil {
return nil, fmt.Errorf("error fetching CA certificate for issuer id %v: %w", issuer, caErr)
}
if bundle == nil {
return nil, fmt.Errorf("faulty reference: %v - CA info not found", issuer)
}
parsedBundle, err := issuing.ParseCABundle(sc.GetContext(), sc.GetPkiManagedView(), bundle)
if err != nil {
return nil, errutil.InternalError{Err: err.Error()}
}
if parsedBundle.Certificate == nil {
return nil, errutil.InternalError{Err: "stored CA information not able to be parsed"}
}
issuerIDCertMap[issuer] = parsedBundle.Certificate
}
return issuerIDCertMap, nil
}