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
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.
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.
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.")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With