Skip to content

Commit

Permalink
fs_metadata: requested review changes #1121 + bugfix
Browse files Browse the repository at this point in the history
* removed mode_human_readable from schema
* added description for "files" in schema
* fixed bug in FS result where file name was used as key instead of path (leading to the results not being displayed for included files)
* added filter for converting octal file mode to human readable
* removed error logging
  • Loading branch information
jstucke authored and maringuu committed Oct 10, 2023
1 parent 58f8e97 commit 4178049
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,59 @@ class StatResult(NamedTuple):


class FileMetadata(BaseModel):
mode: str = Field(description="The file's permissions as octal number")
mode_human_readable: str = Field(description="The file's permissions as human-readable string (e.g. '-rwxrwxrwx')")
name: str = Field(description="The file's name")
path: str = Field(description="The file's path")
user: str = Field(description="The user name of the file's owner")
uid: int = Field(description="The user ID of the file's owner")
group: str = Field(description="The group name of the file's owner")
gid: int = Field(description="The group ID of the file's owner")
modification_time: float = Field(description="The time of the file's last modification (as UNIX timestamp)")
access_time: Optional[float] = Field(None, description="The time of the file's last access (as UNIX timestamp)")
creation_time: Optional[float] = Field(None, description="The time of the file's creation (as UNIX timestamp)")
suid_bit: bool = Field(description='Whether the Setuid bit is set for this file')
sgid_bit: bool = Field(description='Whether the Setgid bit is set for this file')
sticky_bit: bool = Field(description='Whether the sticky bit is set for this file')
key: str = Field(description='Used internally for matching this file in the parent container')
mode: str = Field(
description="The file's permissions as octal number",
)
name: str = Field(
description="The file's name",
)
path: str = Field(
description="The file's path",
)
user: str = Field(
description="The user name of the file's owner",
)
uid: int = Field(
description="The user ID of the file's owner",
)
group: str = Field(
description="The group name of the file's owner",
)
gid: int = Field(
description="The group ID of the file's owner",
)
modification_time: float = Field(
description="The time of the file's last modification (as UNIX timestamp)",
)
access_time: Optional[float] = Field(
None,
description="The time of the file's last access (as UNIX timestamp)",
)
creation_time: Optional[float] = Field(
None,
description="The time of the file's creation (as UNIX timestamp)",
)
suid_bit: bool = Field(
description='Whether the Setuid bit is set for this file',
)
sgid_bit: bool = Field(
description='Whether the Setgid bit is set for this file',
)
sticky_bit: bool = Field(
description='Whether the sticky bit is set for this file',
)
key: str = Field(
description='Used internally for matching this file in the parent container',
)


class AnalysisPlugin(AnalysisPluginV0, AnalysisBasePluginAdapterMixin):
NAME = 'file_system_metadata'

class Schema(BaseModel):
files: List[FileMetadata]
files: List[FileMetadata] = Field(
description='A list of metadata dictionaries (each representing the results of a contained file)',
)

def __init__(self):
metadata = self.MetaData(
Expand All @@ -90,7 +121,6 @@ def __init__(self):
'extract file system metadata (e.g. owner, group, etc.) from file system images contained in firmware'
),
version='1.0.0',
timeout=600,
Schema=self.Schema,
)
super().__init__(metadata=metadata)
Expand Down Expand Up @@ -174,7 +204,6 @@ def _get_results_for_mounted_file(file_name: str, file_path: str, stats: StatRes
file_mode = _get_mounted_file_mode(stats)
return FileMetadata(
mode=file_mode,
mode_human_readable=stat.filemode(stats.mode),
name=file_name,
path=file_path,
uid=stats.uid,
Expand All @@ -187,7 +216,7 @@ def _get_results_for_mounted_file(file_name: str, file_path: str, stats: StatRes
suid_bit=_file_mode_contains_bit(file_mode, SUID_BIT),
sgid_bit=_file_mode_contains_bit(file_mode, SGID_BIT),
sticky_bit=_file_mode_contains_bit(file_mode, STICKY_BIT),
key=b64encode(file_name.encode()).decode(),
key=b64encode(file_path.encode()).decode(),
)


Expand All @@ -201,9 +230,7 @@ def _extract_metadata_from_tar(file_handle: FileIO) -> list[FileMetadata]:
except EOFError:
logging.warning(f'File {file_handle.name} ended unexpectedly')
except (tarfile.TarError, zlib.error, tarfile.ReadError) as error:
message = 'Could not open tar archive'
logging.exception(f'{message} {file_handle.name}: {error}', exc_info=True)
raise RuntimeError(message) from error
raise RuntimeError('Could not open tar archive') from error
return result


Expand All @@ -214,7 +241,6 @@ def _get_results_for_tar_file(file_info: tarfile.TarInfo) -> FileMetadata:
file_mode = _get_tar_file_mode_str(file_info)
return FileMetadata(
mode=file_mode,
mode_human_readable=stat.filemode(file_info.mode),
name=Path(file_path).name,
path=file_path,
user=file_info.uname,
Expand Down
2 changes: 0 additions & 2 deletions src/plugins/analysis/file_system_metadata/routes/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import logging
from base64 import b64encode
from pathlib import Path

Expand Down Expand Up @@ -68,7 +67,6 @@ def _init_component(self):
@roles_accepted(*PRIVILEGES['view_analysis'])
def _get_analysis_results_of_parent_fo(self, uid):
results = self.get_analysis_results_for_included_uid(uid)
logging.warning(f'_get_analysis_results_of_parent_fo {results=}')
return render_template_string(VIEW_PATH.read_text(), results=results)


Expand Down
1 change: 1 addition & 0 deletions src/web_interface/components/jinja_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def _setup_filters(self): # noqa: PLR0915
self._app.jinja_env.filters['nice_unix_time'] = flt.nice_unix_time
self._app.jinja_env.filters['nice_virtual_path_list'] = self._nice_virtual_path_list
self._app.jinja_env.filters['number_format'] = flt.byte_number_filter
self._app.jinja_env.filters['octal_to_readable'] = flt.octal_to_readable
self._app.jinja_env.filters['print_program_version'] = self._filter_print_program_version
self._app.jinja_env.filters['regex_meta'] = flt.comment_out_regex_meta_chars
self._app.jinja_env.filters['remaining_time'] = elapsed_time
Expand Down
6 changes: 6 additions & 0 deletions src/web_interface/filter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

import binascii
import stat

import semver
import json
import logging
Expand Down Expand Up @@ -507,3 +509,7 @@ def _coerce_version(version: str) -> semver.Version:
def as_ascii_table(data: dict) -> str:
"""Format a flat dictionary as two column ascii table"""
return ''.join([f'{k:<10} {v!s:<10}\n' for k, v in data.items()])


def octal_to_readable(octal: str) -> str:
return stat.filemode(int(octal, 8)).lstrip('?')

0 comments on commit 4178049

Please sign in to comment.