Add test for pkg/hsm/context.go

This commit is contained in:
Jan Dittberner 2022-04-24 14:05:46 +02:00 committed by Jan Dittberner
parent 23c9e6f3e0
commit 510ba2ad25
6 changed files with 236 additions and 9 deletions

View file

@ -33,7 +33,7 @@ linters-settings:
gomnd: gomnd:
ignored-functions: ignored-functions:
- 'strconv.*' - 'strconv.*'
ignored-numbers: ["2", "16", "128", "0o600"] ignored-numbers: ["2", "16", "128", "0o600", "0o700"]
goimports: goimports:
local-prefixes: code.cacert.org,git.cacert.org local-prefixes: code.cacert.org,git.cacert.org
misspell: misspell:

View file

@ -170,7 +170,7 @@ func (k *KeyStorage) UnmarshalYAML(n *yaml.Node) error {
type SignerConfig struct { type SignerConfig struct {
global *Settings `yaml:"Settings"` global *Settings `yaml:"Settings"`
caMap map[string]*CaCertificateEntry `yaml:"CAs"` caMap map[string]*CaCertificateEntry `yaml:"CAs"`
KeyStorage map[string]*KeyStorage `yaml:"KeyStorage"` keyStorage map[string]*KeyStorage `yaml:"KeyStorage"`
} }
func (c *SignerConfig) GetCADefinition(label string) (*CaCertificateEntry, error) { func (c *SignerConfig) GetCADefinition(label string) (*CaCertificateEntry, error) {
@ -268,6 +268,16 @@ func (c *SignerConfig) IntermediaryCAs() []string {
return intermediaries return intermediaries
} }
func (c *SignerConfig) GetKeyStorage(label string) (*KeyStorage, error) {
keyStorage, ok := c.keyStorage[label]
if !ok {
return nil, fmt.Errorf("could not find storage definition with label %s", label)
}
return keyStorage, nil
}
// LoadConfiguration reads YAML configuration from the given reader as a SignerConfig structure // LoadConfiguration reads YAML configuration from the given reader as a SignerConfig structure
func LoadConfiguration(r io.Reader) (*SignerConfig, error) { func LoadConfiguration(r io.Reader) (*SignerConfig, error) {
config := struct { config := struct {
@ -298,7 +308,7 @@ func LoadConfiguration(r io.Reader) (*SignerConfig, error) {
return &SignerConfig{ return &SignerConfig{
global: config.Global, global: config.Global,
caMap: config.CAs, caMap: config.CAs,
KeyStorage: config.KeyStorage, keyStorage: config.KeyStorage,
}, nil }, nil
} }

View file

@ -954,3 +954,23 @@ func TestSignerConfig_CalculateSubject(t *testing.T) {
}) })
} }
} }
func TestSignerConfig_GetKeyStorage(t *testing.T) {
var (
keyStorage *config.KeyStorage
err error
)
sc := loadSignerConfig(t)
keyStorage, err = sc.GetKeyStorage("default")
assert.NoError(t, err)
assert.NotNil(t, keyStorage)
keyStorage, err = sc.GetKeyStorage("undefined")
assert.Error(t, err)
assert.ErrorContains(t, err, "could not find storage definition with label")
assert.Nil(t, keyStorage)
}

View file

@ -98,7 +98,7 @@ func IsVerbose(ctx context.Context) bool {
func GetP11Context(ctx context.Context, entry *config.CaCertificateEntry) (*crypto11.Context, error) { func GetP11Context(ctx context.Context, entry *config.CaCertificateEntry) (*crypto11.Context, error) {
contexts, ok := ctx.Value(ctxP11Contexts).(map[string]*crypto11.Context) contexts, ok := ctx.Value(ctxP11Contexts).(map[string]*crypto11.Context)
if !ok { if !ok {
return nil, errors.New("type assertion failed") return nil, errors.New("type assertion failed, use hsm.SetupContext first")
} }
if p11Context, ok := contexts[entry.Storage]; ok { if p11Context, ok := contexts[entry.Storage]; ok {

197
pkg/hsm/context_test.go Normal file
View file

@ -0,0 +1,197 @@
/*
Copyright 2022 CAcert Inc.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hsm_test
import (
"context"
"fmt"
"os"
"os/exec"
"path"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"git.cacert.org/cacert-gosigner/pkg/config"
"git.cacert.org/cacert-gosigner/pkg/hsm"
)
func TestCaConfigOption(t *testing.T) {
testSignerConfig := config.SignerConfig{}
theContext := hsm.SetupContext(hsm.CaConfigOption(&testSignerConfig))
assert.Equal(t, &testSignerConfig, hsm.GetSignerConfig(theContext))
}
func TestGetSignerConfig_empty(t *testing.T) {
theContext := hsm.SetupContext()
assert.Nil(t, hsm.GetSignerConfig(theContext))
}
func TestSetupModeOption(t *testing.T) {
theContext := hsm.SetupContext(hsm.SetupModeOption())
assert.True(t, hsm.IsSetupMode(theContext))
}
func TestIsSetupMode_not_set(t *testing.T) {
theContext := hsm.SetupContext()
assert.False(t, hsm.IsSetupMode(theContext))
}
func TestVerboseLoggingOption(t *testing.T) {
theContext := hsm.SetupContext(hsm.VerboseLoggingOption())
assert.True(t, hsm.IsVerbose(theContext))
}
func TestIsVerbose_not_set(t *testing.T) {
theContext := hsm.SetupContext()
assert.False(t, hsm.IsVerbose(theContext))
}
const testSignerConfig = `---
Settings:
organization:
organization: ["Acme CAs Ltd."]
validity-years:
root: 30
intermediary: 10
url-patterns:
ocsp: http://ocsp.example.org/
crl: http://crl.example.org/%s.crl
issuer: http://%s.cas.example.org/
CAs:
root:
common-name: "Acme CAs root"
key-info:
algorithm: EC
ecc-curve: secp521r1
sub1:
common-name: "Acme CAs server sub CA"
parent: root
key-info:
algorithm: EC
ecc-curve: secp256r1
sub2:
common-name: "Acme CAs people sub CA"
parent: root
key-info:
algorithm: EC
ecc-curve: secp256r1
KeyStorage:
default:
type: softhsm
label: acme-test-hsm
`
func TestSetupContext(t *testing.T) {
testConfig, err := config.LoadConfiguration(strings.NewReader(testSignerConfig))
require.NoError(t, err)
theContext := hsm.SetupContext(hsm.SetupModeOption(), hsm.VerboseLoggingOption(), hsm.CaConfigOption(testConfig))
assert.True(t, hsm.IsSetupMode(theContext))
assert.True(t, hsm.IsVerbose(theContext))
assert.Equal(t, hsm.GetSignerConfig(theContext), testConfig)
}
func TestGetP11Context_missing_SetupContext(t *testing.T) {
p11Context, err := hsm.GetP11Context(context.Background(), &config.CaCertificateEntry{Storage: "default"})
assert.Error(t, err)
assert.ErrorContains(t, err, "type assertion failed, use hsm.SetupContext first")
assert.Nil(t, p11Context)
}
func TestGetP11Context_unknown_storage(t *testing.T) {
testConfig, err := config.LoadConfiguration(strings.NewReader(testSignerConfig))
require.NoError(t, err)
theContext := hsm.SetupContext(hsm.SetupModeOption(), hsm.CaConfigOption(testConfig))
definition := &config.CaCertificateEntry{Storage: "undefined"}
p11Context, err := hsm.GetP11Context(theContext, definition)
assert.Error(t, err)
assert.ErrorContains(t, err, "key storage undefined not available")
assert.Nil(t, p11Context)
}
func TestGetP11Context(t *testing.T) {
testConfig, err := config.LoadConfiguration(strings.NewReader(testSignerConfig))
require.NoError(t, err)
tempdir := t.TempDir()
tokenDir := path.Join(tempdir, "tokens")
softhsmConfig := path.Join(tempdir, "softhsm2.conf")
err = os.Mkdir(tokenDir, 0o700)
require.NoError(t, err)
err = os.WriteFile(softhsmConfig, []byte(fmt.Sprintf("directories.tokendir = %s", tokenDir)), 0o600)
require.NoError(t, err)
t.Setenv("SOFTHSM2_CONF", softhsmConfig)
err = exec.Command(
"softhsm2-util",
"--init-token",
"--free",
"--label",
"acme-test-hsm",
"--so-pin",
"12345678",
"--pin",
"123456",
).Run()
require.NoError(t, err)
t.Setenv("TOKEN_PIN_ACME_TEST_HSM", "123456")
theContext := hsm.SetupContext(hsm.CaConfigOption(testConfig))
definition, err := testConfig.GetCADefinition("root")
require.NoError(t, err)
p11Context1, err := hsm.GetP11Context(theContext, definition)
assert.NoError(t, err)
assert.NotNil(t, p11Context1)
p11Context2, err := hsm.GetP11Context(theContext, definition)
assert.NoError(t, err)
assert.NotNil(t, p11Context1)
assert.Equal(t, p11Context1, p11Context2)
}

View file

@ -31,16 +31,16 @@ import (
) )
func prepareCrypto11Context(ctx context.Context, label string) (*crypto11.Context, error) { func prepareCrypto11Context(ctx context.Context, label string) (*crypto11.Context, error) {
storage, ok := GetSignerConfig(ctx).KeyStorage[label]
if !ok {
return nil, fmt.Errorf("could not find storage definition with label %s", label)
}
var ( var (
err error err error
p11Context *crypto11.Context p11Context *crypto11.Context
) )
storage, err := GetSignerConfig(ctx).GetKeyStorage(label)
if err != nil {
return nil, fmt.Errorf("key storage %s not available: %w", label, err)
}
p11Config := &crypto11.Config{ p11Config := &crypto11.Config{
Path: storage.Module, Path: storage.Module,
TokenLabel: storage.Label, TokenLabel: storage.Label,