예제 #1
0
    def kms_connection_for(self, location):
        if KMSConnection is None:
            raise SyncrError("Sorry, need python3 to do anything related to kms")

        if getattr(self, "_kms_connections", None) is None:
            self._kms_connections = {}

        if location not in self._kms_connections:
            try:
                self._kms_connections[location] = boto.kms.connect_to_region(location)
            except boto.exception.NoAuthHandlerFound:
                raise SyncrError("Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before running this script (your aws credentials)")
        return self._kms_connections[location]
예제 #2
0
 def s3_connection(self):
     if getattr(self, "_s3_connection", None) is None:
         try:
             self._s3_connection = S3Connection()
         except boto.exception.NoAuthHandlerFound:
             raise SyncrError("Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before running this script (your aws credentials)")
     return self._s3_connection
예제 #3
0
    def add(self, configuration, location, only_consider=None):
        """Add a new configuration"""
        if not self.types:
            raise SyncrError("Syncr doesn't know about anything, try syncr.register_default_types() first")

        if not isinstance(configuration, dict):
            raise InvalidConfiguration("Configuration needs to be a dict", found=type(configuration))

        for name in self.types:
            if not only_consider or name in only_consider:
                if name in configuration:
                    self.configurations[name].append((location, configuration[name]))
예제 #4
0
def accounts_from(location):
    """Get the accounts dictionary"""
    if not os.path.exists(location):
        raise SyncrError("Could not find an accounts.yaml", location=location)

    if not os.access(location, os.R_OK):
        raise SyncrError("Could not read the accounts.yaml", location=location)

    try:
        accounts = yaml.load(open(location))
    except yaml.parser.ParserError as error:
        raise SyncrError("Failed to parse the accounts yaml file",
                         location=location,
                         error_typ=error.__class__.__name__,
                         error=error)

    for account_id in list(accounts.values()):
        if account_id not in accounts:
            accounts[account_id] = account_id

    return accounts
예제 #5
0
    def setup(self):
        """Make sure our current credentials are for this account and set self.connection"""
        try:
            connection = IAMConnection()
        except boto.exception.NoAuthHandlerFound:
            raise SyncrError("Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before running this script (your aws credentials)")

        # Need roles to make sure we have the correct account
        log.info("Finding roles in your account")
        try:
            result = connection.list_roles()
        except boto.exception.BotoServerError as error:
            if error.status == 403:
                raise SyncrError("Your credentials aren't allowed to look at iam roles :(")
            else:
                raise

        roles = self.all_roles = result["list_roles_response"]["list_roles_result"]["roles"]
        if not roles:
            raise SyncrError("There are no roles in your account, I can't figure out the account id")

        # Need users for kms to be able to grant to users
        log.info("Finding users in your account")
        try:
            result = connection.get_all_users()
        except boto.exception.BotoServerError as error:
            if error.status == 403:
                raise SyncrError("Your credentials aren't allowed to look at iam users :(")
            else:
                raise
        self.all_users = result["list_users_response"]["list_users_result"]["users"]

        amazon_account_id = roles[0]['arn'].split(":")[4]
        if str(self.account_id) != str(amazon_account_id):
            raise SyncrError("Please use credentials for the right account", expect=self.account_id, got=amazon_account_id)

        # If reached this far, the credentials belong to the correct account :)
        self.connection = connection
        return connection
예제 #6
0
def make_amazon(folder, accounts_location=None, dry_run=False):
    """Find the account we're using and return a setup Amazon object"""
    if not accounts_location:
        accounts_location = os.path.join(folder, '..', 'accounts.yaml')

    accounts = accounts_from(accounts_location)
    account_name = os.path.basename(folder)

    if account_name not in accounts:
        raise SyncrError("Please add this account to accounts.yaml",
                         accounts_yaml_location=accounts_location,
                         account_name=account_name)
    account_id = accounts[account_name]

    amazon = Amazon(account_id, account_name, accounts, dry_run=dry_run)
    amazon.setup()

    return amazon
예제 #7
0
    def setup(self):
        """Raise errors if the definition doesn't make sense"""
        self.tags = self.definition.get("tags", {})
        if type(self.tags) != dict or any(
                not isinstance(tag_name, six.string_types)
                or not isinstance(tag_val, six.string_types)
                for tag_name, tag_val in self.tags.items()):
            raise SyncrError(
                "Bucket tags should be a dictionary of {<string> : <string>}",
                got=self.tags)

        self.location = self.definition.get("location", "ap-southeast-2")
        for key, default_allow in (("permission", None), ("allow_permission",
                                                          True),
                                   ("deny_permission", False)):
            for policy in listified(self.definition, key):
                for statement in self.statements.make_permission_statements(
                        policy, allow=default_allow):
                    self.permission.append(statement)
예제 #8
0
def do_sync(amazon, found, only_consider=None):
    """Sync the configuration from this folder"""
    try:
        parsed = parse_configurations(found)
    except BadConfiguration as err:
        log.error("Failed to parse all the yaml specifications")
        for _, error in sorted(err.kwargs["parse_errors"].items()):
            log.error(error)
        raise BadConfiguration()

    sync = Sync(amazon)
    sync.register_default_types()

    if only_consider:
        dont_consider = [
            considering for considering in only_consider
            if considering not in sync.types
        ]
        if dont_consider:
            raise SyncrError("Told to sync unknown types",
                             only_sync=list(sync.types.keys()),
                             unknown_types=dont_consider)

    for location, configuration in sorted(parsed.items()):
        sync.add(configuration, location, only_consider)

    try:
        log.info("Combining configuration")
        combined = sync.combine_configurations()
    except BadConfiguration as err:
        log.error("Your configuration didn't make sense")
        for error in err.kwargs["errors"]:
            log.error(error)
        raise BadConfiguration()

    log.info("Starting sync")
    sync.sync(combined)