diff --git a/builtin/logical/pki/cert_util.go b/builtin/logical/pki/cert_util.go index 5733b489d9..63a4b4eec7 100644 --- a/builtin/logical/pki/cert_util.go +++ b/builtin/logical/pki/cert_util.go @@ -17,8 +17,8 @@ import ( "strings" "time" + "github.com/hashicorp/uuid" "github.com/hashicorp/vault/helper/certutil" - "github.com/hashicorp/vault/helper/uuid" "github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical/framework" ) @@ -50,7 +50,7 @@ type certCreationBundle struct { PKIAddress string // Only used when signing a CA cert - UseCSRSubject bool + UseCSRValues bool } type caInfoBundle struct { @@ -296,7 +296,7 @@ func signCert(b *backend, role *roleEntry, signingBundle *caInfoBundle, isCA bool, - useCSRSubject bool, + useCSRValues bool, req *logical.Request, data *framework.FieldData) (*certutil.ParsedCertBundle, error) { @@ -323,7 +323,7 @@ func signCert(b *backend, if isCA { creationBundle.IsCA = isCA - creationBundle.UseCSRSubject = useCSRSubject + creationBundle.UseCSRValues = useCSRValues } parsedBundle, err := signCertificate(creationBundle, csr) @@ -435,7 +435,7 @@ func generateCreationBundle(b *backend, ttl = maxTTL } else { 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: certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } + 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 != "" { certTemplate.CRLDistributionPoints = []string{ creationInfo.SigningBundle.PKIAddress + "/crl", @@ -747,33 +742,23 @@ func signCertificate(creationInfo *certCreationBundle, return nil, certutil.InternalError{Err: fmt.Sprintf("error getting random serial number")} } - subject := pkix.Name{ - CommonName: creationInfo.CommonName, - } - marshaledKey, err := x509.MarshalPKIXPublicKey(csr.PublicKey) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} } subjKeyID := sha1.Sum(marshaledKey) + subject := pkix.Name{ + CommonName: creationInfo.CommonName, + } + certTemplate := &x509.Certificate{ SerialNumber: serialNumber, Subject: subject, NotBefore: time.Now(), NotAfter: time.Now().Add(creationInfo.TTL), - KeyUsage: x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement), BasicConstraintsValid: true, - IsCA: false, - SubjectKeyId: subjKeyID[:], - } - - if creationInfo.UseCSRSubject { - certTemplate.Subject = csr.Subject - } else { - certTemplate.DNSNames = creationInfo.DNSNames - certTemplate.EmailAddresses = creationInfo.EmailAddresses - certTemplate.IPAddresses = creationInfo.IPAddresses + SubjectKeyId: subjKeyID[:], } switch creationInfo.SigningBundle.PrivateKeyType { @@ -783,28 +768,46 @@ func signCertificate(creationInfo *certCreationBundle, certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } - 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.UseCSRValues { + certTemplate.Subject = csr.Subject + + certTemplate.DNSNames = csr.DNSNames + certTemplate.EmailAddresses = csr.EmailAddresses + certTemplate.IPAddresses = csr.IPAddresses + + if creationInfo.IsCA { + certTemplate.IsCA = true + certTemplate.ExtraExtensions = csr.Extensions + } + } 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 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 != "" { 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) if err != nil { diff --git a/builtin/logical/pki/path_config_ca.go b/builtin/logical/pki/path_config_ca.go index 7d92c80d57..a4f5270e9d 100644 --- a/builtin/logical/pki/path_config_ca.go +++ b/builtin/logical/pki/path_config_ca.go @@ -210,13 +210,17 @@ func pathSignIntermediateCA(b *backend) *framework.Path { Description: `PEM-format CSR to be signed.`, } - ret.Fields["use_csr_subject"] = &framework.FieldSchema{ + ret.Fields["use_csr_values"] = &framework.FieldSchema{ Type: framework.TypeBool, - Description: `If true, the subject information, -including names and alternate names, -will be preserved from the CSR rather -than using values provided in the -other parameters to this path.`, + Description: `If true, then: +1) Subject information, including names and alternate +names, will be preserved from the CSR rather than +using values provided in the other parameters to +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 @@ -515,7 +519,7 @@ func (b *backend) pathCASignIntermediate( "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) if err != nil {