def find_modified(self, previous=[], current=[], exception_map={}):
        """
        Find any objects that have been changed since the last run of the watcher.
        Add these items to the changed_items list.
        """
        prev_map = {item.location(): item for item in previous}
        curr_map = {item.location(): item for item in current}

        item_locations = list(set(curr_map).intersection(set(prev_map)))
        item_locations = [item_location for item_location in item_locations if not self.location_in_exception_map(item_location, exception_map)]

        for location in item_locations:
            prev_item = prev_map[location]
            curr_item = curr_map[location]
            # ChangeItem with and without ephemeral changes
            eph_change_item = None
            dur_change_item = None

            if not sub_dict(prev_item.config) == sub_dict(curr_item.config):
                eph_change_item = ChangeItem.from_items(old_item=prev_item, new_item=curr_item, source_watcher=self)

            if self.ephemerals_skipped():
                # deepcopy configs before filtering
                dur_prev_item = deepcopy(prev_item)
                dur_curr_item = deepcopy(curr_item)
                # filter-out ephemeral paths in both old and new config dicts
                if self.ephemeral_paths:
                    for path in self.ephemeral_paths:
                        for cfg in [dur_prev_item.config, dur_curr_item.config]:
                            try:
                                dpath.util.delete(cfg, path, separator='$')
                            except PathNotFound:
                                pass

                # now, compare only non-ephemeral paths
                if not sub_dict(dur_prev_item.config) == sub_dict(dur_curr_item.config):
                    dur_change_item = ChangeItem.from_items(old_item=dur_prev_item, new_item=dur_curr_item,
                                                            source_watcher=self)

                # store all changes, divided in specific categories
                if eph_change_item:
                    self.ephemeral_items.append(eph_change_item)
                    app.logger.debug("%s: ephemeral changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
                if dur_change_item:
                    self.changed_items.append(dur_change_item)
                    app.logger.debug("%s: durable changes in item %s/%s/%s" % (self.i_am_singular, dur_change_item.account, dur_change_item.region, dur_change_item.name))

            elif eph_change_item is not None:
                # store all changes, handle them all equally
                self.changed_items.append(eph_change_item)
                app.logger.debug("%s: changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
Example #2
0
    def find_modified(self, previous=[], current=[], exception_map={}):
        """
        Find any objects that have been changed since the last run of the watcher.
        Add these items to the changed_items list.
        """
        prev_map = {item.location(): item for item in previous}
        curr_map = {item.location(): item for item in current}

        item_locations = list(set(curr_map).intersection(set(prev_map)))
        item_locations = [item_location for item_location in item_locations if not self.location_in_exception_map(item_location, exception_map)]

        for location in item_locations:
            prev_item = prev_map[location]
            curr_item = curr_map[location]
            # ChangeItem with and without ephemeral changes
            eph_change_item = None
            dur_change_item = None

            if not sub_dict(prev_item.config) == sub_dict(curr_item.config):
                eph_change_item = ChangeItem.from_items(old_item=prev_item, new_item=curr_item, source_watcher=self)

            if self.ephemerals_skipped():
                # deepcopy configs before filtering
                dur_prev_item = deepcopy(prev_item)
                dur_curr_item = deepcopy(curr_item)
                # filter-out ephemeral paths in both old and new config dicts
                for path in self.ephemeral_paths:
                    for cfg in [dur_prev_item.config, dur_curr_item.config]:
                        try:
                            dpath.util.delete(cfg, path, separator='$')
                        except PathNotFound:
                            pass

                # now, compare only non-ephemeral paths
                if not sub_dict(dur_prev_item.config) == sub_dict(dur_curr_item.config):
                    dur_change_item = ChangeItem.from_items(old_item=dur_prev_item, new_item=dur_curr_item,
                                                            source_watcher=self)

                # store all changes, divided in specific categories
                if eph_change_item:
                    self.ephemeral_items.append(eph_change_item)
                    app.logger.debug("%s: ephemeral changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
                if dur_change_item:
                    self.changed_items.append(dur_change_item)
                    app.logger.debug("%s: durable changes in item %s/%s/%s" % (self.i_am_singular, dur_change_item.account, dur_change_item.region, dur_change_item.name))

            elif eph_change_item is not None:
                # store all changes, handle them all equally
                self.changed_items.append(eph_change_item)
                app.logger.debug("%s: changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
Example #3
0
 def hash_config(self, config):
     """
     Finds the hash for a config.
     Calls sub_dict, which is a recursive method which sorts lists which may be buried in the structure.
     Dumps the config to json with sort_keys set.
     Grabs an MD5 hash.
     :param config: dict describing item
     :return: 32 character string (MD5 Hash)
     """
     item = sub_dict(config)
     item_str = json.dumps(item, sort_keys=True)
     item_hash = hashlib.md5(item_str)  # nosec: not used for security
     return item_hash.hexdigest()
Example #4
0
 def hash_config(self, config):
     """
     Finds the hash for a config.
     Calls sub_dict, which is a recursive method which sorts lists which may be buried in the structure.
     Dumps the config to json with sort_keys set.
     Grabs an MD5 hash.
     :param config: dict describing item
     :return: 32 character string (MD5 Hash)
     """
     item = sub_dict(config)
     item_str = json.dumps(item, sort_keys=True)
     item_hash = hashlib.md5(item_str) # nosec: not used for security
     return item_hash.hexdigest()
    def get(self, revision_id):
        """
            .. http:get:: /api/1/revision/1234

            Get a specific revision.

            **Example Request**:

            .. sourcecode:: http

                GET /api/1/revision/123 HTTP/1.1
                Host: example.com
                Accept: application/json, text/javascript

            **Example Response**:

            .. sourcecode:: http

                HTTP/1.1 200 OK
                Vary: Accept
                Content-Type: application/json

                {
                    "auth": {
                        "authenticated": true,
                        "user": "******"
                    },
                    "item_id": 114,
                    "comments": [],
                    "active": false,
                    "date_created": "2013-10-04 22:01:47",
                    "config": {},
                    "id":123
                }

            :statuscode 200: no error
            :statuscode 401: Authentication failure. Please login.
        """
        query = ItemRevision.query.filter(ItemRevision.id == revision_id)
        result = query.first()

        comments = []
        for comment in result.comments:
            comment_marshaled = marshal(comment, REVISION_COMMENT_FIELDS)
            comments.append(
                dict(comment_marshaled.items() +
                     {'user': comment.user.email}.items()))

        cloudtrail_entries = []
        for entry in result.cloudtrail_entries:
            cloudtrail_entries.append(entry.full_entry)

        revision_marshaled = marshal(result, REVISION_FIELDS)
        revision_marshaled = dict(
            revision_marshaled.items() +
            {'config': OrderedDict(sorted(sub_dict(result.config).items()))
             }.items() + {'auth': self.auth_dict}.items() +
            {'comments': comments}.items() +
            {'cloudtrail': cloudtrail_entries}.items())

        self.reqparse.add_argument('compare',
                                   type=int,
                                   default=None,
                                   location='args')
        args = self.reqparse.parse_args()
        compare_id = args.pop('compare', None)
        if compare_id:
            query = ItemRevision.query.filter(ItemRevision.id == compare_id)
            compare_result = query.first()
            pdiff = PolicyDiff(
                OrderedDict(sorted(sub_dict(result.config).items())),
                OrderedDict(sorted(sub_dict(compare_result.config).items())))
            revision_marshaled = dict(
                revision_marshaled.items() +
                {'diff_html': pdiff.produceDiffHTML()}.items())

        return revision_marshaled, 200
Example #6
0
    def get(self, revision_id):
        """
            .. http:get:: /api/1/revision/1234

            Get a specific revision.

            **Example Request**:

            .. sourcecode:: http

                GET /api/1/revision/123 HTTP/1.1
                Host: example.com
                Accept: application/json, text/javascript

            **Example Response**:

            .. sourcecode:: http

                HTTP/1.1 200 OK
                Vary: Accept
                Content-Type: application/json

                {
                    "auth": {
                        "authenticated": true,
                        "user": "******"
                    },
                    "item_id": 114,
                    "comments": [],
                    "active": false,
                    "date_created": "2013-10-04 22:01:47",
                    "config": {},
                    "id":123
                }

            :statuscode 200: no error
            :statuscode 401: Authentication failure. Please login.
        """
        query = ItemRevision.query.filter(ItemRevision.id == revision_id)
        result = query.first()

        comments = []
        for comment in result.comments:
            comment_marshaled = marshal(comment, REVISION_COMMENT_FIELDS)
            comments.append(dict(
                comment_marshaled.items() +
                {'user': comment.user.email}.items()
            ))

        cloudtrail_entries = []
        for entry in result.cloudtrail_entries:
            cloudtrail_entries.append(entry.full_entry)

        revision_marshaled = marshal(result, REVISION_FIELDS)
        revision_marshaled = dict(
            revision_marshaled.items() +
            {'config': OrderedDict(sorted(sub_dict(result.config).items()))}.items() +
            {'auth': self.auth_dict}.items() +
            {'comments': comments}.items() +
            {'cloudtrail': cloudtrail_entries}.items()
        )

        self.reqparse.add_argument('compare', type=int, default=None, location='args')
        args = self.reqparse.parse_args()
        compare_id = args.pop('compare', None)
        if compare_id:
            query = ItemRevision.query.filter(ItemRevision.id == compare_id)
            compare_result = query.first()
            pdiff = PolicyDiff(
                OrderedDict(sorted(sub_dict(result.config).items())),
                OrderedDict(sorted(sub_dict(compare_result.config).items())))
            revision_marshaled = dict(
                revision_marshaled.items() +
                {'diff_html': pdiff.produceDiffHTML()}.items()
            )

        return revision_marshaled, 200