diff --git a/ai-edge/basic-auth.mdx b/ai-edge/basic-auth.mdx new file mode 100644 index 0000000..b3770d5 --- /dev/null +++ b/ai-edge/basic-auth.mdx @@ -0,0 +1,299 @@ +--- +title: "HTTP Basic Authentication with Datum" +description: "Configure HTTP Basic Authentication for applications behind a Datum gateway using datumctl and Envoy Gateway SecurityPolicy." +--- + +This guide describes how to configure **HTTP Basic Authentication** for applications running behind a **Datum gateway** using `datumctl`. The configuration uses **Envoy Gateway `SecurityPolicy`** resources and applies to **Windows, macOS, and Linux**. + +--- + +## Overview + +HTTP Basic Authentication protects an application by requiring a username and password before requests are forwarded to the origin. + +At a high level, this setup: + +1. Generates credentials in **htpasswd (SHA)** format +2. Stores credentials in a **Kubernetes Secret** +3. Labels the Secret so it is synced to edge clusters +4. Attaches a **SecurityPolicy** to an `HTTPRoute` +5. Verifies authentication behavior + +--- + +## Prerequisites + +- `datumctl` installed and authenticated +- A valid **Project** +- Existing: + - `Gateway` + - `HTTPRoute` +- Permission to create: + - `Secret` + - `SecurityPolicy` + +Verify access: + +```bash +datumctl get gateway +datumctl get httproute +``` + +--- + +## Critical Requirement: Secret Syncing + +Secrets and ConfigMaps referenced by gateway configurations are **not automatically synced** to edge clusters. + +To make a Secret available to edge gateways, it **must** include the following label: + +```yaml +networking.datumapis.com/gateway-sync: "true" +``` + +### Why This Matters + +- Without this label, the gateway receives the policy but **not the Secret** +- Envoy fails to load the Basic Auth credentials +- All requests return **HTTP 500** instead of a login prompt + +This requirement exists to prevent accidental replication of unrelated secrets. + +--- + +## Configuration Steps + +### Step 1: Set Variables + +#### Windows (PowerShell) + +```powershell +$project = "your-project-id" +$namespace = "default" +$route = "your-route-name" +$username = "demo" +$password = "ChangeMe123!" +``` + +#### macOS / Linux + +```bash +project="your-project-id" +namespace="default" +route="your-route-name" +username="demo" +password="ChangeMe123!" +``` + +--- + +### Step 2: Generate htpasswd Entry (SHA) + +Envoy Gateway currently supports **SHA-based htpasswd entries only**. + +Other formats (bcrypt, APR1) are **not supported** and will cause failures. + +#### Windows (PowerShell) + +```powershell +$bytes = [Text.Encoding]::UTF8.GetBytes($password) +$sha1 = [System.Security.Cryptography.SHA1]::Create().ComputeHash($bytes) +$hash = [Convert]::ToBase64String($sha1) + +$htpasswd = "${username}:{SHA}${hash}`n" +$b64 = [Convert]::ToBase64String( + [Text.Encoding]::UTF8.GetBytes($htpasswd) +) +``` + +#### macOS / Linux + +```bash +hash=$(printf "%s" "$password" | shasum | awk '{print $1}' | xxd -r -p | base64) +htpasswd="${username}:{SHA}${hash}\n" +b64=$(printf "%s" "$htpasswd" | base64) +``` + +--- + +### Step 3: Create the Secret + +The Secret must: + +- Use the key `.htpasswd` +- Exist in the same namespace as the `SecurityPolicy` +- Include the **gateway-sync** label + +#### Windows (PowerShell) + +```powershell +@" +apiVersion: v1 +kind: Secret +metadata: + name: ${route}-basic-auth + labels: + networking.datumapis.com/gateway-sync: "true" +type: Opaque +data: + .htpasswd: $b64 +"@ | datumctl apply --project $project --namespace $namespace -f - +``` + +#### macOS / Linux + +```bash +cat < **Note:** The HTTPProxy name is the name of the auto-generated HTTPRoute that the SecurityPolicy will target. Find it with: +> ```bash +> datumctl get httproute --project --namespace default +> ``` + +--- + +## Part 1: Auth0 Setup + +### Step 1: Create an Auth0 Tenant + +1. Sign up at [auth0.com](https://auth0.com) and create a tenant +2. Note your **tenant domain** — it looks like `dev-xxxxxxxx.us.auth0.com` + +--- + +### Step 2: Create an Application + +1. In the Auth0 dashboard go to **Applications** → **Applications** → **Create Application** +2. Name it (e.g., `datum-gateway-app`) +3. Select **Regular Web Applications** +4. Click **Create** +5. On the **Settings** tab, note your **Client ID** and **Client Secret** +6. Under **Allowed Callback URLs** add: + ``` + https:///oauth2/callback + ``` +7. Under **Allowed Logout URLs** add: + ``` + https:// + ``` +8. Click **Save Changes** + +--- + +### Step 3: Enable Google Social Login + +1. Go to **Authentication** → **Social** → **Create Connection** +2. Select **Google / Gmail** +3. Enter your **Google OAuth Client ID** and **Client Secret** + (from [Google Cloud Console](https://console.cloud.google.com) → APIs & Services → Credentials) +4. Enable the connection for your application under the **Applications** tab of the connection +5. In **Google Cloud Console**, add Auth0's callback URL to your OAuth client's **Authorized redirect URIs**: + ``` + https:///login/callback + ``` + This is required so Google can redirect back to Auth0 after login. Without it, Google returns `Error 400: redirect_uri_mismatch`. + +> **Note:** If you do not have Google OAuth credentials yet, Auth0 provides a built-in dev key for testing. Go to the Google connection settings and leave Client ID/Secret blank — Auth0 will use its own dev credentials. Create dedicated Google OAuth credentials before moving to production. + +--- + +### Step 4: Create an Access Control Action + +This is where individual user access is enforced. Auth0 runs this code during login — users not in the list are denied before a token is ever issued. + +1. Go to **Actions** → **Library** → **Build Custom** +2. Name it `enforce-email-allowlist` +3. Select **Login / Post Login** trigger +4. Replace the default code with: + +```javascript +exports.onExecutePostLogin = async (event, api) => { + const allowedEmails = [ + "alice@example.com", + "bob@datum.net", + ]; + + if (!allowedEmails.includes(event.user.email)) { + api.access.deny("Access denied: you are not authorized to use this application."); + } +}; +``` + +5. Click **Deploy** +6. Go to **Actions** → **Triggers** → **post-login** +7. Drag your `enforce-email-allowlist` action from the right sidebar into the flow between **Start** and **Complete** +8. Click **Apply** + +To add or remove a user: edit the `allowedEmails` array and click **Deploy**. No gateway config changes required. + +--- + +## Part 2: Datum Gateway Configuration + +The Datum HTTPProxy already manages the Gateway and HTTPRoute. You only need to create a **Secret** (to store the Auth0 client secret) and a **SecurityPolicy** (to attach OIDC to the route). + +### Step 1: Set Variables + +#### Windows (PowerShell) + +```powershell +$project = "your-project-id" +$namespace = "default" +$route = "your-httpproxy-name" +$hostname = "your-app.example.com" +$auth0Domain = "dev-xxxxxxxx.us.auth0.com" +$clientID = "your-auth0-client-id" +$clientSecret = "your-auth0-client-secret" +``` + +#### macOS / Linux + +```bash +project="your-project-id" +namespace="default" +route="your-httpproxy-name" +hostname="your-app.example.com" +auth0Domain="dev-xxxxxxxx.us.auth0.com" +clientID="your-auth0-client-id" +clientSecret="your-auth0-client-secret" +``` + +--- + +### Step 2: Create the Auth0 Client Secret + +The Secret must include the `gateway-sync` label or the edge proxy will not receive it and all requests will return HTTP 500. + +#### Windows (PowerShell) + +```powershell +$b64Secret = [Convert]::ToBase64String( + [Text.Encoding]::UTF8.GetBytes($clientSecret) +) + +@" +apiVersion: v1 +kind: Secret +metadata: + name: ${route}-oidc-secret + labels: + networking.datumapis.com/gateway-sync: "true" +type: Opaque +data: + client-secret: $b64Secret +"@ | datumctl apply --project $project --namespace $namespace -f - +``` + +#### macOS / Linux + +```bash +b64Secret=$(printf "%s" "$clientSecret" | base64) + +cat < **Warning:** Use only the `oidc` block — do not add a `jwt` block, as it conflicts with the OIDC filter and causes HTTP 500. + +#### Windows (PowerShell) + +```powershell +@" +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: ${route}-oidc +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: $route + oidc: + provider: + issuer: "https://${auth0Domain}" + clientID: "$clientID" + clientSecret: + name: ${route}-oidc-secret + redirectURL: "https://${hostname}/oauth2/callback" + scopes: + - openid + - email + - profile +"@ | datumctl apply --project $project --namespace $namespace -f - +``` + +#### macOS / Linux + +```bash +cat </oauth2/callback` in Auth0 Application Settings | +| Google error 400: `redirect_uri_mismatch` | Auth0 callback not in Google OAuth client | Add `https:///login/callback` to Google Cloud Console Authorized redirect URIs | +| Redirect loop | `redirectURL` mismatch | Ensure it matches **Allowed Callback URLs** in Auth0 exactly | +| User sees "Access denied" at Auth0 | Not in allow-list | Add email to the Action and redeploy | +| User bypasses allow-list | Action not in Login flow | Verify action is added under **Actions** → **Triggers** → **post-login** | + +### Useful Debug Commands + +```bash +datumctl get securitypolicy --project $project --namespace $namespace +datumctl get secret --project $project --namespace $namespace +datumctl get httproute --project $project --namespace $namespace +datumctl get trafficprotectionpolicy --project $project --namespace $namespace +``` + +--- + +## Summary + +| Concern | Where it lives | +|---------|----------------| +| Google social login | Auth0 social connection | +| Who is allowed | Auth0 Action (`enforce-email-allowlist`) | +| Token issuance | Auth0 — denied users never get a token | +| Token validation | Envoy OIDC block (handled automatically) | +| Session management | Envoy OIDC block (cookie) | +| App changes required | None | diff --git a/ai-edge/oidc-google.mdx b/ai-edge/oidc-google.mdx new file mode 100644 index 0000000..5a3013f --- /dev/null +++ b/ai-edge/oidc-google.mdx @@ -0,0 +1,316 @@ +--- +title: "OAuth 2.0 / OIDC Authentication with Google and Datum" +description: "Configure OIDC authentication using Google OAuth 2.0 for applications behind a Datum gateway using datumctl and Envoy Gateway SecurityPolicy." +--- + +This guide describes how to configure **OAuth 2.0 / OIDC Authentication** for applications running behind a **Datum gateway** using `datumctl`. The configuration uses **Envoy Gateway `SecurityPolicy`** resources and applies to **Windows, macOS, and Linux**. + +--- + +## Overview + +OIDC authentication protects an application by requiring users to sign in with their Google account before requests are forwarded to the origin. Envoy Gateway handles the OAuth 2.0 flow transparently — users are redirected to Google, authenticate, and are redirected back without any changes to your application. + +At a high level, this setup: + +1. Creates a **Google OAuth 2.0 Client** in Google Cloud Console +2. Stores the client secret in a **Kubernetes Secret** +3. Labels the Secret so it is synced to edge clusters +4. Attaches a **SecurityPolicy** with OIDC config to an `HTTPRoute` +5. Verifies authentication behavior + +--- + +## Prerequisites + +- `datumctl` installed and authenticated +- A valid **Project** +- A **Google Cloud** account with a project +- Existing: + - `Gateway` + - `HTTPRoute` +- Permission to create: + - `Secret` + - `SecurityPolicy` + +Verify access: + +```bash +datumctl get gateway +datumctl get httproute +``` + +--- + +## Critical Requirement: Secret Syncing + +Secrets and ConfigMaps referenced by gateway configurations are **not automatically synced** to edge clusters. + +To make a Secret available to edge gateways, it **must** include the following label: + +```yaml +networking.datumapis.com/gateway-sync: "true" +``` + +### Why This Matters + +- Without this label, the gateway receives the policy but **not the Secret** +- Envoy fails to load the OAuth client credentials +- All requests return **HTTP 500** instead of redirecting to Google + +This requirement exists to prevent accidental replication of unrelated secrets. + +--- + +## Configuration Steps + +### Step 1: Create Google OAuth 2.0 Credentials + +1. Go to [Google Cloud Console](https://console.cloud.google.com) → **APIs & Services** → **Credentials** +2. Click **Create Credentials** → **OAuth 2.0 Client ID** +3. Set **Application type** to **Web application** +4. Under **Authorized redirect URIs**, add: + ``` + https:///oauth2/callback + ``` + Replace `` with the public hostname of your `HTTPRoute`. +5. Click **Create** and copy the **Client ID** and **Client Secret** + +> **Note:** The redirect URI must exactly match the value you will configure in the `SecurityPolicy`. Any mismatch causes Google to reject the OAuth flow. + +--- + +### Step 2: Set Variables + +#### Windows (PowerShell) + +```powershell +$project = "your-project-id" +$namespace = "default" +$route = "your-route-name" +$hostname = "your-app.example.com" +$clientID = "your-client-id.apps.googleusercontent.com" +$clientSecret = "your-client-secret" +``` + +#### macOS / Linux + +```bash +project="your-project-id" +namespace="default" +route="your-route-name" +hostname="your-app.example.com" +clientID="your-client-id.apps.googleusercontent.com" +clientSecret="your-client-secret" +``` + +--- + +### Step 3: Create the Client Secret + +The Secret must: + +- Use the key `client-secret` +- Exist in the same namespace as the `SecurityPolicy` +- Include the **gateway-sync** label + +#### Windows (PowerShell) + +```powershell +$b64Secret = [Convert]::ToBase64String( + [Text.Encoding]::UTF8.GetBytes($clientSecret) +) + +@" +apiVersion: v1 +kind: Secret +metadata: + name: ${route}-oidc-secret + labels: + networking.datumapis.com/gateway-sync: "true" +type: Opaque +data: + client-secret: $b64Secret +"@ | datumctl apply --project $project --namespace $namespace -f - +``` + +#### macOS / Linux + +```bash +b64Secret=$(printf "%s" "$clientSecret" | base64) + +cat <