Skip to content

Commit 753799c

Browse files
committed
test(pkcs11): Add tedge-p11-server compatibility suite
New compatibility.robot suite uses pinned tedge-p11-server to ensure new versions of thin-edge.io are backwards compatibile with tedge-p11-server. Shared keywords were extracted into a resource file. Signed-off-by: Marcel Guzik <marcel.guzik@cumulocity.com>
1 parent c3c7b24 commit 753799c

File tree

3 files changed

+278
-76
lines changed

3 files changed

+278
-76
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
*** Settings ***
2+
Documentation This test suite runs the tests with tedge-p11-server pinned to a fixed version to ensure that new
3+
... versions of thin-edge remain backwards compatible with tedge-p11-server's binary communication protocol. The
4+
... scope of this test is limited to tedge-p11-server's initial feature set and will generally not be expanded.
5+
6+
Resource pkcs11_common.resource
7+
8+
Suite Setup Custom Setup
9+
Suite Teardown Get Suite Logs
10+
11+
Test Tags adapter:docker theme:cryptoki compatibility
12+
13+
14+
*** Variables ***
15+
${TEDGE_P11_SERVER_VERSION} 1.5.1
16+
17+
18+
*** Test Cases ***
19+
# the test cases are basically copy-pasted from private_key_storage.robot, as the purpose of this suite is to run the
20+
# exact same tests with a slightly different setup. It would be easiest if we could import the test cases themselves
21+
# from another test suite, but this isn't possible. So we extract reusable keywords into a resource file, but test cases
22+
# remain duplicated.
23+
Use Private Key in SoftHSM2 using tedge-p11-server
24+
Tedge Reconnect Should Succeed
25+
26+
Select Private key using tedge-p11-server URI
27+
[Documentation] Make sure that we can select different keys and tokens using a PKCS#11 URI.
28+
... The URI can either point to a specific key, or to a specific token where we will attempt to find a key.
29+
...
30+
... To ensure that correct key is selected and reduce the need to generate and upload different keys and
31+
... certificates, we'll only be using one key and we'll only import it to the chosen token, keeping other tokens
32+
... empty.
33+
...
34+
... We set the URI on tedge-p11-server, which means that all connecting clients will use the selected key until
35+
... tedge-p11-server is restarted with a different URI.
36+
37+
Set tedge-p11-server Uri value=
38+
Tedge Reconnect Should Succeed
39+
40+
# expect failure if we try to use a token that doesn't exist
41+
Set tedge-p11-server Uri value=pkcs11:token=asdf
42+
Tedge Reconnect Should Fail With Failed to find a signing key: Didn't find a slot to use
43+
44+
# create tokens with no keys on them, so key selection fails if wrong token is selected
45+
Execute Command softhsm2-util --init-token --free --label token1 --pin "123456" --so-pin "123456"
46+
47+
Set tedge-p11-server Uri value=pkcs11:token=token1
48+
Tedge Reconnect Should Fail With Failed to find a signing key
49+
50+
Set tedge-p11-server Uri value=pkcs11:token=tedge
51+
Tedge Reconnect Should Succeed
52+
53+
# import another private key to the primary token (one that has valid tedge key) so we can select a key
54+
Execute Command
55+
... cmd=p11tool --set-pin=123456 --login --generate-privkey ECDSA --curve=secp256r1 --label "key2" "pkcs11:token=tedge"
56+
57+
Set tedge-p11-server Uri value=pkcs11:token=tedge;object=key2
58+
Tedge Reconnect Should Fail With HandshakeFailure
59+
60+
# but when URI has correct label, we expect valid key to be used again
61+
Set tedge-p11-server Uri value=pkcs11:token=tedge;object=tedge
62+
Tedge Reconnect Should Succeed
63+
64+
Set tedge-p11-server Uri value=
65+
66+
Select Private key using a request URI
67+
[Documentation] Like above, we select the key using a URI, but this time we include it in a request, which means
68+
... we can select different keys without restarting tedge-p11-server.
69+
70+
Execute Command cmd=tedge config set device.key_uri pkcs11:token=token123
71+
${stderr}= Tedge Reconnect Should Fail With Failed to find a signing key
72+
Should Contain ${stderr} item=cryptoki: socket (key: pkcs11:token=token123)
73+
74+
Execute Command cmd=tedge config unset device.key_uri
75+
Execute Command cmd=tedge config set device.key_uri pkcs11:token=token123
76+
${stderr}= Tedge Reconnect Should Fail With Failed to find a signing key
77+
Should Contain ${stderr} item=cryptoki: socket (key: pkcs11:token=token123)
78+
79+
Execute Command cmd=tedge config set device.key_uri "pkcs11:token=tedge;object=tedge"
80+
${stderr}= Tedge Reconnect Should Succeed
81+
Should Contain ${stderr} item=cryptoki: socket (key: pkcs11:token=tedge;object=tedge)
82+
83+
Connects to C8y using an RSA key
84+
[Documentation] Test that we can connect to C8y using an RSA private keys of all sizes.
85+
[Setup] Set tedge-p11-server Uri value=${EMPTY}
86+
[Template] Connect to C8y using new keypair
87+
type=rsa bits=4096
88+
type=rsa bits=3072
89+
type=rsa bits=2048
90+
# type=rsa bits=1024 # RSA 1024 is considered to be insecure is not supported when using the Cumulocity Certificate Authority feature
91+
92+
Connects to C8y supporting all TLS13 ECDSA signature algorithms
93+
[Documentation] Check that we support all ECDSA sigschemes used in TLS1.3, i.e: ecdsa_secp256r1_sha256,
94+
... ecdsa_secp384r1_sha384, ecdsa_secp521r1_sha512.
95+
[Setup] Set tedge-p11-server Uri value=${EMPTY}
96+
[Template] Connect to C8y using new keypair
97+
type=ecdsa curve=secp256r1
98+
99+
Ignore tedge.toml if missing
100+
Execute Command rm -f ./tedge.toml
101+
${stderr}= Execute Command tedge-p11-server --config-dir . --module-path xx.so exp_exit_code=!0
102+
# Don't log anything (this is normal behaviour as the user does not have to create a tedge.toml file)
103+
Should Not Contain ${stderr} Failed to read ./tedge.toml: No such file
104+
# And proceed
105+
Should Contain ${stderr} Using cryptoki configuration
106+
# Using default values
107+
Should Contain ${stderr} tedge-p11-server.sock
108+
109+
Ignore tedge.toml if empty
110+
Execute Command touch ./tedge.toml
111+
${stderr}= Execute Command tedge-p11-server --config-dir . --module-path xx.so exp_exit_code=!0
112+
# Don't log anything (this is normal behaviour, where the file is used for tedge and not tedge-p11-server)
113+
Should Not Contain ${stderr} Failed to parse ./tedge.toml: invalid TOML
114+
# And proceed
115+
Should Contain ${stderr} Using cryptoki configuration
116+
# Using default values
117+
Should Contain ${stderr} tedge-p11-server.sock
118+
119+
Ignore tedge.toml if incomplete
120+
Execute Command echo '[device]' >./tedge.toml
121+
${stderr}= Execute Command tedge-p11-server --config-dir . --module-path xx.so exp_exit_code=!0
122+
# Don't log anything (this is normal behaviour, where the file is used for tedge and not tedge-p11-server)
123+
Should Not Contain ${stderr} Failed to parse ./tedge.toml: invalid TOML
124+
Should Not Contain ${stderr} missing field `cryptoki`
125+
# And proceed
126+
Should Contain ${stderr} Using cryptoki configuration
127+
# Using default values
128+
Should Contain ${stderr} tedge-p11-server.sock
129+
130+
Do not warn the user if tedge.toml is incomplete but not used
131+
Execute Command rm -f ./tedge.toml
132+
${stderr}= Execute Command
133+
... tedge-p11-server --config-dir . --module-path xx.so --pin 11.pin --socket-path yy.sock --uri zz.uri
134+
... exp_exit_code=!0
135+
# Don't warn as all values are provided on the command line
136+
Should Not Contain ${stderr} Failed to read ./tedge.toml: No such file
137+
# And proceed
138+
Should Contain ${stderr} Using cryptoki configuration
139+
# Using the values provided on the command lin
140+
Should Contain ${stderr} xx.so
141+
Should Contain ${stderr} yy.sock
142+
Should Contain ${stderr} zz.uri
143+
144+
Warn the user if tedge.toml exists but cannot be read
145+
Execute Command echo '[device.cryptoki]' >./tedge.toml
146+
Execute Command chmod a-rw ./tedge.toml
147+
${stderr}= Execute Command
148+
... sudo -u tedge tedge-p11-server --config-dir . --module-path xx.so
149+
... exp_exit_code=!0
150+
# Warn the user
151+
Should Contain ${stderr} Failed to read ./tedge.toml: Permission denied
152+
# But proceed
153+
Should Contain ${stderr} Using cryptoki configuration
154+
155+
Warn the user if tedge.toml cannot be parsed
156+
Execute Command rm -f ./tedge.toml
157+
Execute Command echo '[corrupted toml ...' >./tedge.toml
158+
${stderr}= Execute Command tedge-p11-server --config-dir . --module-path xx.so exp_exit_code=!0
159+
# Warn the user
160+
Should Contain ${stderr} Failed to parse ./tedge.toml: invalid TOML
161+
# But proceed
162+
Should Contain ${stderr} Using cryptoki configuration
163+
164+
165+
*** Keywords ***
166+
Custom Setup
167+
${DEVICE_SN}= Setup register=${False}
168+
Set Suite Variable ${DEVICE_SN}
169+
170+
# this doesn't install anything but adds cloudsmith repo to apt
171+
Execute Command curl -1sLf 'https://dl.cloudsmith.io/public/thinedge/tedge-main/setup.deb.sh' | sudo -E bash
172+
Execute Command cmd=apt-get install -y --allow-downgrades tedge-p11-server=${TEDGE_P11_SERVER_VERSION}
173+
${stdout}= Execute Command tedge-p11-server -V strip=True
174+
Should Be Equal ${stdout} tedge-p11-server ${TEDGE_P11_SERVER_VERSION}
175+
176+
# Allow the tedge user to access softhsm
177+
Execute Command sudo usermod -a -G softhsm tedge
178+
Transfer To Device ${CURDIR}/data/init_softhsm.sh /usr/bin/
179+
180+
# initialize the soft hsm and create a certificate signing request
181+
Execute Command tedge config set device.cryptoki.pin 123456
182+
Execute Command tedge config set device.cryptoki.module_path /usr/lib/softhsm/libsofthsm2.so
183+
Execute Command sudo -u tedge /usr/bin/init_softhsm.sh --device-id "${DEVICE_SN}" --pin 123456
184+
185+
# configure tedge
186+
${domain}= Cumulocity.Get Domain
187+
Execute Command tedge config set c8y.url "${domain}"
188+
Execute Command tedge config set mqtt.bridge.built_in true
189+
Execute Command tedge config set device.cryptoki.mode socket
190+
191+
${csr_path}= Execute Command cmd=tedge config get device.csr_path strip=${True}
192+
Register Device With Cumulocity CA ${csr_path}
193+
194+
Set tedge-p11-server Uri value=
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
*** Settings ***
2+
Documentation Keywords used for testing thin-edge.io PKCS11 integration and tedge-p11-server.
3+
4+
Resource ../resources/common.resource
5+
Library String
6+
Library Cumulocity
7+
Library ThinEdgeIO
8+
9+
10+
*** Variables ***
11+
${DEVICE_SN} ${EMPTY} # should be set in setup of test suites
12+
${CERT_TEMPLATE} /etc/tedge/hsm/cert.template # created by init_softhsm script
13+
14+
15+
*** Keywords ***
16+
Connect to C8y using new keypair
17+
[Documentation] Connects to C8y with a newly generated keypair and a self-signed certificate.
18+
... The private key is saved on the token, and the self-signed certificate is registered with c8y.
19+
[Arguments] ${type} # ecdsa or rsa
20+
... ${curve}=secp256r1 # if type == ECDSA, curve of the key - one of {secp256r1, secp384r1, secp521r1}
21+
... ${bits}=4096 # if type == RSA, length in bits of the RSA key - one of {1024, 2048, 3072, 4096}
22+
23+
# We could alternatively use Cumulocity CA to start with a signed cert, but for testing certificate renewal, we want
24+
# to test both renewing a self-signed cert and a cert issued by C8y CA. When we start with self-signed cert, after
25+
# the first renewal we get a cert signed by CA, so we test all scenarios by just doing renew 2 times.
26+
27+
IF '${type}' == 'ecdsa'
28+
VAR ${object_name}= ${type}-${curve}
29+
VAR ${p11tool_args}= --curve=${curve}
30+
ELSE IF '${type}' == 'rsa'
31+
VAR ${object_name}= ${type}-${bits}
32+
VAR ${p11tool_args}= --bits=${bits}
33+
ELSE
34+
Fail Wrong key type provided.
35+
END
36+
37+
# guarantee name of the object is unique even if multiple keys of the same type and bits/curve are generated
38+
${identifier}= String.Generate Random String
39+
VAR ${object_name}= ${object_name}-${identifier}
40+
41+
VAR ${cert_path}= /etc/tedge/device-certs/${object_name}.csr
42+
Execute Command cmd=tedge config set device.cert_path ${cert_path}
43+
44+
Execute Command
45+
... cmd=p11tool --set-pin=123456 --login --generate-privkey ${type} ${p11tool_args} --label ${object_name} "pkcs11:token=tedge"
46+
Execute Command
47+
... cmd=GNUTLS_PIN=123456 certtool --generate-self-signed --template "${CERT_TEMPLATE}" --outfile "${cert_path}" --load-privkey "pkcs11:token=tedge;object=${object_name}"
48+
49+
Execute Command cmd=tedge config set device.key_uri "pkcs11:token=tedge;object=${object_name}"
50+
51+
Execute Command
52+
... cmd=sudo env C8Y_USER="${C8Y_CONFIG.username}" C8Y_PASSWORD="${C8Y_CONFIG.password}" tedge cert upload c8y
53+
ThinEdgeIO.Register Certificate For Cleanup
54+
55+
Tedge Reconnect Should Succeed
56+
57+
Set tedge-p11-server Uri
58+
[Arguments] ${value}
59+
Execute Command tedge config set device.cryptoki.uri '${value}'
60+
Restart Service tedge-p11-server
61+
62+
Tedge Reconnect Should Succeed
63+
${stderr}= Execute Command tedge reconnect c8y stdout=false stderr=true
64+
RETURN ${stderr}
65+
66+
Tedge Reconnect Should Fail With
67+
[Arguments] ${error}
68+
${stderr}= Command Should Fail With tedge reconnect c8y ${error}
69+
RETURN ${stderr}
70+
71+
Command Should Fail With
72+
[Arguments] ${command} ${error}
73+
${stderr}= Execute Command ${command} exp_exit_code=!0 stdout=false stderr=true
74+
Should Contain ${stderr} ${error}
75+
RETURN ${stderr}
76+
77+
Register Device With Cumulocity CA
78+
[Documentation] Registers a new certificate with Cumulocity CA and places it under `c8y.device.cert_path`
79+
[Arguments] ${csr_path}
80+
${credentials}= Cumulocity.Bulk Register Device With Cumulocity CA external_id=${DEVICE_SN}
81+
Execute Command
82+
... cmd=tedge cert download c8y --csr-path "${csr_path}" --device-id "${DEVICE_SN}" --one-time-password '${credentials.one_time_password}' --retry-every 5s --max-timeout 60s

tests/RobotFramework/tests/pkcs11/private_key_storage.robot

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,14 @@ Documentation Test thin-edge.io MQTT client authentication using a Hardwar
66
... hardware device would be used.
77
88
# it would be good to explain here why we use the tedge-p11-server exclusively and not the module mode
9-
Resource ../resources/common.resource
10-
Library String
11-
Library Cumulocity
12-
Library ThinEdgeIO
9+
Resource pkcs11_common.resource
1310

1411
Suite Setup Custom Setup
1512
Suite Teardown Get Suite Logs
1613

1714
Test Tags adapter:docker theme:cryptoki
1815

1916

20-
*** Variables ***
21-
${CERT_TEMPLATE} /etc/tedge/hsm/cert.template # created by init_softhsm script
22-
23-
2417
*** Test Cases ***
2518
Use Private Key in SoftHSM2 using tedge-p11-server
2619
Tedge Reconnect Should Succeed
@@ -222,50 +215,10 @@ Warn the user if tedge.toml cannot be parsed
222215

223216

224217
*** Keywords ***
225-
Connect to C8y using new keypair
226-
[Documentation] Connects to C8y with a newly generated keypair and a self-signed certificate.
227-
... The private key is saved on the token, and the self-signed certificate is registered with c8y.
228-
[Arguments] ${type} # ecdsa or rsa
229-
... ${curve}=secp256r1 # if type == ECDSA, curve of the key - one of {secp256r1, secp384r1, secp521r1}
230-
... ${bits}=4096 # if type == RSA, length in bits of the RSA key - one of {1024, 2048, 3072, 4096}
231-
232-
# We could alternatively use Cumulocity CA to start with a signed cert, but for testing certificate renewal, we want
233-
# to test both renewing a self-signed cert and a cert issued by C8y CA. When we start with self-signed cert, after
234-
# the first renewal we get a cert signed by CA, so we test all scenarios by just doing renew 2 times.
235-
236-
IF '${type}' == 'ecdsa'
237-
VAR ${object_name}= ${type}-${curve}
238-
VAR ${p11tool_args}= --curve=${curve}
239-
ELSE IF '${type}' == 'rsa'
240-
VAR ${object_name}= ${type}-${bits}
241-
VAR ${p11tool_args}= --bits=${bits}
242-
ELSE
243-
Fail Wrong key type provided.
244-
END
245-
246-
# guarantee name of the object is unique even if multiple keys of the same type and bits/curve are generated
247-
${identifier}= String.Generate Random String
248-
VAR ${object_name}= ${object_name}-${identifier}
249-
250-
VAR ${cert_path}= /etc/tedge/device-certs/${object_name}.csr
251-
Execute Command cmd=tedge config set device.cert_path ${cert_path}
252-
253-
Execute Command
254-
... cmd=p11tool --set-pin=123456 --login --generate-privkey ${type} ${p11tool_args} --label ${object_name} "pkcs11:token=tedge"
255-
Execute Command
256-
... cmd=GNUTLS_PIN=123456 certtool --generate-self-signed --template "${CERT_TEMPLATE}" --outfile "${cert_path}" --load-privkey "pkcs11:token=tedge;object=${object_name}"
257-
258-
Execute Command cmd=tedge config set device.key_uri "pkcs11:token=tedge;object=${object_name}"
259-
260-
Execute Command
261-
... cmd=sudo env C8Y_USER="${C8Y_CONFIG.username}" C8Y_PASSWORD="${C8Y_CONFIG.password}" tedge cert upload c8y
262-
ThinEdgeIO.Register Certificate For Cleanup
263-
264-
Tedge Reconnect Should Succeed
265-
266218
Custom Setup
267219
${DEVICE_SN}= Setup register=${False}
268220
Set Suite Variable ${DEVICE_SN}
221+
269222
# Allow the tedge user to access softhsm
270223
Execute Command sudo usermod -a -G softhsm tedge
271224
Transfer To Device ${CURDIR}/data/init_softhsm.sh /usr/bin/
@@ -285,30 +238,3 @@ Custom Setup
285238
Register Device With Cumulocity CA ${csr_path}
286239

287240
Set tedge-p11-server Uri value=
288-
289-
Set tedge-p11-server Uri
290-
[Arguments] ${value}
291-
Execute Command tedge config set device.cryptoki.uri '${value}'
292-
Restart Service tedge-p11-server
293-
294-
Tedge Reconnect Should Succeed
295-
${stderr}= Execute Command tedge reconnect c8y stdout=false stderr=true
296-
RETURN ${stderr}
297-
298-
Tedge Reconnect Should Fail With
299-
[Arguments] ${error}
300-
${stderr}= Command Should Fail With tedge reconnect c8y ${error}
301-
RETURN ${stderr}
302-
303-
Command Should Fail With
304-
[Arguments] ${command} ${error}
305-
${stderr}= Execute Command ${command} exp_exit_code=!0 stdout=false stderr=true
306-
Should Contain ${stderr} ${error}
307-
RETURN ${stderr}
308-
309-
Register Device With Cumulocity CA
310-
[Documentation] Registers a new certificate with Cumulocity CA and places it under `c8y.device.cert_path`
311-
[Arguments] ${csr_path}
312-
${credentials}= Cumulocity.Bulk Register Device With Cumulocity CA external_id=${DEVICE_SN}
313-
Execute Command
314-
... cmd=tedge cert download c8y --csr-path "${csr_path}" --device-id "${DEVICE_SN}" --one-time-password '${credentials.one_time_password}' --retry-every 5s --max-timeout 60s

0 commit comments

Comments
 (0)