Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
from colin.core.checks.abstract_check import DockerfileAbstractCheck
from colin.core.checks.dockerfile import InstructionCountAbstractCheck
from colin.core.checks.fmf_check import FMFAbstractCheck
from colin.core.exceptions import ColinException
from colin.core.result import CheckResult
from colin.utils.cont import ImageName
class FromTagNotLatestCheck(FMFAbstractCheck, DockerfileAbstractCheck):
name = "from_tag_not_latest"
def check(self, target):
if not target.instance.parent_images:
raise ColinException("Cannot find FROM instruction.")
im = ImageName.parse(target.instance.baseimage)
passed = im.tag and im.tag != "latest"
return CheckResult(ok=passed,
description=self.description,
message=self.message,
reference_url=self.reference_url,
check_name=self.name,
logs=[])
def check(self, target):
passed = check_label(labels=self.labels,
required=self.required,
value_regex=self.value_regex,
target_labels=target.labels)
return CheckResult(ok=passed,
description=self.description,
message=self.message,
reference_url=self.reference_url,
check_name=self.name,
logs=[])
class DeprecatedLabelAbstractCheck(ImageAbstractCheck, DockerfileAbstractCheck):
def __init__(self, message, description, reference_url, tags, old_label, new_label):
super(DeprecatedLabelAbstractCheck, self) \
.__init__(message, description, reference_url, tags)
self.old_label = old_label
self.new_label = new_label
def check(self, target):
labels = target.labels
old_present = labels is not None and self.old_label in labels
passed = (not old_present) or (self.new_label in labels)
return CheckResult(ok=passed,
description=self.description,
message=self.message,
return True
elif value_regex:
pattern = re.compile(value_regex)
present_labels = set(labels) & set(target_labels)
for l in present_labels:
if not bool(pattern.search(target_labels[l])):
return False
return True
else:
return False
else:
return not required
class NotLoadedCheck(DockerfileAbstractCheck, ImageAbstractCheck):
def __init__(self, check_name, reason):
self.name = check_name
super(NotLoadedCheck, self).__init__(
message="Check code '{}' {}.".format(check_name, reason),
description="Did you set the right name in the ruleset file?",
reference_url="",
tags=[])
def check(self, target):
raise ColinException(self.message)
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
import logging
from .abstract_check import ImageAbstractCheck, DockerfileAbstractCheck
from .check_utils import check_label
from ..result import CheckResult
logger = logging.getLogger(__name__)
class LabelAbstractCheck(ImageAbstractCheck, DockerfileAbstractCheck):
def __init__(self, message, description, reference_url, tags, labels, required,
value_regex=None):
"""
Abstract check for Dockerfile/Image labels.
:param message: str
:param description: str
:param reference_url: str
:param tags: [str]
:param labels: [str]
:param required: bool
:param value_regex: str (using search method)
"""
super(LabelAbstractCheck, self) \
.__init__(message, description, reference_url, tags)
log = "Value for instruction {} " \
"{}mach regex: '{}'.".format(inst["content"],
"" if match else "does not ",
self.value_regex)
logs.append(log)
logger.debug(log)
return CheckResult(ok=passed,
description=self.description,
message=self.message,
reference_url=self.reference_url,
check_name=self.name,
logs=logs)
class InstructionCountAbstractCheck(DockerfileAbstractCheck):
def __init__(self, message, description, reference_url, tags, instruction, min_count=None,
max_count=None):
super(InstructionCountAbstractCheck, self) \
.__init__(message, description, reference_url, tags)
self.instruction = instruction
self.min_count = min_count
self.max_count = max_count
def check(self, target):
count = len(get_instructions_from_dockerfile_parse(target.instance, self.instruction))
log = "Found {} occurrences of the {} instruction. Needed: min {} | max {}" \
.format(count,
self.instruction,
self.min_count,
logger.debug(log)
passed = True
if self.min_count is not None:
passed = passed and self.min_count <= count
if self.max_count is not None:
passed = passed and count <= self.max_count
return CheckResult(ok=passed,
description=self.description,
message=self.message,
reference_url=self.reference_url,
check_name=self.name,
logs=[log])
class DockerfileLabelAbstractCheck(DockerfileAbstractCheck):
def __init__(self, message, description, reference_url, tags, label, required,
value_regex=None):
super(DockerfileLabelAbstractCheck, self) \
.__init__(message, description, reference_url, tags)
self.label = label
self.required = required
self.value_regex = value_regex
def check(self, target):
labels = target.instance.labels
passed = check_label(labels=self.label,
required=self.required,
value_regex=self.value_regex,
target_labels=labels)
def get_compatible_check_class(cls):
return DockerfileAbstractCheck
logger = logging.getLogger(__name__)
def get_instructions_from_dockerfile_parse(dfp, instruction):
"""
Get the list of instruction dictionary for given instruction name.
(Subset of DockerfileParser.structure only for given instruction.)
:param dfp: DockerfileParser
:param instruction: str
:return: list
"""
return [inst for inst in dfp.structure if inst["instruction"] == instruction]
class InstructionAbstractCheck(DockerfileAbstractCheck):
def __init__(self, message, description, reference_url, tags, instruction, value_regex,
required):
super(InstructionAbstractCheck, self) \
.__init__(message, description, reference_url, tags)
self.instruction = instruction
self.value_regex = value_regex
self.required = required
def check(self, target):
instructions = get_instructions_from_dockerfile_parse(target.instance, self.instruction)
pattern = re.compile(self.value_regex)
logs = []
passed = True
for inst in instructions:
match = bool(pattern.match(inst["value"]))