def save_sts_token(session: Session, client: boto3.client, saml: str, role: Role, duration: int = 0) -> datetime: params = dict( RoleArn=role[1], PrincipalArn=role[0], SAMLAssertion=saml, ) if duration: # Mypy reports that DurationSeconds should be a string but # botocore dies unless it is an int so ignore mypy. params['DurationSeconds'] = duration # type: ignore[assignment] # duration is optional and can be set by the role; # avoid passing if not set. token = client.assume_role_with_saml(**params) logger.info("Retrieved temporary Amazon credentials for role: " + role[1]) return save_credentials(session, token)
def _assume_role_with_saml( self, sts_client: boto3.client, role_arn: str, assume_role_kwargs: Dict[str, Any] ) -> Dict[str, Any]: saml_config = self.extra_config['assume_role_with_saml'] principal_arn = saml_config['principal_arn'] idp_auth_method = saml_config['idp_auth_method'] if idp_auth_method == 'http_spegno_auth': saml_assertion = self._fetch_saml_assertion_using_http_spegno_auth(saml_config) else: raise NotImplementedError( f'idp_auth_method={idp_auth_method} in Connection {self.conn.conn_id} Extra.' 'Currently only "http_spegno_auth" is supported, and must be specified.' ) self.log.info("Doing sts_client.assume_role_with_saml to role_arn=%s", role_arn) return sts_client.assume_role_with_saml( RoleArn=role_arn, PrincipalArn=principal_arn, SAMLAssertion=saml_assertion, **assume_role_kwargs )
def save_sts_token(session: Session, client: boto3.client, saml: str, role: Role, duration: int = 0) -> datetime: params = dict( RoleArn=role[1], PrincipalArn=role[0], SAMLAssertion=saml, ) if duration: params['DurationSeconds'] = str(duration) # duration is optional and can be set by the role; # avoid passing if not set. token = client.assume_role_with_saml(**params) logger.info("Retrieved temporary Amazon credentials for role: " + role[1]) return save_credentials(session, token)
def _assume_role_with_saml(self, sts_client: boto3.client, extra_config: dict, role_arn: str, assume_role_kwargs: dict): saml_config = extra_config['assume_role_with_saml'] principal_arn = saml_config['principal_arn'] idp_url = saml_config["idp_url"] self.log.info("idp_url= %s", idp_url) idp_request_kwargs = saml_config["idp_request_kwargs"] idp_auth_method = saml_config['idp_auth_method'] if idp_auth_method == 'http_spegno_auth': # requests_gssapi will need paramiko > 2.6 since you'll need # 'gssapi' not 'python-gssapi' from PyPi. # https://github.com/paramiko/paramiko/pull/1311 import requests_gssapi auth = requests_gssapi.HTTPSPNEGOAuth() if 'mutual_authentication' in saml_config: mutual_auth = saml_config['mutual_authentication'] if mutual_auth == 'REQUIRED': auth = requests_gssapi.HTTPSPNEGOAuth( requests_gssapi.REQUIRED) elif mutual_auth == 'OPTIONAL': auth = requests_gssapi.HTTPSPNEGOAuth( requests_gssapi.OPTIONAL) elif mutual_auth == 'DISABLED': auth = requests_gssapi.HTTPSPNEGOAuth( requests_gssapi.DISABLED) else: raise NotImplementedError( f'mutual_authentication={mutual_auth} in Connection {self.aws_conn_id} Extra.' 'Currently "REQUIRED", "OPTIONAL" and "DISABLED" are supported.' '(Exclude this setting will default to HTTPSPNEGOAuth() ).' ) # Query the IDP import requests idp_reponse = requests.get(idp_url, auth=auth, **idp_request_kwargs) idp_reponse.raise_for_status() # Assist with debugging. Note: contains sensitive info! xpath = saml_config['saml_response_xpath'] log_idp_response = 'log_idp_response' in saml_config and saml_config[ 'log_idp_response'] if log_idp_response: self.log.warning( 'The IDP response contains sensitive information,' ' but log_idp_response is ON (%s).', log_idp_response) self.log.info('idp_reponse.content= %s', idp_reponse.content) self.log.info('xpath= %s', xpath) # Extract SAML Assertion from the returned HTML / XML from lxml import etree xml = etree.fromstring(idp_reponse.content) saml_assertion = xml.xpath(xpath) if isinstance(saml_assertion, list): if len(saml_assertion) == 1: saml_assertion = saml_assertion[0] if not saml_assertion: raise ValueError('Invalid SAML Assertion') else: raise NotImplementedError( f'idp_auth_method={idp_auth_method} in Connection {self.aws_conn_id} Extra.' 'Currently only "http_spegno_auth" is supported, and must be specified.' ) self.log.info("Doing sts_client.assume_role_with_saml to role_arn=%s", role_arn) return sts_client.assume_role_with_saml(RoleArn=role_arn, PrincipalArn=principal_arn, SAMLAssertion=saml_assertion, **assume_role_kwargs)