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] enable_mfa_device | ||||
| - [ ] generate_credential_report | ||||
| - [ ] get_access_key_last_used | ||||
| - [X] get_access_key_last_used | ||||
| - [X] get_account_authorization_details | ||||
| - [ ] get_account_password_policy | ||||
| - [ ] get_account_summary | ||||
|  | ||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -19,6 +19,7 @@ test: lint | ||||
| 	rm -f .coverage | ||||
| 	rm -rf cover | ||||
| 	@nosetests -sv --with-coverage --cover-html ./tests/ $(TEST_EXCLUDE) | ||||
| 
 | ||||
| test_server: | ||||
| 	@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/ | ||||
| 
 | ||||
|  | ||||
| @ -250,6 +250,10 @@ class AccessKey(BaseModel): | ||||
|             datetime.utcnow(), | ||||
|             "%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): | ||||
|         from moto.cloudformation.exceptions import UnformattedGetAttTemplateException | ||||
| @ -379,21 +383,20 @@ class User(BaseModel): | ||||
|         return self.access_keys | ||||
| 
 | ||||
|     def delete_access_key(self, access_key_id): | ||||
|         for key in self.access_keys: | ||||
|             if key.access_key_id == access_key_id: | ||||
|                 self.access_keys.remove(key) | ||||
|                 break | ||||
|         else: | ||||
|             raise IAMNotFoundException( | ||||
|                 "Key {0} not found".format(access_key_id)) | ||||
|         key = self.get_access_key_by_id(access_key_id) | ||||
|         self.access_keys.remove(key) | ||||
| 
 | ||||
|     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: | ||||
|             if key.access_key_id == access_key_id: | ||||
|                 key.status = status | ||||
|                 break | ||||
|                 return key | ||||
|         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): | ||||
|         from moto.cloudformation.exceptions import UnformattedGetAttTemplateException | ||||
| @ -908,6 +911,24 @@ class IAMBackend(BaseBackend): | ||||
|         user = self.get_user(user_name) | ||||
|         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): | ||||
|         user = self.get_user(user_name) | ||||
|         keys = user.get_all_access_keys() | ||||
|  | ||||
| @ -454,9 +454,14 @@ class IamResponse(BaseResponse): | ||||
|         template = self.response_template(GENERIC_EMPTY_TEMPLATE) | ||||
|         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): | ||||
|         user_name = self._get_param('UserName') | ||||
| 
 | ||||
|         keys = iam_backend.get_all_access_keys(user_name) | ||||
|         template = self.response_template(LIST_ACCESS_KEYS_TEMPLATE) | ||||
|         return template.render(user_name=user_name, keys=keys) | ||||
| @ -1308,6 +1313,18 @@ LIST_ACCESS_KEYS_TEMPLATE = """<ListAccessKeysResponse> | ||||
|    </ResponseMetadata> | ||||
| </ListAccessKeysResponse>""" | ||||
| 
 | ||||
| 
 | ||||
| GET_ACCESS_KEY_LAST_USED_TEMPLATE = """ | ||||
| <GetAccessKeyLastUsedResponse> | ||||
|     <GetAccessKeyLastUsedResult> | ||||
|         <UserName>{{ user_name }}</UserName> | ||||
|         <AccessKeyLastUsed> | ||||
|             <LastUsedDate>{{ last_used }}</LastUsedDate> | ||||
|         </AccessKeyLastUsed> | ||||
|     </GetAccessKeyLastUsedResult> | ||||
| </GetAccessKeyLastUsedResponse> | ||||
| """ | ||||
| 
 | ||||
| CREDENTIAL_REPORT_GENERATING = """ | ||||
| <GenerateCredentialReportResponse> | ||||
|     <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 raises | ||||
| 
 | ||||
| from datetime import datetime | ||||
| from tests.helpers import requires_boto_gte | ||||
| 
 | ||||
| 
 | ||||
| @ -735,6 +736,24 @@ def test_update_access_key(): | ||||
|     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 | ||||
| def test_get_account_authorization_details(): | ||||
|     import json | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user