Skip to content

Commit 358ab75

Browse files
authored
feat: add docker build detection (#409)
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]>
1 parent 2bcc3b2 commit 358ab75

File tree

13 files changed

+473
-1
lines changed

13 files changed

+473
-1
lines changed

scripts/dev_scripts/integration_tests.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ python $COMPARE_DEPS $DEP_RESULT $DEP_EXPECTED || log_fail
9090

9191
python $COMPARE_JSON_OUT $JSON_RESULT $JSON_EXPECTED || log_fail
9292

93+
echo "timyarkov/docker_test: Analyzing the repo path, the branch name and the commit digest"
94+
echo "when automatic dependency resolution is skipped, for a project using docker as a build tool."
95+
echo -e "----------------------------------------------------------------------------------\n"
96+
JSON_EXPECTED=$WORKSPACE/tests/e2e/expected_results/docker_test/docker_test.json
97+
JSON_RESULT=$WORKSPACE/output/reports/github.com/timyarkov/docker_test/docker_test.json
98+
$RUN_MACARON analyze -rp https://github.com/timyarkov/docker_test -b main -d 404a51a2f38c4470af6b32e4e00b5318c2d7c0cc --skip-deps || log_fail
99+
100+
python $COMPARE_JSON_OUT $JSON_RESULT $JSON_EXPECTED || log_fail
101+
93102
echo -e "\n----------------------------------------------------------------------------------"
94103
echo "apache/maven: Analyzing with PURL and repository path without dependency resolution."
95104
echo -e "----------------------------------------------------------------------------------\n"

src/macaron/config/defaults.ini

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,24 @@ deploy_arg =
300300
[builder.poetry.ci.deploy]
301301
github_actions = pypa/gh-action-pypi-publish
302302

303+
# This is the spec for trusted Docker build tool usages.
304+
[builder.docker]
305+
entry_conf =
306+
# Also account for if there's multiple dockerfiles, e.g. test.Dockerfile
307+
build_configs =
308+
Dockerfile
309+
Dockerfile.*
310+
*.Dockerfile
311+
builder =
312+
docker
313+
build_arg =
314+
build
315+
deploy_arg =
316+
push
317+
[builder.docker.ci.deploy]
318+
github_actions =
319+
docker/build-push-action
320+
303321
# This is the spec for GitHub Actions CI.
304322
[ci.github_actions]
305323
entry_conf =

src/macaron/slsa_analyzer/build_tool/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
"""The build_tool package contains the supported build tools for Macaron."""
55

66
from .base_build_tool import BaseBuildTool
7+
from .docker import Docker
78
from .gradle import Gradle
89
from .maven import Maven
910
from .pip import Pip
1011
from .poetry import Poetry
1112

1213
# The list of supported build tools. The order of the list determine the order
1314
# in which each build tool is checked against the target repository.
14-
BUILD_TOOLS: list[BaseBuildTool] = [Gradle(), Maven(), Poetry(), Pip()]
15+
BUILD_TOOLS: list[BaseBuildTool] = [Gradle(), Maven(), Poetry(), Pip(), Docker()]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
3+
4+
"""This module contains the Docker class which inherits BaseBuildTool.
5+
6+
This module is used to work with repositories that use Docker as a build tool.
7+
"""
8+
9+
from macaron.config.defaults import defaults
10+
from macaron.dependency_analyzer.dependency_resolver import NoneDependencyAnalyzer
11+
from macaron.slsa_analyzer.build_tool.base_build_tool import BaseBuildTool, file_exists
12+
13+
14+
class Docker(BaseBuildTool):
15+
"""This class contains the information of Docker when used as a build tool."""
16+
17+
def __init__(self) -> None:
18+
"""Initialize instance."""
19+
super().__init__(name="docker")
20+
21+
def load_defaults(self) -> None:
22+
"""Load the default values from defaults.ini."""
23+
if "builder.docker" in defaults:
24+
for item in defaults["builder.docker"]:
25+
if hasattr(self, item):
26+
setattr(self, item, defaults.get_list("builder.docker", item))
27+
28+
if "builder.docker.ci.deploy" in defaults:
29+
for item in defaults["builder.docker.ci.deploy"]:
30+
if item in self.ci_deploy_kws:
31+
self.ci_deploy_kws[item] = defaults.get_list("builder.docker.ci.deploy", item)
32+
33+
def is_detected(self, repo_path: str) -> bool:
34+
"""Return True if this build tool is used in the target repo.
35+
36+
Parameters
37+
----------
38+
repo_path : str
39+
The path to the target repo.
40+
41+
Returns
42+
-------
43+
bool
44+
True if this build tool is detected, else False.
45+
"""
46+
for file in self.build_configs:
47+
if file_exists(repo_path, file):
48+
return True
49+
50+
return False
51+
52+
def prepare_config_files(self, wrapper_path: str, build_dir: str) -> bool:
53+
"""Make necessary preparations for using this build tool.
54+
55+
Parameters
56+
----------
57+
wrapper_path : str
58+
The path where all necessary wrapper files are located.
59+
build_dir : str
60+
The path of the build dir. This is where all files are copied to.
61+
62+
Returns
63+
-------
64+
bool
65+
True if succeed else False.
66+
"""
67+
# TODO: Future dependency analysis may require some preprocessing, e.g.
68+
# saving images to tar files. Need to investigate when implementing
69+
# and work with this method accordingly.
70+
71+
return False
72+
73+
def get_dep_analyzer(self, repo_path: str) -> NoneDependencyAnalyzer:
74+
"""Create a DependencyAnalyzer for the Docker build tool. Currently unimplemented.
75+
76+
Parameters
77+
----------
78+
repo_path: str
79+
The path to the target repo.
80+
81+
Returns
82+
-------
83+
NoneDependencyAnalyser
84+
The NoneDependencyAnalyser object.
85+
86+
Raises
87+
------
88+
DependencyAnalyzerError
89+
"""
90+
# TODO: Find a suitable tool to analyse dependencies; as of now Syft
91+
# seems to be a good option, but need to experiment.
92+
return NoneDependencyAnalyzer()

tests/conftest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from macaron.config.defaults import create_defaults, defaults, load_defaults
1111
from macaron.database.table_definitions import Analysis, Component, Repository
1212
from macaron.slsa_analyzer.analyze_context import AnalyzeContext
13+
from macaron.slsa_analyzer.build_tool.docker import Docker
1314
from macaron.slsa_analyzer.build_tool.gradle import Gradle
1415
from macaron.slsa_analyzer.build_tool.maven import Maven
1516
from macaron.slsa_analyzer.build_tool.pip import Pip
@@ -148,6 +149,25 @@ def pip_tool(setup_test) -> Pip: # type: ignore # pylint: disable=unused-argume
148149
return pip
149150

150151

152+
@pytest.fixture(autouse=True)
153+
def docker_tool(setup_test) -> Docker: # type: ignore # pylint: disable=unused-argument
154+
"""Create a Docker tool instance.
155+
156+
Parameters
157+
----------
158+
setup_test
159+
Depends on setup_test fixture.
160+
161+
Returns
162+
-------
163+
Docker
164+
The Docker instance.
165+
"""
166+
docker = Docker()
167+
docker.load_defaults()
168+
return docker
169+
170+
151171
class MockGitHubActions(GitHubActions):
152172
"""Mock the GitHubActions class."""
153173

0 commit comments

Comments
 (0)