open-vault/builtin/logical/pki/cert_util_test.go

238 lines
5.9 KiB
Go
Raw Permalink Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2017-04-26 06:46:01 +00:00
package pki
import (
"context"
2017-04-27 21:09:59 +00:00
"fmt"
2019-05-02 21:31:29 +00:00
"reflect"
2017-04-27 21:09:59 +00:00
"strings"
"testing"
2017-04-27 21:09:59 +00:00
2019-05-02 21:31:29 +00:00
"github.com/hashicorp/vault/sdk/framework"
2019-05-02 23:29:41 +00:00
"github.com/hashicorp/vault/sdk/logical"
2017-04-26 06:46:01 +00:00
)
func TestPki_FetchCertBySerial(t *testing.T) {
t.Parallel()
b, storage := CreateBackendWithStorage(t)
sc := b.makeStorageContext(ctx, storage)
2017-04-26 06:46:01 +00:00
cases := map[string]struct {
2017-04-27 21:09:59 +00:00
Req *logical.Request
Prefix string
Serial string
2017-04-26 06:46:01 +00:00
}{
2017-04-27 21:09:59 +00:00
"valid cert": {
2017-04-26 06:46:01 +00:00
&logical.Request{
2017-04-28 12:55:28 +00:00
Storage: storage,
2017-04-26 06:46:01 +00:00
},
2017-04-27 21:09:59 +00:00
"certs/",
"00:00:00:00:00:00:00:00",
2017-04-26 06:46:01 +00:00
},
2017-04-27 21:09:59 +00:00
"revoked cert": {
2017-04-26 06:46:01 +00:00
&logical.Request{
2017-04-28 12:55:28 +00:00
Storage: storage,
2017-04-26 06:46:01 +00:00
},
2017-04-27 21:09:59 +00:00
"revoked/",
"11:11:11:11:11:11:11:11",
2017-04-26 06:46:01 +00:00
},
}
2017-04-27 21:09:59 +00:00
// Test for colon-based paths in storage
for name, tc := range cases {
storageKey := fmt.Sprintf("%s%s", tc.Prefix, tc.Serial)
err := storage.Put(context.Background(), &logical.StorageEntry{
2017-04-27 21:09:59 +00:00
Key: storageKey,
Value: []byte("some data"),
})
if err != nil {
t.Fatalf("error writing to storage on %s colon-based storage path: %s", name, err)
}
certEntry, err := fetchCertBySerial(sc, tc.Prefix, tc.Serial)
2017-04-27 21:09:59 +00:00
if err != nil {
t.Fatalf("error on %s for colon-based storage path: %s", name, err)
}
// Check for non-nil on valid/revoked certs
if certEntry == nil {
t.Fatalf("nil on %s for colon-based storage path", name)
}
// Ensure that cert serials are converted/updated after fetch
2017-05-03 14:12:58 +00:00
expectedKey := tc.Prefix + normalizeSerial(tc.Serial)
se, err := storage.Get(context.Background(), expectedKey)
2017-04-27 21:09:59 +00:00
if err != nil {
t.Fatalf("error on %s for colon-based storage path:%s", name, err)
}
if strings.Compare(expectedKey, se.Key) != 0 {
t.Fatalf("expected: %s, got: %s", expectedKey, certEntry.Key)
}
}
// Reset storage
storage = &logical.InmemStorage{}
// Test for hyphen-base paths in storage
2017-04-26 06:46:01 +00:00
for name, tc := range cases {
2017-05-03 14:12:58 +00:00
storageKey := tc.Prefix + normalizeSerial(tc.Serial)
err := storage.Put(context.Background(), &logical.StorageEntry{
2017-04-27 21:09:59 +00:00
Key: storageKey,
2017-04-26 06:46:01 +00:00
Value: []byte("some data"),
})
if err != nil {
2017-04-27 21:09:59 +00:00
t.Fatalf("error writing to storage on %s hyphen-based storage path: %s", name, err)
2017-04-26 06:46:01 +00:00
}
certEntry, err := fetchCertBySerial(sc, tc.Prefix, tc.Serial)
2017-04-28 12:55:28 +00:00
if err != nil || certEntry == nil {
t.Fatalf("error on %s for hyphen-based storage path: err: %v, entry: %v", name, err, certEntry)
}
}
2017-04-26 06:46:01 +00:00
}
2019-05-02 21:31:29 +00:00
// Demonstrate that multiple OUs in the name are handled in an
2019-05-02 21:31:29 +00:00
// order-preserving way.
func TestPki_MultipleOUs(t *testing.T) {
t.Parallel()
var b backend
2019-05-02 21:31:29 +00:00
fields := addCACommonFields(map[string]*framework.FieldSchema{})
apiData := &framework.FieldData{
Schema: fields,
2019-05-02 23:29:41 +00:00
Raw: map[string]interface{}{
"cn": "example.com",
"ttl": 3600,
2019-05-02 21:31:29 +00:00
},
}
input := &inputBundle{
2019-05-02 23:29:41 +00:00
apiData: apiData,
role: &roleEntry{
MaxTTL: 3600,
OU: []string{"Z", "E", "V"},
2019-05-02 21:31:29 +00:00
},
}
cb, _, err := generateCreationBundle(&b, input, nil, nil)
2019-05-02 21:31:29 +00:00
if err != nil {
t.Fatalf("Error: %v", err)
}
2019-05-02 23:29:41 +00:00
expected := []string{"Z", "E", "V"}
actual := cb.Params.Subject.OrganizationalUnit
2019-05-02 21:31:29 +00:00
2019-05-02 23:29:41 +00:00
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %v, got %v", expected, actual)
2019-05-02 21:31:29 +00:00
}
}
func TestPki_PermitFQDNs(t *testing.T) {
t.Parallel()
var b backend
fields := addCACommonFields(map[string]*framework.FieldSchema{})
cases := map[string]struct {
input *inputBundle
expectedDnsNames []string
expectedEmails []string
}{
"base valid case": {
input: &inputBundle{
apiData: &framework.FieldData{
Schema: fields,
Raw: map[string]interface{}{
"common_name": "example.com.",
"ttl": 3600,
},
},
role: &roleEntry{
AllowAnyName: true,
MaxTTL: 3600,
EnforceHostnames: true,
},
},
expectedDnsNames: []string{"example.com."},
expectedEmails: []string{},
},
"case insensitivity validation": {
input: &inputBundle{
apiData: &framework.FieldData{
Schema: fields,
Raw: map[string]interface{}{
"common_name": "Example.Net",
"alt_names": "eXaMPLe.COM",
"ttl": 3600,
},
},
role: &roleEntry{
AllowedDomains: []string{"example.net", "EXAMPLE.COM"},
AllowBareDomains: true,
MaxTTL: 3600,
},
},
expectedDnsNames: []string{"Example.Net", "eXaMPLe.COM"},
expectedEmails: []string{},
},
"case email as AllowedDomain with bare domains": {
input: &inputBundle{
apiData: &framework.FieldData{
Schema: fields,
Raw: map[string]interface{}{
"common_name": "test@testemail.com",
"ttl": 3600,
},
},
role: &roleEntry{
AllowedDomains: []string{"test@testemail.com"},
AllowBareDomains: true,
MaxTTL: 3600,
},
},
expectedDnsNames: []string{},
expectedEmails: []string{"test@testemail.com"},
},
"case email common name with bare domains": {
input: &inputBundle{
apiData: &framework.FieldData{
Schema: fields,
Raw: map[string]interface{}{
"common_name": "test@testemail.com",
"ttl": 3600,
},
},
role: &roleEntry{
AllowedDomains: []string{"testemail.com"},
AllowBareDomains: true,
MaxTTL: 3600,
},
},
expectedDnsNames: []string{},
expectedEmails: []string{"test@testemail.com"},
},
}
for name, testCase := range cases {
name := name
testCase := testCase
t.Run(name, func(t *testing.T) {
cb, _, err := generateCreationBundle(&b, testCase.input, nil, nil)
if err != nil {
t.Fatalf("Error: %v", err)
}
actualDnsNames := cb.Params.DNSNames
if !reflect.DeepEqual(testCase.expectedDnsNames, actualDnsNames) {
t.Fatalf("Expected dns names %v, got %v", testCase.expectedDnsNames, actualDnsNames)
}
actualEmails := cb.Params.EmailAddresses
if !reflect.DeepEqual(testCase.expectedEmails, actualEmails) {
t.Fatalf("Expected email addresses %v, got %v", testCase.expectedEmails, actualEmails)
}
})
}
}