PKI Responses Part 4 (#18612)
This commit is contained in:
parent
85f845c3e0
commit
65e5730c6c
|
@ -2694,6 +2694,7 @@ func TestBackend_SignSelfIssued(t *testing.T) {
|
|||
},
|
||||
MountPoint: "pki/",
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("root/sign-self-issued"), logical.UpdateOperation), resp, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -5247,6 +5248,7 @@ func TestBackend_IfModifiedSinceHeaders(t *testing.T) {
|
|||
}
|
||||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
|
||||
HandlerFunc: vaulthttp.Handler,
|
||||
RequestResponseCallback: schema.ResponseValidatingCallback(t),
|
||||
})
|
||||
cluster.Start()
|
||||
defer cluster.Cleanup()
|
||||
|
@ -5966,6 +5968,7 @@ func TestPKI_ListRevokedCerts(t *testing.T) {
|
|||
|
||||
// Test empty cluster
|
||||
resp, err := CBList(b, s, "certs/revoked")
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("certs/revoked"), logical.ListOperation), resp, true)
|
||||
requireSuccessNonNilResponse(t, resp, err, "failed listing empty cluster")
|
||||
require.Empty(t, resp.Data, "response map contained data that we did not expect")
|
||||
|
||||
|
|
|
@ -600,10 +600,11 @@ func TestPoP(t *testing.T) {
|
|||
require.NotNil(t, resp)
|
||||
require.NotEmpty(t, resp.Data["certificate"])
|
||||
|
||||
_, err = CBWrite(b, s, "revoke-with-key", map[string]interface{}{
|
||||
resp, err = CBWrite(b, s, "revoke-with-key", map[string]interface{}{
|
||||
"certificate": resp.Data["certificate"],
|
||||
"private_key": resp.Data["private_key"],
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("revoke-with-key"), logical.UpdateOperation), resp, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Issue a second leaf, but hold onto it for now.
|
||||
|
@ -780,7 +781,9 @@ func TestIssuerRevocation(t *testing.T) {
|
|||
require.NotZero(t, resp.Data["revocation_time"])
|
||||
|
||||
// Regenerate the CRLs
|
||||
_, err = CBRead(b, s, "crl/rotate")
|
||||
resp, err = CBRead(b, s, "crl/rotate")
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("crl/rotate"), logical.ReadOperation), resp, true)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure the old cert isn't on its own CRL.
|
||||
|
|
|
@ -25,12 +25,12 @@ var pathFetchReadSchema = map[int][]framework.Response{
|
|||
Required: false,
|
||||
},
|
||||
"revocation_time": {
|
||||
Type: framework.TypeInt,
|
||||
Type: framework.TypeString,
|
||||
Description: `Revocation time`,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_time_rfc3339": {
|
||||
Type: framework.TypeInt,
|
||||
Type: framework.TypeString,
|
||||
Description: `Revocation time RFC 3339 formatted`,
|
||||
Required: false,
|
||||
},
|
||||
|
|
|
@ -171,67 +171,75 @@ to be set on all PR secondary clusters.`,
|
|||
"issuer_id": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Issuer Id`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"issuer_name": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Issuer Name`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"key_id": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Key Id`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"certificate": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Certificate`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"manual_chain": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `Manual Chain`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"ca_chain": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `CA Chain`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"leaf_not_after_behavior": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Leaf Not After Behavior`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"usage": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `Usage`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_signature_algorithm": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Revocation Signature Alogrithm`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"revoked": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Revoked`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_time": {
|
||||
Type: framework.TypeInt,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_time_rfc3339": {
|
||||
Type: framework.TypeString,
|
||||
Required: false,
|
||||
},
|
||||
"issuing_certificates": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `Issuing Certificates`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"crl_distribution_points": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `CRL Distribution Points`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
"ocsp_servers": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `OSCP Servers`,
|
||||
Required: true,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
|
@ -1068,7 +1076,6 @@ func buildPathGetIssuerCRL(b *backend, pattern string) *framework.Path {
|
|||
Fields: map[string]*framework.FieldSchema{
|
||||
"crl": {
|
||||
Type: framework.TypeString,
|
||||
Description: ``,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -14,6 +14,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
|
||||
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
|
||||
|
@ -197,6 +199,7 @@ func TestOcsp_UnknownIssuerIdWithDefaultHavingOcspUsageRemoved(t *testing.T) {
|
|||
resp, err := CBWrite(b, s, "revoke", map[string]interface{}{
|
||||
"serial_number": serial,
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("revoke"), logical.UpdateOperation), resp, true)
|
||||
requireSuccessNonNilResponse(t, resp, err, "revoke")
|
||||
|
||||
// Twiddle the entry so that the issuer id is no longer valid.
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -77,6 +78,18 @@ base64 encoded. Defaults to "pem".`,
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathUpdateResignCrlsHandler,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"crl": {
|
||||
Type: framework.TypeString,
|
||||
Description: `CRL`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -133,6 +146,18 @@ value (string)`,
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathUpdateSignRevocationListHandler,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"crl": {
|
||||
Type: framework.TypeString,
|
||||
Description: `CRL`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
|
||||
|
||||
"github.com/hashicorp/vault/api"
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
|
@ -55,6 +57,7 @@ func TestResignCrls_NormalCrl(t *testing.T) {
|
|||
"format": "pem",
|
||||
"crls": []string{crl1, crl2},
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b1.Route("issuer/default/resign-crls"), logical.UpdateOperation), resp, true)
|
||||
requireSuccessNonNilResponse(t, resp, err)
|
||||
requireFieldsSetInResp(t, resp, "crl")
|
||||
pemCrl := resp.Data["crl"].(string)
|
||||
|
@ -351,6 +354,7 @@ func TestSignRevocationList_NoRevokedCerts(t *testing.T) {
|
|||
"next_update": "12h",
|
||||
"format": "pem",
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuer/default/sign-revocation-list"), logical.UpdateOperation), resp, true)
|
||||
requireSuccessNonNilResponse(t, resp, err)
|
||||
requireFieldsSetInResp(t, resp, "crl")
|
||||
pemCrl := resp.Data["crl"].(string)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -25,6 +26,18 @@ func pathListCertsRevoked(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ListOperation: &framework.PathOperation{
|
||||
Callback: b.pathListRevokedCertsHandler,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"keys": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `List of Keys`,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -71,6 +84,28 @@ signed by an issuer in this mount.`,
|
|||
// If this needs to write, the entire request will be forwarded to the
|
||||
// active node of the current performance cluster, but we don't want to
|
||||
// forward invalid revoke requests there.
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"revocation_time": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: `Revocation Time`,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_time_rfc3339": {
|
||||
Type: framework.TypeTime,
|
||||
Description: `Revocation Time`,
|
||||
Required: false,
|
||||
},
|
||||
"state": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Revocation State`,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -107,6 +142,28 @@ be in PEM format.`,
|
|||
// If this needs to write, the entire request will be forwarded to the
|
||||
// active node of the current performance cluster, but we don't want to
|
||||
// forward invalid revoke requests there.
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"revocation_time": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: `Revocation Time`,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_time_rfc3339": {
|
||||
Type: framework.TypeTime,
|
||||
Description: `Revocation Time`,
|
||||
Required: false,
|
||||
},
|
||||
"state": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Revocation State`,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -126,6 +183,18 @@ func pathRotateCRL(b *backend) *framework.Path {
|
|||
// so this request should be forwarded when it is first seen, not
|
||||
// when it is ready to write.
|
||||
ForwardPerformanceStandby: true,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"success": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Whether rotation was successful`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -145,6 +214,18 @@ func pathRotateDeltaCRL(b *backend) *framework.Path {
|
|||
// so this request should be forwarded when it is first seen, not
|
||||
// when it is ready to write.
|
||||
ForwardPerformanceStandby: true,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"success": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Whether rotation was successful`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -160,6 +241,23 @@ func pathListUnifiedRevoked(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ListOperation: &framework.PathOperation{
|
||||
Callback: b.pathListUnifiedRevokedCertsHandler,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"keys": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `List of Keys`,
|
||||
Required: false,
|
||||
},
|
||||
"key_info": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Key information`,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -23,6 +24,18 @@ func pathListRoles(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ListOperation: &framework.PathOperation{
|
||||
Callback: b.pathRoleList,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"keys": {
|
||||
Type: framework.TypeMap,
|
||||
Description: `List of keys`,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -32,6 +45,352 @@ func pathListRoles(b *backend) *framework.Path {
|
|||
}
|
||||
|
||||
func pathRoles(b *backend) *framework.Path {
|
||||
pathRolesResponse := map[string]*framework.FieldSchema{
|
||||
"ttl": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Required: true,
|
||||
Description: `The lease duration (validity period of the
|
||||
certificate) if no specific lease duration is requested.
|
||||
The lease duration controls the expiration of certificates
|
||||
issued by this backend. Defaults to the system default
|
||||
value or the value of max_ttl, whichever is shorter.`,
|
||||
},
|
||||
|
||||
"max_ttl": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Required: true,
|
||||
Description: `The maximum allowed lease duration. If not
|
||||
set, defaults to the system maximum lease TTL.`,
|
||||
},
|
||||
"allow_token_displayname": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `Whether to allow "localhost" and "localdomain"
|
||||
as a valid common name in a request, independent of allowed_domains value.`,
|
||||
},
|
||||
|
||||
"allow_localhost": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `Whether to allow "localhost" and "localdomain"
|
||||
as a valid common name in a request, independent of allowed_domains value.`,
|
||||
},
|
||||
|
||||
"allowed_domains": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
Description: `Specifies the domains this role is allowed
|
||||
to issue certificates for. This is used with the allow_bare_domains,
|
||||
allow_subdomains, and allow_glob_domains to determine matches for the
|
||||
common name, DNS-typed SAN entries, and Email-typed SAN entries of
|
||||
certificates. See the documentation for more information. This parameter
|
||||
accepts a comma-separated string or list of domains.`,
|
||||
},
|
||||
"allowed_domains_template": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, Allowed domains can be specified using identity template policies.
|
||||
Non-templated domains are also permitted.`,
|
||||
},
|
||||
"allow_bare_domains": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, clients can request certificates
|
||||
for the base domains themselves, e.g. "example.com" of domains listed
|
||||
in allowed_domains. This is a separate option as in some cases this can
|
||||
be considered a security threat. See the documentation for more
|
||||
information.`,
|
||||
},
|
||||
|
||||
"allow_subdomains": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, clients can request certificates for
|
||||
subdomains of domains listed in allowed_domains, including wildcard
|
||||
subdomains. See the documentation for more information.`,
|
||||
},
|
||||
|
||||
"allow_glob_domains": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, domains specified in allowed_domains
|
||||
can include shell-style glob patterns, e.g. "ftp*.example.com".
|
||||
See the documentation for more information.`,
|
||||
},
|
||||
|
||||
"allow_wildcard_certificates": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, allows certificates with wildcards in
|
||||
the common name to be issued, conforming to RFC 6125's Section 6.4.3; e.g.,
|
||||
"*.example.net" or "b*z.example.net". See the documentation for more
|
||||
information.`,
|
||||
},
|
||||
|
||||
"allow_any_name": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, clients can request certificates for
|
||||
any domain, regardless of allowed_domains restrictions.
|
||||
See the documentation for more information.`,
|
||||
},
|
||||
|
||||
"enforce_hostnames": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, only valid host names are allowed for
|
||||
CN and DNS SANs, and the host part of email addresses. Defaults to true.`,
|
||||
},
|
||||
|
||||
"allow_ip_sans": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, IP Subject Alternative Names are allowed.
|
||||
Any valid IP is accepted and No authorization checking is performed.`,
|
||||
},
|
||||
|
||||
"allowed_uri_sans": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
Description: `If set, an array of allowed URIs for URI Subject Alternative Names.
|
||||
Any valid URI is accepted, these values support globbing.`,
|
||||
},
|
||||
|
||||
"allowed_uri_sans_template": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, Allowed URI SANs can be specified using identity template policies.
|
||||
Non-templated URI SANs are also permitted.`,
|
||||
},
|
||||
|
||||
"allowed_other_sans": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
Description: `If set, an array of allowed other names to put in SANs. These values support globbing and must be in the format <oid>;<type>:<value>. Currently only "utf8" is a valid type. All values, including globbing values, must use this syntax, with the exception being a single "*" which allows any OID and any value (but type must still be utf8).`,
|
||||
},
|
||||
|
||||
"allowed_serial_numbers": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
Description: `If set, an array of allowed serial numbers to put in Subject. These values support globbing.`,
|
||||
},
|
||||
"allowed_user_ids": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, an array of allowed user-ids to put in user system login name specified here: https://www.rfc-editor.org/rfc/rfc1274#section-9.3.1`,
|
||||
},
|
||||
"server_flag": {
|
||||
Type: framework.TypeBool,
|
||||
Default: true,
|
||||
Description: `If set, certificates are flagged for server auth use.
|
||||
Defaults to true. See also RFC 5280 Section 4.2.1.12.`,
|
||||
},
|
||||
|
||||
"client_flag": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, certificates are flagged for client auth use.
|
||||
Defaults to true. See also RFC 5280 Section 4.2.1.12.`,
|
||||
},
|
||||
|
||||
"code_signing_flag": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, certificates are flagged for code signing
|
||||
use. Defaults to false. See also RFC 5280 Section 4.2.1.12.`,
|
||||
},
|
||||
|
||||
"email_protection_flag": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, certificates are flagged for email
|
||||
protection use. Defaults to false. See also RFC 5280 Section 4.2.1.12.`,
|
||||
},
|
||||
|
||||
"key_type": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
Description: `The type of key to use; defaults to RSA. "rsa"
|
||||
"ec", "ed25519" and "any" are the only valid values.`,
|
||||
},
|
||||
|
||||
"key_bits": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
Description: `The number of bits to use. Allowed values are
|
||||
0 (universal default); with rsa key_type: 2048 (default), 3072, or
|
||||
4096; with ec key_type: 224, 256 (default), 384, or 521; ignored with
|
||||
ed25519.`,
|
||||
},
|
||||
"signature_bits": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
Description: `The number of bits to use in the signature
|
||||
algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384, and 512 for
|
||||
SHA-2-512. Defaults to 0 to automatically detect based on key length
|
||||
(SHA-2-256 for RSA keys, and matching the curve size for NIST P-Curves).`,
|
||||
},
|
||||
"use_pss": {
|
||||
Type: framework.TypeBool,
|
||||
Required: false,
|
||||
Description: `Whether or not to use PSS signatures when using a
|
||||
RSA key-type issuer. Defaults to false.`,
|
||||
},
|
||||
"key_usage": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
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. See also RFC 5280
|
||||
Section 4.2.1.3.`,
|
||||
},
|
||||
|
||||
"ext_key_usage": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
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. See also RFC 5280
|
||||
Section 4.2.1.12.`,
|
||||
},
|
||||
|
||||
"ext_key_usage_oids": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Required: true,
|
||||
Description: `A comma-separated string or list of extended key usage oids.`,
|
||||
},
|
||||
|
||||
"use_csr_common_name": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, when used with a signing profile,
|
||||
the common name in the CSR will be used. This
|
||||
does *not* include any requested Subject Alternative
|
||||
Names; use use_csr_sans for that. Defaults to true.`,
|
||||
},
|
||||
|
||||
"use_csr_sans": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
Description: `If set, when used with a signing profile,
|
||||
the SANs in the CSR will be used. This does *not*
|
||||
include the Common Name (cn); use use_csr_common_name
|
||||
for that. Defaults to true.`,
|
||||
},
|
||||
|
||||
"ou": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, OU (OrganizationalUnit) will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"organization": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, O (Organization) will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"country": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, Country will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"locality": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, Locality will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"province": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, Province will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"street_address": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, Street Address will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"postal_code": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `If set, Postal Code will be set to
|
||||
this value in certificates issued by this role.`,
|
||||
},
|
||||
|
||||
"generate_lease": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `
|
||||
If set, certificates issued/signed against this role will have Vault leases
|
||||
attached to them. Defaults to "false". Certificates can be added to the CRL by
|
||||
"vault revoke <lease_id>" when certificates are associated with leases. It can
|
||||
also be done using the "pki/revoke" endpoint. However, when lease generation is
|
||||
disabled, invoking "pki/revoke" would be the only way to add the certificates
|
||||
to the CRL. When large number of certificates are generated with long
|
||||
lifetimes, it is recommended that lease generation be disabled, as large amount of
|
||||
leases adversely affect the startup time of Vault.`,
|
||||
},
|
||||
|
||||
"no_store": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `
|
||||
If set, certificates issued/signed against this role will not be stored in the
|
||||
storage backend. This can improve performance when issuing large numbers of
|
||||
certificates. However, certificates issued in this way cannot be enumerated
|
||||
or revoked, so this option is recommended only for certificates that are
|
||||
non-sensitive, or extremely short-lived. This option implies a value of "false"
|
||||
for "generate_lease".`,
|
||||
},
|
||||
|
||||
"require_cn": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `If set to false, makes the 'common_name' field optional while generating a certificate.`,
|
||||
},
|
||||
|
||||
"cn_validations": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `List of allowed validations to run against the
|
||||
Common Name field. Values can include 'email' to validate the CN is a email
|
||||
address, 'hostname' to validate the CN is a valid hostname (potentially
|
||||
including wildcards). When multiple validations are specified, these take
|
||||
OR semantics (either email OR hostname are allowed). The special value
|
||||
'disabled' allows disabling all CN name validations, allowing for arbitrary
|
||||
non-Hostname, non-Email address CNs.`,
|
||||
},
|
||||
|
||||
"policy_identifiers": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `A comma-separated string or list of policy OIDs, or a JSON list of qualified policy
|
||||
information, which must include an oid, and may include a notice and/or cps url, using the form
|
||||
[{"oid"="1.3.6.1.4.1.7.8","notice"="I am a user Notice"}, {"oid"="1.3.6.1.4.1.44947.1.2.4 ","cps"="https://example.com"}].`,
|
||||
},
|
||||
|
||||
"basic_constraints_valid_for_non_ca": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Mark Basic Constraints valid when issuing non-CA certificates.`,
|
||||
},
|
||||
"not_before_duration": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: `The duration before now which the certificate needs to be backdated by.`,
|
||||
},
|
||||
"not_after": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Set the not after field of the certificate with specified date value.
|
||||
The value format should be given in UTC format YYYY-MM-ddTHH:MM:SSZ.`,
|
||||
},
|
||||
"issuer_ref": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Reference to the issuer used to sign requests
|
||||
serviced by this role.`,
|
||||
},
|
||||
}
|
||||
|
||||
return &framework.Path{
|
||||
Pattern: "roles/" + framework.GenericNameRegex("name"),
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
|
@ -450,21 +809,44 @@ serviced by this role.`,
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.pathRoleRead,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: pathRolesResponse,
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathRoleCreate,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: pathRolesResponse,
|
||||
}},
|
||||
},
|
||||
// Read more about why these flags are set in backend.go.
|
||||
ForwardPerformanceStandby: true,
|
||||
ForwardPerformanceSecondary: true,
|
||||
},
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: b.pathRoleDelete,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusNoContent: {{
|
||||
Description: "No Content",
|
||||
}},
|
||||
},
|
||||
// Read more about why these flags are set in backend.go.
|
||||
ForwardPerformanceStandby: true,
|
||||
ForwardPerformanceSecondary: true,
|
||||
},
|
||||
logical.PatchOperation: &framework.PathOperation{
|
||||
Callback: b.pathRolePatch,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: pathRolesResponse,
|
||||
}},
|
||||
},
|
||||
// Read more about why these flags are set in backend.go.
|
||||
ForwardPerformanceStandby: true,
|
||||
ForwardPerformanceSecondary: true,
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
|
@ -141,12 +143,14 @@ func TestPki_RoleKeyUsage(t *testing.T) {
|
|||
}
|
||||
|
||||
resp, err = b.HandleRequest(context.Background(), roleReq)
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("roles/testrole"), logical.UpdateOperation), resp, true)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
||||
}
|
||||
|
||||
roleReq.Operation = logical.ReadOperation
|
||||
resp, err = b.HandleRequest(context.Background(), roleReq)
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("roles/testrole"), logical.ReadOperation), resp, true)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -35,6 +36,11 @@ func pathDeleteRoot(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.DeleteOperation: &framework.PathOperation{
|
||||
Callback: b.pathCADeleteRoot,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
}},
|
||||
},
|
||||
// Read more about why these flags are set in backend.go
|
||||
ForwardPerformanceStandby: true,
|
||||
ForwardPerformanceSecondary: true,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package pki
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
@ -23,6 +25,38 @@ func buildPathIssuerSignIntermediateRaw(b *backend, pattern string) *framework.P
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathIssuerSignIntermediate,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"expiration": {
|
||||
Type: framework.TypeInt64,
|
||||
Description: `Expiration Time`,
|
||||
Required: true,
|
||||
},
|
||||
"serial_number": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Serial Number`,
|
||||
Required: false,
|
||||
},
|
||||
"certificate": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Certificate`,
|
||||
Required: true,
|
||||
},
|
||||
"issuing_ca": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Issuing CA`,
|
||||
Required: true,
|
||||
},
|
||||
"ca_chain": {
|
||||
Type: framework.TypeStringSlice,
|
||||
Description: `CA Chain`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -140,6 +174,23 @@ func buildPathIssuerSignSelfIssued(b *backend, pattern string) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathIssuerSignSelfIssued,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"certificate": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Certificate`,
|
||||
Required: true,
|
||||
},
|
||||
"issuing_ca": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Issuing CA`,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -102,6 +102,12 @@ func pathTidy(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathTidyWrite,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusAccepted: {{
|
||||
Description: "Accepted",
|
||||
Fields: map[string]*framework.FieldSchema{},
|
||||
}},
|
||||
},
|
||||
ForwardPerformanceStandby: true,
|
||||
},
|
||||
},
|
||||
|
@ -116,6 +122,121 @@ func pathTidyCancel(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathTidyCancelWrite,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Safety buffer time duration`,
|
||||
Required: false,
|
||||
},
|
||||
"issuer_safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Issuer safety buffer`,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_cert_store": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy certificate store`,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy revoked certificates`,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_revoked_cert_issuer_associations": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy revoked certificate issuer associations`,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_expired_issuers": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy expired issuers`,
|
||||
Required: false,
|
||||
},
|
||||
"pause_duration": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Duration to pause between tidying certificates`,
|
||||
Required: false,
|
||||
},
|
||||
"state": {
|
||||
Type: framework.TypeString,
|
||||
Description: `One of Inactive, Running, Finished, or Error`,
|
||||
Required: false,
|
||||
},
|
||||
"error": {
|
||||
Type: framework.TypeString,
|
||||
Description: `The error message`,
|
||||
Required: false,
|
||||
},
|
||||
"time_started": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Time the operation started`,
|
||||
Required: false,
|
||||
},
|
||||
"time_finished": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Time the operation finished`,
|
||||
Required: false,
|
||||
},
|
||||
"message": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Message of the operation`,
|
||||
Required: false,
|
||||
},
|
||||
"cert_store_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of certificate storage entries deleted`,
|
||||
Required: false,
|
||||
},
|
||||
"revoked_cert_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: false,
|
||||
},
|
||||
"current_cert_store_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: false,
|
||||
},
|
||||
"current_revoked_cert_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: false,
|
||||
},
|
||||
"missing_issuer_cert_count": {
|
||||
Type: framework.TypeInt,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_move_legacy_ca_bundle": {
|
||||
Type: framework.TypeBool,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_cross_cluster_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Required: false,
|
||||
},
|
||||
"tidy_revocation_queue": {
|
||||
Type: framework.TypeBool,
|
||||
Required: false,
|
||||
},
|
||||
"revocation_queue_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Required: false,
|
||||
},
|
||||
"cross_revoked_cert_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Required: false,
|
||||
},
|
||||
"internal_backend_uuid": {
|
||||
Type: framework.TypeString,
|
||||
Required: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
ForwardPerformanceStandby: true,
|
||||
},
|
||||
},
|
||||
|
@ -130,6 +251,123 @@ func pathTidyStatus(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.pathTidyStatusRead,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Safety buffer time duration`,
|
||||
Required: true,
|
||||
},
|
||||
"issuer_safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Issuer safety buffer`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cert_store": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy certificate store`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy revoked certificates`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_cert_issuer_associations": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy revoked certificate issuer associations`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_expired_issuers": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Tidy expired issuers`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cross_cluster_revoked_certs": {
|
||||
Type: framework.TypeString,
|
||||
Description: ``,
|
||||
Required: false,
|
||||
},
|
||||
"pause_duration": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Duration to pause between tidying certificates`,
|
||||
Required: true,
|
||||
},
|
||||
"state": {
|
||||
Type: framework.TypeString,
|
||||
Description: `One of Inactive, Running, Finished, or Error`,
|
||||
Required: true,
|
||||
},
|
||||
"error": {
|
||||
Type: framework.TypeString,
|
||||
Description: `The error message`,
|
||||
Required: true,
|
||||
},
|
||||
"time_started": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Time the operation started`,
|
||||
Required: true,
|
||||
},
|
||||
"time_finished": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Time the operation finished`,
|
||||
Required: true,
|
||||
},
|
||||
"message": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Message of the operation`,
|
||||
Required: true,
|
||||
},
|
||||
"cert_store_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of certificate storage entries deleted`,
|
||||
Required: true,
|
||||
},
|
||||
"revoked_cert_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: true,
|
||||
},
|
||||
"current_cert_store_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: true,
|
||||
},
|
||||
"cross_revoked_cert_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: ``,
|
||||
Required: true,
|
||||
},
|
||||
"current_revoked_cert_count": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `The number of revoked certificate entries deleted`,
|
||||
Required: true,
|
||||
},
|
||||
"revocation_queue_deleted_count": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_move_legacy_ca_bundle": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revocation_queue": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"missing_issuer_cert_count": {
|
||||
Type: framework.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"internal_backend_uuid": {
|
||||
Type: framework.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
ForwardPerformanceStandby: true,
|
||||
},
|
||||
},
|
||||
|
@ -155,9 +393,153 @@ func pathConfigAutoTidy(b *backend) *framework.Path {
|
|||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.pathConfigAutoTidyRead,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"enabled": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether automatic tidy is enabled or not`,
|
||||
Required: true,
|
||||
},
|
||||
"interval_duration": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Specifies the duration between automatic tidy operation`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cert_store": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to tidy up the certificate store`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to remove all invalid and expired certificates from storage`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_cert_issuer_associations": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to associate revoked certificates with their corresponding issuers`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_expired_issuers": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether tidy expired issuers`,
|
||||
Required: true,
|
||||
},
|
||||
"safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Safety buffer time duration`,
|
||||
Required: true,
|
||||
},
|
||||
"issuer_safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Issuer safety buffer`,
|
||||
Required: true,
|
||||
},
|
||||
"pause_duration": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Duration to pause between tidying certificates`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_move_legacy_ca_bundle": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cross_cluster_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revocation_queue": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"revocation_queue_safety_buffer": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Required: true,
|
||||
},
|
||||
"publish_stored_certificate_count_metrics": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"maintain_stored_certificate_counts": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathConfigAutoTidyWrite,
|
||||
Responses: map[int][]framework.Response{
|
||||
http.StatusOK: {{
|
||||
Description: "OK",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"enabled": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether automatic tidy is enabled or not`,
|
||||
Required: true,
|
||||
},
|
||||
"interval_duration": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Specifies the duration between automatic tidy operation`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cert_store": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to tidy up the certificate store`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to remove all invalid and expired certificates from storage`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revoked_cert_issuer_associations": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether to associate revoked certificates with their corresponding issuers`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_expired_issuers": {
|
||||
Type: framework.TypeBool,
|
||||
Description: `Specifies whether tidy expired issuers`,
|
||||
Required: true,
|
||||
},
|
||||
"safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Safety buffer time duration`,
|
||||
Required: true,
|
||||
},
|
||||
"issuer_safety_buffer": {
|
||||
Type: framework.TypeInt,
|
||||
Description: `Issuer safety buffer`,
|
||||
Required: true,
|
||||
},
|
||||
"pause_duration": {
|
||||
Type: framework.TypeString,
|
||||
Description: `Duration to pause between tidying certificates`,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_cross_cluster_revoked_certs": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_revocation_queue": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"tidy_move_legacy_ca_bundle": {
|
||||
Type: framework.TypeBool,
|
||||
Required: true,
|
||||
},
|
||||
"revocation_queue_safety_buffer": {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
// Read more about why these flags are set in backend.go.
|
||||
ForwardPerformanceStandby: true,
|
||||
ForwardPerformanceSecondary: true,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/testhelpers"
|
||||
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
|
||||
|
@ -224,17 +225,19 @@ func TestTidyCancellation(t *testing.T) {
|
|||
|
||||
// Kick off a tidy operation (which runs in the background), but with
|
||||
// a slow-ish pause between certificates.
|
||||
_, err = CBWrite(b, s, "tidy", map[string]interface{}{
|
||||
resp, err := CBWrite(b, s, "tidy", map[string]interface{}{
|
||||
"tidy_cert_store": true,
|
||||
"safety_buffer": "1s",
|
||||
"pause_duration": "1s",
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("tidy"), logical.UpdateOperation), resp, true)
|
||||
|
||||
// If we wait six seconds, the operation should still be running. That's
|
||||
// how we check that pause_duration works.
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
resp, err := CBRead(b, s, "tidy-status")
|
||||
resp, err = CBRead(b, s, "tidy-status")
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.NotNil(t, resp.Data)
|
||||
|
@ -242,6 +245,7 @@ func TestTidyCancellation(t *testing.T) {
|
|||
|
||||
// If we now cancel the operation, the response should say Cancelling.
|
||||
cancelResp, err := CBWrite(b, s, "tidy-cancel", map[string]interface{}{})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("tidy-cancel"), logical.UpdateOperation), resp, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, cancelResp)
|
||||
require.NotNil(t, cancelResp.Data)
|
||||
|
@ -261,6 +265,7 @@ func TestTidyCancellation(t *testing.T) {
|
|||
time.Sleep(3 * time.Second)
|
||||
|
||||
statusResp, err := CBRead(b, s, "tidy-status")
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("tidy-status"), logical.ReadOperation), resp, true)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, statusResp)
|
||||
require.NotNil(t, statusResp.Data)
|
||||
|
@ -385,6 +390,7 @@ func TestTidyIssuerConfig(t *testing.T) {
|
|||
|
||||
// Ensure the default auto-tidy config matches expectations
|
||||
resp, err := CBRead(b, s, "config/auto-tidy")
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("config/auto-tidy"), logical.ReadOperation), resp, true)
|
||||
requireSuccessNonNilResponse(t, resp, err)
|
||||
|
||||
jsonBlob, err := json.Marshal(&defaultTidyConfig)
|
||||
|
@ -407,6 +413,8 @@ func TestTidyIssuerConfig(t *testing.T) {
|
|||
"tidy_expired_issuers": true,
|
||||
"issuer_safety_buffer": "5s",
|
||||
})
|
||||
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("config/auto-tidy"), logical.UpdateOperation), resp, true)
|
||||
|
||||
requireSuccessNonNilResponse(t, resp, err)
|
||||
require.Equal(t, true, resp.Data["tidy_expired_issuers"])
|
||||
require.Equal(t, 5, resp.Data["issuer_safety_buffer"])
|
||||
|
|
Loading…
Reference in New Issue