sql-data-guard 0.1.6__tar.gz → 0.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {sql_data_guard-0.1.6/src/sql_data_guard.egg-info → sql_data_guard-0.1.8}/PKG-INFO +1 -1
  2. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/pyproject.toml +1 -1
  3. sql_data_guard-0.1.8/src/sql_data_guard/mcpwrapper/mcp_wrapper.py +86 -0
  4. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/restriction_verification.py +2 -2
  5. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/sql_data_guard.py +1 -1
  6. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8/src/sql_data_guard.egg-info}/PKG-INFO +1 -1
  7. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard.egg-info/SOURCES.txt +1 -0
  8. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_unit.py +2 -3
  9. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_validation_unit.py +1 -0
  10. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/LICENSE.md +0 -0
  11. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/README.md +0 -0
  12. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/setup.cfg +0 -0
  13. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/__init__.py +0 -0
  14. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/rest/__init__.py +0 -0
  15. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/rest/sql_data_guard_rest.py +0 -0
  16. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/restriction_validation.py +0 -0
  17. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/verification_context.py +0 -0
  18. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard/verification_utils.py +0 -0
  19. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard.egg-info/dependency_links.txt +0 -0
  20. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard.egg-info/requires.txt +0 -0
  21. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/src/sql_data_guard.egg-info/top_level.txt +0 -0
  22. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_duckdb_unit.py +0 -0
  23. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_rest_api_unit.py +0 -0
  24. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_curr_unit.py +0 -0
  25. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_joins_unit.py +0 -0
  26. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_llm.py +0 -0
  27. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_sql_guard_updates_unit.py +0 -0
  28. {sql_data_guard-0.1.6 → sql_data_guard-0.1.8}/test/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-data-guard
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Safety Layer for LLM Database Interactions
5
5
  Author-email: Imperva - Threat Reseach Infra <ww.dis.imperva.threat-research-infra@thalesgroup.com>
6
6
  License: MIT License
@@ -9,7 +9,7 @@ package-dir = {"" = "src"}
9
9
  extra-index-url = ["https://pypi.org/simple"]
10
10
  [project]
11
11
  name = "sql-data-guard"
12
- version = "0.1.6"
12
+ version = "0.1.8"
13
13
  dependencies = [
14
14
  "sqlglot"
15
15
  ]
@@ -0,0 +1,86 @@
1
+ import json
2
+ import os
3
+ import sys
4
+ import threading
5
+ from typing import Optional
6
+
7
+ import docker
8
+ from sql_data_guard import verify_sql
9
+
10
+
11
+ def load_config() -> dict:
12
+ return json.load(open("/conf/config.json"))
13
+
14
+
15
+ def start_inner_container():
16
+ client = docker.from_env()
17
+ container = client.containers.run(
18
+ config["mcp-server"]["image"],
19
+ " ".join(config["mcp-server"]["args"]),
20
+ volumes=[
21
+ v.replace("$PWD", os.environ["PWD"])
22
+ for v in config["mcp-server"]["volumes"]
23
+ ],
24
+ stdin_open=True,
25
+ auto_remove=True,
26
+ detach=True,
27
+ stdout=True,
28
+ )
29
+
30
+ def stream_output():
31
+ for line in container.logs(stream=True):
32
+ sys.stdout.write(line.decode("utf-8"))
33
+ sys.stdout.flush()
34
+
35
+ threading.Thread(target=stream_output, daemon=True).start()
36
+ return container
37
+
38
+
39
+ def main():
40
+ container = start_inner_container()
41
+
42
+ try:
43
+ socket = container.attach_socket(params={"stdin": True, "stream": True})
44
+ # noinspection PyProtectedMember
45
+ socket._sock.setblocking(True)
46
+ for line in sys.stdin:
47
+ line = input_line(line)
48
+ # noinspection PyProtectedMember
49
+ socket._sock.sendall(line.encode("utf-8"))
50
+ except (KeyboardInterrupt, EOFError):
51
+ pass
52
+ finally:
53
+ container.stop()
54
+
55
+
56
+ def get_sql(json_line: dict) -> Optional[str]:
57
+ sys.stderr.write(f"json_line: {json_line}\n")
58
+ if json_line["method"] == "tools/call":
59
+ for tool in config["mcp-tools"]:
60
+ if tool["tool-name"] == json_line["params"]["name"]:
61
+ return json_line["params"]["arguments"][tool["arg-name"]]
62
+ return None
63
+
64
+
65
+ def input_line(line: str) -> str:
66
+ json_line = json.loads(line.encode("utf-8"))
67
+ sql = get_sql(json_line)
68
+ if sql:
69
+ result = verify_sql(
70
+ sql,
71
+ config["sql-data-guard"],
72
+ config["sql-data-guard"]["dialect"],
73
+ )
74
+ if not result["allowed"]:
75
+ sys.stderr.write(f"Blocked SQL: {sql}\nErrors: {list(result['errors'])}\n")
76
+ updated_sql = "SELECT 'Blocked by SQL Data Guard' AS message"
77
+ for error in result["errors"]:
78
+ updated_sql += f"\nUNION ALL SELECT '{error}' AS message"
79
+ json_line["params"]["arguments"]["query"] = updated_sql
80
+ line = json.dumps(json_line) + "\n"
81
+ return line
82
+
83
+
84
+ if __name__ == "__main__":
85
+ config = load_config()
86
+ main()
@@ -3,8 +3,8 @@ from typing import List
3
3
  import sqlglot
4
4
  import sqlglot.expressions as expr
5
5
 
6
- from sql_data_guard.verification_context import VerificationContext
7
- from sql_data_guard.verification_utils import split_to_expressions
6
+ from .verification_context import VerificationContext
7
+ from .verification_utils import split_to_expressions
8
8
 
9
9
 
10
10
  def verify_restrictions(
@@ -63,7 +63,7 @@ def verify_sql(sql: str, config: dict, dialect: str = None) -> dict:
63
63
  else:
64
64
  result.add_error("Could not find a query statement", False, 0.7)
65
65
  if result.can_fix and len(result.errors) > 0:
66
- result.fixed = parsed.sql()
66
+ result.fixed = parsed.sql(dialect=dialect)
67
67
  return {
68
68
  "allowed": len(result.errors) == 0,
69
69
  "errors": result.errors,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-data-guard
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Safety Layer for LLM Database Interactions
5
5
  Author-email: Imperva - Threat Reseach Infra <ww.dis.imperva.threat-research-infra@thalesgroup.com>
6
6
  License: MIT License
@@ -12,6 +12,7 @@ src/sql_data_guard.egg-info/SOURCES.txt
12
12
  src/sql_data_guard.egg-info/dependency_links.txt
13
13
  src/sql_data_guard.egg-info/requires.txt
14
14
  src/sql_data_guard.egg-info/top_level.txt
15
+ src/sql_data_guard/mcpwrapper/mcp_wrapper.py
15
16
  src/sql_data_guard/rest/__init__.py
16
17
  src/sql_data_guard/rest/sql_data_guard_rest.py
17
18
  test/test_duckdb_unit.py
@@ -369,14 +369,13 @@ class TestTrinoWithRestrictions:
369
369
  ]
370
370
  }
371
371
 
372
- @pytest.mark.skip(reason="Bug in sqlglot. Waiting for fix")
373
372
  def test_date_add(self, config):
374
373
  verify_sql_test(
375
- "SELECT id FROM accounts WHERE DATE(day) >= DATE_ADD('day', -7, CURRENT_DATE)",
374
+ "SELECT id FROM accounts WHERE DATE(day) >= DATE_ADD('DAY', -7, CURRENT_DATE)",
376
375
  config,
377
376
  dialect="trino",
378
377
  errors={"Missing restriction for table: accounts column: id value: 123"},
379
- fix="SELECT id FROM accounts WHERE DATE(day) >= DATE_ADD('day', -7, CURRENT_DATE) AND id = 123",
378
+ fix="SELECT id FROM accounts WHERE (DATE(day) >= DATE_ADD('DAY', -7, CURRENT_DATE)) AND id = 123",
380
379
  )
381
380
 
382
381
 
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from sql_data_guard.restriction_validation import (
3
4
  validate_restrictions,
4
5
  UnsupportedRestrictionError,
File without changes
File without changes