简体   繁体   中英

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

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.")

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.

Here is how I solved that:

import boto3
import botocore

def check_login():
    sts = boto3.client('sts')
    try:
        sts.get_caller_identity()
        return True
    except botocore.exceptions.UnauthorizedSSOTokenError:
        return False

if check_login():
    print("Credentials are valid.")
else:
    # do something to log in

The difference to the answer before is the import of botocore and the catch of the correct error (UnauthorizedSSOTokenError). Also it works with Python3 (eg new boolean types to return).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM