Merge pull request #1972 from surfaslt/implement-get-access-key-last-used
Implement get_access_key_last_used
This commit is contained in:
commit
25595815e5
@ -2257,7 +2257,7 @@
|
|||||||
- [X] detach_user_policy
|
- [X] detach_user_policy
|
||||||
- [X] enable_mfa_device
|
- [X] enable_mfa_device
|
||||||
- [ ] generate_credential_report
|
- [ ] generate_credential_report
|
||||||
- [ ] get_access_key_last_used
|
- [X] get_access_key_last_used
|
||||||
- [X] get_account_authorization_details
|
- [X] get_account_authorization_details
|
||||||
- [ ] get_account_password_policy
|
- [ ] get_account_password_policy
|
||||||
- [ ] get_account_summary
|
- [ ] get_account_summary
|
||||||
|
1
Makefile
1
Makefile
@ -19,6 +19,7 @@ test: lint
|
|||||||
rm -f .coverage
|
rm -f .coverage
|
||||||
rm -rf cover
|
rm -rf cover
|
||||||
@nosetests -sv --with-coverage --cover-html ./tests/ $(TEST_EXCLUDE)
|
@nosetests -sv --with-coverage --cover-html ./tests/ $(TEST_EXCLUDE)
|
||||||
|
|
||||||
test_server:
|
test_server:
|
||||||
@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/
|
@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/
|
||||||
|
|
||||||
|
@ -250,6 +250,10 @@ class AccessKey(BaseModel):
|
|||||||
datetime.utcnow(),
|
datetime.utcnow(),
|
||||||
"%Y-%m-%dT%H:%M:%SZ"
|
"%Y-%m-%dT%H:%M:%SZ"
|
||||||
)
|
)
|
||||||
|
self.last_used = datetime.strftime(
|
||||||
|
datetime.utcnow(),
|
||||||
|
"%Y-%m-%dT%H:%M:%SZ"
|
||||||
|
)
|
||||||
|
|
||||||
def get_cfn_attribute(self, attribute_name):
|
def get_cfn_attribute(self, attribute_name):
|
||||||
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
||||||
@ -379,21 +383,20 @@ class User(BaseModel):
|
|||||||
return self.access_keys
|
return self.access_keys
|
||||||
|
|
||||||
def delete_access_key(self, access_key_id):
|
def delete_access_key(self, access_key_id):
|
||||||
for key in self.access_keys:
|
key = self.get_access_key_by_id(access_key_id)
|
||||||
if key.access_key_id == access_key_id:
|
self.access_keys.remove(key)
|
||||||
self.access_keys.remove(key)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise IAMNotFoundException(
|
|
||||||
"Key {0} not found".format(access_key_id))
|
|
||||||
|
|
||||||
def update_access_key(self, access_key_id, status):
|
def update_access_key(self, access_key_id, status):
|
||||||
|
key = self.get_access_key_by_id(access_key_id)
|
||||||
|
key.status = status
|
||||||
|
|
||||||
|
def get_access_key_by_id(self, access_key_id):
|
||||||
for key in self.access_keys:
|
for key in self.access_keys:
|
||||||
if key.access_key_id == access_key_id:
|
if key.access_key_id == access_key_id:
|
||||||
key.status = status
|
return key
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
raise IAMNotFoundException("The Access Key with id {0} cannot be found".format(access_key_id))
|
raise IAMNotFoundException(
|
||||||
|
"The Access Key with id {0} cannot be found".format(access_key_id))
|
||||||
|
|
||||||
def get_cfn_attribute(self, attribute_name):
|
def get_cfn_attribute(self, attribute_name):
|
||||||
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
|
||||||
@ -908,6 +911,24 @@ class IAMBackend(BaseBackend):
|
|||||||
user = self.get_user(user_name)
|
user = self.get_user(user_name)
|
||||||
user.update_access_key(access_key_id, status)
|
user.update_access_key(access_key_id, status)
|
||||||
|
|
||||||
|
def get_access_key_last_used(self, access_key_id):
|
||||||
|
access_keys_list = self.get_all_access_keys_for_all_users()
|
||||||
|
for key in access_keys_list:
|
||||||
|
if key.access_key_id == access_key_id:
|
||||||
|
return {
|
||||||
|
'user_name': key.user_name,
|
||||||
|
'last_used': key.last_used
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
raise IAMNotFoundException(
|
||||||
|
"The Access Key with id {0} cannot be found".format(access_key_id))
|
||||||
|
|
||||||
|
def get_all_access_keys_for_all_users(self):
|
||||||
|
access_keys_list = []
|
||||||
|
for user_name in self.users:
|
||||||
|
access_keys_list += self.get_all_access_keys(user_name)
|
||||||
|
return access_keys_list
|
||||||
|
|
||||||
def get_all_access_keys(self, user_name, marker=None, max_items=None):
|
def get_all_access_keys(self, user_name, marker=None, max_items=None):
|
||||||
user = self.get_user(user_name)
|
user = self.get_user(user_name)
|
||||||
keys = user.get_all_access_keys()
|
keys = user.get_all_access_keys()
|
||||||
|
@ -454,9 +454,14 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
return template.render(name='UpdateAccessKey')
|
return template.render(name='UpdateAccessKey')
|
||||||
|
|
||||||
|
def get_access_key_last_used(self):
|
||||||
|
access_key_id = self._get_param('AccessKeyId')
|
||||||
|
last_used_response = iam_backend.get_access_key_last_used(access_key_id)
|
||||||
|
template = self.response_template(GET_ACCESS_KEY_LAST_USED_TEMPLATE)
|
||||||
|
return template.render(user_name=last_used_response["user_name"], last_used=last_used_response["last_used"])
|
||||||
|
|
||||||
def list_access_keys(self):
|
def list_access_keys(self):
|
||||||
user_name = self._get_param('UserName')
|
user_name = self._get_param('UserName')
|
||||||
|
|
||||||
keys = iam_backend.get_all_access_keys(user_name)
|
keys = iam_backend.get_all_access_keys(user_name)
|
||||||
template = self.response_template(LIST_ACCESS_KEYS_TEMPLATE)
|
template = self.response_template(LIST_ACCESS_KEYS_TEMPLATE)
|
||||||
return template.render(user_name=user_name, keys=keys)
|
return template.render(user_name=user_name, keys=keys)
|
||||||
@ -1308,6 +1313,18 @@ LIST_ACCESS_KEYS_TEMPLATE = """<ListAccessKeysResponse>
|
|||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</ListAccessKeysResponse>"""
|
</ListAccessKeysResponse>"""
|
||||||
|
|
||||||
|
|
||||||
|
GET_ACCESS_KEY_LAST_USED_TEMPLATE = """
|
||||||
|
<GetAccessKeyLastUsedResponse>
|
||||||
|
<GetAccessKeyLastUsedResult>
|
||||||
|
<UserName>{{ user_name }}</UserName>
|
||||||
|
<AccessKeyLastUsed>
|
||||||
|
<LastUsedDate>{{ last_used }}</LastUsedDate>
|
||||||
|
</AccessKeyLastUsed>
|
||||||
|
</GetAccessKeyLastUsedResult>
|
||||||
|
</GetAccessKeyLastUsedResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
CREDENTIAL_REPORT_GENERATING = """
|
CREDENTIAL_REPORT_GENERATING = """
|
||||||
<GenerateCredentialReportResponse>
|
<GenerateCredentialReportResponse>
|
||||||
<GenerateCredentialReportResult>
|
<GenerateCredentialReportResult>
|
||||||
|
@ -13,6 +13,7 @@ from moto.iam.models import aws_managed_policies
|
|||||||
from nose.tools import assert_raises, assert_equals
|
from nose.tools import assert_raises, assert_equals
|
||||||
from nose.tools import raises
|
from nose.tools import raises
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from tests.helpers import requires_boto_gte
|
from tests.helpers import requires_boto_gte
|
||||||
|
|
||||||
|
|
||||||
@ -735,6 +736,24 @@ def test_update_access_key():
|
|||||||
resp['AccessKeyMetadata'][0]['Status'].should.equal('Inactive')
|
resp['AccessKeyMetadata'][0]['Status'].should.equal('Inactive')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_get_access_key_last_used():
|
||||||
|
iam = boto3.resource('iam', region_name='us-east-1')
|
||||||
|
client = iam.meta.client
|
||||||
|
username = 'test-user'
|
||||||
|
iam.create_user(UserName=username)
|
||||||
|
with assert_raises(ClientError):
|
||||||
|
client.get_access_key_last_used(AccessKeyId='non-existent-key-id')
|
||||||
|
create_key_response = client.create_access_key(UserName=username)['AccessKey']
|
||||||
|
resp = client.get_access_key_last_used(AccessKeyId=create_key_response['AccessKeyId'])
|
||||||
|
|
||||||
|
datetime.strftime(resp["AccessKeyLastUsed"]["LastUsedDate"], "%Y-%m-%d").should.equal(datetime.strftime(
|
||||||
|
datetime.utcnow(),
|
||||||
|
"%Y-%m-%d"
|
||||||
|
))
|
||||||
|
resp["UserName"].should.equal(create_key_response["UserName"])
|
||||||
|
|
||||||
|
|
||||||
@mock_iam
|
@mock_iam
|
||||||
def test_get_account_authorization_details():
|
def test_get_account_authorization_details():
|
||||||
import json
|
import json
|
||||||
|
Loading…
Reference in New Issue
Block a user