Merge pull request #881 from smarlowucf/master
Add mfa device endpoints to iam backend.
This commit is contained in:
commit
42f6487c88
@ -11,6 +11,19 @@ from .utils import random_access_key, random_alphanumeric, random_resource_id, r
|
|||||||
ACCOUNT_ID = 123456789012
|
ACCOUNT_ID = 123456789012
|
||||||
|
|
||||||
|
|
||||||
|
class MFADevice(object):
|
||||||
|
"""MFA Device class."""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2):
|
||||||
|
self.enable_date = datetime.now(pytz.utc)
|
||||||
|
self.serial_number = serial_number
|
||||||
|
self.authentication_code_1 = authentication_code_1
|
||||||
|
self.authentication_code_2 = authentication_code_2
|
||||||
|
|
||||||
|
|
||||||
class Policy(BaseModel):
|
class Policy(BaseModel):
|
||||||
|
|
||||||
is_attachable = False
|
is_attachable = False
|
||||||
@ -226,6 +239,7 @@ class User(BaseModel):
|
|||||||
datetime.utcnow(),
|
datetime.utcnow(),
|
||||||
"%Y-%m-%d-%H-%M-%S"
|
"%Y-%m-%d-%H-%M-%S"
|
||||||
)
|
)
|
||||||
|
self.mfa_devices = {}
|
||||||
self.policies = {}
|
self.policies = {}
|
||||||
self.access_keys = []
|
self.access_keys = []
|
||||||
self.password = None
|
self.password = None
|
||||||
@ -251,6 +265,9 @@ class User(BaseModel):
|
|||||||
def put_policy(self, policy_name, policy_json):
|
def put_policy(self, policy_name, policy_json):
|
||||||
self.policies[policy_name] = policy_json
|
self.policies[policy_name] = policy_json
|
||||||
|
|
||||||
|
def deactivate_mfa_device(self, serial_number):
|
||||||
|
self.mfa_devices.pop(serial_number)
|
||||||
|
|
||||||
def delete_policy(self, policy_name):
|
def delete_policy(self, policy_name):
|
||||||
if policy_name not in self.policies:
|
if policy_name not in self.policies:
|
||||||
raise IAMNotFoundException(
|
raise IAMNotFoundException(
|
||||||
@ -263,6 +280,16 @@ class User(BaseModel):
|
|||||||
self.access_keys.append(access_key)
|
self.access_keys.append(access_key)
|
||||||
return access_key
|
return access_key
|
||||||
|
|
||||||
|
def enable_mfa_device(self,
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2):
|
||||||
|
self.mfa_devices[serial_number] = MFADevice(
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2
|
||||||
|
)
|
||||||
|
|
||||||
def get_all_access_keys(self):
|
def get_all_access_keys(self):
|
||||||
return self.access_keys
|
return self.access_keys
|
||||||
|
|
||||||
@ -724,6 +751,39 @@ class IAMBackend(BaseBackend):
|
|||||||
user = self.get_user(user_name)
|
user = self.get_user(user_name)
|
||||||
user.delete_access_key(access_key_id)
|
user.delete_access_key(access_key_id)
|
||||||
|
|
||||||
|
def enable_mfa_device(self,
|
||||||
|
user_name,
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2):
|
||||||
|
"""Enable MFA Device for user."""
|
||||||
|
user = self.get_user(user_name)
|
||||||
|
if serial_number in user.mfa_devices:
|
||||||
|
raise IAMConflictException(
|
||||||
|
"EntityAlreadyExists",
|
||||||
|
"Device {0} already exists".format(serial_number)
|
||||||
|
)
|
||||||
|
|
||||||
|
user.enable_mfa_device(
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2
|
||||||
|
)
|
||||||
|
|
||||||
|
def deactivate_mfa_device(self, user_name, serial_number):
|
||||||
|
"""Deactivate and detach MFA Device from user if device exists."""
|
||||||
|
user = self.get_user(user_name)
|
||||||
|
if serial_number not in user.mfa_devices:
|
||||||
|
raise IAMNotFoundException(
|
||||||
|
"Device {0} not found".format(serial_number)
|
||||||
|
)
|
||||||
|
|
||||||
|
user.deactivate_mfa_device(serial_number)
|
||||||
|
|
||||||
|
def list_mfa_devices(self, user_name):
|
||||||
|
user = self.get_user(user_name)
|
||||||
|
return user.mfa_devices.values()
|
||||||
|
|
||||||
def delete_user(self, user_name):
|
def delete_user(self, user_name):
|
||||||
try:
|
try:
|
||||||
del self.users[user_name]
|
del self.users[user_name]
|
||||||
|
@ -326,6 +326,35 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
return template.render(name='DeleteAccessKey')
|
return template.render(name='DeleteAccessKey')
|
||||||
|
|
||||||
|
def deactivate_mfa_device(self):
|
||||||
|
user_name = self._get_param('UserName')
|
||||||
|
serial_number = self._get_param('SerialNumber')
|
||||||
|
|
||||||
|
iam_backend.deactivate_mfa_device(user_name, serial_number)
|
||||||
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
|
return template.render(name='DeactivateMFADevice')
|
||||||
|
|
||||||
|
def enable_mfa_device(self):
|
||||||
|
user_name = self._get_param('UserName')
|
||||||
|
serial_number = self._get_param('SerialNumber')
|
||||||
|
authentication_code_1 = self._get_param('AuthenticationCode1')
|
||||||
|
authentication_code_2 = self._get_param('AuthenticationCode2')
|
||||||
|
|
||||||
|
iam_backend.enable_mfa_device(
|
||||||
|
user_name,
|
||||||
|
serial_number,
|
||||||
|
authentication_code_1,
|
||||||
|
authentication_code_2
|
||||||
|
)
|
||||||
|
template = self.response_template(GENERIC_EMPTY_TEMPLATE)
|
||||||
|
return template.render(name='EnableMFADevice')
|
||||||
|
|
||||||
|
def list_mfa_devices(self):
|
||||||
|
user_name = self._get_param('UserName')
|
||||||
|
devices = iam_backend.list_mfa_devices(user_name)
|
||||||
|
template = self.response_template(LIST_MFA_DEVICES_TEMPLATE)
|
||||||
|
return template.render(user_name=user_name, devices=devices)
|
||||||
|
|
||||||
def delete_user(self):
|
def delete_user(self):
|
||||||
user_name = self._get_param('UserName')
|
user_name = self._get_param('UserName')
|
||||||
iam_backend.delete_user(user_name)
|
iam_backend.delete_user(user_name)
|
||||||
@ -922,3 +951,20 @@ LIST_INSTANCE_PROFILES_FOR_ROLE_TEMPLATE = """<ListInstanceProfilesForRoleRespon
|
|||||||
<RequestId>6a8c3992-99f4-11e1-a4c3-27EXAMPLE804</RequestId>
|
<RequestId>6a8c3992-99f4-11e1-a4c3-27EXAMPLE804</RequestId>
|
||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</ListInstanceProfilesForRoleResponse>"""
|
</ListInstanceProfilesForRoleResponse>"""
|
||||||
|
|
||||||
|
LIST_MFA_DEVICES_TEMPLATE = """<ListMFADevicesResponse>
|
||||||
|
<ListMFADevicesResult>
|
||||||
|
<MFADevices>
|
||||||
|
{% for device in devices %}
|
||||||
|
<member>
|
||||||
|
<UserName>{{ user_name }}</UserName>
|
||||||
|
<SerialNumber>{{ device.serial_number }}</SerialNumber>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</MFADevices>
|
||||||
|
<IsTruncated>false</IsTruncated>
|
||||||
|
</ListMFADevicesResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ListMFADevicesResponse>"""
|
||||||
|
@ -292,6 +292,29 @@ def test_delete_access_key():
|
|||||||
conn.delete_access_key(access_key_id, 'my-user')
|
conn.delete_access_key(access_key_id, 'my-user')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam()
|
||||||
|
def test_mfa_devices():
|
||||||
|
# Test enable device
|
||||||
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
conn.create_user(UserName='my-user')
|
||||||
|
conn.enable_mfa_device(
|
||||||
|
UserName='my-user',
|
||||||
|
SerialNumber='123456789',
|
||||||
|
AuthenticationCode1='234567',
|
||||||
|
AuthenticationCode2='987654'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test list mfa devices
|
||||||
|
response = conn.list_mfa_devices(UserName='my-user')
|
||||||
|
device = response['MFADevices'][0]
|
||||||
|
device['SerialNumber'].should.equal('123456789')
|
||||||
|
|
||||||
|
# Test deactivate mfa device
|
||||||
|
conn.deactivate_mfa_device(UserName='my-user', SerialNumber='123456789')
|
||||||
|
response = conn.list_mfa_devices(UserName='my-user')
|
||||||
|
len(response['MFADevices']).should.equal(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_iam_deprecated()
|
@mock_iam_deprecated()
|
||||||
def test_delete_user():
|
def test_delete_user():
|
||||||
conn = boto.connect_iam()
|
conn = boto.connect_iam()
|
||||||
|
Loading…
Reference in New Issue
Block a user