feat(analyst): Implement audit logging for query denial and clarification
- Enhanced the `AnalystAgent` class to include an `_audit_terminal` method for logging query denials, clarifications, and errors, ensuring compliance and traceability. - Updated error handling paths to call the new audit method, capturing relevant details such as question, user authentication, and SQL context. - Introduced new validation checks in `sql_guard.py` to enforce ownership filters for sensitive queries, improving security measures. - Added unit tests to verify the correct logging behavior and ownership filter enforcement, ensuring robust functionality. This update significantly strengthens the auditing capabilities of the analyst agent, enhancing security and compliance in query handling.
This commit is contained in:
@@ -44,6 +44,47 @@ class TestSqlGuard(unittest.TestCase):
|
||||
r = validate("SELECT COUNT(DISTINCT customer_id) AS cnt FROM core_holding", "aggregate")
|
||||
self.assertTrue(r.allowed)
|
||||
|
||||
def test_created_at_in_select_allowed(self):
|
||||
"""Q17:列名 created_at 不应触发 create 关键字误杀。"""
|
||||
r = validate(
|
||||
"SELECT alert_id, created_at FROM jinrong_agent.risk_alert WHERE status='pending_review'",
|
||||
"full",
|
||||
)
|
||||
self.assertTrue(r.allowed)
|
||||
|
||||
def test_gap_a_select_customer_id_column_without_where_denied_self(self):
|
||||
with self.assertRaises(SqlGuardError) as cm:
|
||||
validate(
|
||||
"SELECT customer_id, product_id, market_value FROM core_holding",
|
||||
"self",
|
||||
["CUST-9527"],
|
||||
)
|
||||
self.assertEqual(cm.exception.error_code, "AUTH_403_SCOPE")
|
||||
|
||||
def test_gap_a_select_customer_id_column_without_where_denied_assigned(self):
|
||||
with self.assertRaises(SqlGuardError) as cm:
|
||||
validate(
|
||||
"SELECT customer_id, product_id, market_value FROM core_holding",
|
||||
"assigned",
|
||||
["CUST-9527"],
|
||||
)
|
||||
self.assertEqual(cm.exception.error_code, "AUTH_403_SCOPE")
|
||||
|
||||
def test_gap_b_ops_risk_alert_denied(self):
|
||||
with self.assertRaises(SqlGuardError) as cm:
|
||||
validate("SELECT * FROM jinrong_agent.risk_alert", "aggregate")
|
||||
self.assertEqual(cm.exception.error_code, "AUTH_403_SCOPE")
|
||||
|
||||
def test_gap_b_advisor_risk_alert_without_filter_denied(self):
|
||||
with self.assertRaises(SqlGuardError) as cm:
|
||||
validate("SELECT * FROM jinrong_agent.risk_alert", "assigned", ["CUST-9527"])
|
||||
self.assertEqual(cm.exception.error_code, "AUTH_403_SCOPE")
|
||||
|
||||
def test_create_table_still_rejected(self):
|
||||
with self.assertRaises(SqlGuardError) as cm:
|
||||
validate("CREATE TABLE evil (id INT)", "full")
|
||||
self.assertIn(cm.exception.error_code, ("SQL_FORBIDDEN", "SQL_NOT_SELECT"))
|
||||
|
||||
def test_inject_ownership(self):
|
||||
out = inject_ownership("SELECT * FROM core_holding", ["CUST-1", "CUST-2"])
|
||||
self.assertIn("CUST-1", out)
|
||||
|
||||
Reference in New Issue
Block a user