Merge pull request #263 from Wikid82/development
Propagate changes from development into feature/beta-release
This commit is contained in:
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -105,7 +105,7 @@ jobs:
|
||||
- name: Extract metadata (tags, labels)
|
||||
if: steps.skip.outputs.skip_build != 'true'
|
||||
id: meta
|
||||
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
|
||||
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
|
||||
95
ACME_STAGING_IMPLEMENTATION.md.bak
Normal file
95
ACME_STAGING_IMPLEMENTATION.md.bak
Normal file
@@ -0,0 +1,95 @@
|
||||
# ACME Staging Implementation Summary
|
||||
|
||||
## What Was Added
|
||||
|
||||
Added support for Let's Encrypt staging environment to prevent rate limiting during development and testing.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Configuration (`backend/internal/config/config.go`)
|
||||
- Added `ACMEStaging bool` field to `Config` struct
|
||||
- Reads from `CHARON_ACME_STAGING` environment variable (legacy `CPM_ACME_STAGING` still supported)
|
||||
|
||||
### 2. Caddy Manager (`backend/internal/caddy/manager.go`)
|
||||
- Added `acmeStaging bool` field to `Manager` struct
|
||||
- Updated `NewManager()` to accept `acmeStaging` parameter
|
||||
- Passes `acmeStaging` to `GenerateConfig()`
|
||||
|
||||
### 3. Config Generation (`backend/internal/caddy/config.go`)
|
||||
- Updated `GenerateConfig()` signature to accept `acmeStaging bool`
|
||||
- When `acmeStaging=true`:
|
||||
- Sets `ca` field to `https://acme-staging-v02.api.letsencrypt.org/directory`
|
||||
- Applies to both "letsencrypt" and "both" SSL provider modes
|
||||
|
||||
### 4. Route Registration (`backend/internal/api/routes/routes.go`)
|
||||
- Passes `cfg.ACMEStaging` to `caddy.NewManager()`
|
||||
|
||||
### 5. Docker Compose (`docker-compose.local.yml`)
|
||||
- Added `CHARON_ACME_STAGING=true` environment variable for local development (legacy `CPM_ACME_STAGING` still supported)
|
||||
|
||||
### 6. Tests
|
||||
- Updated all test files to pass new `acmeStaging` parameter
|
||||
- Added `TestGenerateConfig_ACMEStaging()` to verify behavior
|
||||
- All tests pass ✅
|
||||
|
||||
### 7. Documentation
|
||||
- Created `/docs/acme-staging.md` - comprehensive guide
|
||||
- Updated `/docs/getting-started.md` - added environment variables section
|
||||
- Explained rate limits, staging vs production, and troubleshooting
|
||||
|
||||
## Usage
|
||||
|
||||
### Development (Avoid Rate Limits)
|
||||
```bash
|
||||
docker run -d \
|
||||
-e CHARON_ACME_STAGING=true \
|
||||
-p 8080:8080 \
|
||||
ghcr.io/wikid82/charon:latest
|
||||
```
|
||||
|
||||
### Production (Real Certificates)
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
ghcr.io/wikid82/charon:latest
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
Container logs confirm staging is active:
|
||||
```
|
||||
"ca":"https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **No Rate Limits**: Test certificate issuance without hitting Let's Encrypt limits
|
||||
2. **Safe Testing**: Won't affect production certificate quotas
|
||||
3. **Easy Toggle**: Single environment variable to switch modes
|
||||
4. **Default Production**: Staging must be explicitly enabled
|
||||
5. **Well Documented**: Clear guides for users and developers
|
||||
|
||||
## Test Results
|
||||
|
||||
- ✅ All backend tests pass (`go test ./...`)
|
||||
- ✅ Config generation tests verify staging CA is set
|
||||
- ✅ Manager tests updated and passing
|
||||
- ✅ Handler tests updated and passing
|
||||
- ✅ Integration verified in running container
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `backend/internal/config/config.go`
|
||||
- `backend/internal/caddy/config.go`
|
||||
- `backend/internal/caddy/manager.go`
|
||||
- `backend/internal/api/routes/routes.go`
|
||||
- `backend/internal/caddy/config_test.go`
|
||||
- `backend/internal/caddy/manager_test.go`
|
||||
- `backend/internal/caddy/client_test.go`
|
||||
- `backend/internal/api/handlers/proxy_host_handler_test.go`
|
||||
- `docker-compose.local.yml`
|
||||
|
||||
## Files Created
|
||||
|
||||
- `docs/acme-staging.md` - User guide
|
||||
- `ACME_STAGING_IMPLEMENTATION.md` - This summary
|
||||
76
DOCKER_TASKS.md.bak
Normal file
76
DOCKER_TASKS.md.bak
Normal file
@@ -0,0 +1,76 @@
|
||||
# Docker Development Tasks
|
||||
|
||||
Quick reference for Docker container management during development.
|
||||
|
||||
## Available VS Code Tasks
|
||||
|
||||
### Build & Run Local Docker
|
||||
**Command:** `Build & Run Local Docker`
|
||||
- Builds the Docker image from scratch with current code
|
||||
- Tags as `charon:local`
|
||||
- Starts container with docker-compose.local.yml
|
||||
- **Use when:** You've made backend code changes that need recompiling
|
||||
|
||||
### Docker: Restart Local (No Rebuild) ⚡
|
||||
**Command:** `Docker: Restart Local (No Rebuild)`
|
||||
- Stops the running container
|
||||
- Starts it back up using existing image
|
||||
- **Use when:** You've changed volume mounts, environment variables, or want to clear runtime state
|
||||
- **Fastest option** for testing volume mount changes
|
||||
|
||||
### Docker: Stop Local
|
||||
**Command:** `Docker: Stop Local`
|
||||
- Stops and removes the running container
|
||||
- Preserves volumes and image
|
||||
- **Use when:** You need to stop the container temporarily
|
||||
|
||||
### Docker: Start Local (Already Built)
|
||||
**Command:** `Docker: Start Local (Already Built)`
|
||||
- Starts container from existing image
|
||||
- **Use when:** Container is stopped but image is built
|
||||
|
||||
## Manual Commands
|
||||
|
||||
```bash
|
||||
# Build and run (full rebuild)
|
||||
docker build --build-arg VCS_REF=$(git rev-parse HEAD) -t charon:local . && \
|
||||
docker compose -f docker-compose.local.yml up -d
|
||||
|
||||
# Quick restart (no rebuild) - FASTEST for volume mount testing
|
||||
docker compose -f docker-compose.local.yml down && \
|
||||
docker compose -f docker-compose.local.yml up -d
|
||||
|
||||
# View logs
|
||||
docker logs -f charon-debug
|
||||
|
||||
# Stop container
|
||||
docker compose -f docker-compose.local.yml down
|
||||
|
||||
# Start existing container
|
||||
docker compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
## Testing Import Feature
|
||||
|
||||
The import feature uses a mounted Caddyfile at `/import/Caddyfile` inside the container.
|
||||
|
||||
**Volume mount in docker-compose.local.yml:**
|
||||
```yaml
|
||||
- /root/docker/containers/caddy/Caddyfile:/import/Caddyfile:ro
|
||||
- /root/docker/containers/caddy/sites:/import/sites:ro
|
||||
```
|
||||
|
||||
**To test import with different Caddyfiles:**
|
||||
1. Edit `/root/docker/containers/caddy/Caddyfile` on the host
|
||||
2. Run task: `Docker: Restart Local (No Rebuild)` ⚡
|
||||
3. Check GUI - import should detect the mounted Caddyfile
|
||||
4. No rebuild needed!
|
||||
|
||||
## Coverage Requirement
|
||||
|
||||
All code changes must maintain **≥80% test coverage**.
|
||||
|
||||
Run coverage check:
|
||||
```bash
|
||||
cd backend && bash ../scripts/go-test-coverage.sh
|
||||
```
|
||||
331
ISSUE_14_SSO_IMPLEMENTATION.md.bak
Normal file
331
ISSUE_14_SSO_IMPLEMENTATION.md.bak
Normal file
@@ -0,0 +1,331 @@
|
||||
# Built-in OAuth/OIDC Server Implementation Summary
|
||||
|
||||
## Overview
|
||||
Implemented Phase 1 (Backend Core) and Phase 2 (Caddy Integration) for Issue #14: Built-in OAuth/OIDC Server (SSO - Plus Feature).
|
||||
|
||||
## Phase 1: Backend Core
|
||||
|
||||
### 1. Docker Configuration
|
||||
**File: `/projects/Charon/Dockerfile`**
|
||||
- Updated `xcaddy build` command to include `github.com/greenpau/caddy-security` plugin
|
||||
- This enables caddy-security functionality in the Caddy binary
|
||||
|
||||
### 2. Database Models
|
||||
Created three new models in `/projects/Charon/backend/internal/models/`:
|
||||
|
||||
#### `auth_user.go` - AuthUser Model
|
||||
- Local user accounts for SSO
|
||||
- Fields: UUID, Username, Email, Name, PasswordHash, Enabled, Roles, MFAEnabled, MFASecret, LastLoginAt
|
||||
- Methods:
|
||||
- `SetPassword()` - Bcrypt password hashing
|
||||
- `CheckPassword()` - Password verification
|
||||
- `HasRole()` - Role checking
|
||||
|
||||
#### `auth_provider.go` - AuthProvider Model
|
||||
- External OAuth/OIDC provider configurations
|
||||
- Fields: UUID, Name, Type (google, github, oidc, saml), ClientID, ClientSecret, IssuerURL, AuthURL, TokenURL, UserInfoURL, Scopes, RoleMapping, IconURL, DisplayName
|
||||
- Supports generic OIDC providers and specific ones (Google, GitHub, etc.)
|
||||
|
||||
#### `auth_policy.go` - AuthPolicy Model
|
||||
- Access control policies for proxy hosts
|
||||
- Fields: UUID, Name, Description, AllowedRoles, AllowedUsers, AllowedDomains, RequireMFA, SessionTimeout
|
||||
- Method: `IsPublic()` - checks if policy allows unrestricted access
|
||||
|
||||
### 3. ProxyHost Model Enhancement
|
||||
**File: `/projects/Charon/backend/internal/models/proxy_host.go`**
|
||||
- Added `AuthPolicyID` field (nullable foreign key)
|
||||
- Added `AuthPolicy` relationship
|
||||
- Enables linking proxy hosts to authentication policies
|
||||
|
||||
### 4. API Handlers
|
||||
**File: `/projects/Charon/backend/internal/api/handlers/auth_handlers.go`**
|
||||
|
||||
Created three handler structs with full CRUD operations:
|
||||
|
||||
#### AuthUserHandler
|
||||
- `List()` - Get all auth users
|
||||
- `Get()` - Get user by UUID
|
||||
- `Create()` - Create new user (with password validation)
|
||||
- `Update()` - Update user (supports partial updates)
|
||||
- `Delete()` - Delete user (prevents deletion of last admin)
|
||||
- `Stats()` - Get user statistics (total, enabled, with MFA)
|
||||
|
||||
#### AuthProviderHandler
|
||||
- `List()` - Get all OAuth providers
|
||||
- `Get()` - Get provider by UUID
|
||||
- `Create()` - Register new OAuth provider
|
||||
- `Update()` - Update provider configuration
|
||||
- `Delete()` - Remove OAuth provider
|
||||
|
||||
#### AuthPolicyHandler
|
||||
- `List()` - Get all access policies
|
||||
- `Get()` - Get policy by UUID
|
||||
- `Create()` - Create new policy
|
||||
- `Update()` - Update policy rules
|
||||
- `Delete()` - Remove policy (prevents deletion if in use)
|
||||
|
||||
### 5. API Routes
|
||||
**File: `/projects/Charon/backend/internal/api/routes/routes.go`**
|
||||
|
||||
Registered new endpoints under `/api/v1/security/`:
|
||||
```
|
||||
GET /security/users
|
||||
GET /security/users/stats
|
||||
GET /security/users/:uuid
|
||||
POST /security/users
|
||||
PUT /security/users/:uuid
|
||||
DELETE /security/users/:uuid
|
||||
|
||||
GET /security/providers
|
||||
GET /security/providers/:uuid
|
||||
POST /security/providers
|
||||
PUT /security/providers/:uuid
|
||||
DELETE /security/providers/:uuid
|
||||
|
||||
GET /security/policies
|
||||
GET /security/policies/:uuid
|
||||
POST /security/policies
|
||||
PUT /security/policies/:uuid
|
||||
DELETE /security/policies/:uuid
|
||||
```
|
||||
|
||||
Added new models to AutoMigrate:
|
||||
- `models.AuthUser`
|
||||
- `models.AuthProvider`
|
||||
- `models.AuthPolicy`
|
||||
|
||||
## Phase 2: Caddy Integration
|
||||
|
||||
### 1. Caddy Configuration Types
|
||||
**File: `/projects/Charon/backend/internal/caddy/types.go`**
|
||||
|
||||
Added new types for caddy-security integration:
|
||||
|
||||
#### SecurityApp
|
||||
- Top-level security app configuration
|
||||
- Contains Authentication and Authorization configs
|
||||
|
||||
#### AuthenticationConfig & AuthPortal
|
||||
- Portal configuration for authentication
|
||||
- Supports multiple backends (local, OAuth, SAML)
|
||||
- Cookie and token management settings
|
||||
|
||||
#### AuthBackend
|
||||
- Configuration for individual auth backends
|
||||
- Supports local users and OAuth providers
|
||||
|
||||
#### AuthorizationConfig & AuthzPolicy
|
||||
- Policy definitions for access control
|
||||
- Role-based and user-based restrictions
|
||||
- MFA requirements
|
||||
|
||||
#### New Handler Functions
|
||||
- `SecurityAuthHandler()` - Authentication middleware
|
||||
- `SecurityAuthzHandler()` - Authorization middleware
|
||||
|
||||
### 2. Config Generation
|
||||
**File: `/projects/Charon/backend/internal/caddy/config.go`**
|
||||
|
||||
#### Updated `GenerateConfig()` Signature
|
||||
Added new parameters:
|
||||
- `authUsers []models.AuthUser`
|
||||
- `authProviders []models.AuthProvider`
|
||||
- `authPolicies []models.AuthPolicy`
|
||||
|
||||
#### New Function: `generateSecurityApp()`
|
||||
Generates the caddy-security app configuration:
|
||||
- Creates authentication portal "charon_portal"
|
||||
- Configures local backend with user credentials
|
||||
- Adds OAuth providers dynamically
|
||||
- Generates authorization policies from database
|
||||
|
||||
#### New Function: `convertAuthUsersToConfig()`
|
||||
Converts AuthUser models to caddy-security user config format:
|
||||
- Maps username, email, password hash
|
||||
- Converts comma-separated roles to arrays
|
||||
- Filters disabled users
|
||||
|
||||
#### Route Handler Integration
|
||||
When generating routes for proxy hosts:
|
||||
- Checks if host has an `AuthPolicyID`
|
||||
- Injects `SecurityAuthHandler("charon_portal")` before other handlers
|
||||
- Injects `SecurityAuthzHandler(policy.Name)` for policy enforcement
|
||||
- Maintains compatibility with legacy Forward Auth
|
||||
|
||||
### 3. Manager Updates
|
||||
**File: `/projects/Charon/backend/internal/caddy/manager.go`**
|
||||
|
||||
Updated `ApplyConfig()` to:
|
||||
- Fetch enabled auth users from database
|
||||
- Fetch enabled auth providers from database
|
||||
- Fetch enabled auth policies from database
|
||||
- Preload AuthPolicy relationships for proxy hosts
|
||||
- Pass auth data to `GenerateConfig()`
|
||||
|
||||
### 4. Test Updates
|
||||
Updated all test files to pass empty slices for new auth parameters:
|
||||
- `client_test.go`
|
||||
- `config_test.go`
|
||||
- `validator_test.go`
|
||||
- `manager_test.go`
|
||||
|
||||
## Architecture Flow
|
||||
|
||||
```
|
||||
1. User Management UI → API → Database (AuthUser, AuthProvider, AuthPolicy)
|
||||
2. ApplyConfig() → Fetch auth data → GenerateConfig()
|
||||
3. GenerateConfig() → Create SecurityApp config
|
||||
4. For each ProxyHost with AuthPolicyID:
|
||||
- Inject SecurityAuthHandler (authentication)
|
||||
- Inject SecurityAuthzHandler (authorization)
|
||||
5. Caddy receives full config with security app
|
||||
6. Incoming requests → Caddy → Security handlers → Backend services
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
### auth_users
|
||||
- id, uuid, created_at, updated_at
|
||||
- username, email, name
|
||||
- password_hash
|
||||
- enabled, roles
|
||||
- mfa_enabled, mfa_secret
|
||||
- last_login_at
|
||||
|
||||
### auth_providers
|
||||
- id, uuid, created_at, updated_at
|
||||
- name, type, enabled
|
||||
- client_id, client_secret
|
||||
- issuer_url, auth_url, token_url, user_info_url
|
||||
- scopes, role_mapping
|
||||
- icon_url, display_name
|
||||
|
||||
### auth_policies
|
||||
- id, uuid, created_at, updated_at
|
||||
- name, description, enabled
|
||||
- allowed_roles, allowed_users, allowed_domains
|
||||
- require_mfa, session_timeout
|
||||
|
||||
### proxy_hosts (updated)
|
||||
- Added: auth_policy_id (nullable FK)
|
||||
|
||||
## Configuration Example
|
||||
|
||||
When a proxy host has `auth_policy_id = 1` (pointing to "Admins Only" policy):
|
||||
|
||||
```json
|
||||
{
|
||||
"apps": {
|
||||
"security": {
|
||||
"authentication": {
|
||||
"portals": {
|
||||
"charon_portal": {
|
||||
"backends": [
|
||||
{
|
||||
"name": "local",
|
||||
"method": "local",
|
||||
"config": {
|
||||
"users": [
|
||||
{
|
||||
"username": "admin",
|
||||
"email": "admin@example.com",
|
||||
"password": "$2a$10$...",
|
||||
"roles": ["admin"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"authorization": {
|
||||
"policies": {
|
||||
"Admins Only": {
|
||||
"allowed_roles": ["admin"],
|
||||
"require_mfa": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"servers": {
|
||||
"charon_server": {
|
||||
"routes": [
|
||||
{
|
||||
"match": [{"host": ["app.example.com"]}],
|
||||
"handle": [
|
||||
{"handler": "authentication", "portal": "charon_portal"},
|
||||
{"handler": "authorization", "policy": "Admins Only"},
|
||||
{"handler": "reverse_proxy", "upstreams": [{"dial": "backend:8080"}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Password Storage**: Uses bcrypt for secure password hashing
|
||||
2. **Secrets**: ClientSecret and MFASecret fields are never exposed in JSON responses
|
||||
3. **Admin Protection**: Cannot delete the last admin user
|
||||
4. **Policy Enforcement**: Cannot delete policies that are in use
|
||||
5. **MFA Support**: Framework ready for TOTP implementation
|
||||
|
||||
## Next Steps (Phase 3 & 4)
|
||||
|
||||
### Phase 3: Frontend Management UI
|
||||
- Create `/src/pages/Security/` directory
|
||||
- Implement Users management page
|
||||
- Implement Providers management page
|
||||
- Implement Policies management page
|
||||
- Add SSO dashboard with session overview
|
||||
|
||||
### Phase 4: Proxy Host Integration
|
||||
- Update ProxyHostForm with "Access Control" tab
|
||||
- Add policy selector dropdown
|
||||
- Display active policy on host list
|
||||
- Show authentication status indicators
|
||||
|
||||
## Testing
|
||||
|
||||
All backend tests pass:
|
||||
```
|
||||
✓ internal/api/handlers
|
||||
✓ internal/api/middleware
|
||||
✓ internal/api/routes
|
||||
✓ internal/caddy (all tests updated)
|
||||
✓ internal/config
|
||||
✓ internal/database
|
||||
✓ internal/models
|
||||
✓ internal/server
|
||||
✓ internal/services
|
||||
✓ internal/version
|
||||
```
|
||||
|
||||
Backend compiles successfully without errors.
|
||||
|
||||
## Acceptance Criteria Status
|
||||
|
||||
- ✅ Can create local users for authentication (AuthUser model + API)
|
||||
- ✅ Can protect services with built-in SSO (AuthPolicy + route integration)
|
||||
- ⏳ 2FA works correctly (framework ready, needs frontend implementation)
|
||||
- ✅ External OIDC providers can be configured (AuthProvider model + API)
|
||||
|
||||
## Reserved Routes
|
||||
|
||||
- `/auth/*` - Reserved for caddy-security authentication portal
|
||||
- Portal URL: `https://yourdomain.com/auth/login`
|
||||
- Logout URL: `https://yourdomain.com/auth/logout`
|
||||
|
||||
## Notes
|
||||
|
||||
1. The implementation uses SQLite as the source of truth
|
||||
2. Configuration is "compiled" from database to Caddy JSON on each ApplyConfig
|
||||
3. No direct database sharing with caddy-security (config-based integration)
|
||||
4. Compatible with existing Forward Auth feature (both can coexist)
|
||||
5. MFA secret storage is ready but TOTP setup flow needs frontend work
|
||||
3
cookies.txt.bak
Normal file
3
cookies.txt.bak
Normal file
@@ -0,0 +1,3 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
Reference in New Issue
Block a user