docs auth
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
- [Deploying Your First Application](#deploying-your-first-application)
|
||||
- [Updating an Existing Application](#updating-an-existing-application)
|
||||
- [Working with Secrets](#working-with-secrets)
|
||||
- [Enabling Authentication for Applications](#enabling-authentication-for-applications)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
@@ -754,6 +755,457 @@ kubectl rollout restart deployment myapp -n myapp
|
||||
|
||||
---
|
||||
|
||||
## Enabling Authentication for Applications
|
||||
|
||||
The cluster supports automatic authentication sidecar injection for applications via Kyverno policies. This allows you to add authentication to your applications without modifying application code.
|
||||
|
||||
### How It Works
|
||||
|
||||
When you enable authentication in your Helm values, the Kyverno policy automatically:
|
||||
1. ✅ Injects an authentication sidecar container into your pod
|
||||
2. ✅ Routes all incoming traffic through the auth sidecar (port 8080)
|
||||
3. ✅ Validates credentials before forwarding requests to your application
|
||||
4. ✅ Creates necessary secrets (if they don't exist)
|
||||
5. ✅ Adds a NetworkPolicy to restrict ingress
|
||||
|
||||
**Architecture**:
|
||||
```
|
||||
Internet → Traefik → Service:8080 → Auth Sidecar:8080 → localhost → Your App:3000
|
||||
│
|
||||
├─ Validates credentials
|
||||
└─ Forwards if valid
|
||||
```
|
||||
|
||||
### Authentication Modes
|
||||
|
||||
Two authentication modes are supported:
|
||||
1. **Token-based**: Static tokens (simple, good for service-to-service or internal apps)
|
||||
2. **OIDC**: OpenID Connect (full SSO, good for user-facing apps)
|
||||
|
||||
---
|
||||
|
||||
### Token-Based Authentication
|
||||
|
||||
#### Step 1: Configure Helm Values
|
||||
|
||||
```yaml
|
||||
# In helm-values/myapp/values.yaml
|
||||
auth:
|
||||
enabled: true
|
||||
type: token # Token mode (default)
|
||||
tokens:
|
||||
- d4f88f6d9292c10cc3e21c4aad56d2be485db532b54fe961d738e1137d247823
|
||||
- 8803f621acc3898df1d7a8f514bc3602551a0681a8f747bd4e43c3c5849d57a7
|
||||
```
|
||||
|
||||
#### Step 2: Generate Token (if needed)
|
||||
|
||||
```bash
|
||||
# Generate a secure random token
|
||||
openssl rand -hex 32
|
||||
|
||||
# Or using Python
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
|
||||
# Example output:
|
||||
# d4f88f6d9292c10cc3e21c4aad56d2be485db532b54fe961d738e1137d247823
|
||||
```
|
||||
|
||||
#### Step 3: Deploy Application
|
||||
|
||||
Commit and push your changes:
|
||||
```bash
|
||||
cd ~/dev/k8s/helm-prod-values
|
||||
git add myapp/values.yaml
|
||||
git commit -m "Enable token auth for myapp"
|
||||
git push
|
||||
```
|
||||
|
||||
ArgoCD will sync, and the Kyverno policy will:
|
||||
- Inject the auth sidecar container
|
||||
- Create an `auth-tokens` Secret with your tokens
|
||||
- Configure the sidecar to validate against these tokens
|
||||
|
||||
#### Step 4: Access Application
|
||||
|
||||
Use your token in the `Authorization` header:
|
||||
|
||||
```bash
|
||||
# Access application with token
|
||||
curl -H "Authorization: Bearer d4f88f6d9292c10cc3e21c4aad56d2be485db532b54fe961d738e1137d247823" \
|
||||
https://myapp.forteapps.net/api/data
|
||||
|
||||
# Without token (will be rejected)
|
||||
curl https://myapp.forteapps.net/api/data
|
||||
# Response: 401 Unauthorized
|
||||
```
|
||||
|
||||
#### Advanced: Custom Secret Name
|
||||
|
||||
To use a different secret for tokens:
|
||||
|
||||
```yaml
|
||||
# In Helm values
|
||||
auth:
|
||||
enabled: true
|
||||
type: token
|
||||
tokens: [] # Empty - using external secret
|
||||
|
||||
# Tokens will be read from custom secret
|
||||
```
|
||||
|
||||
Then reference it via annotation (configured by Helm chart automatically):
|
||||
```yaml
|
||||
# Helm chart sets this annotation:
|
||||
policies.forteapps.io/auth-token-secret-name: "myapp-auth-tokens"
|
||||
```
|
||||
|
||||
Create the secret manually:
|
||||
```bash
|
||||
kubectl create secret generic myapp-auth-tokens \
|
||||
--from-file=tokens=tokens.txt \
|
||||
--namespace=myapp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### OIDC Authentication
|
||||
|
||||
OIDC mode integrates with identity providers like Keycloak, Okta, Auth0, Azure AD, etc.
|
||||
|
||||
#### Step 1: Configure Identity Provider
|
||||
|
||||
In your identity provider (e.g., Keycloak):
|
||||
1. Create a new client (e.g., `myapp`)
|
||||
2. Set redirect URI: `https://myapp.forteapps.net/auth/callback`
|
||||
3. Note the **Client ID** and **Client Secret**
|
||||
4. Note the **Authority URL** (e.g., `https://keycloak.forteapps.net/realms/master`)
|
||||
|
||||
#### Step 2: Create OIDC Secret
|
||||
|
||||
```bash
|
||||
# Create plain secret
|
||||
kubectl create secret generic auth-oidc \
|
||||
--from-literal=client-secret=your-oidc-client-secret \
|
||||
--from-literal=cookie-secret=$(openssl rand -hex 32) \
|
||||
--namespace=myapp \
|
||||
--dry-run=client -o yaml > private/myapp-auth-oidc.yaml
|
||||
|
||||
# Seal it
|
||||
kubeseal --format=yaml \
|
||||
--cert=pub-cert.pem \
|
||||
--namespace=myapp \
|
||||
< private/myapp-auth-oidc.yaml \
|
||||
> secrets/myapp-auth-oidc-sealed.yaml
|
||||
|
||||
# Commit sealed secret
|
||||
cd ~/dev/k8s/launchpad
|
||||
git add secrets/myapp-auth-oidc-sealed.yaml
|
||||
git commit -m "Add OIDC secrets for myapp"
|
||||
git push
|
||||
|
||||
# Clean up
|
||||
rm private/myapp-auth-oidc.yaml
|
||||
```
|
||||
|
||||
#### Step 3: Configure Helm Values
|
||||
|
||||
```yaml
|
||||
# In helm-values/myapp/values.yaml
|
||||
auth:
|
||||
enabled: true
|
||||
type: oidc # OIDC mode
|
||||
oidc:
|
||||
authority: https://keycloak.forteapps.net/realms/master
|
||||
clientId: myapp
|
||||
scopes: "openid,profile,email"
|
||||
callbackPath: /auth/callback
|
||||
```
|
||||
|
||||
#### Step 4: Deploy Application
|
||||
|
||||
```bash
|
||||
cd ~/dev/k8s/helm-prod-values
|
||||
git add myapp/values.yaml
|
||||
git commit -m "Enable OIDC auth for myapp"
|
||||
git push
|
||||
```
|
||||
|
||||
#### Step 5: Access Application
|
||||
|
||||
When users access `https://myapp.forteapps.net`:
|
||||
1. They're redirected to the identity provider login page
|
||||
2. After successful login, redirected back to `/auth/callback`
|
||||
3. Session cookie is set
|
||||
4. Subsequent requests are authenticated via cookie
|
||||
|
||||
**User flow**:
|
||||
```
|
||||
User → https://myapp.forteapps.net
|
||||
↓
|
||||
Redirect → https://keycloak.forteapps.net/login
|
||||
↓
|
||||
Login successful → Redirect with auth code
|
||||
↓
|
||||
https://myapp.forteapps.net/auth/callback?code=xyz
|
||||
↓
|
||||
Auth sidecar exchanges code for tokens
|
||||
↓
|
||||
Sets session cookie
|
||||
↓
|
||||
Redirects to application → https://myapp.forteapps.net
|
||||
↓
|
||||
User sees application (authenticated)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Authentication Configuration Reference
|
||||
|
||||
#### Helm Values Schema
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
enabled: false # Enable/disable authentication
|
||||
type: token # "token" or "oidc"
|
||||
|
||||
# Token mode configuration
|
||||
tokens: [] # List of valid bearer tokens
|
||||
# - token1
|
||||
# - token2
|
||||
|
||||
# OIDC mode configuration
|
||||
oidc:
|
||||
authority: "" # OIDC provider URL (required for OIDC)
|
||||
clientId: "" # OIDC client ID (required for OIDC)
|
||||
scopes: "openid,profile,email" # OIDC scopes (optional)
|
||||
callbackPath: /auth/callback # OAuth callback path (optional)
|
||||
```
|
||||
|
||||
#### Annotations Set by Helm Chart
|
||||
|
||||
When `auth.enabled: true`, the Helm chart sets these pod annotations:
|
||||
|
||||
**Token mode**:
|
||||
```yaml
|
||||
policies.forteapps.io/auth: "true"
|
||||
policies.forteapps.io/auth-type: "token"
|
||||
policies.forteapps.io/auth-token-secret-name: "auth-tokens"
|
||||
policies.forteapps.io/auth-upstream-url: "http://localhost:3000"
|
||||
```
|
||||
|
||||
**OIDC mode**:
|
||||
```yaml
|
||||
policies.forteapps.io/auth: "true"
|
||||
policies.forteapps.io/auth-type: "oidc"
|
||||
policies.forteapps.io/auth-oidc-authority: "https://keycloak.forteapps.net/realms/master"
|
||||
policies.forteapps.io/auth-oidc-client-id: "myapp"
|
||||
policies.forteapps.io/auth-oidc-scopes: "openid,profile,email"
|
||||
policies.forteapps.io/auth-oidc-callback-path: "/auth/callback"
|
||||
policies.forteapps.io/auth-upstream-url: "http://localhost:3000"
|
||||
```
|
||||
|
||||
#### Sidecar Configuration
|
||||
|
||||
The auth sidecar container:
|
||||
- **Image**: `ghcr.io/snothub/stunning-memory:latest`
|
||||
- **Port**: 8080
|
||||
- **Resources**: 10m CPU / 32Mi memory (requests), 50m CPU / 64Mi memory (limits)
|
||||
- **Health checks**: `/healthz` endpoint
|
||||
- **Security**: Read-only root filesystem, no privilege escalation
|
||||
|
||||
#### Advanced: Custom Sidecar Image
|
||||
|
||||
To use a different auth sidecar image:
|
||||
|
||||
```yaml
|
||||
# These annotations can be set in the Helm chart template if needed
|
||||
policies.forteapps.io/auth-image: "your-registry/your-auth-proxy"
|
||||
policies.forteapps.io/auth-image-version: "v1.2.3"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Authentication Examples
|
||||
|
||||
#### Example 1: Internal API with Token Auth
|
||||
|
||||
```yaml
|
||||
# helm-values/internal-api/values.yaml
|
||||
app:
|
||||
image:
|
||||
repository: ghcr.io/company/internal-api
|
||||
tag: v1.0.0
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
type: token
|
||||
tokens:
|
||||
- d4f88f6d9292c10cc3e21c4aad56d2be485db532b54fe961d738e1137d247823 # Service A
|
||||
- 8803f621acc3898df1d7a8f514bc3602551a0681a8f747bd4e43c3c5849d57a7 # Service B
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: internal-api.forteapps.net
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Service A calls API
|
||||
curl -H "Authorization: Bearer d4f88f..." \
|
||||
https://internal-api.forteapps.net/api/endpoint
|
||||
```
|
||||
|
||||
#### Example 2: User-Facing App with OIDC
|
||||
|
||||
```yaml
|
||||
# helm-values/web-app/values.yaml
|
||||
app:
|
||||
image:
|
||||
repository: ghcr.io/company/web-app
|
||||
tag: v2.1.0
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
type: oidc
|
||||
oidc:
|
||||
authority: https://auth.company.com/realms/employees
|
||||
clientId: web-app-prod
|
||||
scopes: "openid,profile,email,groups"
|
||||
callbackPath: /auth/callback
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: web-app.forteapps.net
|
||||
```
|
||||
|
||||
**With sealed OIDC secret**:
|
||||
```bash
|
||||
# Create and seal secret
|
||||
kubectl create secret generic auth-oidc \
|
||||
--from-literal=client-secret=super-secret-value \
|
||||
--from-literal=cookie-secret=$(openssl rand -hex 32) \
|
||||
--namespace=web-app \
|
||||
--dry-run=client -o yaml | \
|
||||
kubeseal --format=yaml --cert=pub-cert.pem --namespace=web-app \
|
||||
> secrets/web-app-auth-oidc-sealed.yaml
|
||||
```
|
||||
|
||||
#### Example 3: Disabling Authentication
|
||||
|
||||
```yaml
|
||||
# helm-values/public-api/values.yaml
|
||||
auth:
|
||||
enabled: false # No authentication
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
host: public-api.forteapps.net
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Troubleshooting Authentication
|
||||
|
||||
#### Issue: 401 Unauthorized (Token Mode)
|
||||
|
||||
**Check token validity**:
|
||||
```bash
|
||||
# Get auth-tokens secret
|
||||
kubectl get secret auth-tokens -n myapp -o yaml
|
||||
|
||||
# Decode tokens
|
||||
kubectl get secret auth-tokens -n myapp \
|
||||
-o jsonpath='{.data.tokens}' | base64 -d
|
||||
|
||||
# Verify your token is in the list
|
||||
```
|
||||
|
||||
**Test with different token**:
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer YOUR-TOKEN-HERE" \
|
||||
https://myapp.forteapps.net/
|
||||
```
|
||||
|
||||
#### Issue: OIDC Login Loop
|
||||
|
||||
**Check OIDC configuration**:
|
||||
```bash
|
||||
# Verify auth-oidc secret exists
|
||||
kubectl get secret auth-oidc -n myapp
|
||||
|
||||
# Check sidecar logs
|
||||
kubectl logs -n myapp <pod-name> -c authn
|
||||
|
||||
# Common issues:
|
||||
# - Wrong authority URL
|
||||
# - Wrong client ID
|
||||
# - Missing client-secret in auth-oidc Secret
|
||||
# - Redirect URI not configured in identity provider
|
||||
```
|
||||
|
||||
**Verify redirect URI** in your identity provider matches:
|
||||
```
|
||||
https://<your-app-domain>/auth/callback
|
||||
```
|
||||
|
||||
#### Issue: Auth Sidecar Not Injected
|
||||
|
||||
**Check pod annotations**:
|
||||
```bash
|
||||
kubectl get pod -n myapp <pod-name> -o yaml | grep policies.forteapps.io
|
||||
|
||||
# Should show:
|
||||
# policies.forteapps.io/auth: "true"
|
||||
```
|
||||
|
||||
**Check Kyverno policy**:
|
||||
```bash
|
||||
kubectl get clusterpolicy inject-auth-sidecar
|
||||
kubectl describe clusterpolicy inject-auth-sidecar
|
||||
```
|
||||
|
||||
**Check Kyverno logs**:
|
||||
```bash
|
||||
kubectl logs -n kyverno deployment/kyverno | grep inject-auth
|
||||
```
|
||||
|
||||
#### Issue: Auth Sidecar Crashes
|
||||
|
||||
**Check sidecar logs**:
|
||||
```bash
|
||||
kubectl logs -n myapp <pod-name> -c authn
|
||||
```
|
||||
|
||||
**Common causes**:
|
||||
- Missing secret (auth-tokens or auth-oidc)
|
||||
- Invalid OIDC configuration
|
||||
- Can't reach OIDC authority URL
|
||||
- Network policy blocking outbound OIDC requests
|
||||
|
||||
---
|
||||
|
||||
### Authentication Best Practices
|
||||
|
||||
✅ **DO**:
|
||||
- Use OIDC for user-facing applications
|
||||
- Use token auth for service-to-service communication
|
||||
- Rotate tokens and secrets regularly
|
||||
- Use strong random tokens (32+ bytes)
|
||||
- Store client secrets in SealedSecrets
|
||||
- Test authentication before deploying to production
|
||||
- Document which tokens/users have access
|
||||
|
||||
❌ **DON'T**:
|
||||
- Share tokens between environments
|
||||
- Commit tokens to application code
|
||||
- Use predictable tokens
|
||||
- Reuse tokens across multiple applications
|
||||
- Disable authentication on sensitive APIs
|
||||
- Log tokens or secrets
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Application Not Deploying
|
||||
|
||||
Reference in New Issue
Block a user