aws / aws-iot-device-sdk-java-v2

Next generation AWS IoT Client SDK for Java using the AWS Common Runtime
Apache License 2.0
115 stars 76 forks source link

Easy way to connect using Java keystore #180

Closed zosnap closed 1 year ago

zosnap commented 3 years ago

Is your feature request related to a problem? Please describe. The previous SDK had a simple constructor that let you use a keystore to make an MQTT connection: https://github.com/aws/aws-iot-device-sdk-java#load-keystore-from-file-to-initialize-the-client. As far as I can tell, there's no equivalent in this new library (which sort of makes sense, since it's a Java wrapper around C libraries, and C libraries wouldn't know much about Java keystores). In order to use an existing cert in a keystore, I had to do some extra legwork to figure out how to extract the right info from the keystore and translate it into PEM-format Strings manually.

Describe the solution you'd like It'd be great to have another static constructor for AwsIotMqttConnectionBuilder, something like: AwsIotMqttConnectionBuilder newMtlsBuilderFromKeystore(String keyStorePath, String keyStorePassword, String alias, String keyPassword) or: AwsIotMqttConnectionBuilder newMtlsBuilderFromKeystore(KeyStore keyStore, String alias, String keyPassword)

Describe alternatives you've considered In the short-term, if you could document a recommended method for loading cert and key info from a keystore and transforming it into a PEM format, that would help a lot.

jmklix commented 3 years ago

Thanks for the feature request! In the short term you could try doing this: https://stackoverflow.com/questions/150167/how-do-i-list-export-private-keys-from-a-keystore

zosnap commented 3 years ago

For posterity, I'll post what I was able to get working after some trial-and-error:

// Load certificate and private key from Java keystore and transform into PEM format
String certPemString;
String keyPemString;
try {
  KeyStore keystore = m_sslConfig.getKeystore(); // loads from file
  Certificate certificate = keystore.getCertificate(m_certAlias);
  certPemString = getPemString("CERTIFICATE", certificate.getEncoded());
  Key privateKey = keystore.getKey(m_certAlias, m_keyPassword.toCharArray());
  keyPemString = getPemString("RSA PRIVATE KEY", privateKey.getEncoded());
} catch (IOException | GeneralSecurityException e) {
  s_log.error("Failed to load keystore info for AWS IoT connection", e);
  throw new BeanCreationException("Failed to load keystore info to initialize AWS IoT connection for Central Alert Queue", e);
}

// Initialize persistent MQTT client
m_builder = AwsIotMqttConnectionBuilder.newMtlsBuilder(certPemString, keyPemString);

....

private String getPemString(String type, `byte[]` encoded) {
  String pemString;
  pemString = "-----BEGIN " + type + "-----\n";
  pemString += Base64.encodeBytes(encoded);
  pemString += "\n-----END " + type + "-----\n";
  return pemString;
}

But I'll also let you know that https://github.com/aws/aws-iot-device-sdk-java-v2/issues/174 also ended up being blocker for us, and we decided to pivot to using the v1 library instead, which let us re-use much more of our existing certificate config system without hacking around stuff like this.

github-actions[bot] commented 2 years ago

Greetings! Sorry to say but this is a very old issue that is probably not getting as much attention as it deservers. We encourage you to check if this is still an issue in the latest release and if you find that this is still a problem, please feel free to open a new one.

github-actions[bot] commented 1 year ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.