Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify AWS Credentials with boto3

I'm trying to write Python code that uses a number of different AWS keys, some of which may have expired. I need, given an AWS key pair as strings, to check whether the given key pair is valid using boto3. I would prefer not to have to do anything like using os.system to run

echo "$aws_key_id
$aws_secret_key\n\n" | aws configure

and then reading the response of aws list-buckets.

The answer should look something like

def check_aws_validity(key_id, secret):
    pass

where key_id and secret are strings.

Note that this is not a repeat of Verifying S3 credentials w/o GET or PUT using boto3, as I do not have the keys in boto3.profile.

Thanks in advance!

EDIT From John Rotenstein's answer, I got the following function to work.

def check_aws_validity(key_id, secret):
    try:
        client = boto3.client('s3', aws_access_key_id=key_id, aws_secret_access_key=secret)
        response = client.list_buckets()
        return true

    except Exception as e:
        if str(e)!="An error occurred (InvalidAccessKeyId) when calling the ListBuckets operation: The AWS Access Key Id you provided does not exist in our records.":
            return true
        return false
like image 750
Plaba Avatar asked Nov 29 '18 22:11

Plaba


People also ask

How do I verify AWS credentials?

To validate a user's credentials with the AWS CLI, run the sts get-caller-identity command. The command returns details about the user's credentials if they are valid, otherwise it throws an error.


2 Answers

You can make a call by directly specifying credentials:

import boto3

client = boto3.client('s3', aws_access_key_id='xxx', aws_secret_access_key='xxx')
response = client.list_buckets()

You can then use the response to determine whether the credentials are valid.

However, it is possible that a user has valid credentials, but does not have permission to call list_buckets(). This might make it harder to determine whether they have valid credentials. You'll need to try various combinations to see what response is sent back to your code.

like image 106
John Rotenstein Avatar answered Oct 21 '22 20:10

John Rotenstein


Such a credential-validating method does exist; it's the STS GetCallerIdentity API call (boto3 method docs).

With expired temporary credentials:

>>> import boto3
>>> sts = boto3.client('sts')
>>> sts.get_caller_identity()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jantman/venv/lib/python3.8/site-packages/botocore/client.py", line 276, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/jantman/venv/lib/python3.8/site-packages/botocore/client.py", line 586, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (ExpiredToken) when calling the GetCallerIdentity operation: The security token included in the request is expired

With invalid credentials:

>>> import boto3
>>> sts = boto3.client('sts')
>>> sts.get_caller_identity()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jantman/venvs/current/lib/python3.8/site-packages/botocore/client.py", line 316, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/jantman/venvs/current/lib/python3.8/site-packages/botocore/client.py", line 626, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid

With valid credentials (IDs replaced with X's):

>>> import boto3
>>> sts = boto3.client('sts')
>>> sts.get_caller_identity()
{'UserId': 'AROAXXXXXXXXXXXXX:XXXXXXX', 'Account': 'XXXXXXXXXXXX', 'Arn': 'arn:aws:sts::XXXXXXXXXXXX:assumed-role/Admin/JANTMAN', 'ResponseMetadata': {'RequestId': 'f44ec1d9-XXXX-XXXX-XXXX-a26c85be1c60', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'f44ec1d9-XXXX-XXXX-XXXX-a26c85be1c60', 'content-type': 'text/xml', 'content-length': '426', 'date': 'Thu, 28 May 2020 10:45:36 GMT'}, 'RetryAttempts': 0}}

Invalid credentials will raise an exception and valid credentials won't, so you can do something such as:

import boto3
sts = boto3.client('sts')
try:
    sts.get_caller_identity()
    print("Credentials are valid.")
except boto3.exceptions.ClientError:
    print("Credentials are NOT valid.")
like image 23
Jason Antman Avatar answered Oct 21 '22 19:10

Jason Antman