Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
gssapi phase 2
  • Loading branch information
jaggederest committed Sep 17, 2025
commit 42bdc27564fd083fb31fdc7eb899263e1172cfd8
125 changes: 125 additions & 0 deletions integration/complex/gssapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# GSSAPI (Kerberos) Authentication Configuration Example

This directory contains example configurations for using GSSAPI/Kerberos authentication with PGDog.

## Overview

PGDog supports GSSAPI authentication in a dual-context model:
- **Frontend**: Accepts GSSAPI authentication from clients
- **Backend**: Uses service credentials to authenticate to PostgreSQL servers

This approach preserves connection pooling while providing strong authentication.

## Files

- `pgdog.toml` - Main configuration with GSSAPI settings
- `users.toml` - User mappings for GSSAPI principals

## Key Features Demonstrated

### 1. Global GSSAPI Configuration
- Server keytab for accepting client connections
- Default backend credentials for PostgreSQL servers
- Ticket refresh intervals
- Realm stripping for username mapping

### 2. Per-Server Backend Authentication
- Different keytabs for different PostgreSQL servers
- Useful for multi-tenant or sharded deployments
- Fine-grained access control per database

### 3. Mixed Authentication
- GSSAPI for some databases, password for others
- Fallback options for migration scenarios

## Setup Requirements

### Prerequisites
1. Kerberos KDC (Key Distribution Center) configured
2. Service principals created for PGDog and PostgreSQL servers
3. Keytab files generated and placed in appropriate locations
4. PostgreSQL servers configured to accept GSSAPI authentication

### Keytab Files

#### Frontend (Client-facing)
```bash
# Create service principal for PGDog
kadmin.local -q "addprinc -randkey postgres/pgdog.example.com"
kadmin.local -q "ktadd -k /etc/pgdog/pgdog.keytab postgres/pgdog.example.com"
```

#### Backend (PostgreSQL-facing)
```bash
# Create service principal for backend connections
kadmin.local -q "addprinc -randkey pgdog-service"
kadmin.local -q "ktadd -k /etc/pgdog/backend.keytab pgdog-service"

# For per-server authentication
kadmin.local -q "addprinc -randkey pgdog-shard1"
kadmin.local -q "ktadd -k /etc/pgdog/shard1.keytab pgdog-shard1"
```

### PostgreSQL Configuration

Configure PostgreSQL servers to accept GSSAPI authentication from PGDog's service principal:

```postgresql
# pg_hba.conf
host all [email protected] 0.0.0.0/0 gss
host all [email protected] 0.0.0.0/0 gss
```

## Authentication Flow

1. **Client → PGDog**: Client authenticates using their Kerberos principal (e.g., [email protected])
2. **Username Mapping**: PGDog maps the principal to a user in users.toml (strips realm if configured)
3. **PGDog → PostgreSQL**: PGDog uses its service credentials to connect to the backend
4. **Connection Pooling**: PGDog maintains pooled connections using its service identity

## Security Considerations

- Keytab files should be readable only by the PGDog process user
- Use separate service principals for different environments (dev/staging/prod)
- Regularly rotate keytabs and update Kerberos passwords
- Consider using GSSAPI encryption if SQL inspection is not required
- Monitor ticket refresh logs for authentication issues

## Testing

```bash
# Test client authentication
kinit [email protected]
psql -h pgdog.example.com -p 6432 -d production -U alice

# Verify PGDog's service ticket
klist -k /etc/pgdog/pgdog.keytab

# Check backend connectivity
kinit -kt /etc/pgdog/backend.keytab [email protected]
psql -h pg1.example.com -p 5432 -d postgres -U pgdog-service
```

## Troubleshooting

### Common Issues

1. **Clock Skew**: Ensure all servers have synchronized time (use NTP)
2. **DNS Resolution**: Kerberos requires proper forward and reverse DNS
3. **Keytab Permissions**: Check file ownership and permissions (600 or 400)
4. **Principal Names**: Verify exact principal names including realm
5. **Ticket Expiration**: Monitor ticket refresh intervals

### Debug Logging

Enable Kerberos debug output:
```bash
export KRB5_TRACE=/tmp/krb5_trace.log
```

## Migration from Password Authentication

1. Enable `fallback_enabled = true` in GSSAPI configuration
2. Deploy PGDog with both authentication methods available
3. Migrate users gradually to GSSAPI
4. Once all users migrated, disable fallback
95 changes: 95 additions & 0 deletions integration/complex/gssapi/pgdog.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Example PGDog configuration with GSSAPI authentication
# This demonstrates both simple and per-server GSSAPI setups
#
# GSSAPI Authentication Flow:
# 1. Clients authenticate to PGDog using GSSAPI (Kerberos)
# 2. PGDog uses its own service credentials to authenticate to backend PostgreSQL servers
# 3. Connection pooling is preserved since PGDog maintains the backend connections

[general]
host = "0.0.0.0"
port = 6432
workers = 2
default_pool_size = 10
min_pool_size = 1
pooler_mode = "transaction"
auth_type = "gssapi" # Enable GSSAPI as the primary authentication method

# Global GSSAPI configuration
[gssapi]
enabled = true

# Frontend authentication (accepting client connections)
# This keytab contains PGDog's service principal for accepting client connections
server_keytab = "/etc/pgdog/pgdog.keytab"
# Service principal name that clients will use to connect to PGDog
# Format: service/hostname@REALM
server_principal = "postgres/[email protected]"

# Backend authentication defaults (connecting to PostgreSQL servers)
# These can be overridden per-database for multi-server deployments
default_backend_keytab = "/etc/pgdog/backend.keytab"
default_backend_principal = "[email protected]"

# Strip realm from client principals for username mapping
# When true: [email protected] becomes "alice" in users.toml
strip_realm = true

# Ticket refresh interval in seconds (2 hours)
# Kerberos tickets are refreshed before expiration
ticket_refresh_interval = 7200

# Fall back to password auth if GSSAPI fails
# Useful during migration or for mixed environments
fallback_enabled = false

# Admin database configuration
[admin]
name = "admin"
password = "admin"
user = "admin"

# Database using global GSSAPI defaults
# This database inherits default_backend_keytab and default_backend_principal
# from the [gssapi] section above
[[databases]]
name = "production"
host = "pg1.example.com"
port = 5432
role = "primary"

# Sharded database with specific GSSAPI configuration
# Each shard can have its own service identity for fine-grained access control
[[databases]]
name = "shard1"
host = "pg-shard1.example.com"
port = 5432
role = "primary"
shard = 1
# Override global GSSAPI settings for this specific server
# Useful when different PostgreSQL servers require different service principals
gssapi_keytab = "/etc/pgdog/shard1.keytab"
gssapi_principal = "[email protected]"

# Another sharded database with its own GSSAPI identity
[[databases]]
name = "shard2"
host = "pg-shard2.example.com"
port = 5432
role = "primary"
shard = 2
# Each shard can have different credentials for security isolation
gssapi_keytab = "/etc/pgdog/shard2.keytab"
gssapi_principal = "[email protected]"

# Mixed authentication example: Database using password authentication
# Not all databases need to use GSSAPI - password auth can still be used
[[databases]]
name = "analytics"
host = "pg-analytics.example.com"
port = 5432
role = "primary"
# When no GSSAPI configuration is provided, falls back to password authentication
# The credentials here override any user-specific settings in users.toml
user = "analytics_user"
password = "analytics_password"
56 changes: 56 additions & 0 deletions integration/complex/gssapi/users.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Users configuration for GSSAPI authentication
#
# Important: When using GSSAPI authentication:
# - User names should match the Kerberos principals (after realm stripping if enabled)
# - Passwords in users.toml are ignored for GSSAPI-authenticated users
# - PGDog uses its own service credentials to connect to backend PostgreSQL servers
# - The server_user/server_password fields control backend database authentication

[[users]]
# GSSAPI-authenticated user example
# Client authenticates as [email protected] via Kerberos
# If strip_realm = true in pgdog.toml, the principal becomes "alice"
name = "alice"
database = "production"
# No password field needed - GSSAPI handles client authentication
# The server_user is the PostgreSQL user that PGDog connects as
server_user = "app_user"
# Connection pool settings
pool_size = 20
min_pool_size = 2

[[users]]
# GSSAPI user connecting to shard1
# [email protected] -> "bob" (with strip_realm = true)
name = "bob"
database = "shard1"
# PGDog will use shard1's specific keytab to connect as app_user
server_user = "app_user"
pool_size = 15

[[users]]
# GSSAPI user connecting to shard2
name = "charlie"
database = "shard2"
# PGDog will use shard2's specific keytab to connect as app_user
server_user = "app_user"
pool_size = 15

[[users]]
# Mixed authentication example: Password-authenticated user
# This user connects to the analytics database which doesn't use GSSAPI
name = "analyst"
database = "analytics"
# Client authenticates to PGDog with this password
password = "analyst_password"
# PGDog connects to PostgreSQL with these credentials
server_user = "analytics_user"
server_password = "analytics_password"
pool_size = 10

[[users]]
# Admin user for PGDog administration
# Uses password authentication regardless of GSSAPI settings
name = "admin"
database = "admin"
password = "admin"
Loading