PKI Response Structures Part 2 (#18479)

Response structures from intermediate --> manage_keys
This commit is contained in:
AnPucel 2023-02-15 15:09:57 -08:00 committed by GitHub
parent e05c8931b9
commit 2d58144620
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 413 additions and 4 deletions

View File

@ -130,9 +130,10 @@ func TestPKI_RequireCN(t *testing.T) {
// Issue a cert with require_cn set to true and with common name supplied.
// It should succeed.
_, err = CBWrite(b, s, "issue/example", map[string]interface{}{
resp, err = CBWrite(b, s, "issue/example", map[string]interface{}{
"common_name": "foobar.com",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issue/example"), logical.UpdateOperation), resp, true)
if err != nil {
t.Fatal(err)
}
@ -2194,6 +2195,8 @@ func runTestSignVerbatim(t *testing.T, keyType string) {
Data: signVerbatimData,
MountPoint: "pki/",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("sign-verbatim"), logical.UpdateOperation), resp, true)
if resp != nil && resp.IsError() {
t.Fatalf("failed to sign-verbatim basic CSR: %#v", *resp)
}
@ -2510,6 +2513,8 @@ func TestBackend_SignIntermediate_AllowedPastCA(t *testing.T) {
resp, err := CBWrite(b_int, s_int, "intermediate/generate/internal", map[string]interface{}{
"common_name": "myint.com",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b_root.Route("intermediate/generate/internal"), logical.UpdateOperation), resp, true)
if err != nil {
t.Fatal(err)
}
@ -4789,6 +4794,7 @@ func TestRootWithExistingKey(t *testing.T) {
"key_type": "rsa",
"issuer_name": "my-issuer1",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuers/generate/root/internal"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
require.NotNil(t, resp.Data["certificate"])
myIssuerId1 := resp.Data["issuer_id"]
@ -4904,6 +4910,7 @@ func TestIntermediateWithExistingKey(t *testing.T) {
"common_name": "root myvault.com",
"key_type": "rsa",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuers/generate/intermediate/internal"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
// csr1 := resp.Data["csr"]
myKeyId1 := resp.Data["key_id"]
@ -5192,6 +5199,7 @@ TgM7RZnmEjNdeaa4M52o7VY=
resp, err := CBWrite(b, s, "issuers/import/bundle", map[string]interface{}{
"pem_bundle": customBundleWithoutCRLBits,
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuers/import/bundle"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotEmpty(t, resp.Data)
@ -6377,6 +6385,7 @@ func TestUserIDsInLeafCerts(t *testing.T) {
resp, err = CBWrite(b, s, "sign/testing", map[string]interface{}{
"csr": csrPem,
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("sign/testing"), logical.UpdateOperation), resp, true)
requireSuccessNonNilResponse(t, resp, err, "failed issuing leaf cert")
requireSubjectUserIDAttr(t, resp.Data["certificate"].(string), "humanoid")

View File

@ -771,6 +771,8 @@ func TestIssuerRevocation(t *testing.T) {
// Revoke it.
resp, err = CBWrite(b, s, "issuer/root2/revoke", map[string]interface{}{})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuer/root2/revoke"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotZero(t, resp.Data["revocation_time"])
@ -801,7 +803,7 @@ func TestIssuerRevocation(t *testing.T) {
require.NoError(t, err)
// Issue a leaf cert and ensure it fails (because the issuer is revoked).
_, err = CBWrite(b, s, "issuer/root2/issue/local-testing", map[string]interface{}{
resp, err = CBWrite(b, s, "issuer/root2/issue/local-testing", map[string]interface{}{
"common_name": "testing",
})
require.Error(t, err)
@ -827,6 +829,8 @@ func TestIssuerRevocation(t *testing.T) {
resp, err = CBWrite(b, s, "intermediate/set-signed", map[string]interface{}{
"certificate": intCert,
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("intermediate/set-signed"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotEmpty(t, resp.Data["imported_issuers"])
@ -842,6 +846,8 @@ func TestIssuerRevocation(t *testing.T) {
resp, err = CBWrite(b, s, "issuer/int1/issue/local-testing", map[string]interface{}{
"common_name": "testing",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("issuer/int1/issue/local-testing"), logical.UpdateOperation), resp, true)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotEmpty(t, resp.Data["certificate"])

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
"net/http"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/errutil"
@ -31,6 +32,28 @@ appended to the bundle.`,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathImportIssuers,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"mapping": {
Type: framework.TypeMap,
Description: "A mapping of issuer_id to key_id for all issuers included in this request",
Required: true,
},
"imported_keys": {
Type: framework.TypeCommaStringSlice,
Description: "Net-new keys imported as a part of this request",
Required: true,
},
"imported_issuers": {
Type: framework.TypeCommaStringSlice,
Description: "Net-new issuers imported as a part of this request",
Required: true,
},
},
}},
},
// Read more about why these flags are set in backend.go
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,

View File

@ -7,6 +7,7 @@ import (
"encoding/base64"
"encoding/pem"
"fmt"
"net/http"
"strings"
"time"
@ -34,6 +35,48 @@ func buildPathIssue(b *backend, pattern string) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.metricsWrap("issue", roleRequired, b.pathIssue),
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 Certificate Authority`,
Required: true,
},
"ca_chain": {
Type: framework.TypeCommaStringSlice,
Description: `Certificate Chain`,
Required: false,
},
"serial_number": {
Type: framework.TypeString,
Description: `Serial Number`,
Required: false,
},
"expiration": {
Type: framework.TypeString,
Description: `Time of expiration`,
Required: false,
},
"private_key": {
Type: framework.TypeString,
Description: `Private key`,
Required: false,
},
"private_key_type": {
Type: framework.TypeString,
Description: `Private key type`,
Required: false,
},
},
}},
},
},
},
@ -62,6 +105,48 @@ func buildPathSign(b *backend, pattern string) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.metricsWrap("sign", roleRequired, b.pathSign),
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 Certificate Authority`,
Required: true,
},
"ca_chain": {
Type: framework.TypeCommaStringSlice,
Description: `Certificate Chain`,
Required: false,
},
"serial_number": {
Type: framework.TypeString,
Description: `Serial Number`,
Required: true,
},
"expiration": {
Type: framework.TypeString,
Description: `Time of expiration`,
Required: true,
},
"private_key": {
Type: framework.TypeString,
Description: `Private key`,
Required: false,
},
"private_key_type": {
Type: framework.TypeString,
Description: `Private key type`,
Required: false,
},
},
}},
},
},
},
@ -98,6 +183,48 @@ func buildPathIssuerSignVerbatim(b *backend, pattern string) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.metricsWrap("sign-verbatim", roleOptional, b.pathSignVerbatim),
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 Certificate Authority`,
Required: true,
},
"ca_chain": {
Type: framework.TypeCommaStringSlice,
Description: `Certificate Chain`,
Required: false,
},
"serial_number": {
Type: framework.TypeString,
Description: `Serial Number`,
Required: false,
},
"expiration": {
Type: framework.TypeString,
Description: `Time of expiration`,
Required: false,
},
"private_key": {
Type: framework.TypeString,
Description: `Private key`,
Required: false,
},
"private_key_type": {
Type: framework.TypeString,
Description: `Private key type`,
Required: false,
},
},
}},
},
},
},

View File

@ -6,6 +6,7 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"net/http"
"strings"
"time"
@ -29,6 +30,58 @@ func buildPathGenerateRoot(b *backend, pattern string) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathCAGenerateRoot,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"expiration": {
Type: framework.TypeString,
Description: `The expiration of the given.`,
Required: true,
},
"serial_number": {
Type: framework.TypeString,
Description: `The requested Subject's named serial number.`,
Required: true,
},
"certificate": {
Type: framework.TypeString,
Description: `The generated self-signed CA certificate.`,
Required: true,
},
"issuing_ca": {
Type: framework.TypeString,
Description: `The issuing certificate authority.`,
Required: true,
},
"issuer_id": {
Type: framework.TypeString,
Description: `The ID of the issuer`,
Required: true,
},
"issuer_name": {
Type: framework.TypeString,
Description: `The name of the issuer.`,
Required: true,
},
"key_id": {
Type: framework.TypeString,
Description: `The ID of the key.`,
Required: true,
},
"key_name": {
Type: framework.TypeString,
Description: `The key name if given.`,
Required: true,
},
"private_key": {
Type: framework.TypeString,
Description: `The private key if exported was specified.`,
Required: false,
},
},
}},
},
// Read more about why these flags are set in backend.go
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
@ -60,6 +113,33 @@ func buildPathGenerateIntermediate(b *backend, pattern string) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathGenerateIntermediate,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"csr": {
Type: framework.TypeString,
Description: `Certificate signing request.`,
Required: true,
},
"key_id": {
Type: framework.TypeString,
Description: `Id of the key.`,
Required: true,
},
"private_key": {
Type: framework.TypeString,
Description: `Generated private key.`,
Required: false,
},
"private_key_type": {
Type: framework.TypeString,
Description: `Specifies the format used for marshaling the private key.`,
Required: false,
},
},
}},
},
// Read more about why these flags are set in backend.go
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
@ -101,6 +181,28 @@ secret-key (optional) and certificates.`,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathImportIssuers,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"mapping": {
Type: framework.TypeMap,
Description: "A mapping of issuer_id to key_id for all issuers included in this request",
Required: true,
},
"imported_keys": {
Type: framework.TypeCommaStringSlice,
Description: "Net-new keys imported as a part of this request",
Required: true,
},
"imported_issuers": {
Type: framework.TypeCommaStringSlice,
Description: "Net-new issuers imported as a part of this request",
Required: true,
},
},
}},
},
// Read more about why these flags are set in backend.go
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
@ -354,6 +456,88 @@ func pathRevokeIssuer(b *backend) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathRevokeIssuer,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"issuer_id": {
Type: framework.TypeString,
Description: `ID of the issuer`,
Required: true,
},
"issuer_name": {
Type: framework.TypeString,
Description: `Name of the issuer`,
Required: true,
},
"key_id": {
Type: framework.TypeString,
Description: `ID of the Key`,
Required: true,
},
"certificate": {
Type: framework.TypeString,
Description: `Certificate`,
Required: true,
},
"manual_chain": {
Type: framework.TypeCommaStringSlice,
Description: `Manual Chain`,
Required: true,
},
"ca_chain": {
Type: framework.TypeCommaStringSlice,
Description: `Certificate Authority Chain`,
Required: true,
},
"leaf_not_after_behavior": {
Type: framework.TypeString,
Description: ``,
Required: true,
},
"usage": {
Type: framework.TypeString,
Description: `Allowed usage`,
Required: true,
},
"revocation_signature_algorithm": {
Type: framework.TypeString,
Description: `Which signature algorithm to use when building CRLs`,
Required: true,
},
"revoked": {
Type: framework.TypeBool,
Description: `Whether the issuer was revoked`,
Required: true,
},
"issuing_certificates": {
Type: framework.TypeCommaStringSlice,
Description: `Specifies the URL values for the Issuing Certificate field`,
Required: true,
},
"crl_distribution_points": {
Type: framework.TypeStringSlice,
Description: `Specifies the URL values for the CRL Distribution Points field`,
Required: true,
},
"ocsp_servers": {
Type: framework.TypeStringSlice,
Description: `Specifies the URL values for the OCSP Servers field`,
Required: true,
},
"revocation_time": {
Type: framework.TypeInt64,
Description: `Time of revocation`,
Required: false,
},
"revocation_time_rfc3339": {
Type: framework.TypeTime,
Description: `RFC formatted time of revocation`,
Required: false,
},
},
}},
},
// Read more about why these flags are set in backend.go
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,

View File

@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/pem"
"net/http"
"strings"
"github.com/hashicorp/vault/sdk/framework"
@ -54,7 +55,36 @@ is required. Ignored for other types.`,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathGenerateKeyHandler,
Callback: b.pathGenerateKeyHandler,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"key_id": {
Type: framework.TypeString,
Description: `ID assigned to this key.`,
Required: true,
},
"key_name": {
Type: framework.TypeString,
Description: `Name assigned to this key.`,
Required: true,
},
"key_type": {
Type: framework.TypeString,
Description: `The type of key to use; defaults to RSA. "rsa"
"ec" and "ed25519" are the only valid values.`,
Required: true,
},
"private_key": {
Type: framework.TypeString,
Description: `The private key string`,
Required: false,
},
},
}},
},
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
},
@ -162,7 +192,30 @@ func pathImportKey(b *backend) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathImportKeyHandler,
Callback: b.pathImportKeyHandler,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"key_id": {
Type: framework.TypeString,
Description: `ID assigned to this key.`,
Required: true,
},
"key_name": {
Type: framework.TypeString,
Description: `Name assigned to this key.`,
Required: true,
},
"key_type": {
Type: framework.TypeString,
Description: `The type of key to use; defaults to RSA. "rsa"
"ec" and "ed25519" are the only valid values.`,
Required: true,
},
},
}},
},
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
},

View File

@ -9,6 +9,8 @@ import (
"fmt"
"testing"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/logical"
@ -95,6 +97,8 @@ func TestPKI_PathManageKeys_GenerateExportedKeys(t *testing.T) {
},
MountPoint: "pki/",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("keys/generate/exported"), logical.UpdateOperation), resp, true)
require.NoError(t, err, "Failed generating exported key")
require.NotNil(t, resp, "Got nil response generating exported key")
require.Equal(t, "ec", resp.Data["key_type"], "key_type field contained an invalid type")
@ -136,6 +140,9 @@ func TestPKI_PathManageKeys_ImportKeyBundle(t *testing.T) {
},
MountPoint: "pki/",
})
schema.ValidateResponse(t, schema.GetResponseSchema(t, b.Route("keys/import"), logical.UpdateOperation), resp, true)
require.NoError(t, err, "Failed importing ec key")
require.NotNil(t, resp, "Got nil response importing ec key")
require.False(t, resp.IsError(), "received an error response: %v", resp.Error())