I'm trying to do the process outlined in this post: https://aws.amazon.com/blogs/security/how-to-eliminate-the-need-for-hardcoded-aws-credentials-in-devices-by-using-the-aws-iot-credentials-provider/.
I've got everything set up,and am able to get the temporary credentials via curl, but want to do it via the Java sdk. I've tried the code mentioned in this post: Get security token from AWS Credentials Provider in the comments from jccampanero, but am getting a javax.net.sslhandshakeexception: bad_certificate error at runtime. I've verified that the certificate and private key are good, as mentioned above they work in curl form for getting the credentials.
When creating to pkcs12 keystore for the client side stuff I use the following commmand:
openssl pkcs12 -export -in certificate.pem -inkey private.key -out keystore.p12 -name exampleName -CAFile AmazonRootCA1.pem -caname root -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -macalg sha1
And when creating the trust store I use the following code:
private void createTrustStore() {
Path pemPath = Paths.get("/directory/AmazonRootCA1.pem");
try (final InputStream is = Files.newInputStream(pemPath)) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(is);
String alias = cert.getSubjectX500Principal().getName();
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
keystore.setCertificateEntry(alias, cert);
FileOutputStream out = new FileOutputStream("/directory/CAtrustStore.jks");
keystore.store(out, "password".toCharArray());
System.setProperty("javax.net.ssl.trustStore", "/directory/CAtrustStore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
}
I've also used keytool to verify both of the stores are being properly created.
To make the request I use the following code:
public void getCredentials() {
HttpExecuteResponse response;
Path clientKeyStore = Path.of("keystore.p12");
TlsKeyManagersProvider provider = FileStoreTlsKeyManagersProvider.create(clientKeyStore, "pkcs12", "password");
KeyManager[] keyManagers = provider.keyManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, null, null);
ConnectionSocketFactory socketFactory = new SdkTlsSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
try (SdkHttpClient client = ApacheHttpClient.builder().socketFactory(socketFactory).build()) {
SdkHttpRequest httpRequest = SdkHttpRequest.builder()
.method(SdkHttpMethod.GET)
.uri(new URI("https://<myPrefix>.credentials.iot.us-east-2.amazonaws.com/role-aliases/<myAlias>/credentials"))
.putHeader("x-amzn-iot-thingname", "<myThingName>")
.build();
HttpExecuteRequest request = HttpExecuteRequest.builder()
.request(httpRequest)
.build();
response = client.prepareRequest(request).call();
}
Log.MainLog().info(response.httpResponse().toString());
Log.MainLog().info(response.responseBody().toString());
}
}
Edit: just to clarify, I did try exactly as in that post, using the System.setProperty for the client keystore as well, and got the same error. I also tried feeding the TlsKeyManagersProvider into the builder with the .TlsKeyManagerProvider method instead of using the socket factory, but also got the same error. Currently using the socket factory as that is what is outlined in the aws java sdk test linked in jccampanero's post. Since I'm getting the same error regardless of which method I use, I'm assuming the issue is with the pkcs12 keystore rather than the code.
Edit2: I've now also tried using the cacerts keystore in my usr/lib/jvm//lib/security folder for the trust store as well, since I've seen some suggestions of that, but no luck.