Example #1
0
    def _create_s3_client(self, loc):
        """Create a client object to use when connecting to S3.

        :param loc: `glance_store.location.Location` object, supplied
                    from glance_store.location.get_location_from_uri()
        :returns: An object with credentials to connect to S3
        """
        s3_host = self._option_get('s3_store_host')
        url_format = self._option_get('s3_store_bucket_url_format')
        calling_format = {'addressing_style': url_format}

        session = boto_session.Session(aws_access_key_id=loc.accesskey,
                                       aws_secret_access_key=loc.secretkey)
        config = boto_client.Config(s3=calling_format)
        location = get_s3_location(s3_host)

        bucket_name = loc.bucket
        if (url_format == 'virtual'
                and not boto_utils.check_dns_name(bucket_name)):
            raise boto_exceptions.InvalidDNSNameError(bucket_name=bucket_name)

        region_name, endpoint_url = None, None
        if location:
            region_name = location
        else:
            endpoint_url = s3_host

        return session.client(service_name='s3',
                              endpoint_url=endpoint_url,
                              region_name=region_name,
                              use_ssl=(loc.scheme == 's3+https'),
                              config=config)
Example #2
0
 def __init__(self, buckets_info):
     boto_config = client.Config(
         connect_timeout=self.BOTO_TIMEOUT,
         read_timeout=self.BOTO_TIMEOUT
     )
     self._s3_client = boto3.resource('s3', config=boto_config)
     self._buckets_info = buckets_info
Example #3
0
    def test_create_client_with_merging_client_configs(self, client_creator):
        config = client.Config(region_name='us-west-2')
        other_config = client.Config(region_name='us-east-1')
        self.session.set_default_client_config(config)
        self.session.create_client('sts', config=other_config)

        # Grab the client config used in creating the client
        used_client_config = (
            client_creator.return_value.create_client.call_args[1][
                'client_config'])
        # Check that the client configs were merged
        self.assertEqual(used_client_config.region_name, 'us-east-1')
        # Make sure that the client config used is not the default client
        # config or the one passed in. It should be a new config.
        self.assertIsNot(used_client_config, config)
        self.assertIsNot(used_client_config, other_config)
Example #4
0
File: aws.py Project: zshell/shimit
 def assume_role(cls,
                 role_arn,
                 principal_arn,
                 saml_response,
                 duration=3600):
     ''' Assumes the desired role using the saml_response given. The response should be b64 encoded.
         Duration is in seconds
         :param role_arn: role amazon resource name
         :param principal_arn: principal name
         :param saml_response: SAML object to assume role with
         :param duration: session duration (default: 3600)
         :return: AWS session token
     '''
     # Assume role with new SAML
     conn = boto3.client('sts',
                         config=client.Config(
                             signature_version=botocore.UNSIGNED,
                             user_agent=cls.USER_AGENT,
                             region_name=None))
     aws_session_token = conn.assume_role_with_saml(
         RoleArn=role_arn,
         PrincipalArn=principal_arn,
         SAMLAssertion=saml_response,
         DurationSeconds=duration,
     )
     return aws_session_token
Example #5
0
def default_config(timeout=BOTO_TIMEOUT, region=REGION):
    return client.Config(
        connect_timeout=timeout,
        read_timeout=timeout,
        region_name=region
        if region else REGION  # Ensure region is never empty
    )
Example #6
0
 def test_client_with_custom_read_timeout(self):
     self.create_client_creator().create_client(
         'myservice',
         'us-west-2',
         client_config=client.Config(read_timeout=234))
     call_kwargs = self.endpoint_creator.create_endpoint.call_args[1]
     self.assertEqual(call_kwargs['timeout'], (DEFAULT_TIMEOUT, 234))
Example #7
0
    def __init__(self, config):
        """
        :param config:
            be complied with cup.util.conf.Configure2Dict().get_dict().
            Shoule be dict like object

        :raise:
            cup.err.ConfigError if there's any config item missing
        """
        ObjectInterface.__init__(self, config)
        required_keys = ['ak', 'sk', 'endpoint', 'bucket']
        if not self._validate_config(config, required_keys):
            raise err.ConfigError(str(required_keys))
        self._config = config
        self._ak = self._config['ak']
        self._sk = self._config['sk']
        self._endpoint = self._config['endpoint']
        self._bucket = self._config['bucket']
        import boto3
        from botocore import exceptions
        from botocore import client as coreclient
        self._s3_config = coreclient.Config(signature_version='s3v4',
                                            s3={'addressing_style': 'path'})
        logging.getLogger('boto3').setLevel(logging.INFO)
        logging.getLogger('botocore').setLevel(logging.INFO)
        logging.getLogger('s3transfer').setLevel(logging.INFO)
        log.info('to connect to boto3')
        self.__s3conn = boto3.client(
            's3',
            aws_access_key_id=self._ak,
            aws_secret_access_key=self._sk,
            endpoint_url=self._endpoint,
            # region_name=conf_dict['region_name'],
            config=self._s3_config)
        self._exception = exceptions.ClientError
Example #8
0
 def test_client_region_overrides_region_from_client_config(self):
     client_config = client.Config()
     client_config.region_name = 'us-west-1'
     creator = self.create_client_creator()
     service_client = creator.create_client('myservice',
                                            'us-west-2',
                                            client_config=client_config)
     self.assertEqual(service_client.meta.region_name, 'us-west-2')
Example #9
0
 def test_client_with_custom_both_timeout(self):
     self.create_client_creator().create_client('myservice',
                                                'us-west-2',
                                                client_config=client.Config(
                                                    connect_timeout=123,
                                                    read_timeout=234))
     call_kwargs = self.endpoint_creator.create_endpoint.call_args[1]
     self.assertEqual(call_kwargs['timeout'], (123, 234))
Example #10
0
    def test_create_client_with_default_client_config(self, client_creator):
        config = client.Config()
        self.session.set_default_client_config(config)
        self.session.create_client('sts')

        client_creator.return_value.create_client.assert_called_with(
            mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
            scoped_config=mock.ANY, client_config=config,
            api_version=mock.ANY)
def assume_role(account_role, samlAssertion, sessionDuration):
    conn = boto3.client('sts', config=client.Config(signature_version=botocore.UNSIGNED))
    aws_session_token = conn.assume_role_with_saml(
        RoleArn=account_role.role_arn,
        PrincipalArn=account_role.principal_arn,
        SAMLAssertion=samlAssertion,
        DurationSeconds=sessionDuration
    )

    return aws_session_token
Example #12
0
    def test_config_passed_to_client_creator(self, client_creator):
        # Make sure there is no default set
        self.assertEqual(self.session.get_default_client_config(), None)

        # The config passed to the client should be the one that is used
        # in creating the client.
        config = client.Config(region_name='us-west-2')
        self.session.create_client('sts', config=config)
        client_creator.return_value.create_client.assert_called_with(
            mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
            scoped_config=mock.ANY, client_config=config,
            api_version=mock.ANY)
Example #13
0
    def test_config_passed_to_client_creator(self, client_creator):
        config = client.Config()
        self.session.create_client('sts', config=config)

        client_creator.return_value.create_client.assert_called_with(
            mock.ANY,
            mock.ANY,
            mock.ANY,
            mock.ANY,
            mock.ANY,
            mock.ANY,
            scoped_config=mock.ANY,
            client_config=config)
Example #14
0
    def __init__(self, region, firehose_config=None, log_sources=None):
        boto_config = client.Config(
            connect_timeout=self.BOTO_TIMEOUT,
            read_timeout=self.BOTO_TIMEOUT,
            region_name=region
        )
        self._client = boto3.client('firehose', config=boto_config)
        # Create a dictionary to hold parsed payloads by log type.
        # Firehose needs this information to send to its corresponding
        # delivery stream.
        self._categorized_payloads = defaultdict(list)

        self.load_enabled_log_sources(firehose_config, log_sources, force_load=True)
Example #15
0
def _make_boto3_kinesis_client(container):
    region = container.get_parameter('aws_region')
    logger = container.get('logger')

    config = botocore_client.Config(connect_timeout=5,
                                    read_timeout=5,
                                    region_name=region)

    session_kwargs = {}
    try:
        session = boto3.Session(**session_kwargs)
        return session.client('kinesis', config=config)
    except ProfileNotFound:
        logger.error('AWS Kinesis Connection via Profile Failed')
Example #16
0
    def test_create_client_with_region_and_client_config(self):
        config = client.Config()
        # Use a client config with no region configured.
        ec2_client = self.session.create_client('ec2',
                                                region_name='us-west-2',
                                                config=config)
        self.assertEqual(ec2_client.meta.region_name, 'us-west-2')

        # If the region name is changed, it should not change the
        # region of the client
        config.region_name = 'us-east-1'
        self.assertEqual(ec2_client.meta.region_name, 'us-west-2')

        # Now make a new client with the updated client config.
        ec2_client = self.session.create_client('ec2', config=config)
        self.assertEqual(ec2_client.meta.region_name, 'us-east-1')
Example #17
0
    def _get_parameters(cls, *names):
        """Simple helper function to house the boto3 ssm client get_parameters operations

        Args:
            names (list): A list of parameter names to retrieve from the aws ssm
                parameter store

        Returns:
            tuple (dict, list): Dictionary with the load parameter names as keys
                and the actual parameter (as a dictionary) as the value. The seconary
                list that is returned contains any invalid parameters that were not loaded
        """
        # Create the ssm boto3 client that will be cached and used throughout this execution
        # if one does not exist already
        if AppConfig.SSM_CLIENT is None:
            boto_config = client.Config(connect_timeout=cls.BOTO_TIMEOUT,
                                        read_timeout=cls.BOTO_TIMEOUT)
            AppConfig.SSM_CLIENT = boto3.client('ssm', config=boto_config)

        LOGGER.debug('Retrieving values from parameter store with names: %s',
                     ', '.join('\'{}\''.format(name) for name in names))
        try:
            parameters = AppConfig.SSM_CLIENT.get_parameters(
                Names=list(names), WithDecryption=True)
        except ClientError as err:
            joined_names = ', '.join('\'{}\''.format(name) for name in names)
            raise AppConfigError(
                'Could not get parameter with names {}. Error: '
                '{}'.format(joined_names, err.response['Error']['Message']))

        decoded_params = {}
        for param in parameters['Parameters']:
            try:
                decoded_params[param['Name']] = json.loads(param['Value'])
            except ValueError:
                raise AppConfigError(
                    'Could not load value for parameter with '
                    'name \'{}\'. The value is not valid json: '
                    '\'{}\''.format(param['Name'], param['Value']))

        return decoded_params, parameters['InvalidParameters']
Example #18
0
def login(profile, region, ssl_verification, adfs_ca_bundle, adfs_host,
          output_format, provider_id, s3_signature_version, env, stdin,
          authfile, stdout, printenv, role_arn, session_duration, assertfile,
          sspi, u2f_trigger_default, username, password):
    """
    Authenticates an user with active directory credentials
    """
    config = prepare.get_prepared_config(
        profile,
        region,
        ssl_verification,
        adfs_ca_bundle,
        adfs_host,
        output_format,
        provider_id,
        s3_signature_version,
        session_duration,
        sspi,
        u2f_trigger_default,
    )

    _verification_checks(config)

    # Try re-authenticating using an existing ADFS session
    if username != None and password != None:
        #print(username)
        #print(password)
        #exit(0)
        principal_roles, assertion, aws_session_duration = authenticator.authenticate(
            config,
            username=username,
            password=password,
            assertfile=assertfile)
    else:
        principal_roles, assertion, aws_session_duration = authenticator.authenticate(
            config, assertfile=assertfile)

    #principal_roles, assertion, aws_session_duration = authenticator.authenticate(config, assertfile=assertfile)

    # If we fail to get an assertion, prompt for credentials and try again
    if assertion is None:
        password = None

        if stdin:
            config.adfs_user, password = _stdin_user_credentials()
        elif env:
            config.adfs_user, password = _env_user_credentials()
        elif authfile:
            config.adfs_user, password = _file_user_credentials(
                config.profile, authfile)

        if not config.adfs_user:
            config.adfs_user = click.prompt(text='Username',
                                            type=str,
                                            default=config.adfs_user)

        if not password:
            password = click.prompt('Password', type=str, hide_input=True)

        principal_roles, assertion, aws_session_duration = authenticator.authenticate(
            config, config.adfs_user, password)

        password = '******'
        del password

    if (role_arn is not None):
        config.role_arn = role_arn
    principal_arn, config.role_arn = role_chooser.choose_role_to_assume(
        config, principal_roles)
    if principal_arn is None or config.role_arn is None:
        click.echo('This account does not have access to any roles', err=True)
        exit(-1)

    # Use the assertion to get an AWS STS token using Assume Role with SAML
    # according to the documentation:
    #   http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html
    # This element contains one AttributeValue element that specifies the maximum time that the user
    # can access the AWS Management Console before having to request new temporary credentials.
    # The value is an integer representing the number of seconds, and can be
    # a maximum of 43200 seconds (12 hours). If this attribute is not present,
    # then the maximum session duration defaults to one hour
    # (the default value of the DurationSeconds parameter of the AssumeRoleWithSAML API).
    # To use this attribute, you must configure the SAML provider to provide single sign-on access
    # to the AWS Management Console through the console sign-in web endpoint at
    # https://signin.aws.amazon.com/saml.
    # Note that this attribute extends sessions only to the AWS Management Console.
    # It cannot extend the lifetime of other credentials.
    # However, if it is present in an AssumeRoleWithSAML API call,
    # it can be used to shorten the lifetime of the credentials returned by the call to less than
    # the default of 60 minutes.
    #
    # Note, too, that if a SessionNotOnOrAfter attribute is also defined,
    # then the lesser value of the two attributes, SessionDuration or SessionNotOnOrAfter,
    # establishes the maximum duration of the console session.
    try:
        session = botocore.session.get_session()
        session.set_config_variable('profile', config.profile)
        conn = session.create_client(
            'sts', config=client.Config(signature_version=botocore.UNSIGNED))
    except botocore.exceptions.ProfileNotFound:
        logging.debug('Profile {} does not exist yet'.format(config.profile))
        session = botocore.session.get_session()
        conn = session.create_client(
            'sts', config=client.Config(signature_version=botocore.UNSIGNED))

    aws_session_token = conn.assume_role_with_saml(
        RoleArn=config.role_arn,
        PrincipalArn=principal_arn,
        SAMLAssertion=assertion,
        DurationSeconds=int(config.session_duration),
    )

    if stdout:
        _emit_json(aws_session_token)
    elif printenv:
        _emit_summary(config, aws_session_duration)
        _print_environment_variables(aws_session_token, config)
    else:
        _store(config, aws_session_token)
        _emit_summary(config, aws_session_duration)
Example #19
0
def default_config(timeout=BOTO_TIMEOUT, region=REGION):
    return client.Config(connect_timeout=timeout,
                         read_timeout=timeout,
                         region_name=region)
Example #20
0
    def load_config(cls, context, event):
        """Load the configuration for this app invocation

        Args:
            context (LambdaContext): The AWS LambdaContext object, passed in via the handler.

        Returns:
            AppConfig: Subclassed dictionary with the below structure that contains all of the
                 methods for configuration validation, updating, saving, etc:
                    {
                        'type': <type>,
                        'cluster': <cluster>,
                        'prefix': <prefix>,
                        'app_name': <app_name>,
                        'schedule_expression': <rate_interval>,
                        'region': <aws_region>,
                        'account_id': <aws_account_id>,
                        'function_name': <function_name>,
                        'qualifier': <qualifier>,
                        'last_timestamp': <time>,
                        'current_state': <running|succeeded|failed>,
                        'auth': {
                            'req_auth_item_01': <req_auth_value_01>
                        }
                    }
        """
        # Load the base config from the context that will get updated with other info
        base_config = AppConfig._parse_context(context)

        LOGGER.debug('Loaded env config: %s', base_config)

        # Create the ssm boto3 client that will be cached and used throughout this execution
        # if one does not exist already
        if AppConfig.SSM_CLIENT is None:
            boto_config = client.Config(
                connect_timeout=cls.BOTO_TIMEOUT,
                read_timeout=cls.BOTO_TIMEOUT,
                region_name=base_config['region']
            )
            AppConfig.SSM_CLIENT = boto3.client('ssm', config=boto_config)

        # Generate a map of all the suffixes and full parameter names
        param_names = {key: '_'.join([base_config['function_name'], key])
                       for key in {cls.AUTH_CONFIG_SUFFIX,
                                   cls.BASE_CONFIG_SUFFIX,
                                   cls.STATE_CONFIG_SUFFIX}}

        LOGGER.debug('Parameter suffixes and names: %s', param_names)

        # Get the loaded parameters and a list of any invalid ones from parameter store
        params, invalid_params = AppConfig._get_parameters(param_names.values())
        LOGGER.debug('Retrieved parameters from parameter store: %s',
                     cls._scrub_auth_info(params, param_names[cls.AUTH_CONFIG_SUFFIX]))
        LOGGER.debug('Invalid parameters could not be retrieved from parameter store: %s',
                     invalid_params)

        # Check to see if there are any required parameters in the invalid params list
        missing_required_params = [param
                                   for param in invalid_params
                                   if param != param_names[cls.STATE_CONFIG_SUFFIX]]

        if missing_required_params:
            joined_params = ', '.join('\'{}\''.format(param) for param in missing_required_params)
            raise AppIntegrationConfigError('Could not load parameters required for this '
                                            'configuration: {}'.format(joined_params))

        # Update the env config with the base config values
        base_config.update(params[param_names[cls.BASE_CONFIG_SUFFIX]])

        # The state config can be None with first time deploys, so us a lookup and
        # add default empty values if there is no state found
        base_config.update(params.get(param_names[cls.STATE_CONFIG_SUFFIX],
                                      {cls._STATE_KEY: None, cls._TIME_KEY: None}))

        # Add the auth config info to the 'auth' key since these key/values can vary
        # from service to service
        base_config[cls.AUTH_CONFIG_SUFFIX] = {
            key: value.encode('utf-8') if isinstance(value, unicode) else value
            for key, value in params[param_names[cls.AUTH_CONFIG_SUFFIX]].iteritems()
        }

        return AppConfig(base_config, event)
Example #21
0
def login(profile, region, ssl_verification, adfs_ca_bundle, adfs_host,
          adfs_user, output_format, provider_id, s3_signature_version, env,
          stdin, authfile, use_keychain, role_chaining_role_arn, stdout,
          printenv, role_arn, session_duration, assertfile, sspi,
          u2f_trigger_default, prompt):
    """
    Authenticates an user with active directory credentials
    """
    config = prepare.get_prepared_config(
        profile,
        region,
        ssl_verification,
        adfs_ca_bundle,
        adfs_host,
        output_format,
        provider_id,
        s3_signature_version,
        session_duration,
        sspi,
        u2f_trigger_default,
        role_chaining_role_arn,
    )

    _verification_checks(config)

    # Try re-authenticating using an existing ADFS session
    principal_roles, assertion, aws_session_duration = authenticator.authenticate(
        config, assertfile=assertfile)

    # If we fail to get an assertion, prompt for credentials and try again
    if assertion is None:
        password = None

        if stdin:
            config.adfs_user, password = _stdin_user_credentials()
        elif env:
            config.adfs_user, password = _env_user_credentials()
        elif authfile:
            config.adfs_user, password = _file_user_credentials(
                config.profile, authfile)

        if not config.adfs_user and use_keychain is None:
            config.adfs_user = adfs_user if adfs_user else click.prompt(
                text='Username', type=str, default=config.adfs_user)

        if use_keychain:
            config.adfs_user, password = _keyring_user_credentials(
                use_keychain)

        if not password:
            if prompt == "osascript":
                # An "out-of-band" password prompt in order not to interrupt
                # the flow of `credential_process` to source the password
                password = prompt_password_using_osascript(config.adfs_user)
            elif prompt == "click":
                password = click.prompt('Password', type=str, hide_input=True)
            else:
                password = click.prompt('Password', type=str, hide_input=True)

            if use_keychain:
                keyring.set_password("aws-adfs", config.adfs_user, password)

        principal_roles, assertion, aws_session_duration = authenticator.authenticate(
            config, config.adfs_user, password)

        password = '******'
        del password

    if (role_arn is not None):
        config.role_arn = role_arn
    principal_arn, config.role_arn = role_chooser.choose_role_to_assume(
        config, principal_roles)
    if principal_arn is None or config.role_arn is None:
        click.echo('This account does not have access to any roles', err=True)
        exit(-1)

    # Use the assertion to get an AWS STS token using Assume Role with SAML
    # according to the documentation:
    #   http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html
    # This element contains one AttributeValue element that specifies the maximum time that the user
    # can access the AWS Management Console before having to request new temporary credentials.
    # The value is an integer representing the number of seconds, and can be
    # a maximum of 43200 seconds (12 hours). If this attribute is not present,
    # then the maximum session duration defaults to one hour
    # (the default value of the DurationSeconds parameter of the AssumeRoleWithSAML API).
    # To use this attribute, you must configure the SAML provider to provide single sign-on access
    # to the AWS Management Console through the console sign-in web endpoint at
    # https://signin.aws.amazon.com/saml.
    # Note that this attribute extends sessions only to the AWS Management Console.
    # It cannot extend the lifetime of other credentials.
    # However, if it is present in an AssumeRoleWithSAML API call,
    # it can be used to shorten the lifetime of the credentials returned by the call to less than
    # the default of 60 minutes.
    #
    # Note, too, that if a SessionNotOnOrAfter attribute is also defined,
    # then the lesser value of the two attributes, SessionDuration or SessionNotOnOrAfter,
    # establishes the maximum duration of the console session.
    _bind_aws_session_to_chosen_profile(config)
    conn = boto3.client(
        'sts', config=client.Config(signature_version=botocore.UNSIGNED))
    aws_session_token = conn.assume_role_with_saml(
        RoleArn=config.role_arn,
        PrincipalArn=principal_arn,
        SAMLAssertion=assertion,
        DurationSeconds=int(config.session_duration),
    )

    if stdout:
        _store(config, aws_session_token)

        if role_chaining_role_arn:
            creds = aws_session_token['Credentials']
            sts = boto3.client(
                "sts",
                aws_access_key_id=creds['AccessKeyId'],
                aws_secret_access_key=creds['SecretAccessKey'],
                aws_session_token=creds['SessionToken'],
            )
            chained_token = sts.assume_role(RoleArn=role_chaining_role_arn,
                                            RoleSessionName=str(uuid4()))
            _emit_json(chained_token)
        else:
            _emit_json(aws_session_token)
    elif printenv:
        _emit_summary(config, aws_session_duration)
        _print_environment_variables(aws_session_token, config)
    else:
        _store(config, aws_session_token)
        _emit_summary(config, aws_session_duration)
Example #22
0
def login(
    profile,
    region,
    ssl_verification,
    adfs_host,
    output_format,
    provider_id,
    s3_signature_version,
):
    """
    Authenticates an user with active directory credentials
    """
    config = prepare.get_prepared_config(
        profile,
        region,
        ssl_verification,
        adfs_host,
        output_format,
        provider_id,
        s3_signature_version,
    )

    _verification_checks(config)

    # Try reauthenticating using an existing ADFS session
    principal_roles, assertion, aws_session_duration = authenticator.authenticate(
        config)

    # If we fail to get an assertion, prompt for credentials and try again
    if assertion is None:
        username, password = _get_user_credentials(config)
        principal_roles, assertion, aws_session_duration = authenticator.authenticate(
            config, username, password)

        username = '******'
        del username
        password = '******'
        del password

    principal_arn, config.role_arn = _chosen_role_to_assume(
        config, principal_roles)

    # Use the assertion to get an AWS STS token using Assume Role with SAML
    # according to the documentation:
    #   http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html
    # This element contains one AttributeValue element that specifies the maximum time that the user
    # can access the AWS Management Console before having to request new temporary credentials.
    # The value is an integer representing the number of seconds, and can be
    # a maximum of 43200 seconds (12 hours). If this attribute is not present,
    # then the maximum session duration defaults to one hour
    # (the default value of the DurationSeconds parameter of the AssumeRoleWithSAML API).
    # To use this attribute, you must configure the SAML provider to provide single sign-on access
    # to the AWS Management Console through the console sign-in web endpoint at
    # https://signin.aws.amazon.com/saml.
    # Note that this attribute extends sessions only to the AWS Management Console.
    # It cannot extend the lifetime of other credentials.
    # However, if it is present in an AssumeRoleWithSAML API call,
    # it can be used to shorten the lifetime of the credentials returned by the call to less than
    # the default of 60 minutes.
    #
    # Note, too, that if a SessionNotOnOrAfter attribute is also defined,
    # then the lesser value of the two attributes, SessionDuration or SessionNotOnOrAfter,
    # establishes the maximum duration of the console session.
    conn = boto3.client(
        'sts', config=client.Config(signature_version=botocore.UNSIGNED))
    aws_session_token = conn.assume_role_with_saml(
        RoleArn=config.role_arn,
        PrincipalArn=principal_arn,
        SAMLAssertion=assertion,
        DurationSeconds=3600,
    )

    _store(config, aws_session_token)
    _emit_summary(config, aws_session_duration)
Example #23
0
 def test_set_and_get_client_config(self):
     client_config = client.Config()
     self.session.set_default_client_config(client_config)
     self.assertIs(self.session.get_default_client_config(), client_config)
Example #24
0
def login(
        profile,
        region,
        ssl_verification,
        adfs_ca_bundle,
        adfs_host,
        output_format,
        provider_id,
        s3_signature_version,
        env,
        stdin,
        authfile,
        stdout,
        printenv,
        role_arn,
        session_duration,
        assertfile,
        sspi,
        print_console_url,
        run_console_url
):
    """
    Authenticates an user with active directory credentials
    """
    config = prepare.get_prepared_config(
        profile,
        region,
        ssl_verification,
        adfs_ca_bundle,
        adfs_host,
        output_format,
        provider_id,
        s3_signature_version,
        session_duration,
        sspi
    )

    _verification_checks(config)

    # Try re-authenticating using an existing ADFS session
    principal_roles, assertion, aws_session_duration = authenticator.authenticate(config, assertfile=assertfile)

    # If we fail to get an assertion, prompt for credentials and try again
    if assertion is None:
        password = None

        if stdin:
            config.adfs_user, password = _stdin_user_credentials()
        elif env:
            config.adfs_user, password = _env_user_credentials()
        elif authfile:
            config.adfs_user, password = _file_user_credentials(config.profile, authfile)

        if not config.adfs_user:
            config.adfs_user = click.prompt(text='Username', type=str, default=config.adfs_user)

        if not password:
            password = click.prompt('Password', type=str, hide_input=True)

        principal_roles, assertion, aws_session_duration = authenticator.authenticate(config, config.adfs_user, password)

        password = '******'
        del password

    if(role_arn is not None):
        config.role_arn = role_arn
    # todo: break up AccountId and Role selection from the ARN strings. Prompt for Account then Role.
    #       have a parameter for prompting for account/role like in yum prompts
    #       make an option available for setting global default behaviors like SSPI, PROMPT, ect...
    principal_arn, config.role_arn = role_chooser.choose_role_to_assume(config, principal_roles)
    if principal_arn is None or config.role_arn is None:
        click.echo('This account does not have access to any roles', err=True)
        exit(-1)

    # Use the assertion to get an AWS STS token using Assume Role with SAML
    # according to the documentation:
    #   http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html
    # This element contains one AttributeValue element that specifies the maximum time that the user
    # can access the AWS Management Console before having to request new temporary credentials.
    # The value is an integer representing the number of seconds, and can be
    # a maximum of 43200 seconds (12 hours). If this attribute is not present,
    # then the maximum session duration defaults to one hour
    # (the default value of the DurationSeconds parameter of the AssumeRoleWithSAML API).
    # To use this attribute, you must configure the SAML provider to provide single sign-on access
    # to the AWS Management Console through the console sign-in web endpoint at
    # https://signin.aws.amazon.com/saml.
    # Note that this attribute extends sessions only to the AWS Management Console.
    # It cannot extend the lifetime of other credentials.
    # However, if it is present in an AssumeRoleWithSAML API call,
    # it can be used to shorten the lifetime of the credentials returned by the call to less than
    # the default of 60 minutes.
    #
    # Note, too, that if a SessionNotOnOrAfter attribute is also defined,
    # then the lesser value of the two attributes, SessionDuration or SessionNotOnOrAfter,
    # establishes the maximum duration of the console session.
    _bind_aws_session_to_chosen_profile(config)
    conn = boto3.client('sts', config=client.Config(signature_version=botocore.UNSIGNED))
    aws_session_token = conn.assume_role_with_saml(
        RoleArn=config.role_arn,
        PrincipalArn=principal_arn,
        SAMLAssertion=assertion,
        DurationSeconds=int(config.session_duration),
    )

    # todo: extract below secton of code to underscore function
    if run_console_url or print_console_url:

        # Format resulting temporary credentials into JSON
        url_credentials = {}
        url_credentials['sessionId'] = aws_session_token.get('Credentials').get('AccessKeyId')
        url_credentials['sessionKey'] = aws_session_token.get('Credentials').get('SecretAccessKey')
        url_credentials['sessionToken'] = aws_session_token.get('Credentials').get('SessionToken')
        json_string_with_temp_credentials = json.dumps(url_credentials)

        # Make request to AWS federation endpoint to get sign-in token.
        # Construct the parameter string with the sign-in action request,
        # a 12-hour session duration, and the JSON document with temporary credentials
        request_parameters = "?Action=getSigninToken"
        request_parameters += "&SessionDuration=43200"
        if sys.version_info[0] < 3:
            def quote_plus_function(s):
                return urllib.quote_plus(s)
        else:
            def quote_plus_function(s):
                return urllib.parse.quote_plus(s)
        request_parameters += "&Session=" + quote_plus_function(json_string_with_temp_credentials)
        request_url = "https://signin.aws.amazon.com/federation" + request_parameters
        r = requests.get(request_url)
        # Returns a JSON document with a single element named SigninToken.
        signin_token = json.loads(r.text)

        # Create URL where users can use the sign-in token to sign in to
        # the console. This URL must be used within 15 minutes after the
        # sign-in token was issued.
        #
        # &Issuer        the form-urlencoded URL for your internal sign-in page
        # &Destination   the form-urlencoded URL to the desired AWS console page
        # &SigninToken   the value of SigninToken received in the previous step 
        #
        request_parameters = "?Action=login" 
        request_parameters += "&Issuer=" + quote_plus_function(config.adfs_host)
        request_parameters += "&Destination=" + quote_plus_function("https://console.aws.amazon.com/")
        request_parameters += "&SigninToken=" + signin_token["SigninToken"]
        request_url = "https://signin.aws.amazon.com/federation" + request_parameters

    # todo: fixed warning on WIN32 platform for ELSE below if no run param was set
    # Default browser opens URL
    if(sys.platform=="win32") and run_console_url:
        # todo: force logout - two URL exist for doing this in console interface
        #logout_url = 'https://signin.aws.amazon.com/oauth?Action=logout&redirect_uri=aws.amazon.com'
        logout_url = 'https://console.aws.amazon.com/console/logout!doLogout'
        # blocking logout before login required
        from subprocess import call
        call(['start', logout_url], shell=True)
        # execute the login to AWS console
        startfile(request_url)
    else:
        click.echo(u"""Warning: Cannot run AWS Console URL on non-windows platform.""")


    if stdout:
        _emit_json(aws_session_token)
    elif printenv:
        _emit_summary(config, aws_session_duration)
        _print_environment_variables(aws_session_token,config)
        if print_console_url:
            _print_console_url(request_url)
    else:
        _store(config, aws_session_token)
        _emit_summary(config, aws_session_duration)
        if print_console_url:
            _print_console_url(request_url)