Fix saml-assertion parsing in assume-role-with-saml (#3523)
* Retrieve SAML Attribute by Name instead of relying on order which is too fragile * Handle case when SAML Attribute SessionDuration is not provided, as it is not a required attribute from SAML response When session duration not provided, AWS consider by default a duration of one hour as cited in the following documentation: "If this attribute is not present, then the credential last for one hour (the default value of the DurationSeconds parameter of the AssumeRoleWithSAML API)." https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html#saml_role-session-duration Traceback was: [...] File "/Users/benjamin.brabant/Projects/PERSO/moto/moto/sts/responses.py", line 79, in assume_role_with_saml role = sts_backend.assume_role_with_saml( File "/Users/benjamin.brabant/Projects/PERSO/moto/moto/sts/models.py", line 99, in assume_role_with_saml role = AssumedRole(**kwargs) TypeError: __init__() missing 1 required positional argument: 'duration' * Process saml xml namespaces properly instead of relying on textual prefix that can vary between identity providers * Handle when SAML response AttributeValue xml tag contains attributes that force xmltodict to build a dictionary as for complex types instead of directly returning string value Leverage force_cdata option of xmltodict parser that always return a complex dictionary even if xml tag contains only text and no attributes. * Improve existing test_assume_role_with_saml to be coherent with other assume_role_with_saml tests and remove dead code at the same time
This commit is contained in:
parent
af60306371
commit
7c7a1222d2
3 changed files with 431 additions and 30 deletions
|
|
@ -10,6 +10,7 @@ from moto.sts.utils import (
|
|||
random_secret_access_key,
|
||||
random_session_token,
|
||||
random_assumed_role_id,
|
||||
DEFAULT_STS_SESSION_DURATION,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -85,15 +86,36 @@ class STSBackend(BaseBackend):
|
|||
del kwargs["principal_arn"]
|
||||
saml_assertion_encoded = kwargs.pop("saml_assertion")
|
||||
saml_assertion_decoded = b64decode(saml_assertion_encoded)
|
||||
saml_assertion = xmltodict.parse(saml_assertion_decoded.decode("utf-8"))
|
||||
kwargs["duration"] = int(
|
||||
saml_assertion["samlp:Response"]["Assertion"]["AttributeStatement"][
|
||||
"Attribute"
|
||||
][2]["AttributeValue"]
|
||||
|
||||
namespaces = {
|
||||
"urn:oasis:names:tc:SAML:2.0:protocol": "samlp",
|
||||
"urn:oasis:names:tc:SAML:2.0:assertion": "saml",
|
||||
}
|
||||
saml_assertion = xmltodict.parse(
|
||||
saml_assertion_decoded.decode("utf-8"),
|
||||
force_cdata=True,
|
||||
process_namespaces=True,
|
||||
namespaces=namespaces,
|
||||
)
|
||||
kwargs["role_session_name"] = saml_assertion["samlp:Response"]["Assertion"][
|
||||
"AttributeStatement"
|
||||
]["Attribute"][0]["AttributeValue"]
|
||||
|
||||
saml_assertion_attributes = saml_assertion["samlp:Response"]["saml:Assertion"][
|
||||
"saml:AttributeStatement"
|
||||
]["saml:Attribute"]
|
||||
for attribute in saml_assertion_attributes:
|
||||
if (
|
||||
attribute["@Name"]
|
||||
== "https://aws.amazon.com/SAML/Attributes/RoleSessionName"
|
||||
):
|
||||
kwargs["role_session_name"] = attribute["saml:AttributeValue"]["#text"]
|
||||
if (
|
||||
attribute["@Name"]
|
||||
== "https://aws.amazon.com/SAML/Attributes/SessionDuration"
|
||||
):
|
||||
kwargs["duration"] = int(attribute["saml:AttributeValue"]["#text"])
|
||||
|
||||
if "duration" not in kwargs:
|
||||
kwargs["duration"] = DEFAULT_STS_SESSION_DURATION
|
||||
|
||||
kwargs["external_id"] = None
|
||||
kwargs["policy"] = None
|
||||
role = AssumedRole(**kwargs)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import six
|
|||
ACCOUNT_SPECIFIC_ACCESS_KEY_PREFIX = "8NWMTLYQ"
|
||||
ACCOUNT_SPECIFIC_ASSUMED_ROLE_ID_PREFIX = "3X42LBCD"
|
||||
SESSION_TOKEN_PREFIX = "FQoGZXIvYXdzEBYaD"
|
||||
DEFAULT_STS_SESSION_DURATION = 3600
|
||||
|
||||
|
||||
def random_access_key_id():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue