Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Response Structures to PKI Config #18376

Merged
merged 38 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7af2481
First response
AnPucel Dec 13, 2022
6af5640
Adding more resposne structures
AnPucel Dec 14, 2022
2f337ec
All config ca response structures
AnPucel Dec 14, 2022
761de13
Format
AnPucel Dec 14, 2022
8b1d9c4
Add response structures
AnPucel Dec 14, 2022
ded7033
Adding path_config_crl
AnPucel Dec 14, 2022
551b128
Formatting & Fixing update/create operations
AnPucel Dec 14, 2022
12bb8df
Removing response structures for update/create
AnPucel Dec 14, 2022
9e2e9a0
Adding path config urls
AnPucel Dec 14, 2022
d8ea655
Adding responses to update & create for config_ca
AnPucel Dec 14, 2022
6862724
Adding response for udpate
AnPucel Dec 14, 2022
841ce1a
Adding response structure to update/create
AnPucel Dec 14, 2022
9c73e85
update/create response struct config_urls
AnPucel Dec 14, 2022
be28b33
Changelog
AnPucel Dec 15, 2022
f4b1b83
Adding last descriptions
AnPucel Dec 15, 2022
090a660
Description change
AnPucel Dec 16, 2022
e9e577e
Add required values
AnPucel Jan 3, 2023
5a1d1f0
Add defaults to config_ca
AnPucel Jan 3, 2023
706942a
Add required fields
AnPucel Jan 3, 2023
2f56d93
tests for config/issuers
AnPucel Jan 25, 2023
4548149
Merge branch 'main' into tmp
AnPucel Jan 27, 2023
7993adb
Unstashing tests
AnPucel Jan 31, 2023
f08416e
removing test
AnPucel Feb 2, 2023
ba80daf
Formatting
AnPucel Feb 2, 2023
46c84a9
Reverting test change
AnPucel Feb 2, 2023
822a48b
Wrong file
AnPucel Feb 2, 2023
1a54ac2
Tests caught this
AnPucel Feb 2, 2023
3a41092
remove comment
AnPucel Feb 2, 2023
b431374
Running go fmt
AnPucel Feb 3, 2023
d5f5983
Merge branch 'main' into anpucel/PKIResponseStructures
AnPucel Feb 3, 2023
195d7d1
config/urls
AnPucel Feb 4, 2023
88bb28a
test config/ca
AnPucel Feb 4, 2023
d70e348
config/cluster test
AnPucel Feb 4, 2023
911aed4
Missed some parameters
AnPucel Feb 4, 2023
fec0a39
more tests
AnPucel Feb 4, 2023
3972a2e
Update tests
AnPucel Feb 6, 2023
05f61f9
Add read check
AnPucel Feb 13, 2023
39b1e5d
Read test
AnPucel Feb 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions builtin/logical/pki/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import (
"testing"
"time"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"

"github.com/stretchr/testify/require"

"github.com/armon/go-metrics"
Expand Down Expand Up @@ -551,7 +554,6 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s
if err != nil {
return err
}

if !reflect.DeepEqual(entries, expected) {
return fmt.Errorf("expected urls\n%#v\ndoes not match provided\n%#v\n", expected, entries)
}
Expand Down Expand Up @@ -1966,6 +1968,7 @@ func TestBackend_PathFetchCertList(t *testing.T) {
t.Parallel()
// create the backend
b, storage := CreateBackendWithStorage(t)
paths := []*framework.Path{pathConfigURLs(b)}

// generate root
rootData := map[string]interface{}{
Expand All @@ -1980,6 +1983,7 @@ func TestBackend_PathFetchCertList(t *testing.T) {
Data: rootData,
MountPoint: "pki/",
})

if resp != nil && resp.IsError() {
t.Fatalf("failed to generate root, %#v", resp)
}
Expand All @@ -2000,6 +2004,8 @@ func TestBackend_PathFetchCertList(t *testing.T) {
Data: urlsData,
MountPoint: "pki/",
})
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), resp, true)

if resp != nil && resp.IsError() {
t.Fatalf("failed to config urls, %#v", resp)
}
Expand Down Expand Up @@ -2366,6 +2372,8 @@ func TestBackend_Root_Idempotency(t *testing.T) {
t.Parallel()
b, s := CreateBackendWithStorage(t)

paths := []*framework.Path{pathConfigCA(b)}

// This is a change within 1.11, we are no longer idempotent across generate/internal calls.
resp, err := CBWrite(b, s, "root/generate/internal", map[string]interface{}{
"common_name": "myvault.com",
Expand Down Expand Up @@ -2407,6 +2415,8 @@ func TestBackend_Root_Idempotency(t *testing.T) {
resp, err = CBWrite(b, s, "config/ca", map[string]interface{}{
"pem_bundle": pemBundleRootCA,
})
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), resp, true)

require.NoError(t, err)
require.NotNil(t, resp, "expected ca info")
firstImportedKeys := resp.Data["imported_keys"].([]string)
Expand Down Expand Up @@ -5979,13 +5989,15 @@ func TestPKI_ListRevokedCerts(t *testing.T) {
func TestPKI_TemplatedAIAs(t *testing.T) {
t.Parallel()
b, s := CreateBackendWithStorage(t)
paths := []*framework.Path{pathConfigCluster(b)}

// Setting templated AIAs should succeed.
_, err := CBWrite(b, s, "config/cluster", map[string]interface{}{
resp, err := CBWrite(b, s, "config/cluster", map[string]interface{}{
"path": "http://localhost:8200/v1/pki",
"aia_path": "http://localhost:8200/cdn/pki",
})
require.NoError(t, err)
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), resp, true)

aiaData := map[string]interface{}{
"crl_distribution_points": "{{cluster_path}}/issuer/{{issuer_id}}/crl/der",
Expand Down Expand Up @@ -6014,7 +6026,7 @@ func TestPKI_TemplatedAIAs(t *testing.T) {
"enable_templating": false,
})
require.NoError(t, err)
resp, err := CBWrite(b, s, "root/generate/internal", rootData)
resp, err = CBWrite(b, s, "root/generate/internal", rootData)
requireSuccessNonNilResponse(t, resp, err)
issuerId := string(resp.Data["issuer_id"].(issuerID))

Expand Down
7 changes: 7 additions & 0 deletions builtin/logical/pki/crl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"testing"
"time"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"

"github.com/hashicorp/vault/api"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/sdk/logical"
Expand Down Expand Up @@ -80,6 +83,7 @@ func TestBackend_CRLConfig(t *testing.T) {
name := fmt.Sprintf("%s-%t-%t", tc.expiry, tc.disable, tc.ocspDisable)
t.Run(name, func(t *testing.T) {
b, s := CreateBackendWithStorage(t)
paths := []*framework.Path{pathConfigCRL(b)}

resp, err := CBWrite(b, s, "config/crl", map[string]interface{}{
"expiry": tc.expiry,
Expand All @@ -90,8 +94,11 @@ func TestBackend_CRLConfig(t *testing.T) {
"auto_rebuild_grace_period": tc.autoRebuildGracePeriod,
})
requireSuccessNonNilResponse(t, resp, err)
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), resp, true)

resp, err = CBRead(b, s, "config/crl")
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.ReadOperation), resp, true)

requireSuccessNonNilResponse(t, resp, err)
requireFieldsSetInResp(t, resp, "disable", "expiry", "ocsp_disable", "auto_rebuild", "auto_rebuild_grace_period")

Expand Down
10 changes: 9 additions & 1 deletion builtin/logical/pki/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import (
"fmt"
"testing"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/testhelpers/schema"

"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -360,6 +363,7 @@ func TestIntegration_CSRGeneration(t *testing.T) {
func TestIntegration_AutoIssuer(t *testing.T) {
t.Parallel()
b, s := CreateBackendWithStorage(t)
paths := []*framework.Path{pathConfigIssuers(b)}

// Generate two roots. The first should become default under the existing
// behavior; when we update the config and generate a second, it should
Expand All @@ -371,6 +375,7 @@ func TestIntegration_AutoIssuer(t *testing.T) {
"issuer_name": "root-1",
"key_type": "ec",
})

requireSuccessNonNilResponse(t, resp, err)
issuerIdOne := resp.Data["issuer_id"]
require.NotEmpty(t, issuerIdOne)
Expand All @@ -381,12 +386,15 @@ func TestIntegration_AutoIssuer(t *testing.T) {
requireSuccessNonNilResponse(t, resp, err)
require.Equal(t, issuerIdOne, resp.Data["default"])

schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.ReadOperation), resp, true)
AnPucel marked this conversation as resolved.
Show resolved Hide resolved

// Enable the new config option.
_, err = CBWrite(b, s, "config/issuers", map[string]interface{}{
resp, err = CBWrite(b, s, "config/issuers", map[string]interface{}{
"default": issuerIdOne,
"default_follows_latest_issuer": true,
})
require.NoError(t, err)
schema.ValidateResponse(t, schema.FindResponseSchema(t, paths, 0, logical.UpdateOperation), resp, true)

// Now generate the second root; it should become default.
resp, err = CBWrite(b, s, "root/generate/internal", map[string]interface{}{
Expand Down
100 changes: 97 additions & 3 deletions builtin/logical/pki/path_config_ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pki

import (
"context"
"net/http"

"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
Expand All @@ -21,6 +22,28 @@ secret key and certificate.`,
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,
AnPucel marked this conversation as resolved.
Show resolved Hide resolved
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,
Expand Down Expand Up @@ -58,13 +81,44 @@ func pathConfigIssuers(b *backend) *framework.Path {
Default: false,
},
},

Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Callback: b.pathCAIssuersRead,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
Required: true,
},
"default_follows_latest_issuer": {
Type: framework.TypeBool,
Description: `Whether the default issuer should automatically follow the latest generated or imported issuer. Defaults to false.`,
Required: true,
},
},
}},
},
},
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathCAIssuersWrite,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
},
"default_follows_latest_issuer": {
Type: framework.TypeBool,
Description: `Whether the default issuer should automatically follow the latest generated or imported issuer. Defaults to false.`,
},
},
}},
},
// Read more about why these flags are set in backend.go.
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
Expand All @@ -90,6 +144,23 @@ func pathReplaceRoot(b *backend) *framework.Path {
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathCAIssuersWrite,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
Required: true,
},
"default_follows_latest_issuer": {
Type: framework.TypeBool,
Description: `Whether the default issuer should automatically follow the latest generated or imported issuer. Defaults to false.`,
Required: true,
},
},
}},
},
// Read more about why these flags are set in backend.go.
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
Expand Down Expand Up @@ -208,12 +279,35 @@ func pathConfigKeys(b *backend) *framework.Path {

Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathKeyDefaultWrite,
Callback: b.pathKeyDefaultWrite,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
Required: true,
},
},
}},
},
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
},
logical.ReadOperation: &framework.PathOperation{
Callback: b.pathKeyDefaultRead,
Callback: b.pathKeyDefaultRead,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
},
},
}},
},
ForwardPerformanceStandby: false,
ForwardPerformanceSecondary: false,
},
Expand Down
62 changes: 62 additions & 0 deletions builtin/logical/pki/path_config_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pki
import (
"context"
"fmt"
"net/http"

"github.com/asaskevich/govalidator"
"github.com/hashicorp/vault/sdk/framework"
Expand Down Expand Up @@ -41,9 +42,70 @@ For example: http://cdn.example.com/pr1/pki`,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathWriteCluster,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: `Canonical URI to this mount on this performance
replication cluster's external address. This is for resolving AIA URLs and
providing the {{cluster_path}} template parameter but might be used for other
purposes in the future.

This should only point back to this particular PR replica and should not ever
point to another PR cluster. It may point to any node in the PR replica,
including standby nodes, and need not always point to the active node.

For example: https://pr1.vault.example.com:8200/v1/pki`,
},
"aia_path": {
Type: framework.TypeString,
Description: `Optional URI to this mount's AIA distribution
point; may refer to an external non-Vault responder. This is for resolving AIA
URLs and providing the {{cluster_aia_path}} template parameter and will not
be used for other purposes. As such, unlike path above, this could safely
be an insecure transit mechanism (like HTTP without TLS).

For example: http://cdn.example.com/pr1/pki`,
},
},
}},
},
},
logical.ReadOperation: &framework.PathOperation{
Callback: b.pathReadCluster,
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: `Canonical URI to this mount on this performance
replication cluster's external address. This is for resolving AIA URLs and
providing the {{cluster_path}} template parameter but might be used for other
purposes in the future.

This should only point back to this particular PR replica and should not ever
point to another PR cluster. It may point to any node in the PR replica,
including standby nodes, and need not always point to the active node.

For example: https://pr1.vault.example.com:8200/v1/pki`,
Required: true,
},
"aia_path": {
Type: framework.TypeString,
Description: `Optional URI to this mount's AIA distribution
point; may refer to an external non-Vault responder. This is for resolving AIA
URLs and providing the {{cluster_aia_path}} template parameter and will not
be used for other purposes. As such, unlike path above, this could safely
be an insecure transit mechanism (like HTTP without TLS).

For example: http://cdn.example.com/pr1/pki`,
},
},
}},
},
},
},

Expand Down
Loading