mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-22 15:11:07 +02:00
* 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.
101 lines
3.0 KiB
Go
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
|
|
}
|