mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-03 20:40:45 -05:00
This commit is contained in:
parent
cb88546ad2
commit
399a10f22d
11 changed files with 105 additions and 44 deletions
|
|
@ -295,6 +295,7 @@ func generateCert(sc *storageContext,
|
|||
if data.Params == nil {
|
||||
return nil, nil, errutil.InternalError{Err: "nil parameters received from parameter bundle generation"}
|
||||
}
|
||||
issuing.EntAdjustCreationBundle(sc.System(), data)
|
||||
|
||||
if isCA {
|
||||
data.Params.IsCA = isCA
|
||||
|
|
|
|||
17
builtin/logical/pki/common_criteria_stubs_oss.go
Normal file
17
builtin/logical/pki/common_criteria_stubs_oss.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright IBM Corp. 2016, 2025
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
//go:build !enterprise
|
||||
|
||||
package pki
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/vault/builtin/logical/pki/issuing"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/hashicorp/vault/tools/stubmaker
|
||||
func (b *backend) adjustInputBundle(input *inputBundle) {}
|
||||
|
||||
func entValidateRole(b *backend, entry *issuing.RoleEntry) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"context"
|
||||
|
||||
ctx509 "github.com/google/certificate-transparency-go/x509"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
|
|
@ -17,3 +18,7 @@ import (
|
|||
func entSetCertVerifyOptions(ctx context.Context, storage logical.Storage, issuerId IssuerID, options *ctx509.VerifyOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func EntAdjustCreationBundle(view logical.SystemView, bundle *certutil.CreationBundle) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ func SignCert(b logical.SystemView, role *RoleEntry, entityInfo EntityInfo, caSi
|
|||
if creation.Params == nil {
|
||||
return nil, nil, errutil.InternalError{Err: "nil parameters received from parameter bundle generation"}
|
||||
}
|
||||
EntAdjustCreationBundle(b, creation)
|
||||
|
||||
creation.Params.IsCA = signInput.IsCA()
|
||||
creation.Params.UseCSRValues = signInput.UseCSRValues()
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ func (b *backend) acmeFinalizeOrderHandler(ac *acmeContext, r *logical.Request,
|
|||
return nil, err
|
||||
}
|
||||
} else {
|
||||
signedCertBundle, issuerId, err = issueCertFromCsr(ac, csr)
|
||||
signedCertBundle, issuerId, err = issueCertFromCsr(b, ac, csr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -553,7 +553,7 @@ func maybeAugmentReqDataWithSuitableCN(ac *acmeContext, csr *x509.CertificateReq
|
|||
}
|
||||
}
|
||||
|
||||
func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil.ParsedCertBundle, issuing.IssuerID, error) {
|
||||
func issueCertFromCsr(b *backend, ac *acmeContext, csr *x509.CertificateRequest) (*certutil.ParsedCertBundle, issuing.IssuerID, error) {
|
||||
pemBlock := &pem.Block{
|
||||
Type: "CERTIFICATE REQUEST",
|
||||
Headers: nil,
|
||||
|
|
@ -625,6 +625,7 @@ func issueCertFromCsr(ac *acmeContext, csr *x509.CertificateRequest) (*certutil.
|
|||
// unit, we have no way of validating this (via ACME here, without perhaps
|
||||
// an external policy engine), and thus should not be setting it on our
|
||||
// final issued certificate.
|
||||
b.adjustInputBundle(input)
|
||||
parsedBundle, _, err := signCert(ac.sc.System(), input, signingBundle, false /* is_ca=false */, false /* use_csr_values */)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("%w: refusing to sign CSR: %s", ErrBadCSR, err.Error())
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, d
|
|||
apiData: data,
|
||||
role: role,
|
||||
}
|
||||
b.adjustInputBundle(input)
|
||||
var parsedBundle *certutil.ParsedCertBundle
|
||||
var warnings []string
|
||||
if useCSR {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/certutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/hashicorp/vault/sdk/helper/errutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
|
|
@ -898,7 +897,7 @@ func (b *backend) GetRole(ctx context.Context, s logical.Storage, n string) (*is
|
|||
}
|
||||
|
||||
// Ensure the role is valid after updating.
|
||||
_, err = validateRole(b, result, ctx, s)
|
||||
_, _, err = validateRole(b, result, ctx, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -948,8 +947,9 @@ func (b *backend) pathRoleRead(ctx context.Context, req *logical.Request, data *
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
resp := &logical.Response{
|
||||
Data: role.ToResponseData(),
|
||||
warnings, err := entValidateRole(b, role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.pkiObserver.RecordPKIObservation(ctx, req, observe.ObservationTypePKIRoleRead,
|
||||
|
|
@ -957,7 +957,10 @@ func (b *backend) pathRoleRead(ctx context.Context, req *logical.Request, data *
|
|||
observe.NewAdditionalPKIMetadata("role_name", role.Name),
|
||||
)
|
||||
|
||||
return resp, nil
|
||||
return &logical.Response{
|
||||
Data: role.ToResponseData(),
|
||||
Warnings: warnings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathRoleList(ctx context.Context, req *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
|
||||
|
|
@ -1059,15 +1062,21 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
}
|
||||
}
|
||||
|
||||
resp, err := validateRole(b, entry, ctx, req.Storage)
|
||||
userError, warnings, err := validateRole(b, entry, ctx, req.Storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if warning != "" {
|
||||
resp.AddWarning(warning)
|
||||
warnings = append(warnings, warning)
|
||||
}
|
||||
if resp.IsError() {
|
||||
return resp, nil
|
||||
if userError != "" {
|
||||
return logical.ErrorResponse(userError), nil
|
||||
}
|
||||
|
||||
if entWarnings, err := entValidateRole(b, entry); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
warnings = append(warnings, entWarnings...)
|
||||
}
|
||||
|
||||
// Store it
|
||||
|
|
@ -1089,42 +1098,44 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
observe.NewAdditionalPKIMetadata("not_before_duration", entry.NotBeforeDuration.String()),
|
||||
)
|
||||
|
||||
return resp, nil
|
||||
return &logical.Response{
|
||||
Warnings: warnings,
|
||||
Data: entry.ToResponseData(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateRole(b *backend, entry *issuing.RoleEntry, ctx context.Context, s logical.Storage) (*logical.Response, error) {
|
||||
resp := &logical.Response{}
|
||||
var err error
|
||||
|
||||
// validateRole takes a role and performs various checks and mutations against it.
|
||||
// If it returns an error, the calling handler should also return an error as
|
||||
// opposed to a logical response. If instead it returns a nonempty string,
|
||||
// that should be returned as a logical.ErrorResponse to the client. Otherwise,
|
||||
// the warnings should be included in any response to the client.
|
||||
func validateRole(b *backend, entry *issuing.RoleEntry, ctx context.Context, s logical.Storage) (string, []string, error) {
|
||||
if entry.MaxTTL > 0 && entry.TTL > entry.MaxTTL {
|
||||
return logical.ErrorResponse(
|
||||
`"ttl" value must be less than "max_ttl" value`,
|
||||
), nil
|
||||
return `"ttl" value must be less than "max_ttl" value`, nil, nil
|
||||
}
|
||||
|
||||
if entry.KeyBits, entry.SignatureBits, err = certutil.ValidateDefaultOrValueKeyTypeSignatureLength(entry.KeyType, entry.KeyBits, entry.SignatureBits); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
keyBits, signatureBits, err := certutil.ValidateDefaultOrValueKeyTypeSignatureLength(entry.KeyType, entry.KeyBits, entry.SignatureBits)
|
||||
if err != nil {
|
||||
return err.Error(), nil, nil
|
||||
}
|
||||
|
||||
if entry.SerialNumberSource != "" &&
|
||||
entry.SerialNumberSource != "json-csr" &&
|
||||
entry.SerialNumberSource != "json" {
|
||||
return logical.ErrorResponse("unknown serial_number_source %s", entry.SerialNumberSource), nil
|
||||
return fmt.Sprintf("unknown serial_number_source %s", entry.SerialNumberSource), nil, nil
|
||||
}
|
||||
|
||||
if len(entry.ExtKeyUsageOIDs) > 0 {
|
||||
for _, oidstr := range entry.ExtKeyUsageOIDs {
|
||||
_, err := certutil.StringToOid(oidstr)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("%q could not be parsed as a valid oid for an extended key usage", oidstr)), nil
|
||||
if _, err := certutil.StringToOid(oidstr); err != nil {
|
||||
return fmt.Sprintf("%q could not be parsed as a valid oid for an extended key usage", oidstr), nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(entry.PolicyIdentifiers) > 0 {
|
||||
_, err := certutil.CreatePolicyInformationExtensionFromStorageStrings(entry.PolicyIdentifiers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if _, err := certutil.CreatePolicyInformationExtensionFromStorageStrings(entry.PolicyIdentifiers); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1132,36 +1143,38 @@ func validateRole(b *backend, entry *issuing.RoleEntry, ctx context.Context, s l
|
|||
// resolve the reference (to an issuerId) at role creation time; instead,
|
||||
// resolve it at use time. This allows values such as `default` or other
|
||||
// user-assigned names to "float" and change over time.
|
||||
if len(entry.Issuer) == 0 {
|
||||
entry.Issuer = defaultRef
|
||||
issuer := entry.Issuer
|
||||
if len(issuer) == 0 {
|
||||
issuer = defaultRef
|
||||
}
|
||||
|
||||
var warnings []string
|
||||
// Check that the issuers reference set resolves to something
|
||||
if !b.UseLegacyBundleCaStorage() {
|
||||
sc := b.makeStorageContext(ctx, s)
|
||||
issuerId, err := sc.resolveIssuerReference(entry.Issuer)
|
||||
issuerId, err := sc.resolveIssuerReference(issuer)
|
||||
if err != nil {
|
||||
if issuerId == issuing.IssuerRefNotFound {
|
||||
resp = &logical.Response{}
|
||||
if entry.Issuer == defaultRef {
|
||||
resp.AddWarning("Issuing Certificate was set to default, but no default issuing certificate (configurable at /config/issuers) is currently set")
|
||||
warnings = append(warnings, "Issuing Certificate was set to default, but no default issuing certificate (configurable at /config/issuers) is currently set")
|
||||
} else {
|
||||
resp.AddWarning(fmt.Sprintf("Issuing Certificate was set to %s but no issuing certificate currently has that name", entry.Issuer))
|
||||
warnings = append(warnings, fmt.Sprintf("Issuing Certificate was set to %s but no issuing certificate currently has that name", issuer))
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensures CNValidations are alright
|
||||
entry.CNValidations, err = checkCNValidations(entry.CNValidations)
|
||||
cnValidations, err := checkCNValidations(entry.CNValidations)
|
||||
if err != nil {
|
||||
return nil, errutil.UserError{Err: err.Error()}
|
||||
return err.Error(), nil, nil
|
||||
}
|
||||
|
||||
resp.Data = entry.ToResponseData()
|
||||
return resp, nil
|
||||
entry.CNValidations, entry.Issuer, entry.KeyBits, entry.SignatureBits = cnValidations, issuer, keyBits, signatureBits
|
||||
return "", warnings, nil
|
||||
}
|
||||
|
||||
func getWithExplicitDefault(data *framework.FieldData, field string, defaultValue interface{}) interface{} {
|
||||
|
|
@ -1284,15 +1297,21 @@ func (b *backend) pathRolePatch(ctx context.Context, req *logical.Request, data
|
|||
}
|
||||
}
|
||||
|
||||
resp, err := validateRole(b, entry, ctx, req.Storage)
|
||||
userError, warnings, err := validateRole(b, entry, ctx, req.Storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if warning != "" {
|
||||
resp.AddWarning(warning)
|
||||
warnings = append(warnings, warning)
|
||||
}
|
||||
if resp.IsError() {
|
||||
return resp, nil
|
||||
if userError != "" {
|
||||
return logical.ErrorResponse(userError), nil
|
||||
}
|
||||
|
||||
if entWarnings, err := entValidateRole(b, entry); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
warnings = append(warnings, entWarnings...)
|
||||
}
|
||||
|
||||
// Store it
|
||||
|
|
@ -1314,7 +1333,10 @@ func (b *backend) pathRolePatch(ctx context.Context, req *logical.Request, data
|
|||
observe.NewAdditionalPKIMetadata("not_before_duration", entry.NotBeforeDuration.String()),
|
||||
)
|
||||
|
||||
return resp, nil
|
||||
return &logical.Response{
|
||||
Warnings: warnings,
|
||||
Data: entry.ToResponseData(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func checkCNValidations(validations []string) ([]string, error) {
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ func (b *backend) pathCAGenerateRoot(ctx context.Context, req *logical.Request,
|
|||
apiData: data,
|
||||
role: role,
|
||||
}
|
||||
b.adjustInputBundle(input)
|
||||
parsedBundle, warnings, err := generateCert(sc, input, nil, true, b.Backend.GetRandomReader())
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
|
|
@ -435,6 +436,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R
|
|||
apiData: data,
|
||||
role: role,
|
||||
}
|
||||
b.adjustInputBundle(input)
|
||||
parsedBundle, warnings, err := signCert(b.System(), input, signingBundle, true, useCSRValues)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
|
|
|
|||
3
changelog/_10739.txt
Normal file
3
changelog/_10739.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
secrets/pki (enterprise): When the common_criteria_mode feature flag is enabled, NotBefore will always be treated as zero.
|
||||
```
|
||||
|
|
@ -933,6 +933,9 @@ func createCertificate(data *CreationBundle, randReader io.Reader, privateKeyGen
|
|||
if data.Params.NotBeforeDuration > 0 {
|
||||
certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration)
|
||||
}
|
||||
if data.Params.ZeroNotBefore {
|
||||
certTemplate.NotBefore = time.Now()
|
||||
}
|
||||
|
||||
if err := HandleOtherSANs(certTemplate, data.Params.OtherSANs); err != nil {
|
||||
return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()}
|
||||
|
|
@ -1296,6 +1299,9 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
|
|||
if data.Params.NotBeforeDuration > 0 {
|
||||
certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration)
|
||||
}
|
||||
if data.Params.ZeroNotBefore {
|
||||
certTemplate.NotBefore = time.Now()
|
||||
}
|
||||
|
||||
privateKeyType := data.SigningBundle.PrivateKeyType
|
||||
if privateKeyType == ManagedPrivateKey {
|
||||
|
|
|
|||
|
|
@ -810,6 +810,8 @@ type CreationParameters struct {
|
|||
// sender of the CSR has proven proof of possession of the associated
|
||||
// private key by some other means, otherwise keep this set to false.
|
||||
IgnoreCSRSignature bool
|
||||
|
||||
ZeroNotBefore bool
|
||||
}
|
||||
|
||||
type CreationBundle struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue