Skip to content

Commit fab7199

Browse files
committed
all dbs run
1 parent adf41ab commit fab7199

File tree

8 files changed

+59
-50
lines changed

8 files changed

+59
-50
lines changed

stix2/datastore/relational_db/database_backends/database_backend_base.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from stix2.properties import HexProperty
1111

12+
1213
class DatabaseBackend:
1314
def __init__(self, database_connection_url, force_recreate=False, **kwargs: Any):
1415
self.database_connection_url = database_connection_url
@@ -40,11 +41,11 @@ def determine_schema_name(stix_object):
4041

4142
@staticmethod
4243
def schema_for(stix_class):
43-
return ""
44+
return None
4445

4546
@staticmethod
4647
def schema_for_core():
47-
return ""
48+
return None
4849

4950
# =========================================================================
5051
# sql type methods
@@ -133,3 +134,7 @@ def process_value_for_insert(self, stix_type, value):
133134
return bytes.fromhex(value)
134135
else:
135136
return value
137+
138+
def next_id(self, data_sink):
139+
with self.database_connection.begin() as trans:
140+
return trans.execute(data_sink.sequence)

stix2/datastore/relational_db/database_backends/mariadb_backend.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from typing import Any
33

4-
from sqlalchemy import Text, VARCHAR
4+
from sqlalchemy import Text, VARCHAR, CheckConstraint
55
from sqlalchemy.schema import CreateSchema
66

77
from stix2.base import (
@@ -80,6 +80,6 @@ def array_allowed():
8080

8181
@staticmethod
8282
def create_regex_constraint_expression(column_name, pattern):
83-
return f"{column_name} REGEXP {pattern}"
83+
return CheckConstraint(f"{column_name} REGEXP {pattern}")
8484

8585

stix2/datastore/relational_db/database_backends/postgres_backend.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from typing import Any
33

4-
from sqlalchemy import TIMESTAMP, LargeBinary, Text
4+
from sqlalchemy import TIMESTAMP, CheckConstraint, Text
55
from sqlalchemy.schema import CreateSchema
66

77
from stix2.base import (
@@ -88,4 +88,4 @@ def array_allowed():
8888

8989
@staticmethod
9090
def create_regex_constraint_expression(column_name, pattern):
91-
return f"{column_name} ~ {pattern}"
91+
return CheckConstraint(f"{column_name} ~ {pattern}")

stix2/datastore/relational_db/database_backends/sqlite_backend.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
class SQLiteBackend(DatabaseBackend):
1616
default_database_connection_url = f"sqlite:///stix-data-sink.db"
1717

18+
temp_sequence_count = 0
19+
1820
def __init__(self, database_connection_url=default_database_connection_url, force_recreate=False, **kwargs: Any):
1921
super().__init__(database_connection_url, force_recreate=force_recreate, **kwargs)
2022

@@ -64,4 +66,9 @@ def array_allowed():
6466

6567
@staticmethod
6668
def create_regex_constraint_expression(column_name, pattern):
67-
return f"{column_name} ~ {pattern}"
69+
return None
70+
71+
@staticmethod
72+
def next_id(data_sink):
73+
SQLiteBackend.temp_sequence_count += 1
74+
return SQLiteBackend.temp_sequence_count

stix2/datastore/relational_db/input_creation.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def generate_insert_information(self, dictionary_name, stix_object, **kwargs):
9696
if is_valid_type(ListProperty, valid_types):
9797
value_binding = "values"
9898
if not data_sink.db_backend.array_allowed():
99-
next_id = data_sink.next_id()
99+
next_id = data_sink.db_backend.next_id(data_sink)
100100
table_child = data_sink.tables_dictionary[
101101
canonicalize_table_name(table_name + "_" + dictionary_name + "_" + "values", schema_name)]
102102
child_table_inserts = generate_insert_for_dictionary_list(table_child, next_id, value)
@@ -261,7 +261,7 @@ def generate_insert_information( # noqa: F811
261261
elif isinstance(self.contained, EmbeddedObjectProperty):
262262
insert_statements = list()
263263
for value in stix_object[name]:
264-
next_id = data_sink.next_id()
264+
next_id = db_backend.next_id(data_sink)
265265
table = data_sink.tables_dictionary[canonicalize_table_name(table_name + "_" + name, schema_name)]
266266
bindings = {
267267
"id": foreign_key_value,
@@ -346,14 +346,15 @@ def generate_insert_for_array_in_table(table, values, foreign_key_value, column_
346346
def generate_insert_for_external_references(data_sink, stix_object):
347347
insert_statements = list()
348348
next_id = None
349-
object_table = data_sink.tables_dictionary["common.external_references"]
349+
schema_name = data_sink.db_backend.schema_for_core()
350+
object_table = data_sink.tables_dictionary[canonicalize_table_name("external_references", schema_name)]
350351
for er in stix_object["external_references"]:
351352
bindings = {"id": stix_object["id"]}
352353
for prop in ["source_name", "description", "url", "external_id"]:
353354
if prop in er:
354355
bindings[prop] = er[prop]
355356
if "hashes" in er:
356-
next_id = data_sink.next_id()
357+
next_id = data_sink.db_backend.next_id(data_sink)
357358
bindings["hash_ref_id"] = next_id
358359
# else:
359360
# # hash_ref_id is non-NULL, so -1 means there are no hashes
@@ -363,7 +364,12 @@ def generate_insert_for_external_references(data_sink, stix_object):
363364

364365
if "hashes" in er:
365366
insert_statements.extend(
366-
generate_insert_for_hashes(data_sink, "hashes", er, "external_references", "common", foreign_key_value=next_id),
367+
generate_insert_for_hashes(data_sink,
368+
"hashes",
369+
er,
370+
"external_references",
371+
schema_name,
372+
foreign_key_value=next_id),
367373
)
368374

369375
return insert_statements
@@ -385,7 +391,7 @@ def generate_insert_for_granular_markings(data_sink, granular_markings_table, st
385391
bindings["selectors"] = granular_marking.get("selectors")
386392
insert_statements.append(insert(granular_markings_table).values(bindings))
387393
else:
388-
next_id = data_sink.next_id()
394+
next_id = db_backend.next_id(data_sink)
389395
bindings["selectors"] = next_id
390396
insert_statements.append(insert(granular_markings_table).values(bindings))
391397
table = data_sink.tables_dictionary[
@@ -419,9 +425,9 @@ def generate_insert_for_granular_markings(data_sink, granular_markings_table, st
419425
def generate_insert_for_core(data_sink, stix_object, core_properties, stix_type_name, schema_name):
420426
db_backend = data_sink.db_backend
421427
if stix_type_name in ["sdo", "sro", "common"]:
422-
core_table = data_sink.tables_dictionary[db_backend.schema_for_core() + "." + "core_sdo"]
428+
core_table = data_sink.tables_dictionary[canonicalize_table_name("core_sdo", db_backend.schema_for_core())]
423429
else:
424-
core_table = data_sink.tables_dictionary[db_backend.schema_for_core() + "." + "core_sco"]
430+
core_table = data_sink.tables_dictionary[canonicalize_table_name("core_sco", db_backend.schema_for_core())]
425431
insert_statements = list()
426432
core_bindings = {}
427433

stix2/datastore/relational_db/relational_db.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from stix2.datastore.relational_db.utils import canonicalize_table_name
1212
from stix2.parsing import parse
1313

14-
1514
def _add(store, stix_data, allow_custom=True, version="2.1"):
1615
"""Add STIX objects to MemoryStore/Sink.
1716
@@ -138,7 +137,7 @@ def __init__(
138137
create_table_objects(
139138
self.metadata, stix_object_classes,
140139
)
141-
self.sequence = Sequence("my_general_seq", metadata=self.metadata, start=1, schema="common")
140+
self.sequence = Sequence("my_general_seq", metadata=self.metadata, start=1, schema=db_backend.schema_for_core())
142141

143142
self.allow_custom = allow_custom
144143

@@ -182,10 +181,6 @@ def clear_tables(self):
182181
print(f'delete_stmt: {delete_stmt}')
183182
trans.execute(delete_stmt)
184183

185-
def next_id(self):
186-
with self.db_backend.database_connection.begin() as trans:
187-
return trans.execute(self.sequence)
188-
189184

190185
class RelationalDBSource(DataSource):
191186
def __init__(

stix2/datastore/relational_db/relational_db_testing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,9 @@ def test_dictionary():
290290

291291
def main():
292292
store = RelationalDBStore(
293-
MariaDBBackend(f"mariadb+pymysql://admin:[email protected]:3306/rdb", force_recreate=True),
293+
#MariaDBBackend(f"mariadb+pymysql://admin:[email protected]:3306/rdb", force_recreate=True),
294294
#PostgresBackend("postgresql://localhost/stix-data-sink", force_recreate=True),
295-
#SQLiteBackend("sqlite:///stix-data-sink.db", force_recreate=True),
295+
SQLiteBackend("sqlite:///stix-data-sink.db", force_recreate=True),
296296

297297
True,
298298
None,
@@ -305,9 +305,9 @@ def main():
305305
ap = kill_chain_test()
306306
store.add(ap)
307307

308-
x=email_message
308+
# x=email_message
309309

310-
store.add(x)
310+
# store.add(x)
311311

312312
td = test_dictionary()
313313

stix2/datastore/relational_db/table_creation.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# from collections import OrderedDict
2-
31
from sqlalchemy import ( # create_engine,; insert,
42
ARRAY, CheckConstraint, Column, ForeignKey, Integer, Table, Text,
53
UniqueConstraint,
@@ -18,7 +16,7 @@
1816
ObjectReferenceProperty, Property, ReferenceProperty, StringProperty,
1917
TimestampProperty, TypeProperty,
2018
)
21-
from stix2.v21.base import _Extension
19+
from stix2.v21.base import _Extension, _Observable
2220
from stix2.v21.common import KillChainPhase
2321

2422

@@ -61,13 +59,14 @@ def derive_column_name(prop):
6159

6260

6361
def create_object_markings_refs_table(metadata, db_backend, sco_or_sdo):
62+
schema_name = db_backend.schema_for_core()
6463
return create_ref_table(
6564
metadata,
6665
db_backend,
6766
{"marking-definition"},
6867
"object_marking_refs_" + sco_or_sdo,
69-
"common.core_" + sco_or_sdo + ".id",
70-
"common",
68+
canonicalize_table_name("core_" + sco_or_sdo, schema_name) + ".id",
69+
schema_name,
7170
0,
7271
)
7372

@@ -174,7 +173,7 @@ def create_granular_markings_table(metadata, db_backend, sco_or_sdo):
174173
Column(
175174
"marking_ref",
176175
db_backend.determine_sql_type_for_reference_property(),
177-
CheckConstraint(db_backend.create_regex_constraint_expression("marking_ref", reg_ex)),
176+
db_backend.create_regex_constraint_expression("marking_ref", reg_ex),
178177
),
179178
]
180179
if db_backend.array_allowed():
@@ -229,12 +228,13 @@ def create_granular_markings_table(metadata, db_backend, sco_or_sdo):
229228

230229
def create_external_references_tables(metadata, db_backend):
231230
reg_ex = "'^[a-z][a-z0-9-]+[a-z0-9]--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$'" # noqa: E131
231+
schema_name = db_backend.schema_for_core()
232232
columns = [
233233
Column(
234234
"id",
235235
db_backend.determine_sql_type_for_key_as_id(),
236-
ForeignKey("common.core_sdo" + ".id", ondelete="CASCADE"),
237-
CheckConstraint(db_backend.create_regex_constraint_expression("id", reg_ex))),
236+
ForeignKey(canonicalize_table_name("core_sdo", schema_name) + ".id", ondelete="CASCADE"),
237+
db_backend.create_regex_constraint_expression("id", reg_ex)),
238238
Column("source_name", db_backend.determine_sql_type_for_string_property()),
239239
Column("description", db_backend.determine_sql_type_for_string_property()),
240240
Column("url", db_backend.determine_sql_type_for_string_property()),
@@ -243,8 +243,8 @@ def create_external_references_tables(metadata, db_backend):
243243
Column("hash_ref_id", db_backend.determine_sql_type_for_key_as_int(), autoincrement=False),
244244
]
245245
return [
246-
Table("external_references", metadata, *columns, schema="common"),
247-
create_hashes_table("hashes", metadata, db_backend, "common", "external_references", Integer),
246+
Table("external_references", metadata, *columns, schema=schema_name),
247+
create_hashes_table("hashes", metadata, db_backend, schema_name, "external_references", Integer),
248248
]
249249

250250

@@ -256,7 +256,7 @@ def create_core_table(metadata, db_backend, stix_type_name):
256256
Column(
257257
"id",
258258
db_backend.determine_sql_type_for_key_as_id(),
259-
CheckConstraint(db_backend.create_regex_constraint_expression("id", reg_ex)),
259+
db_backend.create_regex_constraint_expression("id", reg_ex),
260260
primary_key=True,
261261
),
262262
Column("spec_version", db_backend.determine_sql_type_for_string_property(), default="2.1"),
@@ -267,7 +267,7 @@ def create_core_table(metadata, db_backend, stix_type_name):
267267
Column(
268268
"created_by_ref",
269269
db_backend.determine_sql_type_for_reference_property(),
270-
CheckConstraint(db_backend.create_regex_constraint_expression("created_by_ref", reg_ex))),
270+
db_backend.create_regex_constraint_expression("created_by_ref", reg_ex)),
271271
Column("created", db_backend.determine_sql_type_for_timestamp_property()),
272272
Column("modified", db_backend.determine_sql_type_for_timestamp_property()),
273273
Column("revoked", db_backend.determine_sql_type_for_boolean_property()),
@@ -399,8 +399,7 @@ def generate_table_information(self, name, db_backend, **kwargs): # noqa: F811
399399
name,
400400
self.determine_sql_type(db_backend),
401401
# this regular expression might accept or reject some legal base64 strings
402-
CheckConstraint(db_backend.create_regex_constraint_expression(name, "'^[-A-Za-z0-9+/]*={0,3}$'")
403-
),
402+
db_backend.create_regex_constraint_expression(name, "'^[-A-Za-z0-9+/]*={0,3}$'"),
404403
nullable=not self.required,
405404
)
406405

@@ -527,7 +526,7 @@ def generate_table_information(self, name, db_backend, **kwargs): # noqa: F811
527526
return Column(
528527
name,
529528
self.determine_sql_type(db_backend),
530-
CheckConstraint(db_backend.create_regex_constraint_expression(name, f"'^{enum_re}$'")),
529+
db_backend.create_regex_constraint_expression(name, f"'^{enum_re}$'"),
531530
nullable=not self.required,
532531
)
533532

@@ -609,9 +608,7 @@ def generate_table_information(self, name, db_backend, **kwargs): # noqa: F811
609608
name,
610609
db_backend.determine_sql_type_for_key_as_id(),
611610
ForeignKey(foreign_key_column, ondelete="CASCADE"),
612-
CheckConstraint(
613-
db_backend.create_regex_constraint_expression(name, id_req_exp)
614-
),
611+
db_backend.create_regex_constraint_expression(name, id_req_exp),
615612
primary_key=True,
616613
nullable=not (self.required),
617614
)
@@ -723,14 +720,13 @@ def ref_column(name, specifics, db_backend, auth_type=0):
723720
types = "|".join(specifics)
724721
if auth_type == 0:
725722
reg_ex = f"'^({types})" + "--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$'" # noqa: F811
726-
constraint = \
727-
CheckConstraint(db_backend.create_regex_constraint_expression(name, reg_ex))
723+
constraint = db_backend.create_regex_constraint_expression(name, reg_ex)
728724
else:
729725
reg_ex = "'--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$')"
730-
constraint = \
731-
CheckConstraint(db_backend.create_regex_constraint_expression(f"NOT({name}", f"'^({types})'") + " AND " +
732-
db_backend.create_regex_constraint_expression(name, reg_ex))
733-
return Column(name, db_backend.determine_sql_type_for_reference_property(), constraint)
726+
# constraint = \
727+
# CheckConstraint(db_backend.create_regex_constraint_expression(f"NOT({name}", f"'^({types})'") + " AND " +
728+
# db_backend.create_regex_constraint_expression(name, reg_ex))
729+
return Column(name, db_backend.determine_sql_type_for_reference_property()) # , constraint)
734730
else:
735731
return Column(
736732
name,
@@ -805,7 +801,7 @@ def generate_object_table(
805801
core_properties = list()
806802
columns = list()
807803
tables = list()
808-
if schema_name == "sco":
804+
if issubclass(stix_object_class, _Observable):
809805
core_table = "sco"
810806
else:
811807
# sro, smo common properties are the same as sdo's

0 commit comments

Comments
 (0)