class ImageMetadataAttributeCheckTrigger(BaseTrigger): __trigger_name__ = 'ATTRIBUTECHECK' __description__ = 'triggers if a named image attribute matches the given condition' __ops__ = { '=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x == y), '!=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x != y), '>': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x > y), '<': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x < y), '>=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x >= y), '<=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x <= y), 'exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: bool(x)), 'not_exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: not bool(x)), 'like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: bool(re.match(y, x))), 'not_like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: not bool(re.match(y, x))) } __valid_attributes__ = { 'size': lambda x: x.size, 'architecture': lambda x: x.docker_data_json.get('Architecture') if x.docker_data_json else None, 'os_type': lambda x: x.docker_data_json.get('Os') if x.docker_data_json else None, 'distro': lambda x: x.distro_name, 'distro_version': lambda x: x.distro_version, 'like_distro': lambda x: x.like_distro, 'layer_count': lambda x: len(x.layers_json) if x.layers_json else 0 } __checks__ = CheckOperations(__ops__) __value_validator__ = lambda x: True #__params__ = { # 'ATTRIBUTES': AttributeListValidator(__valid_attributes__.keys()), # 'CHECK': __checks__, # 'CHECK_VALUE': __value_validator__ #} attributes = EnumCommaDelimStringListParameter( name='attributes', description= 'List of attribute names to apply as rvalues to the check operation', enum_values=__valid_attributes__) check = EnumStringParameter( name='check', description='The operation to perform the evaluation', enum_values=__ops__.keys()) check_value = TriggerParameter( name='check_value', description='The lvalue in the check operation.', validator=TypeValidator('string')) 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') attrs = self.attributes.value() check = self.check.value() rval = self.check_value.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))
class ImageMetadataAttributeCheckTrigger(BaseTrigger): __trigger_name__ = 'attributecheck' __description__ = 'triggers if a named image attribute matches the given condition' __ops__ = { '=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x == y), '!=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x != y), '>': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x > y), '<': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x < y), '>=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x >= y), '<=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x <= y), 'exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: bool(x)), 'not_exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: not bool(x)), 'like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: bool(re.match(y, x))), 'not_like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: not bool(re.match(y, x))), 'in': CheckOperation( requires_rvalue=True, eval_function=lambda x, y: x in [z.strip() for z in y.split(',')]), 'not_in': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x not in [z.strip() for z in y.split(',')]) } __valid_attributes__ = { 'size': lambda x: x.size, 'architecture': lambda x: x.docker_data_json.get('Architecture') if x.docker_data_json else None, 'os_type': lambda x: x.docker_data_json.get('Os') if x.docker_data_json else None, 'distro': lambda x: x.distro_name, 'distro_version': lambda x: x.distro_version, 'like_distro': lambda x: x.like_distro, 'layer_count': lambda x: len(x.layers_json) if x.layers_json else 0 } __checks__ = CheckOperations(__ops__) __value_validator__ = lambda x: True attribute = EnumStringParameter( name='attributes', description='Attribute name to apply as rvalue to the check operation', enum_values=__valid_attributes__.keys(), is_required=True, sort_order=1) check = EnumStringParameter( name='check', description='The operation to perform the evaluation', enum_values=__ops__.keys(), is_required=True, sort_order=2) check_value = TriggerParameter( name='check_value', description='The lvalue in the check operation.', validator=TypeValidator('string'), sort_order=3) def evaluate(self, image_obj, context): attr = self.attribute.value() check = self.check.value() rval = self.check_value.value() if not attr or not check: return if self.__checks__.get_op(check).requires_rvalue and not rval: # Raise exception or fall thru return 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))
class InstructionCheckTrigger(ParameterizedDockerfileModeBaseTrigger): __trigger_name__ = "instruction" __description__ = "Triggers if any directives in the list are found to match the described condition in the dockerfile." instruction = EnumStringParameter( name="instruction", example_str="from", description="The Dockerfile instruction to check.", enum_values=DIRECTIVES, is_required=True, related_to="check", sort_order=1, ) operator = EnumStringParameter( name="check", example_str="=", description="The type of check to perform.", enum_values=CONDITIONS, is_required=True, related_to="directive, check_value", sort_order=2, ) compare_to = TriggerParameter( name="value", example_str="scratch", description="The value to check the dockerfile instruction against.", is_required=False, related_to="directive, check", validator=TypeValidator("string"), sort_order=3, ) _operations_requiring_check_val = [ "=", "!=", "like", "not_like", "in", "not_in" ] ops = { "=": lambda x, y: x == y, "!=": lambda x, y: x != y, "exists": lambda x, y: True, "not_exists": lambda x, y: False, "like": lambda x, y: bool(re.match(y, x)), "not_like": lambda x, y: not bool(re.match(y, x)), "in": lambda x, y: x in [z.strip() for z in y.split(",")], "not_in": lambda x, y: x not in [z.strip() for z in y.split(",")], } def _evaluate(self, image_obj, context): directive = (self.instruction.value() ) # Note: change from multiple values to a single value condition = self.operator.value(default_if_none="") check_value = self.compare_to.value() operation = self.ops.get(condition) if condition in self._operations_requiring_check_val and check_value is None: return if not condition or not directive: return df = context.data.get("prepared_dockerfile") for directive_name, lines in [ x for x in list(df.items()) if x[0] == directive ]: for l in lines: l = l[len(directive_name):].strip() if operation(l, check_value): self._fire( msg= "Dockerfile directive '{}' check '{}' matched against '{}' for line '{}'" .format( directive_name, condition, check_value if check_value else "", l, )) upper_keys = set([x.upper() for x in list(df.keys())]) if condition == "not_exists" and directive not in upper_keys: self._fire( msg= "Dockerfile directive '{}' not found, matching condition '{}' check" .format(directive, condition))
class RequiredPackageTrigger(BaseTrigger): __trigger_name__ = 'required_package' __description__ = 'Triggers if the specified package and optionally a specific version is not found in the image.' pkg_name = TriggerParameter( name='name', example_str='libssl', description='Name of package that must be found installed in image.', is_required=True, validator=TypeValidator('string'), sort_order=1) pkg_version = TriggerParameter( name='version', example_str='1.10.3rc3', description='Optional version of package for exact version match.', is_required=False, validator=TypeValidator('string'), sort_order=2) version_comparison = EnumStringParameter( name='version_match_type', example_str='exact', enum_values=['exact', 'minimum'], is_required=False, description= 'The type of comparison to use for version if a version is provided.', sort_order=3) def evaluate(self, image_obj, context): name = self.pkg_name.value() version = self.pkg_version.value() comparison = self.version_comparison.value(default_if_none='exact') found = False # 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 == name).all(): if version is None: found = True break elif comparison == 'exact': if img_pkg.fullversion != version: self._fire( msg="Required input package (" + str(img_pkg.name) + ") is present (" + str(img_pkg.fullversion) + "), but not at the version specified in policy (" + str(name) + ")") found = True break elif comparison == 'minimum': if img_pkg.fullversion != version: # 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, version) < 0: self._fire( msg="Required min-version input package (" + str(img_pkg.name) + ") is present (" + str(img_pkg.fullversion) + "), but is lower version than what is specified in policy (" + str(version) + ")") # >=, so ok found = True break if not found: if version and comparison != 'name_only': self._fire( msg= "Required input package ({},{}) is not present in container image" .format(str(name), str(version))) else: self._fire( msg= "Required input package ({}) is not present in container image" .format(str(name)))
class FileAttributeMatchTrigger(BaseTrigger): __trigger_name__ = "attribute_match" __description__ = "Triggers if a filename exists in the container that has attributes that match those which are provided . This check has a performance impact on policy evaluation." filename = TriggerParameter( validator=TypeValidator("string"), name="filename", example_str="/etc/passwd", description="Filename to check against provided checksum.", is_required=True, sort_order=1, ) checksum_algo = EnumStringParameter( name="checksum_algorithm", enum_values=["sha256"], example_str="sha256", description="Checksum algorithm", is_required=False, sort_order=2, ) checksum = TriggerParameter( validator=TypeValidator("string"), name="checksum", example_str="832cd0f75b227d13aac82b1f70b7f90191a4186c151f9db50851d209c45ede11", description="Checksum of file.", is_required=False, sort_order=3, ) checksum_op = EnumStringParameter( name="checksum_match", enum_values=["equals", "not_equals"], example_str="equals", description="Checksum operation to perform.", is_required=False, sort_order=4, ) mode = TriggerParameter( validator=TypeValidator("string"), name="mode", example_str="00644", description="File mode of file.", is_required=False, sort_order=5, ) mode_op = EnumStringParameter( name="mode_op", enum_values=["equals", "not_equals"], example_str="equals", description="File mode operation to perform.", is_required=False, sort_order=6, ) skip_if_file_missing = BooleanStringParameter( name="skip_missing", example_str="true", description="If set to true, do not fire this trigger if the file is not present. If set to false, fire this trigger ignoring the other parameter settings.", is_required=False, sort_order=7, ) def evaluate(self, image_obj, context): filename = self.filename.value() checksum_algo = self.checksum_algo.value(default_if_none="sha256") checksum = self.checksum.value() checksum_op = self.checksum_op.value(default_if_none="equals") mode = self.mode.value() mode_op = self.mode_op.value(default_if_none="equals") skip_if_file_missing = self.skip_if_file_missing.value(default_if_none=True) filedetails = {} if hasattr(context, "data"): filedetails = context.data.get("filedetail") fire_params = {} filedetail = filedetails.get(filename, None) if filedetail: # checksum checks if checksum and checksum_op and checksum_algo: file_checksum = None if checksum_algo == "sha256": file_checksum = filedetail.get("sha256_checksum", "") if checksum_op == "equals" and file_checksum == checksum: fire_params[ "checksum" ] = "checksum={} op={} specified_checksum={}".format( file_checksum, checksum_op, checksum ) elif checksum_op == "not_equals" and file_checksum != checksum: fire_params[ "checksum" ] = "checksum={} op={} specified_checksum={}".format( file_checksum, checksum_op, checksum ) else: return # mode checks if mode and mode_op: file_mode = filedetail.get("mode", 0) file_mode_cmp = oct(stat.S_IMODE(file_mode)) input_mode_cmp = oct(int(mode, 8)) if mode_op == "equals" and file_mode_cmp == input_mode_cmp: fire_params["mode"] = "mode={} op={} specified_mode={}".format( file_mode_cmp, mode_op, input_mode_cmp ) elif mode_op == "not_equals" and file_mode_cmp != input_mode_cmp: fire_params["mode"] = "mode={} op={} specified_mode={}".format( file_mode_cmp, mode_op, input_mode_cmp ) else: return else: # case where file doesn't exist if skip_if_file_missing: return fire_params["skip"] = "skip_missing=False" if fire_params: msg = "filename={}".format(filename) for k in fire_params.keys(): msg += " and {}".format(fire_params[k]) self._fire(msg=msg)
class FileAttributeMatchTrigger(BaseTrigger): __trigger_name__ = 'attribute_match' __description__ = 'Triggers if a filename exists in the container that has attributes that match those which are provided . This check has a performance impact on policy evaluation.' filename = TriggerParameter( validator=TypeValidator('string'), name='filename', example_str='/etc/passwd', description='Filename to check against provided checksum.', is_required=True, sort_order=1) checksum_algo = EnumStringParameter(name='checksum_algorithm', enum_values=['sha256'], example_str='sha256', description='Checksum algorithm', is_required=False, sort_order=2) checksum = TriggerParameter( validator=TypeValidator('string'), name='checksum', example_str= '832cd0f75b227d13aac82b1f70b7f90191a4186c151f9db50851d209c45ede11', description='Checksum of file.', is_required=False, sort_order=3) checksum_op = EnumStringParameter( name='checksum_match', enum_values=['equals', 'not_equals'], example_str='equals', description='Checksum operation to perform.', is_required=False, sort_order=4) mode = TriggerParameter(validator=TypeValidator('string'), name='mode', example_str='00644', description='File mode of file.', is_required=False, sort_order=5) mode_op = EnumStringParameter( name='mode_op', enum_values=['equals', 'not_equals'], example_str='equals', description='File mode operation to perform.', is_required=False, sort_order=6) skip_if_file_missing = BooleanStringParameter( name='skip_missing', example_str='true', description= 'If set to true, do not fire this trigger if the file is not present. If set to false, fire this trigger ignoring the other parameter settings.', is_required=False, sort_order=7) def evaluate(self, image_obj, context): filename = self.filename.value() checksum_algo = self.checksum_algo.value(default_if_none='sha256') checksum = self.checksum.value() checksum_op = self.checksum_op.value(default_if_none='equals') mode = self.mode.value() mode_op = self.mode_op.value(default_if_none='equals') skip_if_file_missing = self.skip_if_file_missing.value( default_if_none=True) files = [] if hasattr(context, 'data'): filedetails = context.data.get('filedetail') fire_params = {} filedetail = filedetails.get(filename, None) if filedetail: # checksum checks if checksum and checksum_op and checksum_algo: file_checksum = None if checksum_algo == 'sha256': file_checksum = filedetail.get('sha256_checksum', "") if checksum_op == 'equals' and file_checksum == checksum: fire_params[ 'checksum'] = "checksum={} op={} specified_checksum={}".format( file_checksum, checksum_op, checksum) elif checksum_op == 'not_equals' and file_checksum != checksum: fire_params[ 'checksum'] = "checksum={} op={} specified_checksum={}".format( file_checksum, checksum_op, checksum) else: return # mode checks if mode and mode_op: file_mode = filedetail.get('mode', 0) file_mode_cmp = oct(stat.S_IMODE(file_mode)) input_mode_cmp = oct(int(mode, 8)) if mode_op == 'equals' and file_mode_cmp == input_mode_cmp: fire_params[ 'mode'] = "mode={} op={} specified_mode={}".format( file_mode_cmp, mode_op, input_mode_cmp) elif mode_op == 'not_equals' and file_mode_cmp != input_mode_cmp: fire_params[ 'mode'] = "mode={} op={} specified_mode={}".format( file_mode_cmp, mode_op, input_mode_cmp) else: return else: # case where file doesn't exist if skip_if_file_missing: return fire_params['skip'] = "skip_missing=False" if fire_params: msg = "filename={}".format(filename) for k in fire_params.keys(): msg += " and {}".format(fire_params[k]) self._fire(msg=msg)
class DirectiveCheckTrigger(BaseTrigger): __trigger_name__ = 'DIRECTIVECHECK' __description__ = 'Triggers if any directives in the list are found to match the described condition in the dockerfile' directives = EnumCommaDelimStringListParameter( name='directives', description='The Dockerfile instruction to check', enum_values=DIRECTIVES, is_required=True, related_to='check') check = EnumStringParameter(name='check', description='The type of check to perform', enum_values=CONDITIONS, is_required=True, related_to='directive, check_value') check_value = TriggerParameter( name='check_value', description='The value to check the dockerfile instruction against', is_required=False, related_to='directive, check', validator=TypeValidator("string")) _conditions_requiring_check_val = ['=', '!=', 'like', 'not_like'] ops = { '=': lambda x, y: x == y, '!=': lambda x, y: x != y, 'exists': lambda x, y: True, 'not_exists': lambda x, y: False, 'like': lambda x, y: bool(re.match(y, x)), 'not_like': lambda x, y: not bool(re.match(y, x)) } 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( self.directives.value(default_if_none=[]) ) # Note: change from multiple values to a single value condition = self.check.value(default_if_none='') check_value = self.check_value.value(default_if_none=[]) operation = self.ops.get(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))
class ImageMetadataAttributeCheckTrigger(BaseTrigger): __trigger_name__ = 'attribute' __description__ = 'Triggers if a named image metadata value matches the given condition.' __ops__ = { '=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x == y), '!=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x != y), '>': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x > y), '<': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x < y), '>=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x >= y), '<=': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x <= y), 'exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: bool(x)), 'not_exists': CheckOperation(requires_rvalue=False, eval_function=lambda x, y: not bool(x)), 'like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: bool(re.match(y, x))), 'not_like': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: not bool(re.match(y, x))), 'in': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x in [z.strip() for z in y.split(',')]), 'not_in': CheckOperation(requires_rvalue=True, eval_function=lambda x, y: x not in [z.strip() for z in y.split(',')]) } __valid_attributes__ = { 'size': (lambda x: x.size, RegexParamValidator(regex=BYTES_REGEX.pattern)), 'architecture': (lambda x: x.docker_data_json.get('Architecture') if x.docker_data_json else None, TypeValidator('string')), 'os_type': (lambda x: x.docker_data_json.get('Os', x.docker_data_json.get('os')) if x.docker_data_json else None, TypeValidator('string')), 'distro': (lambda x: x.distro_name, TypeValidator('string')), 'distro_version': (lambda x: x.distro_version, TypeValidator('string')), 'like_distro': (lambda x: x.like_distro, TypeValidator('string')), 'layer_count': (lambda x: len(x.layers_json) if x.layers_json else 0, IntegerValidator()) } attribute = EnumStringParameter(name='attribute', example_str='size', description='Attribute name to be checked.', enum_values=list(__valid_attributes__.keys()), is_required=True, sort_order=1) check = EnumStringParameter(name='check', example_str='>', description='The operation to perform the evaluation.', enum_values=list(__ops__.keys()), is_required=True, sort_order=2) _check_value_validator = LinkedValidator(discriminator_parameter='attribute', default_validator=TypeValidator('string'), value_map={k: v[1] for k, v in __valid_attributes__.items()}) check_value = TriggerParameter(name='value', example_str='1073741824', description='Value used in comparison.', validator=_check_value_validator, is_required=False, sort_order=3) def evaluate(self, image_obj, context): attr = self.attribute.value() check = self.check.value() rval = self.check_value.value() if not attr or not check: return op = self.__ops__.get(check) if op is None or op.requires_rvalue and not rval: # Raise exception or fall thru return img_val = self.__valid_attributes__[attr][0](image_obj) # Make consistent types (specifically for int/float/str) if type(img_val) in [int, float, str]: if attr == 'size': rval = convert_bytes_size(rval) else: rval = type(img_val)(rval) if op.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))
class SecretContentChecksTrigger(BaseTrigger): __trigger_name__ = 'content_regex_checks' __description__ = 'Triggers if the secret content search analyzer has found any matches with the configured and named regexes. Checks can be configured to trigger if a match is found or is not found (selected using match_type parameter). Matches are filtered by the content_regex_name and filename_regex if they are set. The content_regex_name shoud be a value from the "secret_search" section of the analyzer_config.yaml.' secret_contentregexp = TriggerParameter( name='content_regex_name', validator=TypeValidator('string'), example_str=default_included_regex_names[0], description= 'Name of content regexps configured in the analyzer that match if found in the image, instead of matching all. Names available by default are: {}.' .format(default_included_regex_names), sort_order=1) name_regexps = TriggerParameter( name='filename_regex', validator=TypeValidator('string'), example_str='/etc/.*', description='Regexp to filter the content matched files by.', sort_order=2) match_type = EnumStringParameter( name='match_type', enum_values=['notfound', 'found'], example_str='found', description= 'Set to define the type of match - trigger if match is found (default) or not found.', is_required=False, sort_order=3) def evaluate(self, image_obj, context): match_filter = self.secret_contentregexp.value(default_if_none=[]) name_filter = self.name_regexps.value() name_re = re.compile( name_filter) if self.name_regexps.value() else None match_type = self.match_type.value(default_if_none="found") if match_filter: matches = [base64.b64encode(ensure_bytes(x)) for x in match_filter] matches_decoded = match_filter else: matches = [] matches_decoded = [] found = False for thefile, regexps in list( context.data.get('secret_content_regexp', {}).items()): thefile = ensure_str(thefile) if not regexps: continue if regexps and (not name_re or name_re.match(thefile)): for regexp in list(regexps.keys()): decoded_regexp = ensure_str( base64.b64decode(ensure_bytes(regexp))) try: regexp_name, theregexp = decoded_regexp.split("=", 1) except: regexp_name = None theregexp = decoded_regexp if not matches: found = True elif regexp in matches or theregexp in matches_decoded: found = True elif regexp_name and regexp_name in matches_decoded: found = True if found and match_type == 'found': self._fire( msg= 'Secret content search analyzer found regexp match in container: file={} regexp={}' .format(thefile, decoded_regexp)) if not found and match_type == 'notfound': f_filter = name_filter if not f_filter: f_filter = '*' m_filter = match_filter if not m_filter: m_filter = 'all' self._fire( msg= 'Secret content search analyzer did not find regexp match in container: filename_regex={} content_regex_name={}' .format(f_filter, m_filter))
class DirectiveCheckTrigger(BaseTrigger): __lifecycle_state__ = LifecycleStates.deprecated __trigger_name__ = 'directivecheck' __description__ = 'Triggers if any directives in the list are found to match the described condition in the dockerfile' directive = EnumStringParameter( name='directives', example_str='COPY', description='The Dockerfile instruction to check', enum_values=DIRECTIVES, is_required=True, related_to='check', sort_order=1) check = EnumStringParameter(name='check', example_str='=', description='The type of check to perform', enum_values=CONDITIONS, is_required=True, related_to='directive, check_value', sort_order=2) check_value = TriggerParameter( name='check_value', example_str='./app /app', description='The value to check the dockerfile instruction against', is_required=False, related_to='directive, check', validator=TypeValidator("string"), sort_order=3) _conditions_requiring_check_val = [ '=', '!=', 'like', 'not_like', 'in', 'not_in' ] ops = { '=': lambda x, y: x == y, '!=': lambda x, y: x != y, 'exists': lambda x, y: True, 'not_exists': lambda x, y: False, 'like': lambda x, y: bool(re.match(y, x)), 'not_like': lambda x, y: not bool(re.match(y, x)), 'in': lambda x, y: x in [z.strip() for z in y.split(',')], 'not_in': lambda x, y: x not in [z.strip() for z in y.split(',')] } 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 directive = self.directive.value( ) # Note: change from multiple values to a single value condition = self.check.value(default_if_none='') check_value = self.check_value.value(default_if_none=[]) operation = self.ops.get(condition) if not condition or not directive: return df = context.data.get('prepared_dockerfile') for directive_name, lines in filter(lambda x: x[0] == directive, df.items()): for l in lines: l = l[len(directive_name):].strip() if operation(l, check_value): self._fire( msg= "Dockerfile directive '{}' check '{}' matched against '{}' for line '{}'" .format(directive_name, condition, check_value if check_value else '', l)) upper_keys = set(map(lambda x: x.upper(), df.keys())) if condition == 'not_exists' and directive not in upper_keys: self._fire( msg= "Dockerfile directive '{}' not found, matching condition '{}' check" .format(directive, condition))
class InstructionCheckTrigger(ParameterizedDockerfileModeBaseTrigger): __trigger_name__ = 'instruction' __description__ = 'Triggers if any directives in the list are found to match the described condition in the dockerfile.' instruction = EnumStringParameter( name='instruction', example_str='from', description='The Dockerfile instruction to check.', enum_values=DIRECTIVES, is_required=True, related_to='check', sort_order=1) operator = EnumStringParameter(name='check', example_str='=', description='The type of check to perform.', enum_values=CONDITIONS, is_required=True, related_to='directive, check_value', sort_order=2) compare_to = TriggerParameter( name='value', example_str='scratch', description='The value to check the dockerfile instruction against.', is_required=False, related_to='directive, check', validator=TypeValidator("string"), sort_order=3) _operations_requiring_check_val = [ '=', '!=', 'like', 'not_like', 'in', 'not_in' ] ops = { '=': lambda x, y: x == y, '!=': lambda x, y: x != y, 'exists': lambda x, y: True, 'not_exists': lambda x, y: False, 'like': lambda x, y: bool(re.match(y, x)), 'not_like': lambda x, y: not bool(re.match(y, x)), 'in': lambda x, y: x in [z.strip() for z in y.split(',')], 'not_in': lambda x, y: x not in [z.strip() for z in y.split(',')] } def _evaluate(self, image_obj, context): directive = self.instruction.value( ) # Note: change from multiple values to a single value condition = self.operator.value(default_if_none='') check_value = self.compare_to.value() operation = self.ops.get(condition) if condition in self._operations_requiring_check_val and check_value is None: return if not condition or not directive: return df = context.data.get('prepared_dockerfile') for directive_name, lines in [ x for x in list(df.items()) if x[0] == directive ]: for l in lines: l = l[len(directive_name):].strip() if operation(l, check_value): self._fire( msg= "Dockerfile directive '{}' check '{}' matched against '{}' for line '{}'" .format(directive_name, condition, check_value if check_value else '', l)) upper_keys = set([x.upper() for x in list(df.keys())]) if condition == 'not_exists' and directive not in upper_keys: self._fire( msg= "Dockerfile directive '{}' not found, matching condition '{}' check" .format(directive, condition))