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

Issue-10: add back in RSA #14

Merged
merged 1 commit into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,16 @@ pathrotatecrl:
pathtidycrl:
go test -v -run TestPathTidyCRL ./pkg/hsmpki

pathgenerateroot:
go test -v -run TestPathGenerateRoot ./pkg/hsmpki

pathgenerateintermediate:
go test -v -run TestPathGenerateIntermediate ./pkg/hsmpki

pathissue:
go test -v -run TestPathIssue ./pkg/hsmpki

pathdeleteroot:
go test -v -run TestPathDeleteRoot ./pkg/hsmpki

.PHONY: build clean fmt start enable
8 changes: 7 additions & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ If you want to run tests in an IDE then source DPoD in a shell and start the IDE

## Makefile Command Line Tests

Test the HSM connection where the conf is loaded in from conf/config-hsm.hcl
Test the HSM connection where the conf is loaded in from conf/config-safenet.hcl

`make test hsmconnection`

Expand All @@ -19,3 +19,9 @@ Test the HSM connection where the conf is loaded in from conf/config-hsm.hcl
`make test pathfetchcrl`

`make test pathsetsignedintermediate`

`make test pathgenerateroot`

`make test pathgenerateintermediate`

`make test pathdeleteroot`
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/miekg/pkcs11 v1.0.3
github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/mode51software/pkcs11helper v0.3.2
github.com/mode51software/pkcs11helper v0.3.3
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/ryanuber/go-glob v1.0.0
github.com/stretchr/objx v0.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mode51software/pkcs11helper v0.3.2 h1:FNCo8jeEOpq5d8kfpSKbMEZ5ft8el9+MmT1zQh0yPc8=
github.com/mode51software/pkcs11helper v0.3.2/go.mod h1:kTP66TAfYMJTuND7oT1y4FWyTmAtkJh/b7QwtH1VOcI=
github.com/mode51software/pkcs11helper v0.3.3 h1:ea11q6DrS8zmRXIst8W7Bs60WN9/ZSPSKyI/sfS1uVg=
github.com/mode51software/pkcs11helper v0.3.3/go.mod h1:kTP66TAfYMJTuND7oT1y4FWyTmAtkJh/b7QwtH1VOcI=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
82 changes: 47 additions & 35 deletions pkg/hsmpki/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type HsmPkiBackend struct {
cachedCAConfig cachedCAConfig // needs to be re-cached on startup
refreshMutex sync.Mutex
store map[string][]byte
connChannel chan int
backendConfig *logical.BackendConfig

// this is the same storage as in the pki Backend, so ref here for convenience
//storage logical.Storage
}
Expand All @@ -45,64 +48,61 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
if err = b.pkiBackend.Backend.Setup(ctx, conf); err != nil {
return nil, err
}
b.backendConfig = conf
if _, ok := conf.Config[CONFIG_PARAM]; !ok {
b.pkiBackend.Backend.Logger().Error("Please add a parameter specifying a file containing the HSM's configuration. Plugin mounting aborted.")
}
return b.pkiBackend.Backend, nil

}

if confFile, ok := conf.Config[CONFIG_PARAM]; ok {
// plugins are launched first in metadata mode then lazily loaded later so don't create the connection until fully loaded
// https://groups.google.com/g/vault-tool/c/z6iaU_B159A/m/ag7OJaeECQAJ
func (b *HsmPkiBackend) initnow(ctx context.Context, req *logical.InitializationRequest) error {
b.pkiBackend.Backend.Logger().Info("Init")

if confFile, ok := b.backendConfig.Config[CONFIG_PARAM]; ok {

b.pkiBackend.Backend.Logger().Info("found conf: " + confFile)

// check the conf is valid
if err = b.loadConf(confFile); err != nil {
return nil, errwrap.Wrapf("Conf file error: {{err}}", err)
if err := b.loadConf(confFile); err != nil {
return errwrap.Wrapf("Conf file error: {{err}}", err)
}
b.loadStorage()

b.loadStorage()
b.configurePkcs11Connection()
b.checkPkcs11ConnectionAsync() //; err != nil {
// b.pkiBackend.Backend.Logger().Error("PKCS#11 connection timed out on startup, will retry on request")
//}

return b.pkiBackend.Backend, nil
b.checkPkcs11ConnectionAsync()

} else {
for key, value := range conf.Config {
b.pkiBackend.Backend.Logger().Info("Conf key=" + key + " Val=" + value)
}
b.pkiBackend.Backend.Logger().Error("Please add a parameter specifying a file containing the HSM's configuration. Plugin mounting aborted.")
// infer whether the plugin is being registered in the catalog or being mounted by checking for the presence of plugin_name
// there may be a better way to do this!
if _, ok := conf.Config[CONFIG_PLUGIN_NAME]; ok {
// if the plugin is being mounted and the config file hasn't been included then fail with a message
return nil, errors.New("Please add a parameter specifying a file containing the HSM's configuration. Plugin mounting aborted.")
} else {
// a Backend is returned here so that the plugin can be registered in the catalog
return b.pkiBackend.Backend, nil
}
return errors.New("Please add a parameter specifying a file containing the HSM's configuration. Plugin mounting aborted.")
}

return nil
}

func Backend(conf *logical.BackendConfig) (*HsmPkiBackend, error) {
b := &HsmPkiBackend{
//keyConfig: pkcs11client.KeyConfig{Label: "SSL Root CA 02", Type: pkcs11client.CKK_RSA },
// keyConfig: pkcs11client.KeyConfig{Id: "0007", Type: pkcs11.CKK_RSA},
store: make(map[string][]byte),
}

b.pkiBackend.Backend.Backend = &framework.Backend{
Help: strings.TrimSpace(PLUGIN_HELP),
BackendType: logical.TypeLogical,
Help: strings.TrimSpace(PLUGIN_HELP),
BackendType: logical.TypeLogical,
InitializeFunc: b.initnow,
Paths: []*framework.Path{
pki.PathListRoles(&b.pkiBackend.Backend),
pki.PathRoles(&b.pkiBackend.Backend),
pathGenerateRoot(b),
pathSignIntermediate(b),
//pathSignSelfIssued(&b),
//pathDeleteRoot(&b),
pathDeleteRoot(b),
pathGenerateIntermediate(b),
pathSetSignedIntermediate(b),
//pathConfigCA(&b),
//pathConfigCA(&b), // not implemented
pki.PathConfigCRL(&b.pkiBackend.Backend),
//pathConfigURLs(&b),
pki.PathConfigURLs(&b.pkiBackend.Backend),
//pathSignVerbatim(&b),
pathSign(b),
pathIssue(b),
Expand All @@ -115,7 +115,7 @@ func Backend(conf *logical.BackendConfig) (*HsmPkiBackend, error) {
pki.PathFetchListCerts(&b.pkiBackend.Backend),
pathRevoke(b),
pathTidy(b),
pathFetchCAKeyAlias(b), // new path
pathFetchCAKeyLabel(b), // new path
},
PathsSpecial: &logical.Paths{
Unauthenticated: []string{
Expand Down Expand Up @@ -156,13 +156,25 @@ func (b *HsmPkiBackend) configurePkcs11Connection() {
// on startup attempt to connect asynchronously
func (b *HsmPkiBackend) checkPkcs11ConnectionAsync() {

go func() {
b.connChannel = make(chan int)

//b.pkcs11client.Pkcs11Mutex.Lock()
//b.pkcs11client.FlushSession()
//b.pkcs11client.Pkcs11Mutex.Unlock()

b.checkPkcs11ConnectionSync()
go func() {
//for {

b.pkiBackend.Backend.Logger().Info("Checking PKCS#11 connection")

// plugins are launched first in metadata mode then lazily loaded later so don't create the connection until fully loaded
// https://groups.google.com/g/vault-tool/c/z6iaU_B159A/m/ag7OJaeECQAJ
timer := time.NewTimer(time.Second * 3)
select {
case <-b.connChannel:
b.pkiBackend.Backend.Logger().Info("Shutting down PKCS#11 connection monitor")
return
case <-timer.C:
// continue
b.checkPkcs11ConnectionSync()
}
//}
}()
return
}
Expand Down
64 changes: 30 additions & 34 deletions pkg/hsmpki/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package hsmpki
import (
"context"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/mode51software/pkcs11helper/pkg/pkcs11client"
"github.com/mode51software/vaultplugin-hsmpki/pkg/pki"
Expand Down Expand Up @@ -92,7 +91,7 @@ func testFetchCAKeyLabel(t *testing.T, integraTest *testEnv) {

req := &logical.Request{
Operation: logical.ReadOperation,
Path: PATH_CAKEYALIAS,
Path: PATH_CAKEYLABEL,
Storage: integraTest.Storage,
}

Expand Down Expand Up @@ -384,8 +383,8 @@ func testGenerateRoot(t *testing.T, integraTest *testEnv) {
}
data.Raw[FIELD_COMMON_NAME] = TEST_CAROOTCOMMONNAME
data.Raw[FIELD_EXPORTED] = TEST_EXPORTED
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPE
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITS
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPERSA
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITSRSA
// data.Raw[FIELD_PERMITTED_DNS_NAMES] = TEST_CAPERMITTEDDNSDOMAINS
data.Raw[FIELD_ORGANIZATION] = TEST_CAORGANIZATION
data.Raw[FIELD_OU] = TEST_CAOU
Expand All @@ -398,7 +397,6 @@ func testGenerateRoot(t *testing.T, integraTest *testEnv) {
data.Raw[FIELD_TTL] = TEST_CATTL

//caKeyAlias := "ECTestCARootKey0017"

//integraTest.HsmPkiBackend.saveCAKeyAlias(context.Background(), integraTest.Storage, &caKeyAlias)
//integraTest.HsmPkiBackend.cachedCAConfig.caKeyAlias = caKeyAlias

Expand Down Expand Up @@ -443,8 +441,8 @@ func testGenerateIntermediate(t *testing.T, integraTest *testEnv) string {
}
data.Raw[FIELD_COMMON_NAME] = TEST_CAINTERCOMMONNAME
data.Raw[FIELD_EXPORTED] = TEST_EXPORTED
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPE
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITS
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPEEC
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITSEC
// data.Raw[FIELD_PERMITTED_DNS_NAMES] = TEST_CAPERMITTEDDNSDOMAINS
data.Raw[FIELD_ORGANIZATION] = TEST_CAORGANIZATION
data.Raw[FIELD_OU] = TEST_CAOU
Expand Down Expand Up @@ -479,6 +477,7 @@ func testGenerateIntermediate(t *testing.T, integraTest *testEnv) string {

}

/*
// sign intermediate needs a CSR as input that is to be signed with the RootCA
// usually Generate Root will be run on mount path A, then Generate Intermediate on mount path B,
// then Sign Intermediate on mount path A, followed by Set Signed Intermediate on mount path B
Expand All @@ -491,25 +490,6 @@ func TestPathSignIntermediate(t *testing.T) {

testConnectPkcs11Connection(t, integraTest)

/* testGenerateRoot(t, integraTest)

bundleEntry, err := integraTest.Storage.Get(context.Background(), "config/rootca_bundle")
var bundle certutil.CertBundle
if err = bundleEntry.DecodeJSON(&bundle); err != nil {
return //, errutil.InternalError{Err: fmt.Sprintf("unable to decode local CA certificate/key: %v", err)}
}
t.Logf("bundle=%s", bundle.Certificate)

csr := testGenerateIntermediate(t, integraTest)

bundleEntry2, err := integraTest.Storage.Get(context.Background(), CA_BUNDLE)
var bundle2 certutil.CertBundle
if err = bundleEntry2.DecodeJSON(&bundle2); err != nil {
return //, errutil.InternalError{Err: fmt.Sprintf("unable to decode local CA certificate/key: %v", err)}
}
t.Logf("bundle2=%s", bundle2.Certificate)
*/

rootCACert, err := pkcs11client.LoadFromFileAsString(TEST_ROOTCACERTFILE)
cb := &certutil.CertBundle{}
cb.Certificate = *rootCACert
Expand Down Expand Up @@ -543,8 +523,8 @@ func testSignIntermediate(t *testing.T, integraTest *testEnv, csr *string) {
}
data.Raw[FIELD_COMMON_NAME] = TEST_CAINTERCOMMONNAME
data.Raw[FIELD_EXPORTED] = TEST_EXPORTED
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPE
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITS
data.Raw[FIELD_KEY_TYPE] = TEST_CAKEYTYPEEC
data.Raw[FIELD_KEY_BITS] = TEST_CAKEYBITSEC
// data.Raw[FIELD_PERMITTED_DNS_NAMES] = TEST_CAPERMITTEDDNSDOMAINS
data.Raw[FIELD_ORGANIZATION] = TEST_CAORGANIZATION
data.Raw[FIELD_OU] = []string{TEST_CAOU}
Expand Down Expand Up @@ -630,8 +610,8 @@ func testIssue(t *testing.T, integraTest *testEnv) {
t.Logf("Issue succeeded: %s", response.Data["certificate"])
}
}

/*func TestGenerateAll(t *testing.T) {
*/
func TestPathDeleteRoot(t *testing.T) {

integraTest, err := newIntegrationTestEnv()
if err != nil {
Expand All @@ -640,7 +620,23 @@ func testIssue(t *testing.T, integraTest *testEnv) {

testConnectPkcs11Connection(t, integraTest)
testGenerateRoot(t, integraTest)
csr := testGenerateIntermediate(t, integraTest)
testSignIntermediate(t, integraTest, &csr)
testPathI
}*/
testDeleteRoot(t, integraTest)
}

func testDeleteRoot(t *testing.T, integraTest *testEnv) {
req := &logical.Request{
Operation: logical.DeleteOperation,
Path: PATH_ROOT,
Storage: integraTest.Storage,
}
if response, err := integraTest.HsmPkiBackend.pathCADeleteRoot(integraTest.Context, req, nil); err != nil || response.Error() != nil {
if err != nil {
t.Error(err)
} else if response.Error() != nil {
t.Error(response.Error())
}
} else {
t.Logf("Delete CA succeeded: %s", integraTest.HsmPkiBackend.cachedCAConfig.caKeyAlias)
}

}
1 change: 0 additions & 1 deletion pkg/hsmpki/hsmcert_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,6 @@ func signCert(b *HsmPkiBackend,
creation.Params.PermittedDNSDomains = data.ApiData.Get("permitted_dns_domains").([]string)
}

//parsedBundle, err := certutil.SignCertificate(creation)
parsedBundle, err := SignCertificate(b, creation)

if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions pkg/hsmpki/hsmconsts.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
PATH_GENERATEINTERMEDIATE = "intermediate/generate/"
PATH_SIGNINTERMEDIATE = "root/sign-intermediate"
PATH_ISSUE = "issue/"
PATH_ROOT = "root"

PATH_HASHALGO = "hash_algo"

Expand Down Expand Up @@ -61,14 +62,16 @@ const (
TEST_COMMON_NAME = "localhost"
TEST_ROLE_NAME = "localhost"
//TEST_SIGNEDCACERTFILE = "../../data/softhsm-inter-0002.ca.cert.pem"
TEST_SIGNEDCACERTFILE = "../../data/safenet-inter-0016.ca.cert.pem"
TEST_SIGNEDCACERTFILE = "../../data/safenet-inter-02.ca.cert.pem"
TEST_ROOTCACERTFILE = "../../data/testrootca.cert.pem"
TEST_INTERCSRFILE = "../../data/testintermediate.csr.pem"
TEST_INTERCERTFILE = "../../data/testintermediate.cert.pem"
TEST_CAROOTCOMMONNAME = "safenet.ec17.rootca.mode51.software"
TEST_CAINTERCOMMONNAME = "safenet.ec17.interca.mode51.software"
TEST_CAKEYTYPE = "ec"
TEST_CAKEYBITS = "521"
TEST_CAKEYTYPERSA = "rsa"
TEST_CAKEYBITSRSA = "4096"
TEST_CAKEYTYPEEC = "ec"
TEST_CAKEYBITSEC = "521"
TEST_CAPERMITTEDDNSDOMAINS = "localhost"
TEST_CAORGANIZATION = "mode51 Software Ltd"
TEST_CAOU = "Security"
Expand Down
Loading