Skip to content

Commit 5390cb9

Browse files
authored
Added unit test to setup Mqtt Connect through EC-based certificate and key (#545)
* adding ecc key unit test * revert test api changes, keep the original api unchanged * fix ecc private key variable name * update README with ecc related test parameters * update c-io * update c-common * update java test arguments * rename parameter to make it clear * rename test context
1 parent 00d9a25 commit 5390cb9

11 files changed

Lines changed: 90 additions & 13 deletions

File tree

.builder/actions/aws_crt_java_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ def run(self, env):
2222

2323
endpoint = env.shell.get_secret("unit-test/endpoint")
2424

25-
with self._write_secret_to_temp_file(env, "unit-test/rootca") as root_ca_file, self._write_secret_to_temp_file(env, "unit-test/certificate") as cert_file, self._write_secret_to_temp_file(env, "unit-test/privatekey") as key_file:
25+
with self._write_secret_to_temp_file(env, "unit-test/rootca") as root_ca_file, self._write_secret_to_temp_file(env, "unit-test/certificate") as cert_file, \
26+
self._write_secret_to_temp_file(env, "unit-test/privatekey") as key_file, self._write_secret_to_temp_file(env, "ecc-test/certificate") as ecc_cert_file, \
27+
self._write_secret_to_temp_file(env, "ecc-test/privatekey") as ecc_key_file:
2628

2729
test_command = "mvn -P continuous-integration -B test -DredirectTestOutputToFile=true -DreuseForks=false " \
2830
"-DrerunFailingTestsCount=5 -Daws.crt.memory.tracing=2 -Daws.crt.debugnative=true -Daws.crt.ci=true " \
29-
"-Dendpoint={} -Dcertificate={} -Dprivatekey={} -Drootca={}".format(endpoint, cert_file.name, key_file.name, root_ca_file.name)
31+
"-Dendpoint={} -Dcertificate={} -Dprivatekey={} -Drootca={} -Decc_certificate={} -Decc_privatekey={}".format(endpoint, \
32+
cert_file.name, key_file.name, root_ca_file.name, ecc_cert_file.name, ecc_key_file.name)
3033

3134
all_test_result = os.system(test_command)
3235

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Full list of test arguments:
7878
- `certificate`: Path to the IoT thing certificate
7979
- `privatekey`: Path to the IoT thing private key
8080
- `privatekey_p8`: Path to the IoT thing private key in PKCS#8 format
81+
- `ecc_certificate`: Path to the IoT thing with EC-based certificate
82+
- `ecc_privatekey`: Path to the IoT thing with ECC private key (The ECC key file should only contains the ECC Private Key section to working on MacOS.)
8183
- `rootca`: Path to the root certificate
8284
- `proxyhost`: Hostname of proxy
8385
- `proxyport`: Port of proxy

android/crt/src/androidTest/assets/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ ca-certificates.crt - Taken from any recent Linux /etc/ssl
33
certificate.pem - IoT Thing Certificate
44
privatekey.pem - IoT Thing Private Key
55
privatekey_p8.pem - IoT Thing Private Key in PKCS#8 format
6+
ecc_certificate.pem - IoT Thing Certificate for ECC private key
7+
ecc_privatekey.pem - IoT Thing ECC Private Key
68
endpoint.txt - IoT ATS Endpoint
79
AmazonRootCA1.pem - Available from https://www.amazontrust.com/repository/AmazonRootCA1.pem

android/crt/src/androidTest/java/software/amazon/awssdk/crt/test/android/CrtPlatformImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public void testSetup(Object context) {
5252
ctx.trustStore = assetContents("ca-certificates.crt");
5353
ctx.iotClientCertificate = assetContents("certificate.pem");
5454
ctx.iotClientPrivateKey = assetContents("privatekey.pem");
55+
ctx.iotClientECCPrivateKey = assetContents("ecc_privatekey.pem");
56+
ctx.iotClientECCCertificate = assetContents("ecc_certificate.pem");
5557
byte[] endpoint = assetContents("endpoint.txt");
5658
if (endpoint != null) {
5759
ctx.iotEndpoint = new String(endpoint).trim();

codebuild/common-linux.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ git submodule update --init
1313
curl https://www.amazontrust.com/repository/AmazonRootCA1.pem --output /tmp/AmazonRootCA1.pem
1414
cert=$(aws secretsmanager get-secret-value --secret-id "unit-test/certificate" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$cert" > /tmp/certificate.pem
1515
key=$(aws secretsmanager get-secret-value --secret-id "unit-test/privatekey" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$key" > /tmp/privatekey.pem
16+
ecc_cert=$(aws secretsmanager get-secret-value --secret-id "ecc-test/certificate" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$cert" > /tmp/ecc_certificate.pem
17+
ecc_privatekey=$(aws secretsmanager get-secret-value --secret-id "ecc-test/privatekey" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$key" > /tmp/ecc_privatekey.pem
1618
key_p8=$(aws secretsmanager get-secret-value --secret-id "unit-test/privatekey-p8" --query "SecretString" | cut -f2 -d":" | cut -f2 -d\") && echo -e "$key_p8" > /tmp/privatekey_p8.pem
1719
ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
1820

@@ -26,6 +28,8 @@ mvn -B test $* \
2628
-Dendpoint=$ENDPOINT \
2729
-Dcertificate=/tmp/certificate.pem \
2830
-Dprivatekey=/tmp/privatekey.pem \
31+
-Decc_certificate=/tmp/ecc_certificate.pem \
32+
-Decc_privatekey=/tmp/ecc_privatekey.pem \
2933
-Drootca=/tmp/AmazonRootCA1.pem \
3034
-Dprivatekey_p8=/tmp/privatekey_p8.pem \
3135
-Daws.crt.debugnative=true \

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@
407407
<systemPropertyVariables>
408408
<certificate>${crt.test.certificate}</certificate>
409409
<privatekey>${crt.test.privatekey}</privatekey>
410+
<ecc_certificate>${crt.test.ecc_certificate}</ecc_certificate>
411+
<ecc_privatekey>${crt.test.ecc_privatekey}</ecc_privatekey>
410412
<endpoint>${crt.test.endpoint}</endpoint>
411413
<rootca>${crt.test.rootca}</rootca>
412414
<privatekey_p8>${crt.test.privatekey_p8}</privatekey_p8>

src/test/java/software/amazon/awssdk/crt/test/CrtTestContext.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ public class CrtTestContext {
1313
public byte[] iotClientCertificate = null;
1414
// IoT Thing private key for testing
1515
public byte[] iotClientPrivateKey = null;
16+
// IoT Thing ecc certificate for testing
17+
public byte[] iotClientEccCertificate = null;
18+
// IoT Thing ecc private key for testing
19+
public byte[] iotClientEccPrivateKey = null;
1620
// IoT ATS endpoint for testing
1721
public String iotEndpoint = null;
1822
// IoT CA Root
1923
public byte[] iotCARoot = null;
20-
}
24+
}

src/test/java/software/amazon/awssdk/crt/test/MqttClientConnectionFixture.java

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public class MqttClientConnectionFixture extends CrtTestFixture {
4848
static final String TEST_ENDPOINT = System.getProperty("endpoint");
4949
static final String TEST_CERTIFICATE = System.getProperty("certificate");
5050
static final String TEST_PRIVATEKEY = System.getProperty("privatekey");
51+
static final String TEST_ECC_CERTIFICATE = System.getProperty("ecc_certificate");
52+
static final String TEST_ECC_PRIVATEKEY = System.getProperty("ecc_privatekey");
5153
static final String TEST_ROOTCA = System.getProperty("rootca");
5254
static final short TEST_PORT = 8883;
5355
static final short TEST_PORT_ALPN = 443;
@@ -62,13 +64,18 @@ public class MqttClientConnectionFixture extends CrtTestFixture {
6264
String caRoot = null;
6365
String iotEndpoint = null;
6466

67+
enum AUTH_KEY_TYPE {
68+
RSA,
69+
ECC
70+
}
71+
6572
Consumer<MqttConnectionConfig> connectionConfigTransformer = null;
6673

6774
protected void setConnectionConfigTransformer(Consumer<MqttConnectionConfig> connectionConfigTransformer) {
6875
this.connectionConfigTransformer = connectionConfigTransformer;
6976
}
7077

71-
private boolean findCredentials() {
78+
private boolean findCredentials(AUTH_KEY_TYPE key_type) {
7279
CrtTestContext ctx = getContext();
7380

7481
// For each parameter, check the context first, then check the file system/system properties
@@ -87,7 +94,7 @@ private boolean findCredentials() {
8794
}
8895
iotEndpoint = ctx.iotEndpoint;
8996

90-
if (ctx.iotClientCertificate == null) {
97+
if (key_type == AUTH_KEY_TYPE.RSA && ctx.iotClientCertificate == null) {
9198
pathToCert = TEST_CERTIFICATE != null? Paths.get(TEST_CERTIFICATE) : null;
9299
if (pathToCert == null || pathToCert.toString().equals("")) {
93100
throw new MissingCredentialsException("Certificate not provided");
@@ -97,10 +104,19 @@ private boolean findCredentials() {
97104
}
98105
ctx.iotClientCertificate = Files.readAllBytes(pathToCert);
99106
}
100-
certificatePem = new String(ctx.iotClientCertificate);
107+
else if (key_type == AUTH_KEY_TYPE.ECC && ctx.iotClientEccCertificate == null) {
108+
pathToCert = TEST_ECC_CERTIFICATE != null? Paths.get(TEST_ECC_CERTIFICATE) : null;
109+
if (pathToCert == null || pathToCert.toString().equals("")) {
110+
throw new MissingCredentialsException("Certificate not provided");
111+
}
112+
if (!pathToCert.toFile().exists()) {
113+
throw new MissingCredentialsException("Certificate could not be found at " + pathToCert);
114+
}
115+
ctx.iotClientEccCertificate = Files.readAllBytes(pathToCert);
116+
}
101117

102-
if (ctx.iotClientPrivateKey == null) {
103-
pathToKey = TEST_PRIVATEKEY != null ? Paths.get(TEST_PRIVATEKEY) : null;
118+
if (key_type == AUTH_KEY_TYPE.RSA && ctx.iotClientPrivateKey == null) {
119+
pathToKey = TEST_PRIVATEKEY != null? Paths.get(TEST_PRIVATEKEY) : null;
104120
if (pathToKey == null || pathToKey.toString().equals("")) {
105121
throw new MissingCredentialsException("Private key not provided");
106122
}
@@ -109,7 +125,27 @@ private boolean findCredentials() {
109125
}
110126
ctx.iotClientPrivateKey = Files.readAllBytes(pathToKey);
111127
}
112-
privateKeyPem = new String(ctx.iotClientPrivateKey);
128+
else if (key_type == AUTH_KEY_TYPE.ECC && ctx.iotClientEccPrivateKey == null) {
129+
pathToKey = TEST_ECC_PRIVATEKEY != null? Paths.get(TEST_ECC_PRIVATEKEY) : null;
130+
if (pathToKey == null || pathToKey.toString().equals("")) {
131+
throw new MissingCredentialsException("Private key not provided");
132+
}
133+
if (!pathToKey.toFile().exists()) {
134+
throw new MissingCredentialsException("Private key could not be found at " + pathToKey);
135+
}
136+
ctx.iotClientEccPrivateKey = Files.readAllBytes(pathToKey);
137+
}
138+
139+
if( key_type == AUTH_KEY_TYPE.ECC)
140+
{
141+
certificatePem = new String(ctx.iotClientEccCertificate);
142+
privateKeyPem = new String(ctx.iotClientEccPrivateKey);
143+
}
144+
else if(key_type == AUTH_KEY_TYPE.RSA)
145+
{
146+
certificatePem = new String(ctx.iotClientCertificate);
147+
privateKeyPem = new String(ctx.iotClientPrivateKey);
148+
}
113149

114150
return true;
115151
} catch (InvalidPathException ex) {
@@ -147,9 +183,12 @@ boolean connect(boolean cleanSession, int keepAliveSecs, int protocolOperationTi
147183
return connect(cleanSession, keepAliveSecs, protocolOperationTimeout, null);
148184
}
149185

150-
boolean connect(boolean cleanSession, int keepAliveSecs, int protocolOperationTimeout, Consumer<MqttMessage> anyMessageHandler) {
151-
Assume.assumeTrue(findCredentials());
186+
boolean connectECC() {
187+
return connectWithKeyType(false, 0, 0, null, AUTH_KEY_TYPE.ECC);
188+
}
152189

190+
boolean connectDirect(boolean cleanSession, int keepAliveSecs, int protocolOperationTimeout, Consumer<MqttMessage> anyMessageHandler)
191+
{
153192
MqttClientConnectionEvents events = new MqttClientConnectionEvents() {
154193
@Override
155194
public void onConnectionResumed(boolean sessionPresent) {
@@ -212,6 +251,17 @@ public void onConnectionInterrupted(int errorCode) {
212251
return false;
213252
}
214253

254+
boolean connect(boolean cleanSession, int keepAliveSecs, int protocolOperationTimeout, Consumer<MqttMessage> anyMessageHandler)
255+
{
256+
Assume.assumeTrue(findCredentials(AUTH_KEY_TYPE.RSA));
257+
return connectDirect(cleanSession,keepAliveSecs,protocolOperationTimeout, anyMessageHandler);
258+
}
259+
260+
boolean connectWithKeyType(boolean cleanSession, int keepAliveSecs, int protocolOperationTimeout, Consumer<MqttMessage> anyMessageHandler, AUTH_KEY_TYPE type) {
261+
Assume.assumeTrue(findCredentials(type));
262+
return connectDirect(cleanSession,keepAliveSecs,protocolOperationTimeout, anyMessageHandler);
263+
}
264+
215265
void disconnect() {
216266
disconnecting = true;
217267
try {

0 commit comments

Comments
 (0)