2023-04-25 13:29:07 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
|
|
package pki
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-05-30 19:34:01 +00:00
|
|
|
"strings"
|
2023-04-25 13:29:07 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TestACMEIssuerRoleLoading validates the role and issuer loading logic within the base
|
|
|
|
// ACME wrapper is correct.
|
|
|
|
func TestACMEIssuerRoleLoading(t *testing.T) {
|
|
|
|
b, s := CreateBackendWithStorage(t)
|
|
|
|
|
|
|
|
_, 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)
|
|
|
|
|
2023-04-27 20:31:13 +00:00
|
|
|
_, err = CBWrite(b, s, "config/acme", map[string]interface{}{
|
|
|
|
"enabled": true,
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-04-25 13:29:07 +00:00
|
|
|
_, err = CBWrite(b, s, "root/generate/internal", map[string]interface{}{
|
|
|
|
"common_name": "myvault1.com",
|
|
|
|
"issuer_name": "issuer-1",
|
|
|
|
"key_type": "ec",
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "failed creating issuer issuer-1")
|
|
|
|
|
|
|
|
_, err = CBWrite(b, s, "root/generate/internal", map[string]interface{}{
|
|
|
|
"common_name": "myvault2.com",
|
|
|
|
"issuer_name": "issuer-2",
|
|
|
|
"key_type": "ec",
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "failed creating issuer issuer-2")
|
|
|
|
|
|
|
|
_, err = CBWrite(b, s, "roles/role-bad-issuer", map[string]interface{}{
|
|
|
|
issuerRefParam: "non-existant",
|
|
|
|
"no_store": "false",
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "failed creating role role-bad-issuer")
|
|
|
|
|
|
|
|
_, err = CBWrite(b, s, "roles/role-no-store-enabled", map[string]interface{}{
|
|
|
|
issuerRefParam: "issuer-2",
|
|
|
|
"no_store": "true",
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "failed creating role role-no-store-enabled")
|
|
|
|
|
|
|
|
_, err = CBWrite(b, s, "roles/role-issuer-2", map[string]interface{}{
|
|
|
|
issuerRefParam: "issuer-2",
|
|
|
|
"no_store": "false",
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "failed creating role role-issuer-2")
|
|
|
|
|
|
|
|
tc := []struct {
|
|
|
|
name string
|
|
|
|
roleName string
|
|
|
|
issuerName string
|
|
|
|
expectedIssuerName string
|
|
|
|
expectErr bool
|
|
|
|
}{
|
|
|
|
{name: "pass-default-use-default", roleName: "", issuerName: "", expectedIssuerName: "issuer-1", expectErr: false},
|
|
|
|
{name: "pass-role-issuer-2", roleName: "role-issuer-2", issuerName: "", expectedIssuerName: "issuer-2", expectErr: false},
|
|
|
|
{name: "pass-issuer-1-no-role", roleName: "", issuerName: "issuer-1", expectedIssuerName: "issuer-1", expectErr: false},
|
|
|
|
{name: "fail-role-has-bad-issuer", roleName: "role-bad-issuer", issuerName: "", expectedIssuerName: "", expectErr: true},
|
|
|
|
{name: "fail-role-no-store-enabled", roleName: "role-no-store-enabled", issuerName: "", expectedIssuerName: "", expectErr: true},
|
|
|
|
{name: "fail-role-no-store-enabled", roleName: "role-no-store-enabled", issuerName: "", expectedIssuerName: "", expectErr: true},
|
|
|
|
{name: "fail-role-does-not-exist", roleName: "non-existant", issuerName: "", expectedIssuerName: "", expectErr: true},
|
|
|
|
{name: "fail-issuer-does-not-exist", roleName: "", issuerName: "non-existant", expectedIssuerName: "", expectErr: true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tc {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
f := b.acmeWrapper(func(acmeCtx *acmeContext, r *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
|
|
|
|
if tt.roleName != acmeCtx.role.Name {
|
|
|
|
return nil, fmt.Errorf("expected role %s but got %s", tt.roleName, acmeCtx.role.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if tt.expectedIssuerName != acmeCtx.issuer.Name {
|
|
|
|
return nil, fmt.Errorf("expected issuer %s but got %s", tt.expectedIssuerName, acmeCtx.issuer.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
})
|
|
|
|
|
2023-05-30 19:34:01 +00:00
|
|
|
var acmePath string
|
2023-04-25 13:29:07 +00:00
|
|
|
fieldRaw := map[string]interface{}{}
|
|
|
|
if tt.issuerName != "" {
|
|
|
|
fieldRaw[issuerRefParam] = tt.issuerName
|
2023-05-30 19:34:01 +00:00
|
|
|
acmePath = "issuer/" + tt.issuerName + "/"
|
2023-04-25 13:29:07 +00:00
|
|
|
}
|
2023-05-30 19:34:01 +00:00
|
|
|
if tt.roleName != "" {
|
|
|
|
fieldRaw["role"] = tt.roleName
|
|
|
|
acmePath = acmePath + "roles/" + tt.roleName + "/"
|
|
|
|
}
|
|
|
|
|
|
|
|
acmePath = strings.TrimLeft(acmePath+"/acme/directory", "/")
|
2023-04-25 13:29:07 +00:00
|
|
|
|
2023-05-30 19:34:01 +00:00
|
|
|
resp, err := f(context.Background(), &logical.Request{Path: acmePath, Storage: s}, &framework.FieldData{
|
2023-04-25 13:29:07 +00:00
|
|
|
Raw: fieldRaw,
|
|
|
|
Schema: getCsrSignVerbatimSchemaFields(),
|
|
|
|
})
|
|
|
|
require.NoError(t, err, "all errors should be re-encoded")
|
|
|
|
|
|
|
|
if tt.expectErr {
|
|
|
|
require.NotEqual(t, 200, resp.Data[logical.HTTPStatusCode])
|
|
|
|
require.Equal(t, ErrorContentType, resp.Data[logical.HTTPContentType])
|
|
|
|
} else {
|
|
|
|
if resp != nil {
|
|
|
|
t.Fatalf("expected no error got %s", string(resp.Data[logical.HTTPRawBody].([]uint8)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|