Skip to content

Commit 7013775

Browse files
committed
feat: add Dockerfile analysis for build command detection
Changes: -Function find_dockerfile_from_job: handles finding Dockerfile inside workflow in 2 cases of workflow jobs: -run and -uses. -Simple DockerNode class, so far it stores mainly the dockerfile path retrieved from workflow -Parsing Dockerfile using dockerfile-parse and RUN instruction commands using bashparser.py -Parsing and storing build commands found in Dockerfiles Signed-off-by: Achraf Maghous <achraf.maghous@oracle.com>
1 parent 4643b74 commit 7013775

File tree

4 files changed

+309
-113
lines changed

4 files changed

+309
-113
lines changed

src/macaron/slsa_analyzer/checks/build_script_check.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,15 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData:
111111
# we parse bash scripts that are reachable through CI only.
112112
result_tables: list[CheckFacts] = []
113113
ci_services = ctx.dynamic_data["ci_services"]
114+
114115
for tool in build_tools:
115116
for ci_info in ci_services:
116117
ci_service: BaseCIService = ci_info["service"]
117118
# Checking if a CI service is discovered for this repo.
118119
if isinstance(ci_service, NoneCIService):
119120
continue
121+
122+
# Process regular workflow build commands
120123
try:
121124
for build_command in ci_service.get_build_tool_commands(
122125
callgraph=ci_info["callgraph"], build_tool=tool
@@ -152,6 +155,38 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData:
152155
except CallGraphError as error:
153156
logger.debug(error)
154157

158+
# Process Docker build commands if the CI service has the method
159+
if hasattr(ci_service, "get_docker_build_commands"):
160+
try:
161+
for build_command in ci_service.get_docker_build_commands(
162+
callgraph=ci_info["callgraph"], build_tool=tool
163+
):
164+
logger.debug("Processing Docker build command %s", build_command)
165+
# For Dockerfile, link to the Dockerfile itself
166+
relative_path = os.path.relpath(build_command["ci_path"], ctx.component.repository.fs_path)
167+
trigger_link = ci_service.api_client.get_file_link(
168+
ctx.component.repository.full_name,
169+
ctx.component.repository.commit_sha,
170+
relative_path,
171+
)
172+
logger.debug("Trigger link for Docker build command: %s", trigger_link)
173+
174+
result_tables.append(
175+
BuildScriptFacts(
176+
build_tool_name=tool.name,
177+
ci_service_name=ci_service.name,
178+
build_trigger=trigger_link,
179+
language=build_command["language"],
180+
language_distributions=None,
181+
language_versions=None,
182+
language_url=None,
183+
build_tool_command=tool.serialize_to_json(build_command["command"]),
184+
confidence=Confidence.HIGH,
185+
)
186+
)
187+
except CallGraphError as error:
188+
logger.debug(error)
189+
155190
return CheckResultData(result_tables=result_tables, result_type=CheckResultType.PASSED)
156191

157192

src/macaron/slsa_analyzer/ci_service/base_ci_service.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,24 @@ def get_third_party_configurations(self) -> list[str]:
280280
"""
281281
return []
282282

283+
def get_docker_build_commands(self, callgraph: CallGraph, build_tool: BaseBuildTool) -> Iterable[BuildToolCommand]:
284+
"""
285+
Traverse the callgraph and find all the reachable Docker build commands.
286+
287+
Parameters
288+
----------
289+
callgraph: CallGraph
290+
The callgraph reachable from the CI workflows.
291+
292+
Yields
293+
------
294+
BuildToolCommand
295+
The object that contains the Docker build command as well useful contextual information.
296+
"""
297+
# By default we assume that there is no Docker build command available for a CI service.
298+
# Each CI service should override this method if a Docker build command is generated for it.
299+
raise CallGraphError("There is no Docker build command for this CI service.")
300+
283301

284302
class NoneCIService(BaseCIService):
285303
"""This class can be used to initialize an empty CI service."""

0 commit comments

Comments
 (0)