Skip to main content

SQL query security gateway for validating database access levels

Project description

AnomalyArmor Query Gateway

Tests Python 3.11+ License

What is this?

This is the open-source SQL security layer that AnomalyArmor uses to control access to customer databases. Every query we execute against your database passes through this gateway.

Why open source? So you can verify exactly what queries we can and cannot run. No black boxes.

What does it do?

                      ┌─────────────────────────────────┐
                      │      AnomalyArmor Platform      │
                      └─────────────────────────────────┘
                                       │
                                       │
                                       ▼
┌────-─────────────────────────────────────────-────────────────────────-───────┐
│                          Query Security Gateway                               │
│   ┌─────────────────┐    ┌─────────────────-┐    ┌────────────────────────┐   │
│   │   SQL Parser    │ -> │ Access Validator │ -> │  Allow / Block + Log   │   │
│   │   (sqlglot)     │    │  (level rules)   │    │  (audit trail)         │   │
│   └─────────────────┘    └─────────────────-┘    └────────────────────────┘   │
└─────-─────────────────────────────────────────────────────────────────────────┘
                                        │
                                        | ALLOWED OPERATIONS ONLY
                                        ▼
                       ┌────────────────-────────────────┐
                       │         Your Database           │
                       └────────────────-────────────────┘

Validates SQL queries against three access levels:

Level What We Can Query What We Cannot Query
Schema Only Table names, column types, indexes Any actual data
Aggregates COUNT(*), AVG(salary), MAX(date) SELECT email FROM users
Full Any SELECT query -

The gateway parses your SQL using sqlglot and blocks queries that violate the configured access level. If parsing fails, the query is blocked (fail-closed).

How do we know it works?

97 tests covering access level enforcement, SQL parsing, and security edge cases.

See TEST_RESULTS.md for the full breakdown, or run them yourself:

pip install -e ".[dev]"
pytest -v

Overview

The Query Security Gateway provides a transparent, auditable layer for controlling what types of SQL queries can be executed against customer databases. It supports three access levels:

Level Description Allowed Queries
schema_only Metadata access only information_schema, pg_catalog, DESCRIBE, system tables
aggregates Aggregate functions only COUNT, SUM, AVG, MIN, MAX, COUNT DISTINCT - no raw column values
full Unrestricted read access Any SELECT query

Installation

pip install anomalyarmor-query-gateway

Quick Start

from anomalyarmor_query_gateway import QuerySecurityGateway, AccessLevel

# Create gateway with desired access level
gateway = QuerySecurityGateway(
    access_level=AccessLevel.AGGREGATES,
    dialect="postgresql",
)

# Validate a query
result = gateway.validate_query_sync("SELECT COUNT(*) FROM users")

if result.allowed:
    print("Query is allowed")
else:
    print(f"Query blocked: {result.reason}")

Access Levels Explained

schema_only

Only allows queries against system/metadata tables:

  • PostgreSQL: information_schema.*, pg_catalog.*
  • MySQL: information_schema.*, mysql.*, performance_schema.*
  • Databricks: information_schema.*, system.*
  • ClickHouse: system.*
  • SQLite: sqlite_master, sqlite_schema

aggregates

Allows aggregate functions but blocks raw column values:

# Allowed
"SELECT COUNT(*) FROM users"
"SELECT AVG(salary) FROM employees"
"SELECT MIN(created_at), MAX(created_at) FROM orders"

# Blocked
"SELECT * FROM users"
"SELECT email FROM users"
"SELECT salary FROM employees WHERE id = 1"

full

Allows any valid SELECT query.

Async Support

from anomalyarmor_query_gateway import QuerySecurityGateway, AccessLevel

gateway = QuerySecurityGateway(
    access_level=AccessLevel.AGGREGATES,
    dialect="postgresql",
)

# Async validation with audit logging
result = await gateway.validate_query(
    "SELECT COUNT(*) FROM users",
    metadata={"asset_id": "123", "user_id": "456"}
)

Audit Logging

Implement the AuditLoggerProtocol to log all query validation attempts:

from anomalyarmor_query_gateway import (
    QuerySecurityGateway,
    AccessLevel,
    AuditLoggerProtocol,
)

class MyAuditLogger(AuditLoggerProtocol):
    async def log_query(
        self,
        query: str,
        access_level: AccessLevel,
        dialect: str,
        allowed: bool,
        rejection_reason: str | None,
        metadata: dict,
    ) -> None:
        # Store to your audit log
        print(f"Query {'allowed' if allowed else 'blocked'}: {query[:50]}...")

gateway = QuerySecurityGateway(
    access_level=AccessLevel.AGGREGATES,
    dialect="postgresql",
    audit_logger=MyAuditLogger(),
)

Supported Dialects

  • postgresql / postgres
  • mysql
  • databricks
  • clickhouse
  • sqlite

Security

This package is designed to be a security control layer. Key security features:

  1. Fail-closed: If parsing fails, the query is blocked
  2. Comment stripping: SQL comments are removed before parsing to prevent obfuscation
  3. Recursive validation: Subqueries and CTEs are validated against the same rules
  4. Window function blocking: Window functions blocked in aggregates mode (can expose row-level data)

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linter
ruff check src/ tests/

# Run type checker
mypy src/

License

Apache 2.0 - See LICENSE for details.

Contributing

See CONTRIBUTING.md for guidelines.

Security Issues

See SECURITY.md for reporting security vulnerabilities.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anomalyarmor_query_gateway-1.0.0.tar.gz (27.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anomalyarmor_query_gateway-1.0.0-py3-none-any.whl (25.0 kB view details)

Uploaded Python 3

File details

Details for the file anomalyarmor_query_gateway-1.0.0.tar.gz.

File metadata

File hashes

Hashes for anomalyarmor_query_gateway-1.0.0.tar.gz
Algorithm Hash digest
SHA256 74cbe9ddf4acb895052e744b2efd7a5aff4a037cb3c9d173a963fd5c4bab8010
MD5 ddd9fc3227bb101c73d517fd322429c6
BLAKE2b-256 ada3ecc11f0c777667473c17de5e93ef18f89280b8ee054ef919870309d8dc5b

See more details on using hashes here.

Provenance

The following attestation bundles were made for anomalyarmor_query_gateway-1.0.0.tar.gz:

Publisher: publish.yml on anomalyarmor/anomalyarmor-query-gateway

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file anomalyarmor_query_gateway-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for anomalyarmor_query_gateway-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 141637c81564b20fb13be1ff8148c3343a0277ae9de3ce313765608bb29f6da6
MD5 aa70c5a519d89c128c311fbd14447835
BLAKE2b-256 c7932c03bb91bfb54fb42bf5904c832df64e292502e82f2d1fa09ca1068346e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for anomalyarmor_query_gateway-1.0.0-py3-none-any.whl:

Publisher: publish.yml on anomalyarmor/anomalyarmor-query-gateway

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page