Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and Enhance Docker Scout Integration #322

Merged
merged 51 commits into from
Jan 15, 2025
Merged
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6e7e488
Added plugin list subcommand functionality
willis89pr Nov 4, 2024
45a1b6d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 4, 2024
d141ce5
changed subcommand from list to display to avoid python builtin redef…
willis89pr Nov 4, 2024
75afc0c
changed subcommand from list to display to avoid python builtin redef…
willis89pr Nov 5, 2024
555490d
changed subcommand from list to display to avoid python builtin redef…
willis89pr Nov 5, 2024
dbd9fba
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 5, 2024
79a3675
fixed import function
willis89pr Nov 5, 2024
229d8b1
fixed import function
willis89pr Nov 5, 2024
4126841
Merge branch 'main' into CYT-828-add-plugin-command
willis89pr Nov 5, 2024
be48bb5
changed subcommand name to list in click decorator
willis89pr Nov 5, 2024
efb07c6
Merge remote-tracking branch 'origin/CYT-828-add-plugin-command' into…
willis89pr Nov 5, 2024
3f911a5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 5, 2024
261cc6e
Changed subcommand definition name. Added docstring description to su…
willis89pr Nov 5, 2024
fabf213
Merge remote-tracking branch 'origin/CYT-828-add-plugin-command' into…
willis89pr Nov 5, 2024
5e20458
Changed subcommand definition name. Added docstring description to su…
willis89pr Nov 5, 2024
b88b0e7
Added boiler plate for disable commmand.
willis89pr Nov 5, 2024
52e0703
Added disable plugin functionality.
willis89pr Nov 6, 2024
768574d
Added disable subcommand to main.
willis89pr Nov 6, 2024
3a8342c
Added variables for config section and key and changed section to core.
willis89pr Nov 6, 2024
da8554f
Re-implemented disable command with functionality in surfactant/plugi…
willis89pr Nov 6, 2024
be12bfa
Added print disabled plugins to list subcommand
willis89pr Nov 6, 2024
4d27807
Added print disabled plugins to list subcommand.
willis89pr Nov 6, 2024
62657de
Added plugin enable functionality.
willis89pr Nov 11, 2024
40babc5
Merge branch 'main' into CYT-1123-plugin-enable-disable
willis89pr Nov 11, 2024
7ac000a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 11, 2024
c0b4a0b
Update surfactant/cmd/plugin.py
willis89pr Nov 11, 2024
093b047
Update surfactant/cmd/plugin.py
willis89pr Nov 11, 2024
dd4b055
Save.
willis89pr Nov 12, 2024
0ec3b91
Added set_plugins function. Changed formatting of print_plugins
willis89pr Nov 12, 2024
03355a2
Added print_plugins in list command and changed formatting
willis89pr Nov 12, 2024
814d9aa
Merge branch 'CYT-1123-plugin-enable-disable' of https://github.com/L…
willis89pr Nov 12, 2024
c827e88
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 12, 2024
6b78b8d
Update surfactant/plugin/manager.py
willis89pr Nov 12, 2024
4a9f744
Updating local
willis89pr Nov 12, 2024
3ce1d93
Merge branch 'main' into CYT-1123-plugin-enable-disable
willis89pr Nov 12, 2024
ddebfef
Added command declarations in main.
willis89pr Nov 12, 2024
b51f35c
Merged deleted branches.
willis89pr Nov 18, 2024
6707d3a
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Nov 18, 2024
80bd3f7
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Dec 11, 2024
f2182e7
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Dec 18, 2024
1a5d7a4
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Jan 6, 2025
9c901bf
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Jan 13, 2025
0f43447
Merge branch 'main' of https://github.com/LLNL/Surfactant
willis89pr Jan 14, 2025
b7db430
Refactor Docker Scout integration
willis89pr Jan 14, 2025
6ba500f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 14, 2025
82d66cf
Added typing library.
willis89pr Jan 14, 2025
451da02
Merge branch 'cyt-1163-init-docker' of https://github.com/LLNL/Surfac…
willis89pr Jan 14, 2025
ac243f6
Removed redundant init.
willis89pr Jan 14, 2025
b38b4f7
Moved docker scout function into the docker scout class.
willis89pr Jan 14, 2025
97ce9af
Added self to method.
willis89pr Jan 14, 2025
4417da4
Removed init logger statements.
willis89pr Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 48 additions & 28 deletions surfactant/infoextractors/docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,79 @@
import json
import subprocess
import tempfile
from typing import Optional

from loguru import logger

import surfactant.plugin
from surfactant.sbomtypes import SBOM, Software


def is_docker_scout_installed():
# Check that Docker Scout can be run
try:
result = subprocess.run(["docker", "scout"], capture_output=True, check=False)
if result.returncode != 0:
class DockerScoutManager:
def __init__(self) -> None:
self.disable_docker_scout = True
self.docker_scout_installed = False

def check_docker_scout_installed(self) -> None:
"""Check if Docker Scout is installed and update the state accordingly."""
try:
result = subprocess.run(["docker", "scout"], capture_output=True, check=False)
self.docker_scout_installed = result.returncode == 0
except FileNotFoundError:
self.docker_scout_installed = False

self.disable_docker_scout = not self.docker_scout_installed
if not self.docker_scout_installed:
logger.warning("Install Docker Scout to scan containers for additional information")
return False
return True
except FileNotFoundError:
return False

def run_docker_scout(self, filename: str) -> object:
"""Run Docker Scout on the given file and return the results."""
try:
result = subprocess.run(
["docker", "scout", "sbom", "--format", "spdx", f"fs://{filename}"],
capture_output=True,
check=False,
)
if result.returncode != 0:
logger.warning(f"Running Docker Scout on {filename} failed")
return {}
spdx_out = json.loads(result.stdout)
return {"dockerSPDX": spdx_out}
except json.JSONDecodeError as e:
logger.error(f"Failed to parse Docker Scout output for {filename}: {e}")
return {}


# Check if Docker Scout is installed when this Python module gets loaded
disable_docker_scout = not is_docker_scout_installed()
# Initialize DockerScoutManager to check installation status
dsManager = DockerScoutManager()


def supports_file(filetype: str) -> bool:
"""Check if the file type is supported."""
return filetype in ("DOCKER_TAR", "DOCKER_GZIP")


@surfactant.plugin.hookimpl
def extract_file_info(sbom: SBOM, software: Software, filename: str, filetype: str) -> object:
if disable_docker_scout or not supports_file(filetype):
"""Extract file information using Docker Scout if supported."""
if dsManager.disable_docker_scout or not supports_file(filetype):
return None
return extract_docker_info(filetype, filename)


def extract_docker_info(filetype: str, filename: str) -> object:
"""Extract Docker information based on file type."""
if filetype == "DOCKER_GZIP":
with open(filename, "rb") as gzip_in:
gzip_data = gzip_in.read()
with tempfile.NamedTemporaryFile() as gzip_out:
gzip_out.write(gzip.decompress(gzip_data))
return run_docker_scout(gzip_out.name)
return run_docker_scout(filename)


# Function that extract_docker_info delegates to to actually run Docker scout
def run_docker_scout(filename: str) -> object:
result = subprocess.run(
["docker", "scout", "sbom", "--format", "spdx", f"fs://{filename}"],
capture_output=True,
check=False,
)
if result.returncode != 0:
logger.warning(f"Running Docker Scout on {filename} failed")
return {}
spdx_out = json.loads(result.stdout)
return {"dockerSPDX": spdx_out}
gzip_out.flush() # Ensure data is written before reading
return dsManager.run_docker_scout(gzip_out.name)
return dsManager.run_docker_scout(filename)


@surfactant.plugin.hookimpl
def init_hook(command_name: Optional[str] = None) -> None:
if command_name != "update-db":
dsManager.check_docker_scout_installed()
Loading