e5f4ca83a0
* Update PKI to natively use time.Duration Among other things this now means PKI will output durations in seconds like other backends, instead of as Go strings. * Add a warning when refusing to blow away an existing root instead of just returning success * Fix another issue found while debugging this... The reason it wasn't caught on tests in the first place is that the ttl and max ttl were only being compared if in addition to a provided csr, a role was also provided. This was because the check was in the role != nil block instead of outside of it. This has been fixed, which made the problem occur in all sign-verbatim cases and the changes in this PR have now verified the fix.
708 lines
20 KiB
Go
708 lines
20 KiB
Go
package pki
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/vault/helper/strutil"
|
|
"github.com/hashicorp/vault/logical"
|
|
"github.com/mitchellh/mapstructure"
|
|
)
|
|
|
|
func createBackendWithStorage(t *testing.T) (*backend, logical.Storage) {
|
|
config := logical.TestBackendConfig()
|
|
config.StorageView = &logical.InmemStorage{}
|
|
|
|
var err error
|
|
b := Backend()
|
|
err = b.Setup(context.Background(), config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return b, config.StorageView
|
|
}
|
|
|
|
func TestPki_RoleGenerateLease(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": "myvault.com",
|
|
"ttl": "5h",
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
// generate_lease cannot be nil. It either has to be set during role
|
|
// creation or has to be filled in by the upgrade code
|
|
generateLease := resp.Data["generate_lease"].(*bool)
|
|
if generateLease == nil {
|
|
t.Fatalf("generate_lease should not be nil")
|
|
}
|
|
|
|
// By default, generate_lease should be `false`
|
|
if *generateLease {
|
|
t.Fatalf("generate_lease should not be set by default")
|
|
}
|
|
|
|
// Update values due to switching of ttl type
|
|
resp.Data["ttl_duration"] = resp.Data["ttl"]
|
|
resp.Data["ttl"] = (time.Duration(resp.Data["ttl"].(int64)) * time.Second).String()
|
|
resp.Data["max_ttl_duration"] = resp.Data["max_ttl"]
|
|
resp.Data["max_ttl"] = (time.Duration(resp.Data["max_ttl"].(int64)) * time.Second).String()
|
|
// role.GenerateLease will be nil after the decode
|
|
var role roleEntry
|
|
err = mapstructure.Decode(resp.Data, &role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Make it explicit
|
|
role.GenerateLease = nil
|
|
|
|
entry, err := logical.StorageEntryJSON("role/testrole", role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := storage.Put(context.Background(), entry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Reading should upgrade generate_lease
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
generateLease = resp.Data["generate_lease"].(*bool)
|
|
if generateLease == nil {
|
|
t.Fatalf("generate_lease should not be nil")
|
|
}
|
|
|
|
// Upgrade should set generate_lease to `true`
|
|
if !*generateLease {
|
|
t.Fatalf("generate_lease should be set after an upgrade")
|
|
}
|
|
|
|
// Make sure that setting generate_lease to `true` works properly
|
|
roleReq.Operation = logical.UpdateOperation
|
|
roleReq.Path = "roles/testrole2"
|
|
roleReq.Data["generate_lease"] = true
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
generateLease = resp.Data["generate_lease"].(*bool)
|
|
if generateLease == nil {
|
|
t.Fatalf("generate_lease should not be nil")
|
|
}
|
|
if !*generateLease {
|
|
t.Fatalf("generate_lease should have been set")
|
|
}
|
|
}
|
|
|
|
func TestPki_RoleKeyUsage(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": "myvault.com",
|
|
"ttl": "5h",
|
|
"key_usage": []string{"KeyEncipherment", "DigitalSignature"},
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
keyUsage := resp.Data["key_usage"].([]string)
|
|
if len(keyUsage) != 2 {
|
|
t.Fatalf("key_usage should have 2 values")
|
|
}
|
|
|
|
// Update values due to switching of ttl type
|
|
resp.Data["ttl_duration"] = resp.Data["ttl"]
|
|
resp.Data["ttl"] = (time.Duration(resp.Data["ttl"].(int64)) * time.Second).String()
|
|
resp.Data["max_ttl_duration"] = resp.Data["max_ttl"]
|
|
resp.Data["max_ttl"] = (time.Duration(resp.Data["max_ttl"].(int64)) * time.Second).String()
|
|
// Check that old key usage value is nil
|
|
var role roleEntry
|
|
err = mapstructure.Decode(resp.Data, &role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if role.KeyUsageOld != "" {
|
|
t.Fatalf("old key usage storage value should be blank")
|
|
}
|
|
|
|
// Make it explicit
|
|
role.KeyUsageOld = "KeyEncipherment,DigitalSignature"
|
|
role.KeyUsage = nil
|
|
|
|
entry, err := logical.StorageEntryJSON("role/testrole", role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := storage.Put(context.Background(), entry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Reading should upgrade key_usage
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
keyUsage = resp.Data["key_usage"].([]string)
|
|
if len(keyUsage) != 2 {
|
|
t.Fatalf("key_usage should have 2 values")
|
|
}
|
|
|
|
// Read back from storage to ensure upgrade
|
|
entry, err = storage.Get(context.Background(), "role/testrole")
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if entry == nil {
|
|
t.Fatalf("role should not be nil")
|
|
}
|
|
var result roleEntry
|
|
if err := entry.DecodeJSON(&result); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
if result.KeyUsageOld != "" {
|
|
t.Fatal("old key usage value should be blank")
|
|
}
|
|
if len(result.KeyUsage) != 2 {
|
|
t.Fatal("key_usage should have 2 values")
|
|
}
|
|
}
|
|
|
|
func TestPki_RoleOUOrganizationUpgrade(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": "myvault.com",
|
|
"ttl": "5h",
|
|
"ou": []string{"abc", "123"},
|
|
"organization": []string{"org1", "org2"},
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
ou := resp.Data["ou"].([]string)
|
|
if len(ou) != 2 {
|
|
t.Fatalf("ou should have 2 values")
|
|
}
|
|
organization := resp.Data["organization"].([]string)
|
|
if len(organization) != 2 {
|
|
t.Fatalf("organization should have 2 values")
|
|
}
|
|
|
|
// Update values due to switching of ttl type
|
|
resp.Data["ttl_duration"] = resp.Data["ttl"]
|
|
resp.Data["ttl"] = (time.Duration(resp.Data["ttl"].(int64)) * time.Second).String()
|
|
resp.Data["max_ttl_duration"] = resp.Data["max_ttl"]
|
|
resp.Data["max_ttl"] = (time.Duration(resp.Data["max_ttl"].(int64)) * time.Second).String()
|
|
// Check that old key usage value is nil
|
|
var role roleEntry
|
|
err = mapstructure.Decode(resp.Data, &role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if role.OUOld != "" {
|
|
t.Fatalf("old ou storage value should be blank")
|
|
}
|
|
if role.OrganizationOld != "" {
|
|
t.Fatalf("old organization storage value should be blank")
|
|
}
|
|
|
|
// Make it explicit
|
|
role.OUOld = "abc,123"
|
|
role.OU = nil
|
|
role.OrganizationOld = "org1,org2"
|
|
role.Organization = nil
|
|
|
|
entry, err := logical.StorageEntryJSON("role/testrole", role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := storage.Put(context.Background(), entry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Reading should upgrade key_usage
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
ou = resp.Data["ou"].([]string)
|
|
if len(ou) != 2 {
|
|
t.Fatalf("ou should have 2 values")
|
|
}
|
|
organization = resp.Data["organization"].([]string)
|
|
if len(organization) != 2 {
|
|
t.Fatalf("organization should have 2 values")
|
|
}
|
|
|
|
// Read back from storage to ensure upgrade
|
|
entry, err = storage.Get(context.Background(), "role/testrole")
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if entry == nil {
|
|
t.Fatalf("role should not be nil")
|
|
}
|
|
var result roleEntry
|
|
if err := entry.DecodeJSON(&result); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
if result.OUOld != "" {
|
|
t.Fatal("old ou value should be blank")
|
|
}
|
|
if len(result.OU) != 2 {
|
|
t.Fatal("ou should have 2 values")
|
|
}
|
|
if result.OrganizationOld != "" {
|
|
t.Fatal("old organization value should be blank")
|
|
}
|
|
if len(result.Organization) != 2 {
|
|
t.Fatal("organization should have 2 values")
|
|
}
|
|
}
|
|
|
|
func TestPki_RoleAllowedDomains(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": []string{"foobar.com", "*example.com"},
|
|
"ttl": "5h",
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
allowedDomains := resp.Data["allowed_domains"].([]string)
|
|
if len(allowedDomains) != 2 {
|
|
t.Fatalf("allowed_domains should have 2 values")
|
|
}
|
|
|
|
// Update values due to switching of ttl type
|
|
resp.Data["ttl_duration"] = resp.Data["ttl"]
|
|
resp.Data["ttl"] = (time.Duration(resp.Data["ttl"].(int64)) * time.Second).String()
|
|
resp.Data["max_ttl_duration"] = resp.Data["max_ttl"]
|
|
resp.Data["max_ttl"] = (time.Duration(resp.Data["max_ttl"].(int64)) * time.Second).String()
|
|
// Check that old key usage value is nil
|
|
var role roleEntry
|
|
err = mapstructure.Decode(resp.Data, &role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if role.AllowedDomainsOld != "" {
|
|
t.Fatalf("old allowed_domains storage value should be blank")
|
|
}
|
|
|
|
// Make it explicit
|
|
role.AllowedDomainsOld = "foobar.com,*example.com"
|
|
role.AllowedDomains = nil
|
|
|
|
entry, err := logical.StorageEntryJSON("role/testrole", role)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := storage.Put(context.Background(), entry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Reading should upgrade key_usage
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
allowedDomains = resp.Data["allowed_domains"].([]string)
|
|
if len(allowedDomains) != 2 {
|
|
t.Fatalf("allowed_domains should have 2 values")
|
|
}
|
|
|
|
// Read back from storage to ensure upgrade
|
|
entry, err = storage.Get(context.Background(), "role/testrole")
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
if entry == nil {
|
|
t.Fatalf("role should not be nil")
|
|
}
|
|
var result roleEntry
|
|
if err := entry.DecodeJSON(&result); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
|
|
if result.AllowedDomainsOld != "" {
|
|
t.Fatal("old allowed_domains value should be blank")
|
|
}
|
|
if len(result.AllowedDomains) != 2 {
|
|
t.Fatal("allowed_domains should have 2 values")
|
|
}
|
|
}
|
|
|
|
func TestPki_RolePkixFields(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"ttl": "5h",
|
|
"country": []string{"c1", "c2"},
|
|
"ou": []string{"abc", "123"},
|
|
"organization": []string{"org1", "org2"},
|
|
"locality": []string{"foocity", "bartown"},
|
|
"province": []string{"bar", "foo"},
|
|
"street_address": []string{"123 foo street", "789 bar avenue"},
|
|
"postal_code": []string{"f00", "b4r"},
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole_pkixfields",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
origCountry := roleData["country"].([]string)
|
|
respCountry := resp.Data["country"].([]string)
|
|
if !strutil.StrListSubset(origCountry, respCountry) {
|
|
t.Fatalf("country did not match values set in role")
|
|
} else if len(origCountry) != len(respCountry) {
|
|
t.Fatalf("country did not have same number of values set in role")
|
|
}
|
|
|
|
origOU := roleData["ou"].([]string)
|
|
respOU := resp.Data["ou"].([]string)
|
|
if !strutil.StrListSubset(origOU, respOU) {
|
|
t.Fatalf("ou did not match values set in role")
|
|
} else if len(origOU) != len(respOU) {
|
|
t.Fatalf("ou did not have same number of values set in role")
|
|
}
|
|
|
|
origOrganization := roleData["organization"].([]string)
|
|
respOrganization := resp.Data["organization"].([]string)
|
|
if !strutil.StrListSubset(origOrganization, respOrganization) {
|
|
t.Fatalf("organization did not match values set in role")
|
|
} else if len(origOrganization) != len(respOrganization) {
|
|
t.Fatalf("organization did not have same number of values set in role")
|
|
}
|
|
|
|
origLocality := roleData["locality"].([]string)
|
|
respLocality := resp.Data["locality"].([]string)
|
|
if !strutil.StrListSubset(origLocality, respLocality) {
|
|
t.Fatalf("locality did not match values set in role")
|
|
} else if len(origLocality) != len(respLocality) {
|
|
t.Fatalf("locality did not have same number of values set in role: ")
|
|
}
|
|
|
|
origProvince := roleData["province"].([]string)
|
|
respProvince := resp.Data["province"].([]string)
|
|
if !strutil.StrListSubset(origProvince, respProvince) {
|
|
t.Fatalf("province did not match values set in role")
|
|
} else if len(origProvince) != len(respProvince) {
|
|
t.Fatalf("province did not have same number of values set in role")
|
|
}
|
|
|
|
origStreetAddress := roleData["street_address"].([]string)
|
|
respStreetAddress := resp.Data["street_address"].([]string)
|
|
if !strutil.StrListSubset(origStreetAddress, respStreetAddress) {
|
|
t.Fatalf("street_address did not match values set in role")
|
|
} else if len(origStreetAddress) != len(respStreetAddress) {
|
|
t.Fatalf("street_address did not have same number of values set in role")
|
|
}
|
|
|
|
origPostalCode := roleData["postal_code"].([]string)
|
|
respPostalCode := resp.Data["postal_code"].([]string)
|
|
if !strutil.StrListSubset(origPostalCode, respPostalCode) {
|
|
t.Fatalf("postal_code did not match values set in role")
|
|
} else if len(origPostalCode) != len(respPostalCode) {
|
|
t.Fatalf("postal_code did not have same number of values set in role")
|
|
}
|
|
}
|
|
|
|
func TestPki_RoleNoStore(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": "myvault.com",
|
|
"ttl": "5h",
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
// By default, no_store should be `false`
|
|
noStore := resp.Data["no_store"].(bool)
|
|
if noStore {
|
|
t.Fatalf("no_store should not be set by default")
|
|
}
|
|
|
|
// Make sure that setting no_store to `true` works properly
|
|
roleReq.Operation = logical.UpdateOperation
|
|
roleReq.Path = "roles/testrole_nostore"
|
|
roleReq.Data["no_store"] = true
|
|
roleReq.Data["allowed_domain"] = "myvault.com"
|
|
roleReq.Data["allow_subdomains"] = true
|
|
roleReq.Data["ttl"] = "5h"
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
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)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
noStore = resp.Data["no_store"].(bool)
|
|
if !noStore {
|
|
t.Fatalf("no_store should have been set to true")
|
|
}
|
|
|
|
// issue a certificate and test that it's not stored
|
|
caData := map[string]interface{}{
|
|
"common_name": "myvault.com",
|
|
"ttl": "5h",
|
|
"ip_sans": "127.0.0.1",
|
|
}
|
|
caReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "root/generate/internal",
|
|
Storage: storage,
|
|
Data: caData,
|
|
}
|
|
resp, err = b.HandleRequest(context.Background(), caReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
issueData := map[string]interface{}{
|
|
"common_name": "cert.myvault.com",
|
|
"format": "pem",
|
|
"ip_sans": "127.0.0.1",
|
|
"ttl": "1h",
|
|
}
|
|
issueReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "issue/testrole_nostore",
|
|
Storage: storage,
|
|
Data: issueData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), issueReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
// list certs
|
|
resp, err = b.HandleRequest(context.Background(), &logical.Request{
|
|
Operation: logical.ListOperation,
|
|
Path: "certs",
|
|
Storage: storage,
|
|
})
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
if len(resp.Data["keys"].([]string)) != 1 {
|
|
t.Fatalf("Only the CA certificate should be stored: %#v", resp)
|
|
}
|
|
}
|
|
|
|
func TestPki_CertsLease(t *testing.T) {
|
|
var resp *logical.Response
|
|
var err error
|
|
b, storage := createBackendWithStorage(t)
|
|
|
|
caData := map[string]interface{}{
|
|
"common_name": "myvault.com",
|
|
"ttl": "5h",
|
|
"ip_sans": "127.0.0.1",
|
|
}
|
|
|
|
caReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "root/generate/internal",
|
|
Storage: storage,
|
|
Data: caData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), caReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
roleData := map[string]interface{}{
|
|
"allowed_domains": "myvault.com",
|
|
"allow_subdomains": true,
|
|
"ttl": "2h",
|
|
}
|
|
|
|
roleReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "roles/testrole",
|
|
Storage: storage,
|
|
Data: roleData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
issueData := map[string]interface{}{
|
|
"common_name": "cert.myvault.com",
|
|
"format": "pem",
|
|
"ip_sans": "127.0.0.1",
|
|
}
|
|
issueReq := &logical.Request{
|
|
Operation: logical.UpdateOperation,
|
|
Path: "issue/testrole",
|
|
Storage: storage,
|
|
Data: issueData,
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), issueReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
if resp.Secret != nil {
|
|
t.Fatalf("expected a response that does not contain a secret")
|
|
}
|
|
|
|
// Turn on the lease generation and issue a certificate. The response
|
|
// should have a `Secret` object populated.
|
|
roleData["generate_lease"] = true
|
|
|
|
resp, err = b.HandleRequest(context.Background(), roleReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
resp, err = b.HandleRequest(context.Background(), issueReq)
|
|
if err != nil || (resp != nil && resp.IsError()) {
|
|
t.Fatalf("bad: err: %v resp: %#v", err, resp)
|
|
}
|
|
|
|
if resp.Secret == nil {
|
|
t.Fatalf("expected a response that contains a secret")
|
|
}
|
|
}
|