AWS IoT certificate file - amazon-web-services

I'm struggling with the client cert and private key embedding or uploading, in order to authenticate with the AWS IoT endpoint assigned to my account. We are currently working in a solution in order to embed that ideal solution of the two certs and the private key at the gateway hardware which will forward the information sent by the sensor in a secure way.
I would like to know if there are any way to connect in the same way of Google IoT (JWT in the password field) o Azure (SAS token in password field) and not have to use the files: private key, CA certificate, certificate x509
The deviced I'm using are MQTT, so I can not use HTTP or similar

There are different possibilities using different protocols, see the Message Broker Protocols topic in the AWS IoT Developer guide: https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
Using the MQTT protocol directly, you have to use certificates, but if you use the MQTT + WebSocket option, you can either use a standard AWS Signature V4 header on the connect request, or you can use a custom authorizer (and your own header on the connect request).
Good starters for understanding those options are
https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
https://docs.aws.amazon.com/iot/latest/developerguide/iot-custom-authentication.html

Related

AWS: Using TLS-certificate without private key

For using an API from the dutch chamber of commerce, It's mandatory to install a TLS-certificate from the Dutch government. Only when the certificate is installed, It's possible to make authorized API-requests. The chamber of commerce has published an install guide here: https://developers.kvk.nl/support/documentation/manual-tls-certificate
We want to use this API in an application that's hosted with AWS amplify as backend with React as frontend. The most obvious approach was using AWS certificate manager, because it's integrated with Amplify. The problem we encounter using the certificate manager is that It's mandatory to provide a private key in PEM format to import a certificate (see picture). The thing is, there are no private keys given since the certificates are from the governments, and the manual does not describe what needs to be done in our case.(https://i.stack.imgur.com/uBXRl.png)
We tried to contact the chamber of commerce but our response was that it was not in their reach and we should try it elsewhere. Our only option as we see now is that we need to host a dedicated server to redirect the api requests and responses, but that would defeat our point of being serverless with Amplify.
AWS Certificate Manager is for certificates that you own. You would use that for the SSL/TLS certificate that matches the domain name that your application runs on.
The TLS certificate you are trying to use is not one that you own, it is one owned by the Dutch government, and you only have the public key info. You need to install that public key info onto your server in order to validate the TLS connections you make to the API you are connecting to. You aren't using it to serve a secure connection, you are using it to validate a secure connection.
The AWS ACM integration with AWS Amplify would not help you here, since that integration is specifically for serving a secure domain name, not for validating API calls your Amplify application is making.
Your Amplify backend will be built using AWS Lambda. It will be the Lambda function that performs the API calls to the Dutch government. You simply need to include the TLS certificate files in the Lambda deployment package that you upload to AWS, and then configure whatever HTTP library you are using in Lambda to make the API calls to use those files for TLS validation.

How to authenticate AWS IOT devices through API Gateway?

I’ve got a use-case where my devices should make GET requests against my API gateway.
What would be the simplest way to have API gateway perform client authentication of the device? Is it possible to use the certificates already generated by IoT Core and used in MQTT?
Authorizing direct calls to AWS services using AWS IoT Core credential provider:
Devices can use X.509 certificates to connect to AWS IoT Core using TLS mutual authentication protocols. Other AWS services do not support certificate-based authentication, but they can be called using AWS credentials in AWS Signature Version 4 format. The Signature Version 4 algorithm normally requires the caller to have an access key ID and a secret access key. AWS IoT Core has a credentials provider that allows you to use the built-in X.509 certificate as the unique device identity to authenticate AWS requests. This eliminates the need to store an access key ID and a secret access key on your device.

How to store certificate as a secret in AWS secret manager ? How to pass that secret in https call using AWS appSync resolver?

I need to get elements from AWS dynamoDB and thrid party https service and merge those results in AWS appSyn and send back the result as graphQL response
Third party service which I am using, expects client side certificate. I am not finding proper AWS documents on how to pass agent using AWS appSync resolver.
I am also not finding documents to store certificate as secret in AWS secret manager.
Is there anyone faced similar problem? Or do you guys have any solution to it?
It depends on the size of your certificate - Secrets for AWS Secrets Manager have various limits such as length in bytes (7168 bytes) or characters (4096) see more here:
https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_limits.html
But otherwise you should be able to store your certificate using AWS Secrets Manager.
See number item 3 in the following link: https://aws.amazon.com/blogs/compute/maintaining-transport-layer-security-all-the-way-to-your-container-part-2-using-aws-certificate-manager-private-certificate-authority/
Using HTTP Resolvers (or even Lambda Resolvers) you will be able to make http calls to AWS Secrets Manager to obtain the secret.
See links:
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-http-resolvers.html
Adding to Ashwin's answer, According to documentation, HTTP resolver supports only public endpoint at this point and does not seem to have ability to pass a certificate for app to app call

Is it possible to connect to the Google IOTCore via JavaScript in browser

AWS IoT supports this via userPools, how this can be done via Google Cloud messaging? -Thanks
Cloud IoT Core recommends HTTP bridge for that. (https://cloud.google.com/iot/docs/how-tos/http-bridge)
To establish a connection to HTTP Bridge you have to prepare a private key signed JWT for authentication. The problems will be: where do you store the PK in a secure way in the browser session and how to make a relation between the browser user and IoT device identity?
Btw, 'Google Cloud Messaging' was not part of Google Cloud IoT, was a different product. Now Firebase Cloud Messaging is a recommended product https://firebase.google.com/docs/cloud-messaging/
use a JavaScript MQTT client, for example Eclipse Paho; this just needs an external IP.

Verify that API call was made from AWS Lambda (or another server)

Is there any way I can check that a call is made from an expected lambda function or you can consider it as another server.
The use case is: I want to emit a websocket event to notify my web app when my EC2 status changes. (Do suggest a better way if any) My web socket server will be an EC2 instance. So I am wondering, if there is some way to allow calls to this specific API to be only from a valid AWS Lambda function?
Currently I am thinking maybe I can just use a shared secret ... but since this never expires, wonder if its a security risk?
UPDATE
A thought came to mind, isit ok to use asymmetric encryption like RSA for this?
Oh wait, is RSA not suitable for such data encryption? I read its for signing keys?
I assume you have already set a EC2 state change trigger to a SNS topic you have created.
You can verify singature of SNS notification by processing the JSON body as instructed in AWS SNS documentation. It also has a Java example but if you want to use Python, here is an example for X509 verification part using M2Crypto module:
from M2Crypto import X509
from base64 import b64decode
cert = X509.load_cert_string(str(r.text))
pubkey = cert.get_pubkey()
pubkey.reset_context(md='sha1')
pubkey.verify_init()
pubkey.verify_update(str_to_sign.encode())
result = pubkey.verify_final(b64decode(signature))
if result != 1:
raise Exception('Signature could not be verified')
else:
return True
As advised in the doc, AWS SDK implemented for language might already have built-in ability just like for Ruby. It is good idea to check that before implementing this.
So basically, you should have the X509 that is used by SNS on the receiving server.
It is also recommended you to subscribe your SNS topic to a HTTPS endpoint so it will validate the authenticity of the server before sending the notification as a secure request. SNS supports verifying certificate authorities listed here.