Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g. 0.0.14). Must match pyproject.toml."
description: "Version to publish (e.g. 0.0.15). Must match pyproject.toml."
required: true
type: string
branch:
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ Open `http://localhost:8080/admin` to see the gateway dashboard. It includes:
- Login with `admin` and `viewer` roles.
- Per-client request, token, cost, model, provider, and cache-hit usage.
- Provider health and routing status.
- Admin-only client token creation, allowed-model updates, enable/disable, and rotation.
- Admin-only client token creation, allowed-model updates, per-client policy actions, enable/disable, and rotation.
- Admin-only upstream provider key updates with masked display and encrypted SQLite storage.
- One-time token reveal on create or rotate; SentinelGuard stores only a hash.

For local testing, the fallback credentials are `admin` / `sentinelguard` and
Expand All @@ -215,6 +216,13 @@ client tokens are separate from upstream LLM provider keys. Apps, SDKs, IDEs,
EKS services, or EC2 services use the generated `sgw_...` token as their API key
when their base URL points to SentinelGuard.

Set a stable `SENTINELGUARD_ENCRYPTION_KEY` if you want the dashboard to store
upstream provider API keys. Generate one with
`sentinelguard token --prefix sgencrypt`, or let
`sentinelguard init --with-env` write it into the local `.env` file. Without it,
provider keys should come from env vars, Docker secrets, Kubernetes Secrets, or
your secret manager.

## Connect Apps, Services, And IDEs

Point clients to SentinelGuard instead of directly to the model provider:
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ services:
HUGGINGFACE_API_KEY: ${HUGGINGFACE_API_KEY:-}
SENTINELGUARD_GATEWAY_API_KEY: ${SENTINELGUARD_GATEWAY_API_KEY:-}
SENTINELGUARD_AUDIT_SALT: ${SENTINELGUARD_AUDIT_SALT:-local-dev-salt}
SENTINELGUARD_ENCRYPTION_KEY: ${SENTINELGUARD_ENCRYPTION_KEY:-}
SENTINELGUARD_ADMIN_USERNAME: ${SENTINELGUARD_ADMIN_USERNAME:-admin}
SENTINELGUARD_ADMIN_PASSWORD: ${SENTINELGUARD_ADMIN_PASSWORD:-sentinelguard}
SENTINELGUARD_VIEWER_USERNAME: ${SENTINELGUARD_VIEWER_USERNAME:-viewer}
Expand Down
2 changes: 1 addition & 1 deletion docs/container-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Use `latest` only for local testing or demos.
docker run --rm -p 8080:8080 \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
-e SENTINELGUARD_GATEWAY_API_KEY="$SENTINELGUARD_GATEWAY_API_KEY" \
aitechnav/sentinelguard:0.0.14
aitechnav/sentinelguard:0.0.15
```

Then point OpenAI-compatible clients to:
Expand Down
13 changes: 13 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ Base URL: http://sentinelguard-gateway:8080/v1
API key: the same sgw_... value from SENTINELGUARD_GATEWAY_API_KEY
```

For Docker Compose, put upstream provider keys such as `OPENAI_API_KEY` in the
Compose `.env` file or Docker secrets so only the SentinelGuard container
receives them. To update provider keys from the dashboard instead, also set a
stable `SENTINELGUARD_ENCRYPTION_KEY`. `sentinelguard init --with-env` generates
one for local Compose. Dashboard-entered provider keys are then stored encrypted
in the gateway SQLite volume and shown only as masked hints.

## Kubernetes

```bash
Expand All @@ -50,6 +57,12 @@ Base URL: http://sentinelguard-gateway.sentinelguard.svc.cluster.local:8080/v1
API key: the same sgw_... value from SENTINELGUARD_GATEWAY_API_KEY
```

For Kubernetes, keep upstream provider keys in Kubernetes Secrets, external
secret operators, or your cloud secret manager and expose them to SentinelGuard
as environment variables referenced by `api_key_env`. Dashboard-entered provider
keys are supported for self-managed deployments, but they are stored in the
gateway SQLite state volume, not written back to a Kubernetes Secret.

For EC2, ECS, another EKS cluster, or another VPC, expose the gateway through a
private DNS name, internal load balancer, PrivateLink, VPN, or peering route:

Expand Down
24 changes: 24 additions & 0 deletions docs/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ client in `/admin`, edit **Allowed models**, and save. For example:
`sentinel-auto, fast-chat, smart-chat, private-chat`. This updates the existing
client token policy; it does not require rotating the token.

Admins can also update policy actions per client from the same dashboard form.
Use this when one app should block attacks and secrets but redact PII, while
another app should audit PII or block PCI data. Supported actions are `block`,
`redact`, `audit`, and `allow` for attack, secret, PII, PCI, PHI, and other
scanner categories.

Admins can update upstream provider API keys from the dashboard when encrypted
provider-secret storage is enabled. Set one stable encryption key on the
gateway process:

```bash
export SENTINELGUARD_ENCRYPTION_KEY="$(sentinelguard token --prefix sgencrypt)"
```

`sentinelguard init --with-env` also generates this value in the local `.env`
file used by Docker Compose.

Dashboard-entered OpenAI, Anthropic, Gemini, or other provider keys are stored
encrypted in the gateway SQLite database and shown only as a masked hint. They
override the environment/YAML key for that provider route until the dashboard
key is removed. SentinelGuard cannot rotate provider API keys because those are
issued by the provider; it can update, replace, test, or remove the configured
key.

A dashboard-managed client can also rotate its own token while it still has a
valid current token:

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "sentinelguard"
version = "0.0.14"
version = "0.0.15"
description = "A comprehensive, production-ready LLM security and guardrails framework"
readme = "README.md"
license = "Apache-2.0"
Expand Down Expand Up @@ -56,6 +56,7 @@ gateway = [
"fastapi>=0.100.0",
"uvicorn>=0.23.0",
"httpx>=0.24.0",
"cryptography>=41.0.0",
"redis>=5.0.0",
"websockets>=12.0",
]
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ regex>=2023.0
# fastapi>=0.100.0
# uvicorn>=0.23.0
# httpx>=0.24.0
# cryptography>=41.0.0 # encrypted dashboard-managed provider secrets

# Monitoring (optional)
# opentelemetry-api>=1.20.0
Expand Down
2 changes: 1 addition & 1 deletion sentinelguard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
guard = SentinelGuard(config=config)
"""

__version__ = "0.0.14"
__version__ = "0.0.15"
__author__ = "SentinelGuard Contributors"

from sentinelguard.core.guard import SentinelGuard
Expand Down
6 changes: 6 additions & 0 deletions sentinelguard/cli/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def _env_example() -> str:
# Generate local SentinelGuard tokens and dashboard passwords with:
# sentinelguard token
# sentinelguard token --prefix sgaudit
# sentinelguard token --prefix sgencrypt
# sentinelguard token --prefix sgadmin
# sentinelguard token --prefix sgviewer

Expand All @@ -243,6 +244,7 @@ def _env_example() -> str:
SENTINELGUARD_IMAGE=sentinelguard-gateway:local
SENTINELGUARD_GATEWAY_API_KEY=
SENTINELGUARD_AUDIT_SALT=
SENTINELGUARD_ENCRYPTION_KEY=
SENTINELGUARD_ADMIN_USERNAME=admin
SENTINELGUARD_ADMIN_PASSWORD=
SENTINELGUARD_VIEWER_USERNAME=viewer
Expand All @@ -268,6 +270,7 @@ def _env_example() -> str:
def _env_file() -> str:
gateway_token = generate_gateway_token()
audit_salt = generate_gateway_token(prefix="sgaudit")
encryption_key = generate_gateway_token(prefix="sgencrypt")
admin_password = generate_gateway_token(prefix="sgadmin")
viewer_password = generate_gateway_token(prefix="sgviewer")
return dedent(
Expand All @@ -280,6 +283,7 @@ def _env_file() -> str:
SENTINELGUARD_IMAGE=sentinelguard-gateway:local
SENTINELGUARD_GATEWAY_API_KEY={gateway_token}
SENTINELGUARD_AUDIT_SALT={audit_salt}
SENTINELGUARD_ENCRYPTION_KEY={encryption_key}
SENTINELGUARD_ADMIN_USERNAME=admin
SENTINELGUARD_ADMIN_PASSWORD={admin_password}
SENTINELGUARD_VIEWER_USERNAME=viewer
Expand Down Expand Up @@ -359,6 +363,7 @@ def _docker_compose(docker_image: str) -> str:
OLLAMA_API_KEY: ${{OLLAMA_API_KEY:-}}
SENTINELGUARD_GATEWAY_API_KEY: ${{SENTINELGUARD_GATEWAY_API_KEY:-}}
SENTINELGUARD_AUDIT_SALT: ${{SENTINELGUARD_AUDIT_SALT:-local-dev-audit-salt}}
SENTINELGUARD_ENCRYPTION_KEY: ${{SENTINELGUARD_ENCRYPTION_KEY:-}}
SENTINELGUARD_ADMIN_USERNAME: ${{SENTINELGUARD_ADMIN_USERNAME:-admin}}
SENTINELGUARD_ADMIN_PASSWORD: ${{SENTINELGUARD_ADMIN_PASSWORD:-sentinelguard}}
SENTINELGUARD_VIEWER_USERNAME: ${{SENTINELGUARD_VIEWER_USERNAME:-viewer}}
Expand Down Expand Up @@ -425,6 +430,7 @@ def _readme(profile: str) -> str:
python -m pip install "sentinelguard[gateway,monitoring]"
export SENTINELGUARD_GATEWAY_API_KEY="$(sentinelguard token)"
export SENTINELGUARD_AUDIT_SALT="$(sentinelguard token --prefix sgaudit)"
export SENTINELGUARD_ENCRYPTION_KEY="$(sentinelguard token --prefix sgencrypt)"
export OPENAI_API_KEY="your-provider-key"
sentinelguard gateway \\
--config sentinelguard.yaml \\
Expand Down
Loading
Loading