diff --git a/builtin/logical/pki/ca_util.go b/builtin/logical/pki/ca_util.go index 6e757f014..3a2c37a8c 100644 --- a/builtin/logical/pki/ca_util.go +++ b/builtin/logical/pki/ca_util.go @@ -22,7 +22,7 @@ func (b *backend) getGenerationParams( format = getFormat(data) if format == "" { errorResp = logical.ErrorResponse( - `The "format" path parameter must be "pem" or "der"`) + `The "format" path parameter must be "pem", "der", or "pem_bundle"`) return } diff --git a/builtin/logical/pki/cert_util.go b/builtin/logical/pki/cert_util.go index 9d8037b86..9d002669e 100644 --- a/builtin/logical/pki/cert_util.go +++ b/builtin/logical/pki/cert_util.go @@ -74,6 +74,7 @@ func getFormat(data *framework.FieldData) string { switch format { case "pem": case "der": + case "pem_bundle": default: format = "" } diff --git a/builtin/logical/pki/fields.go b/builtin/logical/pki/fields.go index cef49144e..bf9b557bd 100644 --- a/builtin/logical/pki/fields.go +++ b/builtin/logical/pki/fields.go @@ -8,8 +8,10 @@ func addIssueAndSignCommonFields(fields map[string]*framework.FieldSchema) map[s fields["format"] = &framework.FieldSchema{ Type: framework.TypeString, Default: "pem", - Description: `Format for returned data. Can be "pem" or "der"; -defaults to "pem".`, + Description: `Format for returned data. Can be "pem", "der", +or "pem_bundle". If "pem_bundle" any private +private key and issuing cert will be appended +to the certificate pem. Defaults to "pem".`, } fields["ip_sans"] = &framework.FieldSchema{ diff --git a/builtin/logical/pki/path_intermediate.go b/builtin/logical/pki/path_intermediate.go index 929ffe276..ff27f9d5c 100644 --- a/builtin/logical/pki/path_intermediate.go +++ b/builtin/logical/pki/path_intermediate.go @@ -88,6 +88,15 @@ func (b *backend) pathGenerateIntermediate( resp.Data["private_key"] = csrb.PrivateKey resp.Data["private_key_type"] = csrb.PrivateKeyType } + + case "pem_bundle": + resp.Data["csr"] = csrb.CSR + if exported { + resp.Data["csr"] = fmt.Sprintf("%s\n%s", csrb.PrivateKey, csrb.CSR) + resp.Data["private_key"] = csrb.PrivateKey + resp.Data["private_key_type"] = csrb.PrivateKeyType + } + case "der": resp.Data["csr"] = base64.StdEncoding.EncodeToString(parsedBundle.CSRBytes) if exported { diff --git a/builtin/logical/pki/path_issue_sign.go b/builtin/logical/pki/path_issue_sign.go index c6da42c94..c85dd8744 100644 --- a/builtin/logical/pki/path_issue_sign.go +++ b/builtin/logical/pki/path_issue_sign.go @@ -133,7 +133,7 @@ func (b *backend) pathIssueSignCert( format := getFormat(data) if format == "" { return logical.ErrorResponse( - `The "format" path parameter must be "pem" or "der"`), nil + `The "format" path parameter must be "pem", "der", or "pem_bundle"`), nil } var caErr error @@ -170,20 +170,33 @@ func (b *backend) pathIssueSignCert( resp := b.Secret(SecretCertsType).Response( map[string]interface{}{ - "certificate": cb.Certificate, - "issuing_ca": cb.IssuingCA, - "serial_number": cb.SerialNumber, + "certificate": cb.Certificate, + "issuing_ca": cb.IssuingCA, }, map[string]interface{}{ "serial_number": cb.SerialNumber, }) - if !useCSR { - resp.Data["private_key"] = cb.PrivateKey - resp.Data["private_key_type"] = cb.PrivateKeyType - } + switch format { + case "pem": + resp.Data["issuing_ca"] = cb.IssuingCA + resp.Data["certificate"] = cb.Certificate - if format == "der" { + if !useCSR { + resp.Data["private_key"] = cb.PrivateKey + resp.Data["private_key_type"] = cb.PrivateKeyType + } + + case "pem_bundle": + resp.Data["issuing_ca"] = cb.IssuingCA + resp.Data["certificate"] = fmt.Sprintf("%s\n%s", cb.Certificate, cb.IssuingCA) + if !useCSR { + resp.Data["private_key"] = cb.PrivateKey + resp.Data["private_key_type"] = cb.PrivateKeyType + resp.Data["certificate"] = fmt.Sprintf("%s\n%s\n%s", cb.PrivateKey, cb.Certificate, cb.IssuingCA) + } + + case "der": resp.Data["certificate"] = base64.StdEncoding.EncodeToString(parsedBundle.CertificateBytes) resp.Data["issuing_ca"] = base64.StdEncoding.EncodeToString(parsedBundle.IssuingCABytes) if !useCSR { diff --git a/builtin/logical/pki/path_root.go b/builtin/logical/pki/path_root.go index d4dee5a6e..6bc14d535 100644 --- a/builtin/logical/pki/path_root.go +++ b/builtin/logical/pki/path_root.go @@ -101,8 +101,6 @@ func (b *backend) pathCAGenerateRoot( map[string]interface{}{ "expiration": int64(parsedBundle.Certificate.NotAfter.Unix()), "serial_number": cb.SerialNumber, - "certificate": cb.Certificate, - "issuing_ca": cb.IssuingCA, }, map[string]interface{}{ "serial_number": cb.SerialNumber, @@ -110,10 +108,24 @@ func (b *backend) pathCAGenerateRoot( switch format { case "pem": + resp.Data["certificate"] = cb.Certificate + resp.Data["issuing_ca"] = cb.IssuingCA if exported { resp.Data["private_key"] = cb.PrivateKey resp.Data["private_key_type"] = cb.PrivateKeyType } + + case "pem_bundle": + resp.Data["issuing_ca"] = cb.IssuingCA + + if exported { + resp.Data["private_key"] = cb.PrivateKey + resp.Data["private_key_type"] = cb.PrivateKeyType + resp.Data["certificate"] = fmt.Sprintf("%s\n%s\n%s", cb.PrivateKey, cb.Certificate, cb.IssuingCA) + } else { + resp.Data["certificate"] = fmt.Sprintf("%s\n%s", cb.Certificate, cb.IssuingCA) + } + case "der": resp.Data["certificate"] = base64.StdEncoding.EncodeToString(parsedBundle.CertificateBytes) resp.Data["issuing_ca"] = base64.StdEncoding.EncodeToString(parsedBundle.IssuingCABytes) @@ -228,14 +240,21 @@ func (b *backend) pathCASignIntermediate( map[string]interface{}{ "expiration": int64(parsedBundle.Certificate.NotAfter.Unix()), "serial_number": cb.SerialNumber, - "certificate": cb.Certificate, - "issuing_ca": cb.IssuingCA, }, map[string]interface{}{ "serial_number": cb.SerialNumber, }) - if format == "der" { + switch format { + case "pem": + resp.Data["certificate"] = cb.Certificate + resp.Data["issuing_ca"] = cb.IssuingCA + + case "pem_bundle": + resp.Data["certificate"] = fmt.Sprintf("%s\n%s", cb.Certificate, cb.IssuingCA) + resp.Data["issuing_ca"] = cb.IssuingCA + + case "der": resp.Data["certificate"] = base64.StdEncoding.EncodeToString(parsedBundle.CertificateBytes) resp.Data["issuing_ca"] = base64.StdEncoding.EncodeToString(parsedBundle.IssuingCABytes) } diff --git a/website/source/docs/secrets/pki/index.html.md b/website/source/docs/secrets/pki/index.html.md index 5a97de9eb..f9b359854 100644 --- a/website/source/docs/secrets/pki/index.html.md +++ b/website/source/docs/secrets/pki/index.html.md @@ -741,8 +741,10 @@ subpath for interactive help output.