2015-05-15 16:13:05 +00:00
|
|
|
package pki
|
|
|
|
|
|
|
|
import (
|
2018-01-08 18:31:38 +00:00
|
|
|
"context"
|
2021-09-15 16:59:12 +00:00
|
|
|
"crypto/rand"
|
2015-11-12 16:24:32 +00:00
|
|
|
"encoding/base64"
|
2015-05-15 16:13:05 +00:00
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2019-04-13 07:44:06 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/certutil"
|
2019-12-05 18:50:28 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/errutil"
|
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
2015-05-15 16:13:05 +00:00
|
|
|
)
|
|
|
|
|
2015-09-29 23:13:54 +00:00
|
|
|
func pathIssue(b *backend) *framework.Path {
|
2015-11-16 16:42:06 +00:00
|
|
|
ret := &framework.Path{
|
2015-09-29 23:13:54 +00:00
|
|
|
Pattern: "issue/" + framework.GenericNameRegex("role"),
|
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2022-02-08 16:37:40 +00:00
|
|
|
logical.UpdateOperation: b.metricsWrap("issue", roleRequired, b.pathIssue),
|
2015-05-15 16:13:05 +00:00
|
|
|
},
|
|
|
|
|
2015-10-02 19:47:45 +00:00
|
|
|
HelpSynopsis: pathIssueHelpSyn,
|
|
|
|
HelpDescription: pathIssueHelpDesc,
|
2015-09-29 23:13:54 +00:00
|
|
|
}
|
2015-11-16 16:42:06 +00:00
|
|
|
|
|
|
|
ret.Fields = addNonCACommonFields(map[string]*framework.FieldSchema{})
|
|
|
|
return ret
|
2015-09-29 23:13:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func pathSign(b *backend) *framework.Path {
|
2015-09-30 01:48:31 +00:00
|
|
|
ret := &framework.Path{
|
2015-09-29 23:13:54 +00:00
|
|
|
Pattern: "sign/" + framework.GenericNameRegex("role"),
|
|
|
|
|
2015-05-15 16:13:05 +00:00
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2022-02-08 16:37:40 +00:00
|
|
|
logical.UpdateOperation: b.metricsWrap("sign", roleRequired, b.pathSign),
|
2015-05-15 16:13:05 +00:00
|
|
|
},
|
|
|
|
|
2015-10-02 19:47:45 +00:00
|
|
|
HelpSynopsis: pathSignHelpSyn,
|
|
|
|
HelpDescription: pathSignHelpDesc,
|
2015-05-15 16:13:05 +00:00
|
|
|
}
|
2015-09-30 01:48:31 +00:00
|
|
|
|
2015-11-16 16:42:06 +00:00
|
|
|
ret.Fields = addNonCACommonFields(map[string]*framework.FieldSchema{})
|
|
|
|
|
2015-09-30 01:48:31 +00:00
|
|
|
ret.Fields["csr"] = &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2015-11-12 16:24:32 +00:00
|
|
|
Default: "",
|
2015-09-30 01:48:31 +00:00
|
|
|
Description: `PEM-format CSR to be signed.`,
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
2015-05-15 16:13:05 +00:00
|
|
|
}
|
|
|
|
|
2015-11-18 15:16:09 +00:00
|
|
|
func pathSignVerbatim(b *backend) *framework.Path {
|
|
|
|
ret := &framework.Path{
|
2017-01-10 14:47:59 +00:00
|
|
|
Pattern: "sign-verbatim" + framework.OptionalParamRegex("role"),
|
2015-11-18 15:16:09 +00:00
|
|
|
|
|
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
2022-02-08 16:37:40 +00:00
|
|
|
logical.UpdateOperation: b.metricsWrap("sign-verbatim", roleOptional, b.pathSignVerbatim),
|
2015-11-18 15:16:09 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
HelpSynopsis: pathSignHelpSyn,
|
|
|
|
HelpDescription: pathSignHelpDesc,
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.Fields = addNonCACommonFields(map[string]*framework.FieldSchema{})
|
|
|
|
|
|
|
|
ret.Fields["csr"] = &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Default: "",
|
|
|
|
Description: `PEM-format CSR to be signed. Values will be
|
|
|
|
taken verbatim from the CSR, except for
|
|
|
|
basic constraints.`,
|
|
|
|
}
|
|
|
|
|
2018-06-15 22:20:43 +00:00
|
|
|
ret.Fields["key_usage"] = &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Default: []string{"DigitalSignature", "KeyAgreement", "KeyEncipherment"},
|
|
|
|
Description: `A comma-separated string or list of key usages (not extended
|
|
|
|
key usages). Valid values can be found at
|
|
|
|
https://golang.org/pkg/crypto/x509/#KeyUsage
|
|
|
|
-- simply drop the "KeyUsage" part of the name.
|
|
|
|
To remove all key usages from being set, set
|
|
|
|
this value to an empty list.`,
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.Fields["ext_key_usage"] = &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Default: []string{},
|
|
|
|
Description: `A comma-separated string or list of extended key usages. Valid values can be found at
|
|
|
|
https://golang.org/pkg/crypto/x509/#ExtKeyUsage
|
|
|
|
-- simply drop the "ExtKeyUsage" part of the name.
|
|
|
|
To remove all key usages from being set, set
|
|
|
|
this value to an empty list.`,
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.Fields["ext_key_usage_oids"] = &framework.FieldSchema{
|
|
|
|
Type: framework.TypeCommaStringSlice,
|
|
|
|
Description: `A comma-separated string or list of extended key usage oids.`,
|
|
|
|
}
|
|
|
|
|
2015-11-18 15:16:09 +00:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2015-11-19 21:51:27 +00:00
|
|
|
// pathIssue issues a certificate and private key from given parameters,
|
|
|
|
// subject to role restrictions
|
2022-02-08 16:37:40 +00:00
|
|
|
func (b *backend) pathIssue(ctx context.Context, req *logical.Request, data *framework.FieldData, role *roleEntry) (*logical.Response, error) {
|
2018-05-19 17:24:43 +00:00
|
|
|
if role.KeyType == "any" {
|
|
|
|
return logical.ErrorResponse("role key type \"any\" not allowed for issuing certificates, only signing"), nil
|
2015-11-18 15:16:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.pathIssueSignCert(ctx, req, data, role, false, false)
|
2015-09-30 01:48:31 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 21:51:27 +00:00
|
|
|
// pathSign issues a certificate from a submitted CSR, subject to role
|
|
|
|
// restrictions
|
2022-02-08 16:37:40 +00:00
|
|
|
func (b *backend) pathSign(ctx context.Context, req *logical.Request, data *framework.FieldData, role *roleEntry) (*logical.Response, error) {
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.pathIssueSignCert(ctx, req, data, role, true, false)
|
2015-11-18 15:16:09 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 21:51:27 +00:00
|
|
|
// pathSignVerbatim issues a certificate from a submitted CSR, *not* subject to
|
|
|
|
// role restrictions
|
2022-02-08 16:37:40 +00:00
|
|
|
func (b *backend) pathSignVerbatim(ctx context.Context, req *logical.Request, data *framework.FieldData, role *roleEntry) (*logical.Response, error) {
|
2017-04-18 19:54:31 +00:00
|
|
|
entry := &roleEntry{
|
Add role parameter to restrict issuance of wildcard certificates (#14238)
* Add new AllowWildcardCertificate field to PKI role
This field allows the PKI role to control whether or not issuance of
wildcard certificates are allowed. We default (both on migration and
new role creation) to the less secure true value for backwards
compatibility with existing Vault versions.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Refactor sanitizedName to reducedName
Per comment, this variable name was confusing during the reproduction
and subsequent fix of the earlier vulnerability and associated bug
report. Because the common name isn't necessarily _sanitized_ in any way
(and indeed must be considered in relation to other parts or the whole),
but portions of the entire name are removed, reducedName appears to make
the most sense.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Enforce AllowWildcardCertificates during issuance
This commit adds the bulk of correctly validating wildcard certificate
Common Names during issuance according to RFC 6125 Section 6.4.3
semantics. As part of this, support for RFC 2818-conforming wildcard
certificates (wherein there are almost no restrictions on issuance) has
been removed.
Note that this flag does take precedence over AllowAnyName, giving a
little more safety in wildcard issuance in this case.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Update test cases to conform with RFC 6125
Test cases 19, 70+71, and 83+84 didn't conform with the RFC 6125, and so
should've been rejected under strict conformance. For 70+71 and 83+84,
we previously conditioned around the value of AllowSubdomains (allowing
issuance when true), but they likely should've been rejected either way.
Additionally, update the notes about globs matching wildcard
certificates to notate this is indeed the case.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Check AllowWildcardCertifciates in issuance tests
This allows for regression tests to cover the new
AllowWildcardCertificate conditional. We add additional test cases
ensuring that wildcard issuance is properly forbidden in all relevant
scenarios, while allowing the existing test cases to validate that
wildcard status doesn't affect non-wildcard certificates.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Add Wildcard allowance during signing operations
When using sign-verbatim, sign-intermediate, or getting certificate
generation parameters, set AllowWildcardCertificates to mirror existing
policies.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Add changelog entry
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-02-24 13:41:56 +00:00
|
|
|
AllowLocalhost: true,
|
|
|
|
AllowAnyName: true,
|
|
|
|
AllowIPSANs: true,
|
|
|
|
AllowWildcardCertificates: new(bool),
|
|
|
|
EnforceHostnames: false,
|
|
|
|
KeyType: "any",
|
|
|
|
UseCSRCommonName: true,
|
|
|
|
UseCSRSANs: true,
|
|
|
|
AllowedOtherSANs: []string{"*"},
|
|
|
|
AllowedSerialNumbers: []string{"*"},
|
|
|
|
AllowedURISANs: []string{"*"},
|
|
|
|
GenerateLease: new(bool),
|
|
|
|
KeyUsage: data.Get("key_usage").([]string),
|
|
|
|
ExtKeyUsage: data.Get("ext_key_usage").([]string),
|
|
|
|
ExtKeyUsageOIDs: data.Get("ext_key_usage_oids").([]string),
|
2017-04-18 19:54:31 +00:00
|
|
|
}
|
Add role parameter to restrict issuance of wildcard certificates (#14238)
* Add new AllowWildcardCertificate field to PKI role
This field allows the PKI role to control whether or not issuance of
wildcard certificates are allowed. We default (both on migration and
new role creation) to the less secure true value for backwards
compatibility with existing Vault versions.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Refactor sanitizedName to reducedName
Per comment, this variable name was confusing during the reproduction
and subsequent fix of the earlier vulnerability and associated bug
report. Because the common name isn't necessarily _sanitized_ in any way
(and indeed must be considered in relation to other parts or the whole),
but portions of the entire name are removed, reducedName appears to make
the most sense.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Enforce AllowWildcardCertificates during issuance
This commit adds the bulk of correctly validating wildcard certificate
Common Names during issuance according to RFC 6125 Section 6.4.3
semantics. As part of this, support for RFC 2818-conforming wildcard
certificates (wherein there are almost no restrictions on issuance) has
been removed.
Note that this flag does take precedence over AllowAnyName, giving a
little more safety in wildcard issuance in this case.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Update test cases to conform with RFC 6125
Test cases 19, 70+71, and 83+84 didn't conform with the RFC 6125, and so
should've been rejected under strict conformance. For 70+71 and 83+84,
we previously conditioned around the value of AllowSubdomains (allowing
issuance when true), but they likely should've been rejected either way.
Additionally, update the notes about globs matching wildcard
certificates to notate this is indeed the case.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Check AllowWildcardCertifciates in issuance tests
This allows for regression tests to cover the new
AllowWildcardCertificate conditional. We add additional test cases
ensuring that wildcard issuance is properly forbidden in all relevant
scenarios, while allowing the existing test cases to validate that
wildcard status doesn't affect non-wildcard certificates.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Add Wildcard allowance during signing operations
When using sign-verbatim, sign-intermediate, or getting certificate
generation parameters, set AllowWildcardCertificates to mirror existing
policies.
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
* Add changelog entry
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-02-24 13:41:56 +00:00
|
|
|
*entry.AllowWildcardCertificates = true
|
2017-04-18 19:54:31 +00:00
|
|
|
|
2018-05-09 14:29:54 +00:00
|
|
|
*entry.GenerateLease = false
|
|
|
|
|
2017-04-18 19:54:31 +00:00
|
|
|
if role != nil {
|
2018-05-09 14:29:54 +00:00
|
|
|
if role.TTL > 0 {
|
|
|
|
entry.TTL = role.TTL
|
2017-04-18 19:54:31 +00:00
|
|
|
}
|
2018-05-09 14:29:54 +00:00
|
|
|
if role.MaxTTL > 0 {
|
|
|
|
entry.MaxTTL = role.MaxTTL
|
2018-03-20 01:01:41 +00:00
|
|
|
}
|
2018-05-09 14:29:54 +00:00
|
|
|
if role.GenerateLease != nil {
|
|
|
|
*entry.GenerateLease = *role.GenerateLease
|
2017-04-18 19:54:31 +00:00
|
|
|
}
|
|
|
|
entry.NoStore = role.NoStore
|
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.pathIssueSignCert(ctx, req, data, entry, true, true)
|
2015-11-18 15:16:09 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *backend) pathIssueSignCert(ctx context.Context, req *logical.Request, data *framework.FieldData, role *roleEntry, useCSR, useCSRValues bool) (*logical.Response, error) {
|
2019-12-05 18:50:28 +00:00
|
|
|
// If storing the certificate and on a performance standby, forward this request on to the primary
|
2022-01-24 16:03:04 +00:00
|
|
|
// Allow performance secondaries to generate and store certificates locally to them.
|
|
|
|
if !role.NoStore && b.System().ReplicationState().HasState(consts.ReplicationPerformanceStandby) {
|
2019-12-05 18:50:28 +00:00
|
|
|
return nil, logical.ErrReadOnly
|
|
|
|
}
|
|
|
|
|
2015-11-16 21:32:49 +00:00
|
|
|
format := getFormat(data)
|
|
|
|
if format == "" {
|
2015-11-12 16:24:32 +00:00
|
|
|
return logical.ErrorResponse(
|
2017-10-27 16:02:18 +00:00
|
|
|
`the "format" path parameter must be "pem", "der", or "pem_bundle"`), nil
|
2015-11-12 16:24:32 +00:00
|
|
|
}
|
|
|
|
|
2015-09-30 01:48:31 +00:00
|
|
|
var caErr error
|
2022-01-27 04:06:25 +00:00
|
|
|
signingBundle, caErr := fetchCAInfo(ctx, b, req)
|
2022-02-22 19:39:21 +00:00
|
|
|
if caErr != nil {
|
|
|
|
switch caErr.(type) {
|
|
|
|
case errutil.UserError:
|
|
|
|
return nil, errutil.UserError{Err: fmt.Sprintf(
|
|
|
|
"could not fetch the CA certificate (was one set?): %s", caErr)}
|
|
|
|
default:
|
|
|
|
return nil, errutil.InternalError{Err: fmt.Sprintf(
|
|
|
|
"error fetching CA certificate: %s", caErr)}
|
|
|
|
}
|
2015-09-30 01:48:31 +00:00
|
|
|
}
|
|
|
|
|
2019-05-09 15:43:11 +00:00
|
|
|
input := &inputBundle{
|
|
|
|
req: req,
|
|
|
|
apiData: data,
|
|
|
|
role: role,
|
2018-02-16 22:19:34 +00:00
|
|
|
}
|
2015-10-02 19:47:45 +00:00
|
|
|
var parsedBundle *certutil.ParsedCertBundle
|
2015-11-18 15:16:09 +00:00
|
|
|
var err error
|
2015-10-02 19:47:45 +00:00
|
|
|
if useCSR {
|
2019-05-09 15:43:11 +00:00
|
|
|
parsedBundle, err = signCert(b, input, signingBundle, false, useCSRValues)
|
2015-10-02 19:47:45 +00:00
|
|
|
} else {
|
2021-09-15 16:59:12 +00:00
|
|
|
parsedBundle, err = generateCert(ctx, b, input, signingBundle, false, rand.Reader)
|
2015-10-02 19:47:45 +00:00
|
|
|
}
|
2015-09-30 01:48:31 +00:00
|
|
|
if err != nil {
|
|
|
|
switch err.(type) {
|
2016-07-28 19:19:27 +00:00
|
|
|
case errutil.UserError:
|
2015-09-30 01:48:31 +00:00
|
|
|
return logical.ErrorResponse(err.Error()), nil
|
2016-07-28 19:19:27 +00:00
|
|
|
case errutil.InternalError:
|
2015-08-29 13:03:02 +00:00
|
|
|
return nil, err
|
2019-12-11 15:16:44 +00:00
|
|
|
default:
|
2021-04-22 15:20:59 +00:00
|
|
|
return nil, fmt.Errorf("error signing/generating certificate: %w", err)
|
2015-08-29 13:03:02 +00:00
|
|
|
}
|
2015-05-15 16:13:05 +00:00
|
|
|
}
|
|
|
|
|
2016-09-28 00:50:17 +00:00
|
|
|
signingCB, err := signingBundle.ToCertBundle()
|
|
|
|
if err != nil {
|
2021-04-22 15:20:59 +00:00
|
|
|
return nil, fmt.Errorf("error converting raw signing bundle to cert bundle: %w", err)
|
2016-09-28 00:50:17 +00:00
|
|
|
}
|
|
|
|
|
2015-06-17 16:43:36 +00:00
|
|
|
cb, err := parsedBundle.ToCertBundle()
|
2015-06-15 17:33:23 +00:00
|
|
|
if err != nil {
|
2021-04-22 15:20:59 +00:00
|
|
|
return nil, fmt.Errorf("error converting raw cert bundle to cert bundle: %w", err)
|
2015-05-15 16:13:05 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 17:12:40 +00:00
|
|
|
respData := map[string]interface{}{
|
2018-10-19 15:13:59 +00:00
|
|
|
"expiration": int64(parsedBundle.Certificate.NotAfter.Unix()),
|
2017-02-24 17:12:40 +00:00
|
|
|
"serial_number": cb.SerialNumber,
|
|
|
|
}
|
2015-05-15 16:13:05 +00:00
|
|
|
|
2016-02-01 18:19:41 +00:00
|
|
|
switch format {
|
|
|
|
case "pem":
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["issuing_ca"] = signingCB.Certificate
|
|
|
|
respData["certificate"] = cb.Certificate
|
2016-09-28 00:50:17 +00:00
|
|
|
if cb.CAChain != nil && len(cb.CAChain) > 0 {
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["ca_chain"] = cb.CAChain
|
2016-09-28 00:50:17 +00:00
|
|
|
}
|
2016-02-01 18:19:41 +00:00
|
|
|
if !useCSR {
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["private_key"] = cb.PrivateKey
|
|
|
|
respData["private_key_type"] = cb.PrivateKeyType
|
2016-02-01 18:19:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case "pem_bundle":
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["issuing_ca"] = signingCB.Certificate
|
|
|
|
respData["certificate"] = cb.ToPEMBundle()
|
2016-09-28 00:50:17 +00:00
|
|
|
if cb.CAChain != nil && len(cb.CAChain) > 0 {
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["ca_chain"] = cb.CAChain
|
2016-09-28 00:50:17 +00:00
|
|
|
}
|
2016-02-01 18:19:41 +00:00
|
|
|
if !useCSR {
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["private_key"] = cb.PrivateKey
|
|
|
|
respData["private_key_type"] = cb.PrivateKeyType
|
2016-02-01 18:19:41 +00:00
|
|
|
}
|
2015-11-19 16:32:18 +00:00
|
|
|
|
2016-02-01 18:19:41 +00:00
|
|
|
case "der":
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["certificate"] = base64.StdEncoding.EncodeToString(parsedBundle.CertificateBytes)
|
|
|
|
respData["issuing_ca"] = base64.StdEncoding.EncodeToString(signingBundle.CertificateBytes)
|
2016-09-28 00:50:17 +00:00
|
|
|
|
|
|
|
var caChain []string
|
|
|
|
for _, caCert := range parsedBundle.CAChain {
|
|
|
|
caChain = append(caChain, base64.StdEncoding.EncodeToString(caCert.Bytes))
|
|
|
|
}
|
|
|
|
if caChain != nil && len(caChain) > 0 {
|
2017-02-24 17:12:40 +00:00
|
|
|
respData["ca_chain"] = caChain
|
2016-09-28 00:50:17 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 16:32:18 +00:00
|
|
|
if !useCSR {
|
2017-02-24 17:41:20 +00:00
|
|
|
respData["private_key"] = base64.StdEncoding.EncodeToString(parsedBundle.PrivateKeyBytes)
|
|
|
|
respData["private_key_type"] = cb.PrivateKeyType
|
2015-11-19 16:32:18 +00:00
|
|
|
}
|
2015-11-12 16:24:32 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 17:12:40 +00:00
|
|
|
var resp *logical.Response
|
|
|
|
switch {
|
|
|
|
case role.GenerateLease == nil:
|
|
|
|
return nil, fmt.Errorf("generate lease in role is nil")
|
|
|
|
case *role.GenerateLease == false:
|
|
|
|
// If lease generation is disabled do not populate `Secret` field in
|
|
|
|
// the response
|
|
|
|
resp = &logical.Response{
|
|
|
|
Data: respData,
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
resp = b.Secret(SecretCertsType).Response(
|
|
|
|
respData,
|
|
|
|
map[string]interface{}{
|
|
|
|
"serial_number": cb.SerialNumber,
|
|
|
|
})
|
|
|
|
resp.Secret.TTL = parsedBundle.Certificate.NotAfter.Sub(time.Now())
|
|
|
|
}
|
2015-05-15 16:13:05 +00:00
|
|
|
|
2017-11-06 17:05:07 +00:00
|
|
|
if data.Get("private_key_format").(string) == "pkcs8" {
|
|
|
|
err = convertRespToPKCS8(resp)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 18:25:47 +00:00
|
|
|
if !role.NoStore {
|
2018-01-19 06:44:44 +00:00
|
|
|
err = req.Storage.Put(ctx, &logical.StorageEntry{
|
2017-05-03 14:12:58 +00:00
|
|
|
Key: "certs/" + normalizeSerial(cb.SerialNumber),
|
2017-04-07 18:25:47 +00:00
|
|
|
Value: parsedBundle.CertificateBytes,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-04-22 15:20:59 +00:00
|
|
|
return nil, fmt.Errorf("unable to store certificate locally: %w", err)
|
2017-04-07 18:25:47 +00:00
|
|
|
}
|
2015-05-15 16:13:05 +00:00
|
|
|
}
|
|
|
|
|
2017-08-02 14:02:40 +00:00
|
|
|
if useCSR {
|
|
|
|
if role.UseCSRCommonName && data.Get("common_name").(string) != "" {
|
|
|
|
resp.AddWarning("the common_name field was provided but the role is set with \"use_csr_common_name\" set to true")
|
|
|
|
}
|
|
|
|
if role.UseCSRSANs && data.Get("alt_names").(string) != "" {
|
|
|
|
resp.AddWarning("the alt_names field was provided but the role is set with \"use_csr_sans\" set to true")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-15 16:13:05 +00:00
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2015-10-02 19:47:45 +00:00
|
|
|
const pathIssueHelpSyn = `
|
|
|
|
Request a certificate using a certain role with the provided details.
|
2015-05-15 16:13:05 +00:00
|
|
|
`
|
|
|
|
|
2015-10-02 19:47:45 +00:00
|
|
|
const pathIssueHelpDesc = `
|
|
|
|
This path allows requesting a certificate to be issued according to the
|
|
|
|
policy of the given role. The certificate will only be issued if the
|
|
|
|
requested details are allowed by the role policy.
|
|
|
|
|
|
|
|
This path returns a certificate and a private key. If you want a workflow
|
|
|
|
that does not expose a private key, generate a CSR locally and use the
|
|
|
|
sign path instead.
|
|
|
|
`
|
|
|
|
|
|
|
|
const pathSignHelpSyn = `
|
|
|
|
Request certificates using a certain role with the provided details.
|
|
|
|
`
|
|
|
|
|
|
|
|
const pathSignHelpDesc = `
|
2015-05-15 16:13:05 +00:00
|
|
|
This path allows requesting certificates to be issued according to the
|
|
|
|
policy of the given role. The certificate will only be issued if the
|
|
|
|
requested common name is allowed by the role policy.
|
2015-10-02 19:47:45 +00:00
|
|
|
|
|
|
|
This path requires a CSR; if you want Vault to generate a private key
|
|
|
|
for you, use the issue path instead.
|
2015-05-15 16:13:05 +00:00
|
|
|
`
|