mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
Allow SignCert callers to override CSR signature checks (#27914)
- We are leveraging this new feature flag to ignore the CSR's signature as we are constructing a CSR based on the information from a CMPv2 message.
This commit is contained in:
@@ -468,6 +468,10 @@ func (i SignCertInputFromDataFields) GetPermittedDomains() []string {
|
|||||||
return i.data.Get("permitted_dns_domains").([]string)
|
return i.data.Get("permitted_dns_domains").([]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i SignCertInputFromDataFields) IgnoreCSRSignature() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func signCert(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) {
|
func signCert(sysView logical.SystemView, data *inputBundle, caSign *certutil.CAInfoBundle, isCA bool, useCSRValues bool) (*certutil.ParsedCertBundle, []string, error) {
|
||||||
if data.role == nil {
|
if data.role == nil {
|
||||||
return nil, nil, errutil.InternalError{Err: "no role found in data bundle"}
|
return nil, nil, errutil.InternalError{Err: "no role found in data bundle"}
|
||||||
@@ -498,6 +502,10 @@ type CreationBundleInputFromFieldData struct {
|
|||||||
data *framework.FieldData
|
data *framework.FieldData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cb CreationBundleInputFromFieldData) IgnoreCSRSignature() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (cb CreationBundleInputFromFieldData) GetCommonName() string {
|
func (cb CreationBundleInputFromFieldData) GetCommonName() string {
|
||||||
return cb.data.Get("common_name").(string)
|
return cb.data.Get("common_name").(string)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ type CreationBundleInput interface {
|
|||||||
GetOptionalSkid() (interface{}, bool)
|
GetOptionalSkid() (interface{}, bool)
|
||||||
IsUserIdInSchema() (interface{}, bool)
|
IsUserIdInSchema() (interface{}, bool)
|
||||||
GetUserIds() []string
|
GetUserIds() []string
|
||||||
|
IgnoreCSRSignature() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateCreationBundle is a shared function that reads parameters supplied
|
// GenerateCreationBundle is a shared function that reads parameters supplied
|
||||||
@@ -428,6 +429,7 @@ func GenerateCreationBundle(b logical.SystemView, role *RoleEntry, entityInfo En
|
|||||||
NotBeforeDuration: role.NotBeforeDuration,
|
NotBeforeDuration: role.NotBeforeDuration,
|
||||||
ForceAppendCaChain: caSign != nil,
|
ForceAppendCaChain: caSign != nil,
|
||||||
SKID: skid,
|
SKID: skid,
|
||||||
|
IgnoreCSRSignature: cb.IgnoreCSRSignature(),
|
||||||
},
|
},
|
||||||
SigningBundle: caSign,
|
SigningBundle: caSign,
|
||||||
CSR: csr,
|
CSR: csr,
|
||||||
|
|||||||
@@ -23,11 +23,16 @@ type SignCertInput interface {
|
|||||||
GetPermittedDomains() []string
|
GetPermittedDomains() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA bool, useCSRValues bool) BasicSignCertInput {
|
func NewBasicSignCertInput(csr *x509.CertificateRequest, isCA, useCSRValues bool) BasicSignCertInput {
|
||||||
|
return NewBasicSignCertInputWithIgnore(csr, isCA, useCSRValues, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBasicSignCertInputWithIgnore(csr *x509.CertificateRequest, isCA, useCSRValues, ignoreCsrSignature bool) BasicSignCertInput {
|
||||||
return BasicSignCertInput{
|
return BasicSignCertInput{
|
||||||
isCA: isCA,
|
isCA: isCA,
|
||||||
useCSRValues: useCSRValues,
|
useCSRValues: useCSRValues,
|
||||||
csr: csr,
|
csr: csr,
|
||||||
|
ignoreCsrSignature: ignoreCsrSignature,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +42,7 @@ type BasicSignCertInput struct {
|
|||||||
isCA bool
|
isCA bool
|
||||||
useCSRValues bool
|
useCSRValues bool
|
||||||
csr *x509.CertificateRequest
|
csr *x509.CertificateRequest
|
||||||
|
ignoreCsrSignature bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b BasicSignCertInput) GetTTL() int {
|
func (b BasicSignCertInput) GetTTL() int {
|
||||||
@@ -91,6 +97,10 @@ func (b BasicSignCertInput) GetCSR() (*x509.CertificateRequest, error) {
|
|||||||
return b.csr, nil
|
return b.csr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b BasicSignCertInput) IgnoreCSRSignature() bool {
|
||||||
|
return b.ignoreCsrSignature
|
||||||
|
}
|
||||||
|
|
||||||
func (b BasicSignCertInput) IsCA() bool {
|
func (b BasicSignCertInput) IsCA() bool {
|
||||||
return b.isCA
|
return b.isCA
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1006,6 +1006,101 @@ func TestBasicConstraintExtension(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestIgnoreCSRSigning Make sure we validate the CSR by default and that we can override
|
||||||
|
// the behavior disabling CSR signature checks
|
||||||
|
func TestIgnoreCSRSigning(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generating ca key: %v", err)
|
||||||
|
}
|
||||||
|
subjKeyID, err := GetSubjKeyID(caKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed generating ca subject key id: %v", err)
|
||||||
|
}
|
||||||
|
caCertTemplate := &x509.Certificate{
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "root.localhost",
|
||||||
|
},
|
||||||
|
SubjectKeyId: subjKeyID,
|
||||||
|
DNSNames: []string{"root.localhost"},
|
||||||
|
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
|
||||||
|
SerialNumber: big.NewInt(mathrand.Int63()),
|
||||||
|
NotBefore: time.Now().Add(-30 * time.Second),
|
||||||
|
NotAfter: time.Now().Add(262980 * time.Hour),
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
IsCA: true,
|
||||||
|
}
|
||||||
|
caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed creating ca certificate: %v", err)
|
||||||
|
}
|
||||||
|
caCert, err := x509.ParseCertificate(caBytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed parsing ca certificate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
signingBundle := &CAInfoBundle{
|
||||||
|
ParsedCertBundle: ParsedCertBundle{
|
||||||
|
PrivateKeyType: ECPrivateKey,
|
||||||
|
PrivateKey: caKey,
|
||||||
|
CertificateBytes: caBytes,
|
||||||
|
Certificate: caCert,
|
||||||
|
CAChain: nil,
|
||||||
|
},
|
||||||
|
URLs: &URLEntries{},
|
||||||
|
}
|
||||||
|
|
||||||
|
key := genEdDSA(t)
|
||||||
|
csr := &x509.CertificateRequest{
|
||||||
|
PublicKeyAlgorithm: x509.ECDSA,
|
||||||
|
PublicKey: key.Public(),
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "test.dadgarcorp.com",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
t.Run(fmt.Sprintf("ignore-csr-disabled"), func(t *testing.T) {
|
||||||
|
params := &CreationParameters{
|
||||||
|
URLs: &URLEntries{},
|
||||||
|
}
|
||||||
|
data := &CreationBundle{
|
||||||
|
Params: params,
|
||||||
|
SigningBundle: signingBundle,
|
||||||
|
CSR: csr,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := SignCertificate(data)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("should have failed signing csr with ignore csr signature disabled")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "request signature invalid") {
|
||||||
|
t.Fatalf("expected error to contain 'request signature invalid': got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(fmt.Sprintf("ignore-csr-enabled"), func(t *testing.T) {
|
||||||
|
params := &CreationParameters{
|
||||||
|
IgnoreCSRSignature: true,
|
||||||
|
URLs: &URLEntries{},
|
||||||
|
}
|
||||||
|
data := &CreationBundle{
|
||||||
|
Params: params,
|
||||||
|
SigningBundle: signingBundle,
|
||||||
|
CSR: csr,
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := SignCertificate(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to sign certificate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cert.Verify(); err != nil {
|
||||||
|
t.Fatalf("signature verification failed: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func genRsaKey(t *testing.T) *rsa.PrivateKey {
|
func genRsaKey(t *testing.T) *rsa.PrivateKey {
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1186,10 +1186,11 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
|
|||||||
return nil, errutil.UserError{Err: "nil csr given to signCertificate"}
|
return nil, errutil.UserError{Err: "nil csr given to signCertificate"}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := data.CSR.CheckSignature()
|
if !data.Params.IgnoreCSRSignature {
|
||||||
if err != nil {
|
if err := data.CSR.CheckSignature(); err != nil {
|
||||||
return nil, errutil.UserError{Err: "request signature invalid"}
|
return nil, errutil.UserError{Err: "request signature invalid"}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result := &ParsedCertBundle{}
|
result := &ParsedCertBundle{}
|
||||||
|
|
||||||
|
|||||||
@@ -819,6 +819,11 @@ type CreationParameters struct {
|
|||||||
|
|
||||||
// The explicit SKID to use; especially useful for cross-signing.
|
// The explicit SKID to use; especially useful for cross-signing.
|
||||||
SKID []byte
|
SKID []byte
|
||||||
|
|
||||||
|
// Ignore validating the CSR's signature. This should only be enabled if the
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreationBundle struct {
|
type CreationBundle struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user