Skip to content

Commit

Permalink
feat: add db view unpacking
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke committed Dec 19, 2024
1 parent 058e49f commit 0b7cb80
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/init_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ def main(command_line_options=None, config_path: str | None = None, skip_user_cr
if not db_setup.table_exists('file_object'):
logging.info('Creating FACT tables...')
db_setup.connection.create_tables()
db_setup.set_table_privileges()
set_alembic_revision()
else:
logging.info('Skipping creation of FACT tables: already exist')
db_setup.create_unpacking_view()
db_setup.set_table_privileges()

return 0

Expand Down
35 changes: 33 additions & 2 deletions src/storage/db_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
from storage.db_connection import AdminConnection, DbConnection
from storage.db_interface_base import ReadWriteDbInterface

CREATE_VIEW_CMD = text(
"""
CREATE VIEW unpacking AS
SELECT
uid,
(result->>'entropy')::float AS entropy,
(result->>'number_of_unpacked_files')::integer AS number_of_unpacked_files
FROM analysis
WHERE plugin = 'unpacker';
"""
)


class Privileges:
SELECT = 'SELECT'
Expand Down Expand Up @@ -38,6 +50,10 @@ def table_exists(self, table_name: str):
with self.connection.engine.connect() as db, db.engine.begin() as connection:
return inspect(connection).has_table(table_name, None)

def view_exists(self, view_name: str):
with self.connection.engine.connect() as db, db.engine.begin() as connection:
return view_name in inspect(connection).get_view_names(schema='public')

def database_exists(self, db_name: str) -> bool:
with self.get_read_only_session() as session:
return bool(session.execute(text(f"SELECT 1 FROM pg_database WHERE datname = '{db_name}'")).scalar())
Expand All @@ -63,8 +79,23 @@ def set_table_privileges(self):
]:
user = getattr(config.backend.postgres, f'{key}_user')
for privilege in privileges:
self.grant_privilege(user, privilege)
self.grant_table_privilege(user, privilege)
self.grant_view_privilege(user, privilege)

def grant_privilege(self, user_name: str, privilege: str):
def grant_table_privilege(self, user_name: str, privilege: str):
with self.get_read_write_session() as session:
session.execute(text(f'GRANT {privilege} ON ALL TABLES IN SCHEMA public TO {user_name};'))

def create_unpacking_view(self):
if not self.view_exists('unpacking'):
with self.get_read_write_session() as session:
session.execute(CREATE_VIEW_CMD)

def grant_view_privilege(self, user_name: str, privilege: str):
with self.get_read_write_session() as session:
session.execute(text(f'GRANT {privilege} ON unpacking TO {user_name};'))

def delete_unpacking_view(self):
if self.view_exists('unpacking'):
with self.get_read_write_session() as session:
session.execute(text('DROP VIEW IF EXISTS unpacking;'))
34 changes: 33 additions & 1 deletion src/storage/graphql/hasura/init_hasura.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
import sys
from itertools import permutations
from pathlib import Path

import requests
Expand All @@ -17,7 +18,15 @@

HTML_OK = 200
HTML_BAD_REQUEST = 400
TRACKED_TABLES = ('analysis', 'file_object', 'firmware', 'fw_files', 'included_files', 'virtual_file_path')
TRACKED_TABLES = (
'analysis',
'file_object',
'firmware',
'fw_files',
'included_files',
'virtual_file_path',
'unpacking',
)
RELATIONSHIPS = {
'pg_create_object_relationship': [
# table, name, constraint
Expand Down Expand Up @@ -64,6 +73,7 @@ def init_hasura(self, db_args: dict | None = None):
self._add_database(db_args)
self._track_tables()
self._add_relationships()
self._add_view_relationship()
self._add_ro_user_role_to_tables()
logging.info('Hasura initialization successful')

Expand Down Expand Up @@ -163,6 +173,28 @@ def _add_relationships(self):
f'Failed to add constraint {name} on table {table}: {response.json().get("error")}'
)

def _add_view_relationship(self):
for source, target in permutations(['unpacking', 'file_object']):
query = {
'type': 'pg_create_object_relationship',
'args': {
'table': {'name': source, 'schema': 'public'},
'name': target,
'source': self.db_name,
'using': {
'manual_configuration': {
'remote_table': target,
'column_mapping': {'uid': 'uid'},
}
},
},
}
response = requests.post(self.url, headers=self.headers, json=query)
if response.status_code != HTML_OK:
if _was_already_added(response):
continue
raise HasuraInitError(f'Failed to add relationships on view unpacking: {response.json().get("error")}')

def _db_was_already_added(self) -> bool:
query = {'type': 'pg_get_source_tables', 'args': {'source': self.db_name}}
response = requests.post(self.url, headers=self.headers, json=query)
Expand Down
2 changes: 2 additions & 0 deletions src/test/common_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,12 @@ def store_binary_on_file_system(tmp_dir: str, test_object: FileObject | Firmware

def setup_test_tables(db_setup):
db_setup.connection.create_tables()
db_setup.create_unpacking_view()
db_setup.set_table_privileges()


def clear_test_tables(db_setup):
db_setup.delete_unpacking_view()
db_setup.connection.base.metadata.drop_all(db_setup.connection.engine)


Expand Down

0 comments on commit 0b7cb80

Please sign in to comment.