From 9ad3bcabdba87390194da1f9f524d8644e5838c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Jutteau?= Date: Mon, 24 May 2021 15:24:00 +0200 Subject: [PATCH] tests: smartcard tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some tests for: - softhsm (v2) - yubikey (disabled by default) Test configuration must be setup in tests/config.env closes #66 Signed-off-by: Jérôme Jutteau --- CONTRIBUTING.md | 12 ++-- tests/_check_test_config | 60 +++++++++++++++++++ tests/_gen_smartcard_softhsm_config_file | 76 ++++++++++++++++++++++++ tests/_gen_smartcard_yubikey_config_file | 60 +++++++++++++++++++ tests/_run | 19 ++++++ tests/config.env | 6 ++ 6 files changed, 225 insertions(+), 8 deletions(-) create mode 100755 tests/_check_test_config create mode 100755 tests/_gen_smartcard_softhsm_config_file create mode 100755 tests/_gen_smartcard_yubikey_config_file create mode 100644 tests/config.env diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6564b65..6235f4d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,18 +22,14 @@ Use the same issue tracker to report problems with the documentation. Pre-requisites: - An Outscale account on eu-west-2 region - At least 10 AccessKeys in your quota +- Have `softhsm`, `pkcs11-tool` and `openssl` installed on a Linux machine (smartcard tests) -Setup: -- Fill a valid `default` profile in `~/.osc/config.json` -- `export OSC_TEST_LOGIN="your.login@mycompany.com"` -- `export OSC_TEST_PASSWORD="MySecretPassword"` -- `export OSC_TEST_ACCESS_KEY="ASJOAEHDIOEXAMPLE"` -- `export OSC_TEST_SECRET_KEY="ASJOAEHSDF4565D4F6D54F6D5F4F654DIOEXAMPLE"` - -Warning: config files in `~/.osc/config.json` and `~/.osc_sdk/config.json` will be overwritten during tests. Make sure to backup them if needed. +Setup: edit `tests/config.env` and fill credentials. Finally, you can run `make test`. +Warning: config files in `~/.osc/config.json` and `~/.osc_sdk/config.json` will be overwritten during tests. + # Pull Requests We’ll do our best to review your pull request (or “PR” for short) quickly. diff --git a/tests/_check_test_config b/tests/_check_test_config new file mode 100755 index 00000000..558c29ef --- /dev/null +++ b/tests/_check_test_config @@ -0,0 +1,60 @@ +#!/bin/bash +set -e + +incomplete=false + +# Note: would be better to use -v to test if variable is set +# but this feature is available on bash >= 4.2 which is not available on macOS. + +echo -n "OSC_TEST_LOGIN: " +if [ -z "$OSC_TEST_LOGIN" ] || [[ "$OSC_TEST_LOGIN" == "user@domain.tld" ]]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +echo -n "OSC_TEST_PASSWORD: " +if [ -z "$OSC_TEST_PASSWORD" ] || [[ "$OSC_TEST_PASSWORD" == "P4ssW0rd" ]]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +echo -n "OSC_TEST_ACCESS_KEY: " +if [ -z "$OSC_TEST_ACCESS_KEY" ] || [[ "$OSC_TEST_ACCESS_KEY" == "S65FD45EXAMPLE" ]]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +echo -n "OSC_TEST_SECRET_KEY: " +if [ -z "$OSC_TEST_SECRET_KEY" ] || [[ "$OSC_TEST_SECRET_KEY" == "54SDFSD5S6D789SF465SF447GS97DEXAMPLE" ]]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +echo -n "OSC_TEST_SMARTCARD_SOFTHSM: " +if [ -z "$OSC_TEST_SMARTCARD_SOFTHSM" ]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +echo -n "OSC_TEST_SMARTCARD_YUBIKEY: " +if [ -z "$OSC_TEST_SMARTCARD_YUBIKEY" ]; then + echo "KO" + incomplete=true +else + echo "OK" +fi + +if $incomplete; then + echo "error: incomplete test configuration, check tests/config.env" + exit 1 +fi diff --git a/tests/_gen_smartcard_softhsm_config_file b/tests/_gen_smartcard_softhsm_config_file new file mode 100755 index 00000000..05f54e23 --- /dev/null +++ b/tests/_gen_smartcard_softhsm_config_file @@ -0,0 +1,76 @@ +#!/bin/bash +set -e +echo -n "$(basename $0): " + + +if [[ "$OSTYPE" == "darwin"* ]]; then + ssl_engine="/usr/local/Cellar/libp11/0.4.11/lib/engines-1.1/pkcs11.dylib" + module="/usr/local/Cellar/yubico-piv-tool/2.2.0/lib/libykcs11.dylib" + openssl="/usr/local/Cellar/openssl@1.1/1.1.1k/bin/openssl" +elif [[ "$OSTYPE" == "linux"* ]]; then + ssl_engine="/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so" + module="/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so" + openssl="openssl" +fi +token_label="osc-test-token" +rsa_label="osc.key" +cert_label="osc.cert" +pin="0000" + +# Test SoftHSMv2 +softhsm2-util --version &> /dev/null || { echo "softhsm2-util not found"; exit 1; } + +# Clean existing SoftHSMv2 token +softhsm2-util --delete-token --token $token_label &> /dev/null || true +softhsm2-util --init-token --pin ${pin} --so-pin 1234 --free --label $token_label &> /dev/null || { echo "Cannot initialize SoftHSM token"; exit 1; } + +# Test pkcs11-tool +pkcs11-tool --test --module $module &> /dev/null || { echo "pkcs11-tool --test failed"; exit 1; } + +# Test openssl +$openssl help &> /dev/null || { echo "openssl not found"; exit 1;} + +# Generate RSA key on smartcard +pkcs11-tool --module $module --keypairgen --key-type rsa:2048 --usage-sign --login --pin ${pin} --token-label $token_label --label $rsa_label &> /dev/null || { echo "Cannot create RSA key"; exit 1; } + +# Test engine +$openssl engine -t -c pkcs11 &> /dev/null || { echo "pkcs11 engine not available to openssl"; exit 1; } + +# Generate cert +$openssl req -new -x509 -out osc.crt -days 365 -addext basicConstraints=critical,CA:TRUE,pathlen:1 -subj "/CN=OSC-TEST-CA" -engine pkcs11 -keyform engine -key "pkcs11:token=${token_label};object=${rsa_label};pin-value=${pin}" &> /dev/null || { echo "Cannot create openssl cert"; exit 1; } + +# Convert to der format +$openssl x509 -inform pem -outform der -in osc.crt -out osc.crt.der &> /dev/null || { echo "Cannot convert to der format"; exit 1; } + +# Send der to smartcard +pkcs11-tool --module $module --write-object osc.crt.der --type cert --token-label $token_label --label $cert_label &> /dev/null || { echo "Cannot write certificate to smartcard"; exit 1; } + +# Clean files +rm -rf osc.crt osc.crt.der + +# Generate configuration +rm -rf ~/.osc +mkdir -p ~/.osc +echo -n " +{ + \"default\": { + \"access_key\": \"${OSC_TEST_ACCESS_KEY}\", + \"secret_key\": \"${OSC_TEST_SECRET_KEY}\", + \"ssl_engine_id\": \"pkcs11\", + \"ssl_engine_path\": \"${ssl_engine}\", + \"ssl_module_path\": \"${module}\", + \"x509_client_cert\": \"pkcs11:token=${token_label};type=cert;object=${cert_label}\", + \"x509_client_key\": \"pkcs11:token=${token_label};type=private;object=${rsa_label};pin-value=${pin}\", + \"region\": \"eu-west-2\", + \"endpoints\": { + \"api\": \"api.eu-west-2.outscale.com/api/v1\", + \"fcu\": \"fcu.eu-west-2.outscale.com\", + \"lbu\": \"lbu.eu-west-2.outscale.com\", + \"eim\": \"eim.eu-west-2.outscale.com\", + \"icu\": \"icu.eu-west-2.outscale.com\", + \"directlink\": \"directlink.eu-west-2.outscale.com\", + \"oos\": \"oos.eu-west-2.outscale.com\" + } + } +}" > ~/.osc/config.json +echo "OK" diff --git a/tests/_gen_smartcard_yubikey_config_file b/tests/_gen_smartcard_yubikey_config_file new file mode 100755 index 00000000..ad92832e --- /dev/null +++ b/tests/_gen_smartcard_yubikey_config_file @@ -0,0 +1,60 @@ +#!/bin/bash +set -e +echo -n "$(basename $0): " + +if [[ "$OSTYPE" == "darwin"* ]]; then + ssl_engine="/usr/local/Cellar/libp11/0.4.11/lib/engines-1.1/pkcs11.dylib" + module="/usr/local/Cellar/yubico-piv-tool/2.2.0/lib/libykcs11.dylib" +elif [[ "$OSTYPE" == "linux"* ]]; then + ssl_engine="/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so" + module="/usr/lib/x86_64-linux-gnu/libykcs11.so.2.2.0" +fi +pin="123456" + +# Test ykman +ykman --help &> /dev/null || { echo "ykman not found"; exit 1; } + +# Reset token with default credentials +ykman piv reset -f &> /dev/null || { echo "Cannot reset yubikey"; exit 1; } + +# Test yubico-piv-tool +yubico-piv-tool --help &> /dev/null || { echo "yubico-piv-tool not found"; exit 1; } + +# Reset token with default credentials +ykman piv reset -f &> /dev/null || { echo "Cannot reset yubikey"; exit 1; } + +# Generate private key +yubico-piv-tool -s 9a -a generate -o public.pem &> /dev/null || { echo "Cannot generate private key"; exit 1; } + +# Generate certificate +yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=SSH key/" -i public.pem -o cert.pem --pin=$pin &> /dev/null || { echo "Cannot generate certificate"; exit 1; } + +# Upload certificate +yubico-piv-tool -a import-certificate -s 9a -i cert.pem &> /dev/null || { echo "Cannot upload certificate"; exit 1; } + +# Generate configuration +rm -rf ~/.osc +mkdir -p ~/.osc +echo -n " +{ + \"default\": { + \"access_key\": \"${OSC_TEST_ACCESS_KEY}\", + \"secret_key\": \"${OSC_TEST_SECRET_KEY}\", + \"ssl_engine_id\": \"pkcs11\", + \"ssl_engine_path\": \"${ssl_engine}\", + \"ssl_module_path\": \"${module}\", + \"x509_client_cert\": \"pkcs11:type=cert;id=%01\", + \"x509_client_key\": \"pkcs11:type=private;id=%01;pin-value=${pin}\", + \"region\": \"eu-west-2\", + \"endpoints\": { + \"api\": \"api.eu-west-2.outscale.com/api/v1\", + \"fcu\": \"fcu.eu-west-2.outscale.com\", + \"lbu\": \"lbu.eu-west-2.outscale.com\", + \"eim\": \"eim.eu-west-2.outscale.com\", + \"icu\": \"icu.eu-west-2.outscale.com\", + \"directlink\": \"directlink.eu-west-2.outscale.com\", + \"oos\": \"oos.eu-west-2.outscale.com\" + } + } +}" > ~/.osc/config.json +echo "OK" diff --git a/tests/_run b/tests/_run index 736fabe6..5aeaf8e5 100755 --- a/tests/_run +++ b/tests/_run @@ -3,6 +3,9 @@ PROJECT_ROOT=$(cd "$(dirname $0)/.." && pwd) cd $PROJECT_ROOT/tests set -e +source ./config.env +./_check_test_config + ./_clean_config_files ./_gen_config_file for t in *.sh ; do @@ -15,6 +18,22 @@ for t in *.sh ; do ./$t done +if $OSC_TEST_SMARTCARD_SOFTHSM; then + ./_clean_config_files + ./_gen_smartcard_softhsm_config_file + for t in *.sh ; do + ./$t + done +fi + +if $OSC_TEST_SMARTCARD_YUBIKEY; then + ./_clean_config_files + ./_gen_smartcard_yubikey_config_file + for t in *.sh ; do + ./$t + done +fi + ./_clean_config_files ./_gen_config_file for t in specific/*.sh ; do diff --git a/tests/config.env b/tests/config.env new file mode 100644 index 00000000..971bca28 --- /dev/null +++ b/tests/config.env @@ -0,0 +1,6 @@ +export OSC_TEST_LOGIN="user@domain.tld" +export OSC_TEST_PASSWORD="P4ssW0rd" +export OSC_TEST_ACCESS_KEY="S65FD45EXAMPLE" +export OSC_TEST_SECRET_KEY="54SDFSD5S6D789SF465SF447GS97DEXAMPLE" +export OSC_TEST_SMARTCARD_SOFTHSM=true +export OSC_TEST_SMARTCARD_YUBIKEY=false \ No newline at end of file