Metadata-Version: 2.4
Name: dagster-authkit
Version: 1.0.1
Summary: Community Auth System for self-hosted Dagster OSS - RBAC, Audit Logging, and Session Management
Author-email: Demetrius Albuquerque <demetrius.albuquerque@yahoo.com.br>
License: Apache-2.0
Project-URL: Homepage, https://github.com/maltzsama/dagster-authkit
Project-URL: Repository, https://github.com/maltzsama/dagster-authkit
Project-URL: Issues, https://github.com/maltzsama/dagster-authkit/issues
Keywords: dagster,data-orchestration,data-pipeline,authentication,authorization,rbac,security,audit-logging,self-hosted,data-platform,data-engineering,devops,dagster-auth,access-control,session-management,data-governance
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Internet :: WWW/HTTP :: Session
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: dagster<2.0.0,>=1.10.0
Requires-Dist: dagster-webserver<2.0.0,>=1.10.0
Requires-Dist: starlette>=0.52.1
Requires-Dist: itsdangerous>=2.2.0
Requires-Dist: python-multipart>=0.0.22
Requires-Dist: peewee>=3.19.0
Requires-Dist: click>=8.0.0
Requires-Dist: graphql-core>=3.2.7
Provides-Extra: sqlite
Requires-Dist: bcrypt>=5.0.0; extra == "sqlite"
Provides-Extra: postgresql
Requires-Dist: psycopg2-binary>=2.9.9; extra == "postgresql"
Requires-Dist: bcrypt>=5.0.0; extra == "postgresql"
Provides-Extra: mysql
Requires-Dist: mysql-connector-python>=8.0.33; extra == "mysql"
Requires-Dist: bcrypt>=5.0.0; extra == "mysql"
Provides-Extra: mariadb
Requires-Dist: mariadb>=1.1.8; extra == "mariadb"
Requires-Dist: bcrypt>=5.0.0; extra == "mariadb"
Provides-Extra: redis
Requires-Dist: redis>=7.1.0; extra == "redis"
Provides-Extra: ldap
Requires-Dist: ldap3>=2.9.0; extra == "ldap"
Provides-Extra: oauth
Requires-Dist: authlib>=1.2.0; extra == "oauth"
Requires-Dist: httpx>=0.24.0; extra == "oauth"
Provides-Extra: dev
Requires-Dist: pytest>=9.0.2; extra == "dev"
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
Requires-Dist: twine>=4.0.0; extra == "dev"
Requires-Dist: build>=0.10.0; extra == "dev"
Requires-Dist: black>=26.1.0; extra == "dev"
Requires-Dist: ruff>=0.14.14; extra == "dev"
Requires-Dist: python-semantic-release>=9.0.0; extra == "dev"
Provides-Extra: ruff
Requires-Dist: ruff>=0.14.14; extra == "ruff"
Provides-Extra: mypy
Requires-Dist: mypy>=1.0.0; extra == "mypy"
Provides-Extra: pyright
Requires-Dist: pyright>=1.1.0; extra == "pyright"
Provides-Extra: test
Requires-Dist: pytest>=9.0.2; extra == "test"
Requires-Dist: pytest-asyncio>=1.3.0; extra == "test"
Requires-Dist: pytest-cov>=6.0.0; extra == "test"
Provides-Extra: all
Requires-Dist: dagster-authkit[ldap,mariadb,mysql,oauth,postgresql,redis,sqlite]; extra == "all"
Dynamic: license-file

# 🛡️ Dagster AuthKit

[![Python Version](https://img.shields.io/badge/python-3.10%20|%203.11%20|%203.12%20|%203.13%20|%203.14-blue.svg?logo=python&logoColor=white)](https://www.python.org/downloads/)
[![Build Status](https://github.com/maltzsama/dagster-authkit/workflows/CI/badge.svg)](https://github.com/maltzsama/dagster-authkit/actions)
[![License](https://img.shields.io/badge/license-Apache%202.0-green.svg?logo=open-source-initiative&logoColor=white)](https://opensource.org/licenses/Apache-2.0)
[![Coverage](https://codecov.io/gh/maltzsama/dagster-authkit/branch/main/graph/badge.svg)](https://codecov.io/gh/maltzsama/dagster-authkit)
[![PyPI Version](https://img.shields.io/pypi/v/dagster-authkit?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/dagster-authkit/)
[![PyPI Stats](/api/badges/dagster-authkit?type=stars)](/packages/dagster-authkit)
[![Downloads](https://img.shields.io/pypi/dm/dagster-authkit?logo=pypi&logoColor=white)](https://pypi.org/project/dagster-authkit/)
[![PyPI Stats](/api/badges/dagster-authkit?period=total)](/packages/dagster-authkit)


**Community authentication wrapper for self-hosted Dagster OSS.**

*Authentication, RBAC, and Audit logs for Dagster without touching internal code.*

---

## 🎯 What is this?

Dagster OSS has no auth. If you run it in a VPC or locally, anyone with the URL has full admin access.

**AuthKit solves this by wrapping the `dagster-webserver` command to add:**

* ✅ **Login Interface:** Simple username/password flow.
* ✅ **RBAC (4 Levels):** Granular control over who can do what.
* ✅ **Audit Logs:** JSON logs for monitoring who is doing what.
* ✅ **Multi-Backend:** Works with SQLite, Postgres, MySQL (via Peewee ORM) and Redis.

**No code changes required.** You don't touch your `repository.py` or `dagster.yaml`.

---

## ✨ What's New in v1.0.0

### ☸️ Helm Chart
- **Production-ready Kubernetes chart** under `helm/dagster-authkit/`, synced with the application's config (env vars, secrets, image tag) and versioned automatically by semantic-release. Requires an explicit `image.tag`.

### 🔄 Automated CHANGELOG
- **`CHANGELOG.md` is now auto-generated** by semantic-release on each release, alongside the version bump. Versions are inserted above the `<!-- version list -->` marker.
- **RBAC deny-by-default** — unknown GraphQL mutations require `ADMIN` by default.

### 🔐 Hardening & Fixes
- **Rebuild of the fix backlog from v0.4.2** across CSRF (per-client double-submit), fail-closed GraphQL batches, token-gated `/auth/metrics`, Redis 6-compatible atomic rate limiting, LDAP connection cleanup, session revoked-token caps, and detection-layer Starlette `Middleware.cls` compatibility.
- **Test coverage boosted** 44% → 52% (+98 tests: detection layer, rate limiter, metrics gate, CookieBackend, CLI, LDAP, middleware).

---

## ⚠️ Upgrading from v0.3.x

1. **Set `DAGSTER_AUTH_SECRET_KEY`** in your environment. Generate one with:
   ```bash
   python -c 'import secrets; print(secrets.token_urlsafe(32))'
   ```
2. **If using proxy mode**, set `DAGSTER_AUTH_PROXY_TRUSTED_IPS` to your proxy's IP address.
3. **Database migration** happens automatically on first boot — no manual steps needed for SQLite/Postgres/MySQL. A `session_version` column is added to the `users` table.
4. **Role serialization** changed from string (`"ADMIN"`) to int (`40`) in session cookies. Existing sessions continue to work (backward-compatible `from_dict`).

---

## 📂 Ready-to-Run Examples

We provide ready-to-use stacks for different scenarios in the `examples/` directory:

```bash
examples
├── authelia              # NEW! Authelia + Caddy + LDAP SSO (Docker)
│   ├── Makefile
│   ├── docker-compose.yml
│   ├── Caddyfile
│   └── authelia/
├── kubernetes            # NEW! Minikube deployment
│   ├── Makefile
│   └── k8s/
├── ldap                  # Active Directory integration (**Experimental**)
│   ├── Makefile
│   ├── docker-compose.yml
│   └── ldap-bootstrap.ldif
├── postgresql_redis      # Recommended production setup
│   ├── Makefile
│   └── docker-compose.yml
└── quickstart-sqlite     # Simple local testing
    ├── Makefile
    └── docker-compose.yml
```

### How to run

Pick a scenario, go into the folder, and check the `Makefile`.

**1. Authelia SSO (Docker)**
Complete SSO with Authelia, Caddy, and OpenLDAP:
```bash
cd examples/authelia
make up
# Access: https://auth.company.com (admin/password123)
# Then:   https://dagster.company.com
```

**2. Kubernetes (Minikube)**
Same stack running on Kubernetes:
```bash
cd examples/kubernetes
make build  # Build the Docker image inside Minikube
make up     # Deploy everything
# In another terminal: make connect (runs minikube tunnel)
# Add to /etc/hosts: $(minikube ip) auth.company.com dagster.company.com
```

**3. Standard Setup (Postgres + Redis)**
```bash
cd examples/postgresql_redis
make up
```

**4. Local Quickstart (SQLite)**
```bash
cd examples/quickstart-sqlite
make up
```

**5. LDAP/AD Testing** ⚠️ **EXPERIMENTAL**
```bash
cd examples/ldap
make up
```

---

## 🚀 Manual Installation (Python)

If you aren't using Docker, you can install via pip.

```bash
# For local testing (SQLite)
pip install dagster-authkit[sqlite]

# For server usage (Postgres + Redis recommended)
pip install dagster-authkit[postgresql,redis]

# For LDAP/Active Directory integration (**Experimental**)
pip install dagster-authkit[ldap]

```

**Usage:**

```bash
# Initialize the database and create the first admin
dagster-authkit init-db --with-admin

# Run Dagster (replaces the standard 'dagster-webserver' command)
dagster-authkit -f your_pipeline.py -h 0.0.0.0 -p 3000

# For proxy mode (Authelia/OAuth2 Proxy)
export DAGSTER_AUTH_BACKEND=proxy
export DAGSTER_AUTH_PROXY_LOGIN_URL=https://auth.yourcompany.com
dagster-authkit -f your_pipeline.py -h 0.0.0.0 -p 3000
```

### ☸️ Helm (Kubernetes)

Deploy on Kubernetes via the Helm chart in [`helm/dagster-authkit/`](./helm/dagster-authkit/):

```bash
helm upgrade --install dagster-authkit ./helm/dagster-authkit \
  --set image.tag="$(git describe --tags --abbrev=0)" \
  --set authkit.secretKey="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')" \
  --set authkit.adminPassword="your-admin-password"
```

See [`values.yaml`](./helm/dagster-authkit/values.yaml) for all configuration options.

---

## 🔐 Roles (RBAC)

We provide **4 levels** of access. Permissions are enforced via GraphQL query analysis.

| Role | Description |
|------|-------------|
| **Admin** | Full access. Can manage users, settings, and all pipelines. |
| **Editor** | Can modify assets and codebase (if allowed) and manage runs. |
| **Launcher** | Can launch runs and re-execute jobs, but cannot modify code/assets. |
| **Viewer** | Read-only. Can view runs and assets. GraphQL mutations are blocked. |

**How it works:** AuthKit analyzes GraphQL queries using the official GraphQL parser to accurately identify mutations and block unauthorized actions.

---

## 📦 Backends

| Backend | Implementation | Status | Use Case |
|---------|---------------|--------|----------|
| **SQLite** | Peewee ORM | **Stable** | Local / Simple. Single instance only. |
| **PostgreSQL** | Peewee + `psycopg2` | **Stable** | Production. Recommended for Docker/K8s. |
| **MySQL/MariaDB** | Peewee + `mysql-connector` | **Stable** | Production. |
| **Redis** | Native `redis` | **Stable** | Session Storage + Distributed Rate Limiting. |
| **LDAP** | `ldap3` library | **Experimental** | Active Directory / OpenLDAP. Community maintained. |
| **Proxy** | Header-based | **Stable** | Authelia, OAuth2 Proxy, Traefik, Caddy. |
| **OpenID Connect**| Header-based | **Experimental** | AuthKit supports OIDC providers (Google, GitHub, Okta, Keycloak) via **Authelia**| 
---

## 🛠️ CLI Management

Manage users directly from the shell. Useful for CI/CD or admin tasks.

```bash
# Create a new launcher
dagster-authkit add-user bob --launcher

# Reset password
dagster-authkit change-password bob

# List everyone
dagster-authkit list-users

# View RBAC permissions matrix
dagster-authkit list-permissions
```

---

## 🔮 Roadmap

### Current (v1.0.0)

* ✅ Username/password auth (bcrypt)
* ✅ 4-level RBAC (ADMIN/EDITOR/LAUNCHER/VIEWER)
* ✅ SQLite, PostgreSQL, MySQL, Redis support
* ✅ GraphQL mutation blocking with official AST parser
* ✅ LDAP backend (experimental)
* ✅ Proxy authentication (Authelia, Caddy, Traefik)
* ✅ Kubernetes example with full SSO stack
* ✅ Helm chart for Kubernetes deployments
* ✅ Redis session revocation and rate limiting
* ✅ Centralized UI templates
* ✅ CSRF protection
* ✅ Cross-pod session revocation (DB-backed `session_version`)
* ✅ WebSocket authentication (GraphQL subscriptions)
* ✅ Dual rate-limiting (username + IP)
* ✅ Proxy trusted IP allowlist
* ✅ Token-protected `/auth/metrics`
* ✅ Automated `CHANGELOG.md` generation

### Next

* 🔄 OIDC backend (beyond proxy mode)

**What we will NOT do:**

* ❌ Inject React code into Dagster UI (too brittle)
* ❌ Complex enterprise features (that's what Dagster+ is for)

---

## 🤝 Contributing

Found a bug? Want to add a feature?
Open a PR. If it works and keeps things simple, we'll merge it.

**Especially needed:**

- People with Active Directory experience to validate the LDAP backend
- Testing on different Dagster versions
- Helm chart contributions

---

## 📄 License

Apache 2.0 - see [LICENSE](LICENSE)

---

## 🙏 Credits

Built by [Demetrius Albuquerque](https://github.com/demetrius-mp) because self-hosting Dagster shouldn't mean no auth.

Inspired by the community's need for a middle ground between "no auth" and "pay for Dagster+".
