Beispiel #1
0
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)
Beispiel #2
0
    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
        )
Beispiel #3
0
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)
Beispiel #4
0
    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)