Пример #1
0
    def __init__(self, profile=None, profile_name=None, config_file=None):
        """Creates a S3 bucket for the backend if one does not exist already"""
        self.config = Config(config_file=config_file)

        if profile_name is None:
            # There must be a profile associated to a keyring
            self.profile_name = self.config.get('default', 'profile')
        else:
            self.profile_name = profile_name

        if profile is None:
            # Either the user passes the profile as a dict, or must be read
            # from the config file.
            try:
                self.profile = self.config.get_profile(self.profile_name)
            except ProfileNotFoundError:
                self.config.initialize_profile(self.profile_name)
                self.profile = self.config.get_profile(self.profile_name)
        elif profile_name is None:
            raise InitError("You must provide parameter 'profile_name' when "
                            "providing a 'profile'")
        else:
            self.profile = profile

        self.__s3 = None
        self.__session = None
        # Will store a boto3 Bucket object
        self.__bucket = None
Пример #2
0
    def __init__(self, profile=None, profile_name=None, config_file=None):
        """Creates a S3 bucket for the backend if one does not exist already"""
        self.config = Config(config_file=config_file)

        if profile_name is None:
            # There must be a profile associated to a keyring
            self.profile_name = self.config.get('default', 'profile')
        else:
            self.profile_name = profile_name

        if profile is None:
            # Either the user passes the profile as a dict, or must be read
            # from the config file.
            try:
                self.profile = self.config.get_profile(self.profile_name)
            except ProfileNotFoundError:
                self.config.initialize_profile(self.profile_name)
                self.profile = self.config.get_profile(self.profile_name)
        elif profile_name is None:
            raise InitError("You must provide parameter 'profile_name' when "
                            "providing a 'profile'")
        else:
            self.profile = profile

        self.__s3 = None
        self.__session = None
        # Will store a boto3 Bucket object
        self.__bucket = None
Пример #3
0
class S3Backed(object):
    def __init__(self, profile=None, profile_name=None, config_file=None):
        """Creates a S3 bucket for the backend if one does not exist already"""
        self.config = Config(config_file=config_file)

        if profile_name is None:
            # There must be a profile associated to a keyring
            self.profile_name = self.config.get('default', 'profile')
        else:
            self.profile_name = profile_name

        if profile is None:
            # Either the user passes the profile as a dict, or must be read
            # from the config file.
            try:
                self.profile = self.config.get_profile(self.profile_name)
            except ProfileNotFoundError:
                self.config.initialize_profile(self.profile_name)
                self.profile = self.config.get_profile(self.profile_name)
        elif profile_name is None:
            raise InitError("You must provide parameter 'profile_name' when "
                            "providing a 'profile'")
        else:
            self.profile = profile

        self.__s3 = None
        self.__session = None
        # Will store a boto3 Bucket object
        self.__bucket = None

    def supported(self):
        try:
            client = self.session.client('s3')
            resp = client.list_objects(Bucket=self.bucket.name)
            return resp['ResponseMetadata']['HTTPStatusCode'] == 200
        except:
            return False

    @property
    def session(self):
        if self.__session is None:
            aws_profile = self.profile.get('aws_profile')
            if aws_profile == '' or aws_profile == 'default':
                # Use the default creds for this system (maybe temporary
                # creds from a role)
                self.__session = Session()
            else:
                self.__session = Session(
                    profile_name=self.profile.get('aws_profile'))
        return self.__session

    @property
    def kms_key_id(self):
        return self.profile['kms_key_id']

    @property
    def bucket(self):
        if self.__bucket is None:
            bucket_name = self.profile['bucket']
            self.__bucket = self.session.resource(
                's3', config=BotoConfig(
                    signature_version='s3v4')).Bucket(bucket_name)
        return self.__bucket

    @property
    def use_local_keyring(self):
        return self.profile.get('use_local_keyring', 'no') == 'yes'

    @property
    def s3(self):
        if self.__s3 is None:
            self.__s3 = self.session.resource('s3')
        return self.__s3

    @property
    def namespace(self):
        """Namespaces allow you to have multiple keyrings backed by the same
        S3 bucket by separating them with different S3 prefixes. Different
        access permissions can then be given to different prefixes so that
        only the right IAM roles/users/groups have access to a keychain
        namespace"""
        return _escape_for_s3(self.profile['namespace'])

    def configure(self, ask=True, **kwargs):
        """Configures the keyring, requesting user input if necessary"""
        fallback = {'namespace': 'default'}
        for option in ['kms_key_id', 'bucket', 'namespace', 'aws_profile']:
            value = kwargs.get(option) or \
                self.get_config(option, ask=ask, fallback=fallback)
            self.config.set_in_profile(self.profile_name, option, value)

        # We just updated the ini file: reload
        self.profile = self.config.get_profile(self.profile_name)

        self._check_config()
        self._configure_signature()

    def _configure_signature(self):
        """Sets up the AWS profile to use signature version 4"""
        aws_profile = self.config.get_from_profile(self.profile_name,
                                                   'aws_profile')
        awscli_config_dir = os.path.join(os.path.expanduser('~'), '.aws')
        if not os.path.isdir(awscli_config_dir):
            os.makedirs(awscli_config_dir)
        awscli_config_file = os.path.join(awscli_config_dir, 'config')
        cfg = configparser.ConfigParser()
        cfg.read(awscli_config_file)
        if aws_profile is None or aws_profile == 'default':
            section = 'default'
        else:
            section = "profile " + aws_profile

        if section in cfg.sections():
            cfg[section]['s3'] = "\nsignature_version = s3v4"
        else:
            cfg[section] = {'s3': "\nsignature_version = s3v4"}

        with open(awscli_config_file, 'w') as f:
            cfg.write(f)

    def _check_config(self):
        """Checks that the configuration is not obviously wrong"""
        required = ['kms_key_id', 'bucket']
        for option in required:
            val = self.profile.get(option, None)
            if val is None or len(val) == 0:
                print("WARNING: {} is required. You must run s3keyring "
                      "configure again.".format(option),
                      file=sys.stderr)

    def get_config(self, option, ask=True, fallback=None):
        val = self.profile.get(option.lower())
        if val is None or val == '':
            val = os.environ.get("KEYRING_" + option.upper())
        if fallback and val is None:
            val = fallback.get(option.lower())
        if ask:
            resp = input("{} [{}]: ".format(
                option.replace('_', ' ').title(), val))
            if len(resp) > 0:
                return resp
        return val
Пример #4
0
class S3Backed(object):
    def __init__(self, profile=None, profile_name=None, config_file=None):
        """Creates a S3 bucket for the backend if one does not exist already"""
        self.config = Config(config_file=config_file)

        if profile_name is None:
            # There must be a profile associated to a keyring
            self.profile_name = self.config.get('default', 'profile')
        else:
            self.profile_name = profile_name

        if profile is None:
            # Either the user passes the profile as a dict, or must be read
            # from the config file.
            try:
                self.profile = self.config.get_profile(self.profile_name)
            except ProfileNotFoundError:
                self.config.initialize_profile(self.profile_name)
                self.profile = self.config.get_profile(self.profile_name)
        elif profile_name is None:
            raise InitError("You must provide parameter 'profile_name' when "
                            "providing a 'profile'")
        else:
            self.profile = profile

        self.__s3 = None
        self.__session = None
        # Will store a boto3 Bucket object
        self.__bucket = None

    def supported(self):
        try:
            client = self.session.client('s3')
            resp = client.list_objects(Bucket=self.bucket.name)
            return resp['ResponseMetadata']['HTTPStatusCode'] == 200
        except:
            return False

    @property
    def session(self):
        if self.__session is None:
            aws_profile = self.profile.get('aws_profile')
            if aws_profile == '' or aws_profile == 'default':
                # Use the default creds for this system (maybe temporary
                # creds from a role)
                self.__session = Session()
            else:
                self.__session = Session(
                    profile_name=self.profile.get('aws_profile'))
        return self.__session

    @property
    def kms_key_id(self):
        return self.profile['kms_key_id']

    @property
    def bucket(self):
        if self.__bucket is None:
            bucket_name = self.profile['bucket']
            self.__bucket = self.session.resource('s3', config=BotoConfig(signature_version='s3v4')).Bucket(bucket_name)
        return self.__bucket

    @property
    def use_local_keyring(self):
        return self.profile.get('use_local_keyring', 'no') == 'yes'

    @property
    def s3(self):
        if self.__s3 is None:
            self.__s3 = self.session.resource('s3')
        return self.__s3

    @property
    def namespace(self):
        """Namespaces allow you to have multiple keyrings backed by the same
        S3 bucket by separating them with different S3 prefixes. Different
        access permissions can then be given to different prefixes so that
        only the right IAM roles/users/groups have access to a keychain
        namespace"""
        return _escape_for_s3(self.profile['namespace'])

    def configure(self, ask=True, **kwargs):
        """Configures the keyring, requesting user input if necessary"""
        fallback = {'namespace': 'default'}
        for option in ['kms_key_id', 'bucket', 'namespace', 'aws_profile']:
            value = kwargs.get(option) or \
                self.get_config(option, ask=ask, fallback=fallback)
            self.config.set_in_profile(self.profile_name, option, value)

        # We just updated the ini file: reload
        self.profile = self.config.get_profile(self.profile_name)

        self._check_config()
        self._configure_signature()

    def _configure_signature(self):
        """Sets up the AWS profile to use signature version 4"""
        aws_profile = self.config.get_from_profile(self.profile_name,
                                                   'aws_profile')
        awscli_config_dir = os.path.join(os.path.expanduser('~'), '.aws')
        if not os.path.isdir(awscli_config_dir):
            os.makedirs(awscli_config_dir)
        awscli_config_file = os.path.join(awscli_config_dir, 'config')
        cfg = configparser.ConfigParser()
        cfg.read(awscli_config_file)
        if aws_profile is None or aws_profile == 'default':
            section = 'default'
        else:
            section = "profile " + aws_profile

        if section in cfg.sections():
            cfg[section]['s3'] = "\nsignature_version = s3v4"
        else:
            cfg[section] = {'s3': "\nsignature_version = s3v4"}

        with open(awscli_config_file, 'w') as f:
            cfg.write(f)

    def _check_config(self):
        """Checks that the configuration is not obviously wrong"""
        required = ['kms_key_id', 'bucket']
        for option in required:
            val = self.profile.get(option, None)
            if val is None or len(val) == 0:
                print("WARNING: {} is required. You must run s3keyring "
                      "configure again.".format(option),
                      file=sys.stderr)

    def get_config(self, option, ask=True, fallback=None):
        val = self.profile.get(option.lower())
        if val is None or val == '':
            val = os.environ.get("KEYRING_" + option.upper())
        if fallback and val is None:
            val = fallback.get(option.lower())
        if ask:
            resp = input("{} [{}]: ".format(
                option.replace('_', ' ').title(), val))
            if len(resp) > 0:
                return resp
        return val