Skip to content

Commit

Permalink
feat: add docker build detection (#409)
Browse files Browse the repository at this point in the history
This PR adds support for the detection of Dockerfiles, so as to cover scenarios where Docker gets used as a build tool.

* Docker presence is detected by finding files either named Dockerfile or in the formats *.Dockerfile or Dockerfile.* to cover different naming conventions of dockerfiles, e.g. dev.Dockerfile or like Macaron's own Dockerfile.base and Dockerfile.final. This is defined in defaults.ini under [builder.docker]

* The supported build command keyword is build, and supported deploy command keyword is push, defined in defaults.ini under [builder.docker]

*For CI deploy commands the GitHub action docker/build-push-action is supported, defined in defaults.ini under [builder.docker.ci.deploy]

Signed-off-by: Tim Yarkov <[email protected]>
  • Loading branch information
timyarkov authored Sep 8, 2023
1 parent 32f2f6d commit d15fffb
Show file tree
Hide file tree
Showing 13 changed files with 473 additions and 1 deletion.
9 changes: 9 additions & 0 deletions scripts/dev_scripts/integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ python $COMPARE_DEPS $DEP_RESULT $DEP_EXPECTED || log_fail

python $COMPARE_JSON_OUT $JSON_RESULT $JSON_EXPECTED || log_fail

echo "timyarkov/docker_test: Analyzing the repo path, the branch name and the commit digest"
echo "when automatic dependency resolution is skipped, for a project using docker as a build tool."
echo -e "----------------------------------------------------------------------------------\n"
JSON_EXPECTED=$WORKSPACE/tests/e2e/expected_results/docker_test/docker_test.json
JSON_RESULT=$WORKSPACE/output/reports/github_com/timyarkov/docker_test/docker_test.json
$RUN_MACARON analyze -rp https://github.com/timyarkov/docker_test -b main -d 404a51a2f38c4470af6b32e4e00b5318c2d7c0cc --skip-deps || log_fail

python $COMPARE_JSON_OUT $JSON_RESULT $JSON_EXPECTED || log_fail

echo -e "\n----------------------------------------------------------------------------------"
echo "apache/maven: Analyzing with PURL and repository path without dependency resolution."
echo -e "----------------------------------------------------------------------------------\n"
Expand Down
18 changes: 18 additions & 0 deletions src/macaron/config/defaults.ini
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,24 @@ deploy_arg =
[builder.poetry.ci.deploy]
github_actions = pypa/gh-action-pypi-publish

# This is the spec for trusted Docker build tool usages.
[builder.docker]
entry_conf =
# Also account for if there's multiple dockerfiles, e.g. test.Dockerfile
build_configs =
Dockerfile
Dockerfile.*
*.Dockerfile
builder =
docker
build_arg =
build
deploy_arg =
push
[builder.docker.ci.deploy]
github_actions =
docker/build-push-action

# This is the spec for GitHub Actions CI.
[ci.github_actions]
entry_conf =
Expand Down
3 changes: 2 additions & 1 deletion src/macaron/slsa_analyzer/build_tool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
"""The build_tool package contains the supported build tools for Macaron."""

from .base_build_tool import BaseBuildTool
from .docker import Docker
from .gradle import Gradle
from .maven import Maven
from .pip import Pip
from .poetry import Poetry

# The list of supported build tools. The order of the list determine the order
# in which each build tool is checked against the target repository.
BUILD_TOOLS: list[BaseBuildTool] = [Gradle(), Maven(), Poetry(), Pip()]
BUILD_TOOLS: list[BaseBuildTool] = [Gradle(), Maven(), Poetry(), Pip(), Docker()]
92 changes: 92 additions & 0 deletions src/macaron/slsa_analyzer/build_tool/docker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.

"""This module contains the Docker class which inherits BaseBuildTool.
This module is used to work with repositories that use Docker as a build tool.
"""

from macaron.config.defaults import defaults
from macaron.dependency_analyzer.dependency_resolver import NoneDependencyAnalyzer
from macaron.slsa_analyzer.build_tool.base_build_tool import BaseBuildTool, file_exists


class Docker(BaseBuildTool):
"""This class contains the information of Docker when used as a build tool."""

def __init__(self) -> None:
"""Initialize instance."""
super().__init__(name="docker")

def load_defaults(self) -> None:
"""Load the default values from defaults.ini."""
if "builder.docker" in defaults:
for item in defaults["builder.docker"]:
if hasattr(self, item):
setattr(self, item, defaults.get_list("builder.docker", item))

if "builder.docker.ci.deploy" in defaults:
for item in defaults["builder.docker.ci.deploy"]:
if item in self.ci_deploy_kws:
self.ci_deploy_kws[item] = defaults.get_list("builder.docker.ci.deploy", item)

def is_detected(self, repo_path: str) -> bool:
"""Return True if this build tool is used in the target repo.
Parameters
----------
repo_path : str
The path to the target repo.
Returns
-------
bool
True if this build tool is detected, else False.
"""
for file in self.build_configs:
if file_exists(repo_path, file):
return True

return False

def prepare_config_files(self, wrapper_path: str, build_dir: str) -> bool:
"""Make necessary preparations for using this build tool.
Parameters
----------
wrapper_path : str
The path where all necessary wrapper files are located.
build_dir : str
The path of the build dir. This is where all files are copied to.
Returns
-------
bool
True if succeed else False.
"""
# TODO: Future dependency analysis may require some preprocessing, e.g.
# saving images to tar files. Need to investigate when implementing
# and work with this method accordingly.

return False

def get_dep_analyzer(self, repo_path: str) -> NoneDependencyAnalyzer:
"""Create a DependencyAnalyzer for the Docker build tool. Currently unimplemented.
Parameters
----------
repo_path: str
The path to the target repo.
Returns
-------
NoneDependencyAnalyser
The NoneDependencyAnalyser object.
Raises
------
DependencyAnalyzerError
"""
# TODO: Find a suitable tool to analyse dependencies; as of now Syft
# seems to be a good option, but need to experiment.
return NoneDependencyAnalyzer()
20 changes: 20 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from macaron.config.defaults import create_defaults, defaults, load_defaults
from macaron.database.table_definitions import Analysis, Component, Repository
from macaron.slsa_analyzer.analyze_context import AnalyzeContext
from macaron.slsa_analyzer.build_tool.docker import Docker
from macaron.slsa_analyzer.build_tool.gradle import Gradle
from macaron.slsa_analyzer.build_tool.maven import Maven
from macaron.slsa_analyzer.build_tool.pip import Pip
Expand Down Expand Up @@ -148,6 +149,25 @@ def pip_tool(setup_test) -> Pip: # type: ignore # pylint: disable=unused-argume
return pip


@pytest.fixture(autouse=True)
def docker_tool(setup_test) -> Docker: # type: ignore # pylint: disable=unused-argument
"""Create a Docker tool instance.
Parameters
----------
setup_test
Depends on setup_test fixture.
Returns
-------
Docker
The Docker instance.
"""
docker = Docker()
docker.load_defaults()
return docker


class MockGitHubActions(GitHubActions):
"""Mock the GitHubActions class."""

Expand Down
Loading

0 comments on commit d15fffb

Please sign in to comment.