This repository has been archived by the owner on Jan 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #105 from rocodes/refactor-cli
Refactor: CLI wrapper, export and print services, single entrypoint
- Loading branch information
Showing
35 changed files
with
3,079 additions
and
1,307 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import datetime | ||
import json | ||
import logging | ||
import os | ||
import tempfile | ||
|
||
from securedrop_export.exceptions import ExportException | ||
from securedrop_export.status import BaseStatus | ||
from securedrop_export.command import Command | ||
from securedrop_export.directory import safe_extractall | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Status(BaseStatus): | ||
ERROR_ARCHIVE_METADATA = "ERROR_ARCHIVE_METADATA" | ||
ERROR_METADATA_PARSING = "ERROR_METADATA_PARSING" | ||
ERROR_EXTRACTION = "ERROR_EXTRACTION" | ||
|
||
|
||
class Metadata(object): | ||
""" | ||
Object to parse, validate and store json metadata from the sd-export archive. | ||
""" | ||
|
||
METADATA_FILE = "metadata.json" | ||
SUPPORTED_ENCRYPTION_METHODS = ["luks"] | ||
|
||
def __init__(self, archive_path: str): | ||
self.metadata_path = os.path.join(archive_path, self.METADATA_FILE) | ||
|
||
def validate(self) -> "Metadata": | ||
# Read metadata json and set relevant attributes | ||
try: | ||
with open(self.metadata_path) as f: | ||
logger.info("Parsing archive metadata") | ||
json_config = json.loads(f.read()) | ||
self.export_method = json_config.get("device", None) | ||
self.encryption_method = json_config.get("encryption_method", None) | ||
self.encryption_key = json_config.get("encryption_key", None) | ||
logger.info( | ||
"Target: {}, encryption_method {}".format( | ||
self.export_method, self.encryption_method | ||
) | ||
) | ||
|
||
except Exception as ex: | ||
logger.error("Metadata parsing failure") | ||
raise ExportException(sdstatus=Status.ERROR_METADATA_PARSING) from ex | ||
|
||
# Validate action - fails if command is not in list of supported commands | ||
try: | ||
logger.debug("Validate export action") | ||
self.command = Command(self.export_method) | ||
if ( | ||
self.command is Command.EXPORT | ||
and self.encryption_method not in self.SUPPORTED_ENCRYPTION_METHODS | ||
): | ||
logger.error("Unsupported encryption method") | ||
raise ExportException(sdstatus=Status.ERROR_ARCHIVE_METADATA) | ||
except ValueError as v: | ||
raise ExportException(sdstatus=Status.ERROR_ARCHIVE_METADATA) from v | ||
|
||
return self | ||
|
||
|
||
class Archive(object): | ||
def __init__(self, archive_path: str): | ||
os.umask(0o077) | ||
self.archive = archive_path | ||
self.target_dirname = "sd-export-{}".format( | ||
datetime.datetime.now().strftime("%Y%m%d-%H%M%S") | ||
) | ||
self.tmpdir = tempfile.mkdtemp() | ||
|
||
def extract_tarball(self) -> "Archive": | ||
""" | ||
Extract tarball, checking for path traversal, and return Archive object. | ||
""" | ||
try: | ||
logger.info( | ||
"Extracting tarball {} into {}".format(self.archive, self.tmpdir) | ||
) | ||
safe_extractall(self.archive, self.tmpdir) | ||
return self | ||
except Exception as ex: | ||
logger.error("Unable to extract tarball: {}".format(ex)) | ||
raise ExportException(sdstatus=Status.ERROR_EXTRACTION) from ex | ||
|
||
def set_metadata(self, metadata: Metadata) -> "Archive": | ||
""" | ||
Set relevant metadata attributes for a given archive. | ||
""" | ||
self.command = metadata.command | ||
if self.command is Command.EXPORT: | ||
# When we support multiple encryption types, we will also want to add the | ||
# encryption_method here | ||
self.encryption_key = metadata.encryption_key | ||
return self |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from enum import Enum | ||
|
||
|
||
class Command(Enum): | ||
""" | ||
All supported commands. | ||
Values are as supplied by the calling VM (sd-app), and a change in any values requires | ||
corresponding changes in the calling VM. | ||
""" | ||
|
||
PRINTER_PREFLIGHT = "printer-preflight" | ||
PRINTER_TEST = "printer-test" | ||
PRINT = "printer" | ||
CHECK_USBS = "usb-test" | ||
CHECK_VOLUME = "disk-test" | ||
EXPORT = "disk" | ||
START_VM = "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .service import Service # noqa: F401 |
Oops, something went wrong.