amazon-web-servicesamazon-ec2

AuthFailure while trying to call a method through amazon api


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.


Solution

  • 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)

    AWS-Signature is Like oauth1

    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

    enter image description here

    Check:

    As you will see, it is similar at OAUTH1 in the way that we need to sign the entire request request

    enter image description here

    Signing http messages

    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

    Try with some client like postman

    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:

    Implement the aws-signature

    If your credentials are ok and the signature works with postman, you can try to implement manually using your favorite language. Here some samples:

    aws sdk instead manually invocation

    Check: