Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS IoT - Access shadow through .Net, REST, with certificate

Trying to learn AWS IoT, I created a few "Things" + a Policy and I am even able to use IoT CLI to list-things or list-policies. I am even able to update the shadow through CLI with update-thing command through CLI. But once I try to access a Shadow through REST GET / POST request (through a .Net program or directly like https://XXXXXXXXXXXXX.iot.us-west-2.amazonaws.com/things/mything/shadow), I receive a

"Missing Authentication Token"

. So I started to use a certificate. Here is part of my code:

string Certificate = "xxxxxxxxx-certificate.crt"; // downloaded from my thing
X509Certificate cert = new X509Certificate(Certificate);
WebRequestHandler handler = new WebRequestHandler();
handler.ClientCertificates.Add(cert);
HttpClient client = new HttpClient(handler);
// url = @"https://xxxxxxxxxxxxx.iot.us-west-2.amazonaws.com/things/<mything>/shadow";
HttpResponseMessage webResponse = client.GetAsync(url, HttpCompletionOption.ResponseContentRead).Result;

The result is:

StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
x-amzn-RequestId: 25f3c1dc-9ddd-4787-a4cf-cb79dc96748b
connection: Keep-Alive
x-amzn-ErrorType: ForbiddenException:
Date: Tue, 15 Dec 2015 08:53:56 GMT
Content-Length: 91
Content-Type: application/json
}

Any assistance?

like image 726
Erez Avatar asked Oct 31 '22 13:10

Erez


1 Answers

If you want to publish and/or subscribe to topics, you can take two different approach.

  1. HTTPS calls to API endpoints.
  2. Using any of the supported AWS SDKs of your choice (python, java, .NET etc.,) or AWS CLI

For the "missing authentication token" exception you get is due to unavailability of authentication tokens and amazon specific headers in your request. To make your HTTPS request work, You either use a rest client to add amazon specific headers or write a program.

You should try doing the following steps to make your https requests to work.

For detailed steps, refer http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

TASK 1: CREATE A CANONICAL REQUEST

  • Step 1 is to define the verb (GET, POST, etc.)
  • Step 2: Create canonical URI.
  • Step 3: Create the canonical query string.
  • Step 4: Create the canonical headers and signed headers.
  • Step 5: Create the list of signed headers.
  • Step 6: Create payload hash (hash of the request body content)
  • Step 7: Combine elements to create create canonical request

TASK 2: CREATE THE STRING TO SIGN Using SHA256 algorithm, hash the canonical request (using any programming language/tools) and create a string to sign like below

string_to_sign = YourHashingAlgorithm + '\n' + CurrentDateInUTC+ '\n' + credential_scope + '\n' + yourHashedCanonicalRequest

API's to AWS services are uniquely identified by service paths. For IOT it is "iotdata/aws4_request". So your credential_scope in the above 'string_to_sign' should be like

credential_scope = datestamp + '/' + us-west-2+ '/' + iotdata+ '/' + 'aws4_request'

TASK 3: CALCULATE THE SIGNATURE

Calculate the hash using the same algorithm used in previous steps.

Refer the above said link for more details.

TASK 4: ADD SIGNING INFORMATION TO THE REQUEST

Here you need to set some of the headers like 'x-amz-date','Authorization', 'SignedHeaders' and 'Signature'. This Signature header will carry the final value of the Step 3.

Note: None of these headers are optional. Every HTTPS request should have all this information for authentication and authorization. Else AWS API will reject it.

You should get a 200 OK response to assure that your request is actually processed.

Coming to your .Net approach, you can try using AWS's .NET SDK and try inspecting the final request. I never tried using x.509 certificates directly in code. I think you are missing headers in your requests.

In cURL it would be something like below

curl "https://iot.amazonaws.com" \ --request GET \ --form "Action=UpdateThing" \ --form "UserName=iam_user" \ --form "CertificateBody=@~/.aws/credentials/sample/cert.pem" \ --form "Version=2010-05-08" \ --form "AUTHPARAMS"

Hope this helps

like image 191
arvinthdd Avatar answered Nov 11 '22 17:11

arvinthdd