Browse files

Added support for MFA in AssumeRole.

  • Loading branch information...
1 parent 3b96965 commit aff22a733278107d9b175356a1c92c7a5988e15e @toastdriven toastdriven committed Feb 18, 2014
Showing with 49 additions and 2 deletions.
  1. +25 −1 boto/sts/connection.py
  2. +1 −1 tests/integration/sts/test_session_token.py
  3. +23 −0 tests/unit/sts/test_connection.py
View
26 boto/sts/connection.py
@@ -238,7 +238,9 @@ def get_federation_token(self, name, duration=None, policy=None):
FederationToken, verb='POST')
def assume_role(self, role_arn, role_session_name, policy=None,
- duration_seconds=None, external_id=None):
+ duration_seconds=None, external_id=None,
+ mfa_serial_number=None,
+ mfa_token=None):
"""
Returns a set of temporary security credentials (consisting of
an access key ID, a secret access key, and a security token)
@@ -328,6 +330,24 @@ def assume_role(self, role_arn, role_session_name, policy=None,
information about the external ID, see `About the External ID`_ in
Using Temporary Security Credentials .
+ :type mfa_serial_number: string
+ :param mfa_serial_number: The identification number of the MFA device that
+ is associated with the user who is making the AssumeRole call.
+ Specify this value if the trust policy of the role being assumed
+ includes a condition that requires MFA authentication. The value is
+ either the serial number for a hardware device (such as
+ GAHT12345678) or an Amazon Resource Name (ARN) for a virtual device
+ (such as arn:aws:iam::123456789012:mfa/user). Minimum length of 9.
+ Maximum length of 256.
+
+ :type mfa_token: string
+ :param mfa_token: The value provided by the MFA device, if the trust
+ policy of the role being assumed requires MFA (that is, if the
+ policy includes a condition that tests for MFA). If the role being
+ assumed requires MFA and if the TokenCode value is missing or
+ expired, the AssumeRole call returns an "access denied" errror.
+ Minimum length of 6. Maximum length of 6.
+
"""
params = {
'RoleArn': role_arn,
@@ -339,6 +359,10 @@ def assume_role(self, role_arn, role_session_name, policy=None,
params['DurationSeconds'] = duration_seconds
if external_id is not None:
params['ExternalId'] = external_id
+ if mfa_serial_number is not None:
+ params['SerialNumber'] = mfa_serial_number
+ if mfa_token is not None:
+ params['TokenCode'] = mfa_token
return self.get_object('AssumeRole', params, AssumedRole, verb='POST')
def assume_role_with_saml(self, role_arn, principal_arn, saml_assertion,
View
2 tests/integration/sts/test_session_token.py
@@ -33,7 +33,7 @@
from boto.s3.connection import S3Connection
-class SessionTokenTest (unittest.TestCase):
+class SessionTokenTest(unittest.TestCase):
sts = True
def test_session_token(self):
View
23 tests/unit/sts/test_connection.py
@@ -81,6 +81,29 @@ def test_assume_role(self):
self.assertEqual(response.user.arn, 'arn:role')
self.assertEqual(response.user.assume_role_id, 'roleid:myrolesession')
+ def test_assume_role_with_mfa(self):
+ self.set_http_response(status_code=200)
+ response = self.service_connection.assume_role(
+ 'arn:role',
+ 'mysession',
+ mfa_serial_number='GAHT12345678',
+ mfa_token='abc123'
+ )
+ self.assert_request_parameters(
+ {'Action': 'AssumeRole',
+ 'RoleArn': 'arn:role',
+ 'RoleSessionName': 'mysession',
+ 'SerialNumber': 'GAHT12345678',
+ 'TokenCode': 'abc123'},
+ ignore_params_values=['Timestamp', 'AWSAccessKeyId',
+ 'SignatureMethod', 'SignatureVersion',
+ 'Version'])
+ self.assertEqual(response.credentials.access_key, 'accesskey')
+ self.assertEqual(response.credentials.secret_key, 'secretkey')
+ self.assertEqual(response.credentials.session_token, 'session_token')
+ self.assertEqual(response.user.arn, 'arn:role')
+ self.assertEqual(response.user.assume_role_id, 'roleid:myrolesession')
+
class TestSTSWebIdentityConnection(AWSMockServiceTestCase):
connection_class = STSConnection

0 comments on commit aff22a7

Please sign in to comment.