Files
Maison/arti-api/auth-service/pipeline
2026-02-10 12:12:11 +01:00
..
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00
2026-02-10 12:12:11 +01:00

Authentication Service with Active Directory Integration

This authentication service provides JWT-based authentication with Active Directory integration and Traefik ForwardAuth support for Kubernetes environments.

Features

  • 🔐 Active Directory Authentication: Validates credentials against your AD server
  • 🎫 JWT Tokens: Secure token-based authentication with configurable expiration
  • 🍪 Cookie & Local Storage: Tokens stored securely in HTTP-only cookies and locally
  • 🚀 Traefik Integration: ForwardAuth middleware for seamless Kubernetes access control
  • 📱 Responsive UI: Clean, modern login interface
  • 🔒 Security Headers: Proper CORS, security headers, and token validation

Architecture

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   User Browser  │───▶│  Auth Service    │───▶│ Active Directory│
│                 │    │                  │    │                 │
│ 1. Login Form   │    │ 2. Validate AD   │    │ 3. LDAP Auth    │
│ 4. Store Token  │◀───│    Create JWT    │    │                 │
└─────────────────┘    └──────────────────┘    └─────────────────┘
         │                        │
         │                        │
         ▼                        ▼
┌─────────────────┐    ┌──────────────────┐
│  Protected API  │◀───│ Traefik Forward  │
│                 │    │ Auth Middleware  │
│ 5. Access with  │    │ 6. Validate JWT  │
│    JWT Token    │    │                  │
└─────────────────┘    └──────────────────┘

Quick Start

1. Build and Deploy

# Build the authentication service
cd auth-service
docker build -t your-registry/auth-service:1.0.0 .
docker push your-registry/auth-service:1.0.0

# Update values in values-example.yaml
cp values-example.yaml values.yaml
# Edit values.yaml with your AD configuration

# Deploy to Kubernetes
kubectl apply -f kubernetes-auth.yaml

2. Configure Active Directory

Update the values.yaml file with your AD configuration:

authService:
  activeDirectory:
    server: "ldap://your-ad-server.yourdomain.com"
    baseDN: "DC=yourdomain,DC=com"
    userSearchBase: "CN=Users,DC=yourdomain,DC=com"
    bindUser: "CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com"
    bindPassword: "your-service-account-password"

3. Configure Traefik ForwardAuth

The service automatically creates a ForwardAuth middleware that:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: auth-forward
spec:
  forwardAuth:
    address: http://auth-service:8080/auth/verify
    authResponseHeaders:
      - "X-Auth-User"
      - "X-Auth-Email" 
      - "X-Auth-Groups"
      - "X-Auth-Display-Name"

4. Protect Your Services

Add the ForwardAuth middleware to any IngressRoute:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: protected-service
spec:
  routes:
  - match: Host(`api.yourdomain.com`)
    kind: Rule
    services:
    - name: your-api-service
      port: 8000
    middlewares:
    - name: auth-forward  # This protects the entire service

How It Works

Authentication Flow

  1. User visits protected resource → Traefik ForwardAuth redirects to login
  2. User enters AD credentials → Service validates against Active Directory
  3. JWT token created → Stored in HTTP-only cookie + localStorage
  4. Subsequent requests → Traefik validates JWT via ForwardAuth
  5. Access granted → User headers passed to backend service

Token Storage

The system uses a dual-storage approach:

  • HTTP-only Cookie: Secure, automatic transmission, protected from XSS
  • localStorage: Available to JavaScript for SPA applications

Security Features

  • LDAP over TLS support for secure AD communication
  • JWT token expiration with configurable timeouts
  • HTTP-only cookies prevent XSS token theft
  • Secure headers for production deployment
  • CORS protection with configurable origins

API Endpoints

Authentication Endpoints

Endpoint Method Description
/ GET Login page (HTML)
/dashboard GET Dashboard page (HTML)
/auth/login POST Authenticate user
/auth/verify POST Verify JWT token (ForwardAuth)
/auth/logout GET Logout user
/auth/user GET Get current user info
/health GET Health check

ForwardAuth Integration

When Traefik calls /auth/verify, the service:

  1. Checks for token in Authorization header or cookies
  2. Validates JWT signature and expiration
  3. Returns user headers for backend services:
    • X-Auth-User: Username
    • X-Auth-Email: User email
    • X-Auth-Groups: AD group memberships
    • X-Auth-Display-Name: User's display name

Configuration

Environment Variables

Variable Description Default
JWT_SECRET Secret key for JWT signing (required)
TOKEN_EXPIRE_HOURS Token expiration in hours 8
AD_SERVER LDAP server URL (required)
AD_BASE_DN Base DN for AD (required)
AD_USER_SEARCH_BASE User search base (required)
AD_BIND_USER Service account for LDAP (optional)
AD_BIND_PASSWORD Service account password (optional)

Kubernetes Secrets

Create the required secrets:

kubectl create secret generic auth-secrets \
  --from-literal=jwt-secret="your-super-secret-key" \
  --from-literal=ad-bind-user="CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com" \
  --from-literal=ad-bind-password="your-service-password"

Advanced Usage

Custom Group-Based Access

The service passes AD group memberships in the X-Auth-Groups header. You can use this in your backend services:

# In your FastAPI backend
from fastapi import Header

def check_admin_access(x_auth_groups: str = Header(None)):
    groups = x_auth_groups.split(',') if x_auth_groups else []
    if 'CN=Admins,CN=Groups,DC=yourdomain,DC=com' not in groups:
        raise HTTPException(status_code=403, detail="Admin access required")

Multiple Protection Levels

You can create different ForwardAuth middlewares for different access levels:

# Admin-only middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: admin-auth
spec:
  forwardAuth:
    address: http://auth-service:8080/auth/verify-admin
    authResponseHeaders:
      - "X-Auth-User"
      - "X-Auth-Groups"

Token Refresh

The service automatically handles token refresh. Configure shorter expiration times and implement refresh logic in your frontend:

// Check token expiration
const token = localStorage.getItem('auth_token');
const payload = JSON.parse(atob(token.split('.')[1]));
const expiry = new Date(payload.exp * 1000);

if (expiry < new Date()) {
    // Redirect to login for refresh
    window.location.href = '/auth/login';
}

Monitoring

Health Checks

The service includes health check endpoints:

curl http://auth-service:8080/health

Logging

The service logs authentication attempts and failures:

INFO: Successfully authenticated user: john.doe
ERROR: Authentication failed for user: invalid.user
ERROR: LDAP connection failed: timeout

Security Considerations

  1. Use HTTPS: Always deploy with TLS certificates
  2. Secure JWT Secret: Use a strong, unique JWT secret
  3. Network Security: Restrict access to AD servers
  4. Token Expiration: Use reasonable token expiration times
  5. Service Account: Use a dedicated AD service account with minimal permissions
  6. Audit Logs: Monitor authentication logs for suspicious activity

Troubleshooting

Common Issues

  1. LDAP Connection Failed

    • Check AD server connectivity
    • Verify LDAP URL format
    • Check firewall rules
  2. Authentication Failed

    • Verify AD credentials
    • Check user search base DN
    • Confirm user exists in specified OU
  3. ForwardAuth Not Working

    • Verify Traefik middleware configuration
    • Check service connectivity
    • Review Traefik logs
  4. Token Issues

    • Verify JWT secret consistency
    • Check token expiration
    • Validate cookie settings

Debug Mode

Enable debug logging by setting log level:

env:
- name: LOG_LEVEL
  value: "DEBUG"

This will provide detailed authentication flow logs.

🔧 Drone Configuration Factorization Options

Drone supports Jsonnet for dynamic configuration generation, which allows you to include files and create reusable components.

2. YAML Anchors & References (Limited)

YAML supports anchors and references for basic factorization:

3. External Configuration Files (Starlark)

Drone also supports Starlark (Python-like) for advanced configuration:

🎯 Recommended: Convert to Jsonnet Let me create a script to help you convert your current .drone.yml to the modular Jsonnet approach:

convert-to-jsonnet.sh

#!/bin/bash

# Convert existing .drone.yml to modular Jsonnet structure
# This script helps migrate from YAML to factorized Jsonnet configuration

echo "🔄 Converting Drone configuration to modular Jsonnet..."

# Generate the final configuration from Jsonnet
echo "📝 Generating .drone.yml from Jsonnet..."
if command -v jsonnet >/dev/null 2>&1; then
    jsonnet .drone.jsonnet > .drone.yml.generated
    echo "✅ Generated .drone.yml.generated from Jsonnet"
    echo ""
    echo "📋 To use the new configuration:"
    echo "1. Review: cat .drone.yml.generated"
    echo "2. Test: python3 -c \"import yaml; yaml.safe_load(open('.drone.yml.generated'))\""
    echo "3. Replace: mv .drone.yml.generated .drone.yml"
    echo "4. Commit: git add .drone.jsonnet common.libsonnet build-steps.libsonnet .drone.yml"
else
    echo "⚠️ jsonnet not installed. Installing..."
    
    # Try to install jsonnet
    if command -v apt-get >/dev/null 2>&1; then
        sudo apt-get update && sudo apt-get install -y jsonnet
    elif command -v apk >/dev/null 2>&1; then
        apk add --no-cache jsonnet
    elif command -v yum >/dev/null 2>&1; then
        sudo yum install -y jsonnet
    else
        echo "❌ Cannot install jsonnet automatically"
        echo "📖 Please install jsonnet manually:"
        echo "   - Ubuntu/Debian: sudo apt-get install jsonnet"
        echo "   - Alpine: apk add jsonnet"
        echo "   - CentOS/RHEL: sudo yum install jsonnet"
        echo "   - Or download from: https://github.com/google/jsonnet"
        exit 1
    fi
    
    # Try generating again
    if command -v jsonnet >/dev/null 2>&1; then
        jsonnet .drone.jsonnet > .drone.yml.generated
        echo "✅ Generated .drone.yml.generated from Jsonnet"
    else
        echo "❌ Failed to install jsonnet"
        exit 1
    fi
fi

echo ""
echo "🎯 Benefits of Jsonnet configuration:"
echo "   ✅ Reusable components (common.libsonnet, build-steps.libsonnet)"
echo "   ✅ Variables and functions"
echo "   ✅ Conditional logic"
echo "   ✅ Better maintainability"
echo "   ✅ DRY principle"
echo ""
echo "📚 Files created:"
echo "   - .drone.jsonnet (main configuration)"
echo "   - common.libsonnet (shared steps and config)"
echo "   - build-steps.libsonnet (build-specific logic)"
echo "   - .drone.yml.generated (generated YAML)"

# Validate the generated YAML
if [ -f ".drone.yml.generated" ]; then
    echo ""
    echo "🔍 Validating generated YAML..."
    if python3 -c "import yaml; yaml.safe_load(open('.drone.yml.generated'))" 2>/dev/null; then
        echo "✅ Generated YAML is valid"
    else
        echo "❌ Generated YAML has syntax errors"
        exit 1
    fi
fi

📋 Summary of Factorization Options

Method Pros Cons Best For
Jsonnet Full programming language
Variables, functions, imports
Conditional logic
Learning curve
Requires jsonnet tool
Complex configurations
YAML Anchors Native YAML
Simple syntax
No extra tools
Limited functionality
No conditionals
Simple repetition
Starlark Python-like syntax
Advanced logic
Built into Drone
Drone-specific
Less common
Advanced pipelines

🎯 Recommendation for Your Project

For your external Buildah build system, I recommend Jsonnet because:

  • Modularity: Separate build logic from common steps
  • Reusability: Common kubectl setup, environment config
  • Maintainability: Easier to update build steps independently
  • Flexibility: Can create variants (dev, staging, prod) easily

🚀 Quick Start with Jsonnet

# Install jsonnet (if needed)
sudo apt-get install jsonnet

# Convert to modular structure
./convert-to-jsonnet.sh

# Review generated configuration
cat .drone.yml.generated

# Test and deploy
mv .drone.yml.generated .drone.yml
git add .drone.jsonnet common.libsonnet build-steps.libsonnet .drone.yml
git commit -m "Convert to modular Jsonnet configuration"
git push

The modular approach will make it much easier to:

  • 🔧 Update build steps without touching common logic
  • 🎯 Create environment-specific configurations
  • 🧪 Test individual components
  • 📦 Share configuration across projects