mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-10 23:49:09 +02:00
Test the PKCS#11 build against SoftHSM in CI and warn once where the build has no driver
This commit is contained in:
@@ -197,8 +197,10 @@ The module is loaded at runtime without cgo, through `purego`, which means the b
|
||||
dynamically linked against libc. The store is therefore compiled in only with `-tags pkcs11`
|
||||
on linux/amd64 and linux/arm64: the deb and rpm packages are built that way, since they
|
||||
target glibc distributions, while the release tarballs and the Alpine-based container
|
||||
images keep the fully static build. Without the tag, setting `NB_TPM_PIN` logs that
|
||||
the build lacks the support.
|
||||
images keep the fully static build. The arm and 386 packages carry the tag too but have
|
||||
no driver, so they behave like the static build. A build without support logs one warning
|
||||
when a token is configured and keeps reading the PEM directory. The "Client PKCS#11 /
|
||||
Unit" CI job builds with the tag and signs with a SoftHSM token.
|
||||
|
||||
To exercise the path without hardware, initialise a SoftHSM token and run the end-to-end
|
||||
test, which imports a key and certificate itself:
|
||||
|
||||
@@ -339,3 +339,26 @@ func TestNewPKCS11Store_PIN(t *testing.T) {
|
||||
assert.ErrorIs(t, err, errPINNeedsToken, "%s: a PIN must not go to whichever token is listed first", name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestPKCS11Store_WrongPINIsTriedOnce logs in to the real token with a wrong PIN: the
|
||||
// token refuses it, and the next collection refuses to send the same PIN again rather
|
||||
// than spending another attempt of the token's lockout counter.
|
||||
func TestPKCS11Store_WrongPINIsTriedOnce(t *testing.T) {
|
||||
_, uri := pkcs11TestStore(t, "")
|
||||
|
||||
wrongPIN := "wrong-pin-" + t.Name()
|
||||
store, err := NewPKCS11Store(PKCS11Config{URI: uri, PIN: wrongPIN}, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = store.Candidates(context.Background())
|
||||
require.Error(t, err)
|
||||
assert.True(t, pkcs11.PINRejected(err), "the token itself rejects the PIN: %v", err)
|
||||
|
||||
_, err = store.Candidates(context.Background())
|
||||
assert.ErrorIs(t, err, errPINRejectedBefore, "the rejected PIN is not sent to the token again")
|
||||
|
||||
good, err := NewPKCS11Store(PKCS11Config{URI: uri}, "")
|
||||
require.NoError(t, err)
|
||||
_, err = good.Candidates(context.Background())
|
||||
assert.NoError(t, err, "the correct PIN for the same token is unaffected")
|
||||
}
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
package certproof
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
import (
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/pkcs11"
|
||||
)
|
||||
|
||||
var unsupportedTokenOnce sync.Once
|
||||
|
||||
// DefaultStore is the PEM directory named by NB_CERT_STORE_DIR, or /etc/netbird/certs.
|
||||
func DefaultStore() Store {
|
||||
@@ -16,6 +24,12 @@ func storeWithToken(cfg Config) Store {
|
||||
if cfg.PKCS11.URI == "" && cfg.PKCS11.PIN == "" {
|
||||
return files
|
||||
}
|
||||
if !pkcs11.Supported() {
|
||||
unsupportedTokenOnce.Do(func() {
|
||||
log.Warnf("ignoring the configured PKCS#11 token: %v", pkcs11.ErrUnsupported)
|
||||
})
|
||||
return files
|
||||
}
|
||||
token, err := NewPKCS11Store(cfg.PKCS11, cfg.dir())
|
||||
if err != nil {
|
||||
log.Warnf("ignoring PKCS#11 URI: %v", err)
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/pkcs11"
|
||||
)
|
||||
|
||||
func TestStoreWithToken(t *testing.T) {
|
||||
@@ -23,10 +25,18 @@ func TestStoreWithToken(t *testing.T) {
|
||||
assert.IsType(t, &FileStore{}, storeWithToken(Config{PKCS11: PKCS11Config{URI: "not-a-pkcs11-uri"}}), "an invalid URI must not hide the PEM directory")
|
||||
assert.IsType(t, &FileStore{}, storeWithToken(Config{PKCS11: PKCS11Config{PIN: "1234"}}), "a PIN naming no token is refused and leaves the PEM directory")
|
||||
|
||||
for name, cfg := range map[string]PKCS11Config{
|
||||
configured := map[string]PKCS11Config{
|
||||
"env pin with token uri": {URI: "pkcs11:token=netbird", PIN: "1234"},
|
||||
"uri alone": {URI: "pkcs11:token=netbird?pin-value=1234"},
|
||||
} {
|
||||
}
|
||||
if !pkcs11.Supported() {
|
||||
for name, cfg := range configured {
|
||||
assert.IsType(t, &FileStore{}, storeWithToken(Config{Dir: dir, PKCS11: cfg}),
|
||||
"%s: a build without PKCS#11 support reads the PEM directory alone", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
for name, cfg := range configured {
|
||||
store, ok := storeWithToken(Config{Dir: dir, PKCS11: cfg}).(Stores)
|
||||
require.True(t, ok, "%s joins the token to the PEM directory", name)
|
||||
require.Len(t, store, 2, name)
|
||||
|
||||
@@ -121,6 +121,11 @@ type module struct {
|
||||
cSign func(session ulong, data *byte, dataLen ulong, signature *byte, signatureLen *ulong) ulong
|
||||
}
|
||||
|
||||
// Supported reports whether this build can load PKCS#11 modules.
|
||||
func Supported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func load(path string) (driver, error) {
|
||||
lib, err := purego.Dlopen(path, purego.RTLD_NOW|purego.RTLD_LOCAL)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
package pkcs11
|
||||
|
||||
// Supported reports whether this build can load PKCS#11 modules.
|
||||
func Supported() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func load(string) (driver, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user