I am trying to create an EC2 instance on AWS in an automatical manner. I am calling a HTTP method through an amazon endpoint using a HTTP client installed on my computer, which clearly is not on AWS.
I am calling the endpoint in the following way, as specified in amazon documentation:
https://ec2.amazonaws.com/?Action=RunInstances&
ImageId=ami-0129bfde49ddb0ed6&
MaxCount=1&
MinCount=1&
KeyName=chiavepem.pem&
SecurityGroupId.1=sg-0983aeb061077d2ab&
Placement.AvailabilityZone=eu-north-1&
AWSSecretKey=<redacted>&
AWSAccessKeyId=<redacted>
However, I get this response:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Errors>
<Error>
<Code>AuthFailure</Code>
<Message>AWS was not able to validate the provided access credentials</Message>
</Error>
</Errors>
<RequestID>c3c559d8-fe3f-4e60-bd16-1db621dfcbe4</RequestID>
</Response>
Regarding AuthFailure, Amazon Documentation says:
The provided credentials could not be validated. You might not be authorized to carry out the request; for example, trying to associate an Elastic IP address that is not yours, or trying to use an AMI for which you do not have permissions. Ensure that your account is authorized to use Amazon EC2, that your credit card details are correct, and that you are using the correct credentials.
I made sure these conditions are respected.
What might be the cause for this specific behavior?
As a side note, I am using access keys here, but I understood that it is not the best way to authenticate a call to the aws api, but i didn't find any valid alternative for doing so. As far as I understand, I cannot use my IAM credentials to authenticate to the API. Maybe someone could point me in the right direction on this matter as well.
Thanks.
The authentication to call an aws platform rest endpoint is not easy like oauth2 client-credentials flow, in which we can exchange the credentials for an access_token and the use it to consume the required endpoint (create an ec2 instance in your case)
I tried in the past and the authorization is something like oauth1 in which the request is signed using some values like credentials and others.
This is not easy, that's why aws and similar (gcp, azure, etc) has a sdk in all the well known languages. That sdk do the request sign by you and other complex tasks (expiration, etc)
Anyway if you want to do it manually (+1 for you), the signature process is called : AWS Signature
Check:
As you will see, it is similar at OAUTH1 in the way that we need to sign the entire request request
As an extreme summary, using some strings (keys, dates, etc) the clean http message:
POST /foo?param=value&pet=dog HTTP/1.1
Host: example.com
Date: Tue, 20 Apr 2021 02:07:55 GMT
Content-Type: application/json
Digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
Content-Length: 18
Body:
{"hello": "world"}
To something like
POST /foo?param=Value&Pet=dog HTTP/1.1
Host: example.com
Date: Tue, 20 Apr 2021 02:07:55 GMT
Content-Type: application/json
Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\
aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==:
Content-Length: 18
Signature-Input: sig1=("@method" "@authority" "@path" \
"content-digest" "content-length" "content-type")\
;created=1618884473;keyid="test-key-rsa-pss"
Signature: sig1=:HIbjH+xF/g==:
Body:
PHK7a9sRL1IXNaagCNN3ZxJsYapFj+JXbmaI5rtAdSf\
SvzPuBCh+ARHBmWuNo1UzVVdHXrl8ePL4cccqlazIJdC4QEjrF+Sn4IxBQzTZsL9y\
9TP5FsZYzHvDqbInkTNigBcE9cKOYNFCn4D/WM7F6TNuZO9EgtzepLWcjTymlHzK7\
aXq6Am6sfOrpIC49yXjj3ae6HRalVc
To fully understand check
Also you can review the code of some library in your favorite language
If you understand that signature is required, I suggest you to use postman, insomnia o soapui to verify that signature exist and your credentials are ok.
Check:
If your credentials are ok and the signature works with postman, you can try to implement manually using your favorite language. Here some samples:
Check: