def _validate_source_profile(self, parent_profile_name,
                                 source_profile_name):
        profiles = self._loaded_config.get('profiles', {})
        if source_profile_name not in profiles:
            raise InvalidConfigError(error_msg=(
                'The source_profile "{source_profile}" referenced in the profile '
                '"{parent_profile}" does not exist.'.format(
                    source_profile=source_profile_name,
                    parent_profile=parent_profile_name,
                ), ), )

        source_profile = profiles[source_profile_name]

        if not self._source_profile_has_credentials(source_profile):
            raise InvalidConfigError(error_msg=(
                'The source_profile "{source_profile}" must specify static '
                'credentials.'.format(
                    source_profile=source_profile_name, ), ), )

        if source_profile_name not in self._visited_profiles:
            return

        if source_profile_name != parent_profile_name:
            raise InfiniteLoopConfigError(
                source_profile=source_profile_name,
                visited_profiles=self._visited_profiles,
            )

        if not self._has_static_credentials(source_profile):
            raise InfiniteLoopConfigError(
                source_profile=source_profile_name,
                visited_profiles=self._visited_profiles,
            )
 def _get_role_config_values(self):
     # This returns the role related configuration.
     profiles = self._loaded_config.get('profiles', {})
     try:
         source_profile = profiles[self._profile_name]['source_profile']
         role_arn = profiles[self._profile_name]['role_arn']
         mfa_serial = profiles[self._profile_name].get('mfa_serial')
     except KeyError as e:
         raise PartialCredentialsError(provider=self.METHOD,
                                       cred_var=str(e))
     external_id = profiles[self._profile_name].get('external_id')
     role_session_name = \
         profiles[self._profile_name].get('role_session_name')
     if source_profile not in profiles:
         raise InvalidConfigError(
             error_msg=('The source_profile "%s" referenced in '
                        'the profile "%s" does not exist.' %
                        (source_profile, self._profile_name)))
     source_cred_values = profiles[source_profile]
     return {
         'role_arn': role_arn,
         'external_id': external_id,
         'source_profile': source_profile,
         'mfa_serial': mfa_serial,
         'source_cred_values': source_cred_values,
         'role_session_name': role_session_name
     }
예제 #3
0
def print_environment_variables(profile=None, include_region=False, **kwargs):
    """
    Prints AWS credentials as environment variables.
    This uses the get_session() function to reuse MFA sessions.

    """

    # Work with profile or profile_name.
    if profile:
        kwargs['profile_name'] = profile

    session = get_session(**kwargs)

    creds = session.get_credentials()

    if not creds:
        raise InvalidConfigError(
            error_msg='No credentials found for {}'.format(kwargs),
        )

    frozen_creds = creds.get_frozen_credentials()
    expiry_time = getattr(creds, '_expiry_time', None)

    print('AWS_ACCESS_KEY_ID={}'.format(frozen_creds.access_key))
    print('AWS_SECRET_ACCESS_KEY={}'.format(frozen_creds.secret_key))

    if expiry_time:
        print('AWS_SESSION_EXPIRATION={}'.format(_serialize_if_needed(expiry_time)))

    if frozen_creds.token:
        print('AWS_SESSION_TOKEN={}'.format(frozen_creds.token))

    if include_region and session.region_name:
        print('AWS_DEFAULT_REGION={}'.format(session.region_name))
        print('AWS_REGION={}'.format(session.region_name))
예제 #4
0
    async def _assume_role_with_web_identity(self):
        token_path = self._get_config('web_identity_token_file')
        if not token_path:
            return None
        token_loader = self._token_loader_cls(token_path)

        role_arn = self._get_config('role_arn')
        if not role_arn:
            error_msg = (
                'The provided profile or the current environment is '
                'configured to assume role with web identity but has no '
                'role ARN configured. Ensure that the profile has the role_arn'
                'configuration set or the AWS_ROLE_ARN env var is set.')
            raise InvalidConfigError(error_msg=error_msg)

        extra_args = {}
        role_session_name = self._get_config('role_session_name')
        if role_session_name is not None:
            extra_args['RoleSessionName'] = role_session_name

        fetcher = AioAssumeRoleWithWebIdentityCredentialFetcher(
            client_creator=self._client_creator,
            web_identity_token_loader=token_loader,
            role_arn=role_arn,
            extra_args=extra_args,
            cache=self.cache,
        )
        # The initial credentials are empty and the expiration time is set
        # to now so that we can delay the call to assume role until it is
        # strictly needed.
        return AioDeferredRefreshableCredentials(
            method=self.METHOD,
            refresh_using=fetcher.fetch_credentials,
        )
예제 #5
0
    async def _resolve_credentials_from_profile(self, profile_name):
        profiles = self._loaded_config.get('profiles', {})
        profile = profiles[profile_name]

        if self._has_static_credentials(profile) and \
                not self._profile_provider_builder:
            return self._resolve_static_credentials_from_profile(profile)
        elif self._has_static_credentials(profile) or \
                not self._has_assume_role_config_vars(profile):
            profile_providers = self._profile_provider_builder.providers(
                profile_name=profile_name,
                disable_env_vars=True,
            )
            profile_chain = AioCredentialResolver(profile_providers)
            credentials = await profile_chain.load_credentials()
            if credentials is None:
                error_message = (
                    'The source profile "%s" must have credentials.'
                )
                raise InvalidConfigError(
                    error_msg=error_message % profile_name,
                )
            return credentials

        return self._load_creds_via_assume_role(profile_name)
예제 #6
0
    def _load_sso_config(self):
        """Load sso config."""
        loaded_config = self._load_config()
        profiles = loaded_config.get("profiles", {})
        profile_name = self._profile_name
        profile_config = profiles.get(self._profile_name, {})

        if all(c not in profile_config for c in self._SSO_CONFIG_VARS):
            return None

        config = {}
        missing_config_vars = []
        for config_var in self._SSO_CONFIG_VARS:
            if config_var in profile_config:
                config[config_var] = profile_config[config_var]
            else:
                missing_config_vars.append(config_var)

        if missing_config_vars:
            missing = ", ".join(missing_config_vars)
            raise InvalidConfigError(error_msg=(
                'The profile "%s" is configured to use SSO but is missing '
                "required configuration: %s" % (profile_name, missing)))

        return config
 def _validate_credential_source(self, profile_name, credential_source):
     if self._credential_sourcer is None:
         raise InvalidConfigError(error_msg=(
             'The credential source "{credential_source}" is specified in profile '
             '"{profile_name}", but no source_provider was configured.'.
             format(
                 credential_source=credential_source,
                 profile_name=profile_name,
             ), ), )
     if not self._credential_sourcer.is_supported(credential_source):
         raise InvalidConfigError(error_msg=(
             'The credential source "{credential_source}" referenced in profile '
             '"{profile_name}" is not valid.'.format(
                 credential_source=credential_source,
                 profile_name=profile_name,
             ), ), )
    def _get_mfa_config(self, profile_name):
        profiles = self._loaded_config.get('profiles', {})

        profile = profiles[profile_name]
        source_profile = profile.get('source_profile')
        credential_source = profile.get('credential_source')

        mfa_config = {
            'mfa_serial': profile.get('mfa_serial'),
            'source_profile': source_profile,
            'credential_source': credential_source,
        }

        if credential_source is not None and source_profile is not None:
            raise InvalidConfigError(error_msg=(
                'The profile "{profile_name}" contains both source_profile and '
                'credential_source.'.format(profile_name=profile_name)), )
        elif credential_source is None and source_profile is None:
            raise PartialCredentialsError(
                provider=self.METHOD,
                cred_var='source_profile or credential_source',
            )
        elif credential_source is not None:
            self._validate_credential_source(profile_name, credential_source)
        else:
            self._validate_source_profile(profile_name, source_profile)

        return mfa_config
def update_location(options: dict):
    """
    Updates a DataSync location's metadata

    Args:
        options (dict): A dictionary containing LocationArn, Type, and Config properties
        - LocationArn [string]
        - Type [string]
            - nfs
            - object_storage
            - smb
        - Config [dict]
            - Conforms to the request syntax for the UpdateLocation APIs
            - nfs: https://docs.aws.amazon.com/datasync/latest/userguide/API_UpdateLocationNfs.html
            - object_storage: https://docs.aws.amazon.com/datasync/latest/userguide/API_UpdateLocationObjectStorage.html
            - smb: https://docs.aws.amazon.com/datasync/latest/userguide/API_UpdateLocationSmb.html

    Raises:
        InvalidConfigError: If LocationArn is not specified, or an invalid Type is specified

    Returns:
        [string]: The updated location's ARN
    """

    location_arn = options.get("LocationArn")
    type = options.get("Type", "").lower()
    config = options.get("Config", {})

    if location_arn is None:
        raise InvalidConfigError("Please specify a location ARN")

    config.update(LocationArn=location_arn)

    if type == "nfs":
        datasync_client.update_location_nfs(**config)

    elif type == "object_storage":
        datasync_client.update_location_object_storage(**config)

    elif type == "smb":
        datasync_client.update_location_smb(**config)

    else:
        raise InvalidConfigError("Please specify a valid location type")

    return location_arn
def create_location(options):
    """
    Creates a DataSync location

    Args:
        options (dict): [description]
        - Type [string]
            - efs
            - fsx_windows
            - nfs
            - object_storage
            - s3
            - smb
        - Config [dict]
            - Conforms to the request syntax for the CreateLocation APIs
            - efs: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationEfs.html
            - fsx_windows: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationFsxWindows.html
            - nfs: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationNfs.html
            - object_storage: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationObjectStorage.html
            - s3: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationS3.html
            - smb: https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationSmb.html

    Raises:
        InvalidConfigError: If an invalid Type or Config is specified

    Returns:
        [string]: The new location's ARN
    """

    type = options.get("Type", "").lower()
    config = options.get("Config", {})

    if type == "efs":
        return datasync_client.create_location_efs(**config)["LocationArn"]

    elif type == "fsx_windows":
        return datasync_client.create_location_fsx_windows(
            **config)["LocationArn"]

    elif type == "nfs":
        return datasync_client.create_location_nfs(**config)["LocationArn"]

    elif type == "object_storage":
        return datasync_client.create_location_object_storage(
            **config)["LocationArn"]

    elif type == "s3":
        return datasync_client.create_location_s3(**config)["LocationArn"]

    elif "type" == "smb":
        return datasync_client.create_location_smb(**config)["LocationArn"]

    else:
        raise InvalidConfigError("Please specify a valid location type")
def main(task_config):
    # ensure log group exists
    if "CloudWatchLogGroup" in task_config:
        cloudwatch_log_group = create_cloudwatch_log_group(
            task_config.get("CloudWatchLogGroup"))
        task_config.update("CloudWatchLogGroupArn",
                           cloudwatch_log_group["arn"])

    if "CloudWatchLogGroupArn" not in task_config:
        raise InvalidConfigError(
            "Please specify a CloudWatchLogGroup or CloudWatchLogGroupArn")

    if task_config.get("TaskArn"):
        task_arn = update_task(task_config)
        logging.info(f"[created] {task_arn}")
    else:
        task_arn = create_task(task_config)
        logging.info(f"[updated] {task_arn}")