示例#1
0
    def evaluate(self, image_obj, context):
        if not context.data.get('prepared_dockerfile'):
            return  # Prep step blocked this due to condition on the dockerfile, so skip

        allowed_ports = delim_parser(self.eval_params.get('ALLOWEDPORTS', ''))
        denied_ports = delim_parser(self.eval_params.get('DENIEDPORTS', ''))

        expose_lines = context.data.get('prepared_dockerfile', {}).get('EXPOSE', [])
        for line in expose_lines:
            matchstr = None
            line = line.strip()
            if re.match("^\s*(EXPOSE|" + 'EXPOSE'.lower() + ")\s+(.*)", line):
                matchstr = re.match("^\s*(EXPOSE|" + 'EXPOSE'.lower() + ")\s+(.*)", line).group(2)

            if matchstr:
                iexpose = matchstr.split()
                if denied_ports:
                    if 'ALL' in denied_ports and len(iexpose) > 0:
                        self._fire(msg="Dockerfile exposes network ports but policy sets DENIEDPORTS=ALL: " + str(iexpose))
                    else:
                        for p in denied_ports:
                            if p in iexpose:
                                self._fire(msg="Dockerfile exposes port (" + p + ") which is in policy file DENIEDPORTS list")
                            elif p + '/tcp' in iexpose:
                                self._fire(msg="Dockerfile exposes port (" + p + "/tcp) which is in policy file DENIEDPORTS list")
                            elif p + '/udp' in iexpose:
                                self._fire(msg="Dockerfile exposes port (" + p + "/udp) which is in policy file DENIEDPORTS list")

                if allowed_ports:
                    if 'NONE' in allowed_ports and len(iexpose) > 0:
                        self._fire(msg="Dockerfile exposes network ports but policy sets ALLOWEDPORTS=NONE: " + str(iexpose))
                    else:
                        for p in allowed_ports:
                            done = False
                            while not done:
                                try:
                                    iexpose.remove(p)
                                    done = False
                                except:
                                    done = True

                                try:
                                    iexpose.remove(p + '/tcp')
                                    done = False
                                except:
                                    done = True

                                try:
                                    iexpose.remove(p + '/udp')
                                    done = False
                                except:
                                    done = True

                        for ip in iexpose:
                            self._fire(msg="Dockerfile exposes port (" + ip + ") which is not in policy file ALLOWEDPORTS list")

                        # Replaecable by:
                        # for port in filter(lambda x: x.split('/')[0] not in allowed_ports, iexpose):
                        #   self._fire(...)
        return
示例#2
0
    def evaluate(self, image_obj, context):
        if not context.data.get('prepared_dockerfile'):
            return  # Prep step blocked this eval due to condition on the dockerfile, so skip

        allowed_users = delim_parser(self.eval_params.get('ALLOWED', ''))
        denied_users = delim_parser(self.eval_params.get('DENIED', ''))
        user_lines = context.data.get('prepared_dockerfile').get('USER', [])

        # If not overt, make it so
        if not user_lines:
            user_lines = ['USER root']

        user = user_lines[-1].strip(
        )  # The last USER line is the determining entry
        match = re.search(self._sanitize_regex, user)
        if match and match.groups():
            user = match.groups()[0]
        else:
            log.warn(
                'Found USER line in dockerfile that does not match expected regex: {}, Line: {}'
                .format(self._sanitize_regex, user))
            return

        if allowed_users and user not in allowed_users:
            self._fire(
                msg=
                'User {} found as effective user, which is not on the allowed list'
                .format(user))
        if denied_users and user in denied_users:
            self._fire(
                msg=
                'User {} found as effective user, which is on the denied list'.
                format(user))
示例#3
0
    def evaluate(self, image_obj, context):
        if not context.data.get('prepared_dockerfile'):
            return  # Prep step blocked this eval due to condition on the dockerfile, so skip

        directives = set(
            map(lambda x: x.upper(),
                delim_parser(self.eval_params.get('DIRECTIVES', ''))))
        condition = self.eval_params.get('CHECK')
        check_value = self.eval_params.get('CHECK_VALUE')
        operation = self.ops[condition]

        if not condition or not directives:
            return

        df = context.data.get('prepared_dockerfile')

        for directive, lines in filter(lambda x: x[0] in directives,
                                       df.items()):
            for l in lines:
                l = l[len(directive):].strip()
                if operation(l, check_value):
                    self._fire(
                        msg=
                        "Dockerfile directive '{}' check '{}' matched against '{}' for line '{}'"
                        .format(directive, condition,
                                check_value if check_value else '', l))

        if condition == 'not_exists':
            for match in directives.difference(
                    directives.intersection(
                        set(map(lambda x: x.upper(), df.keys())))):
                self._fire(
                    msg=
                    "Dockerfile directive '{}' not found, matching condition '{}' check"
                    .format(match, condition))
示例#4
0
 def evaluate(self, image_obj, context):
     for pval in delim_parser(self.eval_params.get('BLACKLIST_NAMEMATCH','')):
         try:
             for pkg in image_obj.packages.filter(ImagePackage.name == pval):
                 self._fire(msg='PKGNAMEMATCH Package is blacklisted: ' + pkg.name)
         except Exception as e:
             log.exception('Error searching packages for blacklisted names')
             pass
示例#5
0
    def evaluate(self, image_obj, context):
        if not context.data.get('prepared_dockerfile'):
            return # Prep step blocked this eval due to condition on the dockerfile, so skip

        allowed_users = delim_parser(self.eval_params.get('ALLOWED', ''))
        denied_users = delim_parser(self.eval_params.get('DENIED', ''))
        user_lines = context.data.get('prepared_dockerfile').get('USER', [])

        # If not overt, make it so
        if not user_lines:
            user_lines = ['USER root']

        user = user_lines[-1].strip()  # The last USER line is the determining entry
        user = user[len('USER'):].strip()
        if allowed_users and user not in allowed_users:
            self._fire(msg='User {} found as effective user, which is not on the allowed list'.format(user))
        if denied_users and user in denied_users:
            self._fire(msg='User {} found as effective user, which is on the denied list'.format(user))
    def evaluate(self, image_obj, context):
        pkg_names = delim_parser(self.eval_params.get('PKGS', ''))
        pkg_dirs = delim_parser(self.eval_params.get('DIRS', ''))
        checks = map(lambda x: x.lower(),
                     delim_parser(self.eval_params.get('CHECK_ONLY', '')))

        outlist = list()
        imageId = image_obj.id
        modified = {}

        if image_obj.fs:
            extracted_files_json = image_obj.fs.files
        else:
            extracted_files_json = []

        if pkg_names:
            pkgs = image_obj.packages.filter(
                ImagePackage.name.in_(pkg_names)).all()
        else:
            pkgs = image_obj.packages.all()

        for pkg in pkgs:
            pkg_name = pkg.name
            records = []
            if pkg_dirs:
                # Filter the specified dirs
                for d in pkg_dirs:
                    records += pkg.pkg_db_entries.filter(
                        ImagePackageManifestEntry.file_path.startswith(d))
            else:
                records = [x for x in pkg.pkg_db_entries.all()]

            for pkg_db_record in records:
                status = self._diff_pkg_meta_and_file(
                    pkg_db_record,
                    extracted_files_json.get(pkg_db_record.file_path))

                if status and (not checks or status.value in checks):
                    self._fire(
                        msg=
                        "VERIFY check against package db for package '{}' failed on entry '{}' with status: '{}'"
                        .format(pkg_name, pkg_db_record.file_path,
                                status.value))
示例#7
0
    def evaluate(self, image_obj, context):
        match_vals = []
        fullmatchpkgs = []
        for match_val in delim_parser(self.eval_params.get('LICBLACKLIST_FULLMATCH', '')):
            match_vals.append(match_val)

        for pkg, license in context.data.get('licenses', []):
            if license in match_vals:
                fullmatchpkgs.append(pkg + "(" + license + ")")

        if fullmatchpkgs:
            self._fire(msg='LICFULLMATCH Packages are installed that have blacklisted licenses: ' + ', '.join(fullmatchpkgs))
示例#8
0
    def evaluate(self, image_obj, context):
        gems = image_obj.gems
        if not gems:
            return

        pkgs = context.data.get(GEM_LIST_KEY)
        if not pkgs:
            return

        for match_val in delim_parser(self.eval_params.get('BLACKLIST_GEMNAMEMATCH', '')):
            if match_val and match_val in pkgs:
                self._fire(msg='GEMPKGNAMEMATCH Package is blacklisted: ' + match_val)
示例#9
0
    def evaluate(self, image_obj, context):
        match_vals = []
        matchpkgs = []

        for match_val in delim_parser(self.eval_params.get('LICBLACKLIST_SUBMATCH', '')):
            match_vals.append(match_val)

        for pkg, license in context.data.get('licenses', []):
            for l in match_vals:
                if re.match(".*" + re.escape(l) + ".*", license):
                    matchpkgs.append(pkg + "(" + license + ")")

        if matchpkgs:
            self._fire(
                msg='LICSUBMATCH Packages are installed that have blacklisted licenses: ' + ', '.join(matchpkgs))
示例#10
0
    def evaluate(self, image_obj, context):
        attrs = delim_parser(self.eval_params.get('ATTRIBUTES', ''))
        check = self.eval_params.get('CHECK')
        rval = self.eval_params.get('CHECK_VALUE')

        if not attrs or not check:
            return

        if self.__checks__.get_op(check).requires_rvalue and not rval:
            # Raise exception or fall thru
            return

        for attr in attrs:
            img_val = self.__valid_attributes__[attr](image_obj)
            # Make consistent types (specifically for int/float/str)
            if type(img_val) in [str, int, float, unicode]:
                rval = type(img_val)(rval)

            if self.__checks__.get_op(check).eval_function(img_val, rval):
                self._fire(
                    msg=
                    "Attribute check for attribute: '{}' check: '{}' check_value: '{}' matched image value: '{}'"
                    .format(attr, check, (
                        str(rval) if rval is not None else ''), img_val))
示例#11
0
    def evaluate(self, image_obj, context):
        fullmatch = barsplit_comma_delim_parser(
            self.eval_params.get('PKGFULLMATCH'))
        namematch = delim_parser(self.eval_params.get('PKGNAMEMATCH'))
        vermatch = barsplit_comma_delim_parser(
            self.eval_params.get('PKGVERSMATCH'))

        outlist = list()
        imageId = image_obj.id

        names = set(fullmatch.keys()).union(set(namematch)).union(
            set(vermatch.keys()))
        if not names:
            return

        # Filter is possible since the lazy='dynamic' is set on the packages relationship in Image.
        for img_pkg in image_obj.packages.filter(
                ImagePackage.name.in_(names)).all():
            if img_pkg.name in fullmatch:
                if img_pkg.fullversion != fullmatch.get(img_pkg.name):
                    # Found but not right version
                    self._fire(
                        msg="PKGNOTPRESENT input package (" +
                        str(img_pkg.name) + ") is present (" +
                        str(img_pkg.fullversion) +
                        "), but not at the version specified in policy (" +
                        str(fullmatch[img_pkg.name]) + ")")
                    fullmatch.pop(
                        img_pkg.name
                    )  # Assume only one version of a given package name is installed
                else:
                    # Remove it from the list
                    fullmatch.pop(img_pkg.name)

            # Name match is sufficient
            if img_pkg.name in namematch:
                namematch.remove(img_pkg.name)

            if img_pkg.name in vermatch:
                if img_pkg.fullversion != vermatch[img_pkg.name]:
                    # Check if version is less than param value
                    if compare_package_versions(
                            img_pkg.distro_namespace_meta.flavor, img_pkg.name,
                            img_pkg.version, img_pkg.name,
                            vermatch[img_pkg.name]) < 0:
                        self._fire(
                            msg="PKGNOTPRESENT input package (" +
                            str(img_pkg.name) + ") is present (" +
                            str(img_pkg.fullversion) +
                            "), but is lower version than what is specified in policy ("
                            + str(vermatch[img_pkg.name]) + ")")

                vermatch.pop(img_pkg.name)

        # Any remaining
        for pkg, version in fullmatch.items():
            self._fire(msg="PKGNOTPRESENT input package (" + str(pkg) + "-" +
                       str(version) + ") is not present in container image")

        for pkg, version in vermatch.items():
            self._fire(msg="PKGNOTPRESENT input package (" + str(pkg) + "-" +
                       str(version) + ") is not present in container image")

        for pkg in namematch:
            self._fire(msg="PKGNOTPRESENT input package (" + str(pkg) +
                       ") is not present in container image")