Change use_csr_subject to use_csr_values; copy not only the subject, but

also the alternate names and the extensions over as well.
This commit is contained in:
Jeff Mitchell 2015-10-12 20:46:58 -04:00
parent e8f1e8eb98
commit aae434576f
2 changed files with 59 additions and 58 deletions

View File

@ -17,8 +17,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/hashicorp/uuid"
"github.com/hashicorp/vault/helper/certutil" "github.com/hashicorp/vault/helper/certutil"
"github.com/hashicorp/vault/helper/uuid"
"github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework" "github.com/hashicorp/vault/logical/framework"
) )
@ -50,7 +50,7 @@ type certCreationBundle struct {
PKIAddress string PKIAddress string
// Only used when signing a CA cert // Only used when signing a CA cert
UseCSRSubject bool UseCSRValues bool
} }
type caInfoBundle struct { type caInfoBundle struct {
@ -296,7 +296,7 @@ func signCert(b *backend,
role *roleEntry, role *roleEntry,
signingBundle *caInfoBundle, signingBundle *caInfoBundle,
isCA bool, isCA bool,
useCSRSubject bool, useCSRValues bool,
req *logical.Request, req *logical.Request,
data *framework.FieldData) (*certutil.ParsedCertBundle, error) { data *framework.FieldData) (*certutil.ParsedCertBundle, error) {
@ -323,7 +323,7 @@ func signCert(b *backend,
if isCA { if isCA {
creationBundle.IsCA = isCA creationBundle.IsCA = isCA
creationBundle.UseCSRSubject = useCSRSubject creationBundle.UseCSRValues = useCSRValues
} }
parsedBundle, err := signCertificate(creationBundle, csr) parsedBundle, err := signCertificate(creationBundle, csr)
@ -435,7 +435,7 @@ func generateCreationBundle(b *backend,
ttl = maxTTL ttl = maxTTL
} else { } else {
return nil, certutil.UserError{Err: fmt.Sprintf( return nil, certutil.UserError{Err: fmt.Sprintf(
"ttl is larger than maximum allowed by this role")} "ttl is larger than maximum allowed (%d)", maxTTL/time.Second)}
} }
} }
@ -586,14 +586,9 @@ func createCertificate(creationInfo *certCreationBundle) (*certutil.ParsedCertBu
case certutil.ECPrivateKey: case certutil.ECPrivateKey:
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
} }
caCert := creationInfo.SigningBundle.Certificate caCert := creationInfo.SigningBundle.Certificate
subject.Country = caCert.Subject.Country
subject.Organization = caCert.Subject.Organization
subject.OrganizationalUnit = caCert.Subject.OrganizationalUnit
subject.Locality = caCert.Subject.Locality
subject.Province = caCert.Subject.Province
subject.StreetAddress = caCert.Subject.StreetAddress
subject.PostalCode = caCert.Subject.PostalCode
if creationInfo.SigningBundle.PKIAddress != "" { if creationInfo.SigningBundle.PKIAddress != "" {
certTemplate.CRLDistributionPoints = []string{ certTemplate.CRLDistributionPoints = []string{
creationInfo.SigningBundle.PKIAddress + "/crl", creationInfo.SigningBundle.PKIAddress + "/crl",
@ -747,33 +742,23 @@ func signCertificate(creationInfo *certCreationBundle,
return nil, certutil.InternalError{Err: fmt.Sprintf("error getting random serial number")} return nil, certutil.InternalError{Err: fmt.Sprintf("error getting random serial number")}
} }
subject := pkix.Name{
CommonName: creationInfo.CommonName,
}
marshaledKey, err := x509.MarshalPKIXPublicKey(csr.PublicKey) marshaledKey, err := x509.MarshalPKIXPublicKey(csr.PublicKey)
if err != nil { if err != nil {
return nil, certutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} return nil, certutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)}
} }
subjKeyID := sha1.Sum(marshaledKey) subjKeyID := sha1.Sum(marshaledKey)
subject := pkix.Name{
CommonName: creationInfo.CommonName,
}
certTemplate := &x509.Certificate{ certTemplate := &x509.Certificate{
SerialNumber: serialNumber, SerialNumber: serialNumber,
Subject: subject, Subject: subject,
NotBefore: time.Now(), NotBefore: time.Now(),
NotAfter: time.Now().Add(creationInfo.TTL), NotAfter: time.Now().Add(creationInfo.TTL),
KeyUsage: x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement),
BasicConstraintsValid: true, BasicConstraintsValid: true,
IsCA: false, SubjectKeyId: subjKeyID[:],
SubjectKeyId: subjKeyID[:],
}
if creationInfo.UseCSRSubject {
certTemplate.Subject = csr.Subject
} else {
certTemplate.DNSNames = creationInfo.DNSNames
certTemplate.EmailAddresses = creationInfo.EmailAddresses
certTemplate.IPAddresses = creationInfo.IPAddresses
} }
switch creationInfo.SigningBundle.PrivateKeyType { switch creationInfo.SigningBundle.PrivateKeyType {
@ -783,28 +768,46 @@ func signCertificate(creationInfo *certCreationBundle,
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
} }
if creationInfo.Usage&serverUsage != 0 { if creationInfo.UseCSRValues {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth) certTemplate.Subject = csr.Subject
}
if creationInfo.Usage&clientUsage != 0 { certTemplate.DNSNames = csr.DNSNames
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth) certTemplate.EmailAddresses = csr.EmailAddresses
} certTemplate.IPAddresses = csr.IPAddresses
if creationInfo.Usage&codeSigningUsage != 0 {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning) if creationInfo.IsCA {
} certTemplate.IsCA = true
if creationInfo.Usage&emailProtectionUsage != 0 { certTemplate.ExtraExtensions = csr.Extensions
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection) }
} else {
certTemplate.DNSNames = creationInfo.DNSNames
certTemplate.EmailAddresses = creationInfo.EmailAddresses
certTemplate.IPAddresses = creationInfo.IPAddresses
certTemplate.KeyUsage = x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement)
if creationInfo.Usage&serverUsage != 0 {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
}
if creationInfo.Usage&clientUsage != 0 {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
}
if creationInfo.Usage&codeSigningUsage != 0 {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning)
}
if creationInfo.Usage&emailProtectionUsage != 0 {
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection)
}
if creationInfo.IsCA {
certTemplate.IsCA = true
certTemplate.KeyUsage = x509.KeyUsage(certTemplate.KeyUsage | x509.KeyUsageCertSign | x509.KeyUsageCRLSign)
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning)
}
} }
var certBytes []byte var certBytes []byte
caCert := creationInfo.SigningBundle.Certificate caCert := creationInfo.SigningBundle.Certificate
subject.Country = caCert.Subject.Country
subject.Organization = caCert.Subject.Organization
subject.OrganizationalUnit = caCert.Subject.OrganizationalUnit
subject.Locality = caCert.Subject.Locality
subject.Province = caCert.Subject.Province
subject.StreetAddress = caCert.Subject.StreetAddress
subject.PostalCode = caCert.Subject.PostalCode
if creationInfo.SigningBundle.PKIAddress != "" { if creationInfo.SigningBundle.PKIAddress != "" {
certTemplate.CRLDistributionPoints = []string{ certTemplate.CRLDistributionPoints = []string{
@ -815,12 +818,6 @@ func signCertificate(creationInfo *certCreationBundle,
} }
} }
if creationInfo.IsCA {
certTemplate.IsCA = true
certTemplate.KeyUsage = x509.KeyUsage(certTemplate.KeyUsage | x509.KeyUsageCertSign | x509.KeyUsageCRLSign)
certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning)
}
certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, csr.PublicKey, creationInfo.SigningBundle.PrivateKey) certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, csr.PublicKey, creationInfo.SigningBundle.PrivateKey)
if err != nil { if err != nil {

View File

@ -210,13 +210,17 @@ func pathSignIntermediateCA(b *backend) *framework.Path {
Description: `PEM-format CSR to be signed.`, Description: `PEM-format CSR to be signed.`,
} }
ret.Fields["use_csr_subject"] = &framework.FieldSchema{ ret.Fields["use_csr_values"] = &framework.FieldSchema{
Type: framework.TypeBool, Type: framework.TypeBool,
Description: `If true, the subject information, Description: `If true, then:
including names and alternate names, 1) Subject information, including names and alternate
will be preserved from the CSR rather names, will be preserved from the CSR rather than
than using values provided in the using values provided in the other parameters to
other parameters to this path.`, this path;
2) Any key usages requested in the CSR will be
added to the basic set of key usages used for CA
certs signed by this path; for instance,
the non-repudiation flag.`,
} }
return ret return ret
@ -515,7 +519,7 @@ func (b *backend) pathCASignIntermediate(
"error fetching CA certificate: %s", caErr)} "error fetching CA certificate: %s", caErr)}
} }
useCSRValues := data.Get("use_csr_subject").(bool) useCSRValues := data.Get("use_csr_values").(bool)
parsedBundle, err := signCert(b, role, signingBundle, true, useCSRValues, req, data) parsedBundle, err := signCert(b, role, signingBundle, true, useCSRValues, req, data)
if err != nil { if err != nil {