# Citadel SSO/OIDC Integration

SSO integration via [Dex](https://dexidp.io/) as an OIDC identity provider,
with support for upstream SAML 2.0 federation and K8s OIDC authentication.

## Architecture

```
                     +-----------+
                     |  User /   |
                     |  kubectl  |
                     +-----+-----+
                           |
                           | 1. Login (browser / device code)
                           v
                     +-----+-----+
                     |    Dex    |  OIDC Identity Provider
                     | (2 pods)  |  https://dex.citadel.local
                     +-----+-----+
                           |
              +------------+------------+
              |            |            |
              v            v            v
        +---------+  +---------+  +---------+
        |  SAML   |  |  LDAP   |  | GitHub  |  Upstream IdPs
        |  IdP    |  |   AD    |  | OAuth   |  (connectors)
        +---------+  +---------+  +---------+

                           |
                           | 2. OIDC token (JWT with groups claim)
                           v
                     +-----+-----+
                     | K3s API   |  Validates OIDC tokens
                     |  Server   |  --oidc-issuer-url
                     +-----+-----+
                           |
                           | 3. RBAC evaluation
                           v
                     +-----+-----+
                     | ClusterRole|
                     | Bindings   |  oidc:group -> ClusterRole
                     +-----------+
```

## Components

| File | Purpose |
|------|---------|
| `dex-install.yaml` | Helm values for Dex deployment (HA, CRD storage, TLS) |
| `dex-connectors.yaml` | Upstream IdP connector templates (SAML, LDAP, GitHub, static) |
| `dex-clients.yaml` | OAuth2 client registrations (K8s API, dashboard, CLI) |
| `rbac-oidc.yaml` | RBAC bindings mapping OIDC groups to K8s roles |

## Prerequisites

- K3s running (`scripts/01-install-k3s.sh`)
- Helm installed (`scripts/02-install-cilium.sh`)
- cert-manager installed (`scripts/09-install-cert-manager.sh`)

## Quick Start

```bash
# Install Dex and configure K8s OIDC authentication
./scripts/10-install-dex.sh

# Verify Dex is running
kubectl get pods -n dex

# Test OIDC flow (static password connector)
# 1. Port-forward Dex
kubectl port-forward -n dex svc/dex 5556:5556

# 2. Open browser to get a token
open https://localhost:5556/auth?client_id=citadel-cli&response_type=code&scope=openid+profile+email+groups

# 3. Use the token with kubectl
kubectl --token="<id-token>" get pods
```

## Group Mapping

| OIDC Group | ClusterRole | Scope | Access Level |
|------------|-------------|-------|--------------|
| `platform-admins` | `cluster-admin` | Cluster | Full unrestricted access |
| `platform-ops` | `citadel-operator` | Cluster | Node + workload management |
| `developers` | `citadel-developer` | Namespace | Deploy and debug workloads |
| `viewers` | `view` | Cluster | Read-only (no secrets) |

Groups are prefixed with `oidc:` by the API server. RBAC subjects reference
`oidc:platform-admins`, not `platform-admins`.

## Connector Configuration

### SAML 2.0 (Enterprise)

Configure your IdP (Okta, Azure AD, PingFederate, ADFS) with:
- Entity ID: `https://dex.citadel.local/callback`
- ACS URL: `https://dex.citadel.local/callback`
- NameID: `emailAddress`
- Attributes: `email`, `groups`

### LDAP (Active Directory)

Requires a service account with read access to the user/group OUs.
Update `dex-connectors.yaml` with your AD server details.

### GitHub (Development)

Create an OAuth App at GitHub > Settings > Developer settings with
callback URL `https://dex.citadel.local/callback`.

## Token Expiry

| Token Type | Lifetime | Rationale |
|------------|----------|-----------|
| Access (ID) | 1 hour | Short-lived for security |
| Refresh | 24 hours (idle) | Re-authentication after inactivity |
| Refresh | 30 days (absolute) | Hard limit regardless of activity |
| Signing keys | 6 hours | Key rotation cadence |

## Python Integration

```python
from citadel_operator.k3s.sso import OIDCConfig, SSOManager

# Generate K3s OIDC flags
config = OIDCConfig(
    issuer_url="https://dex.citadel.local",
    client_id="kubernetes",
)
flags = SSOManager.generate_k8s_oidc_flags(config)
# {'oidc-issuer-url': 'https://dex.citadel.local', 'oidc-client-id': 'kubernetes', ...}

# Generate kubeconfig with OIDC token
kubeconfig = SSOManager.generate_kubeconfig(config, token="eyJhbGciOi...")

# Generate RBAC binding
binding = SSOManager.create_rbac_binding(
    group="platform-admins",
    cluster_role="cluster-admin",
)
```

## Security Notes

- Dex runs with read-only root filesystem and non-root user
- TLS certificates issued by the internal CA (cert-manager)
- Static password connector is for testing only
- LDAP bind password should use a Kubernetes Secret, not plaintext
- GitHub OAuth client secret should use a Kubernetes Secret
- SAML assertions must be signed (insecureSkipSignatureValidation=false)
