- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
292 lines
7.8 KiB
Markdown
292 lines
7.8 KiB
Markdown
# Route Authorization System
|
|
|
|
Dokumentation des namespace-basierten Route Authorization Systems.
|
|
|
|
## Übersicht
|
|
|
|
Das Route Authorization System ermöglicht die Zugangskontrolle für Routes auf Basis von:
|
|
1. **Legacy `#[Auth]` Attribute** - Backward compatibility
|
|
2. **Namespace-basierte Blockierung** - Blockiere ganze Controller-Namespaces (z.B. `App\Application\Admin\*`)
|
|
3. **Namespace-basierte IP-Restrictions** - IP-basierte Zugriffskontrolle per Namespace
|
|
4. **Route-spezifische `#[IpAuth]` Attribute** - Feinkörnige IP-Kontrolle per Route
|
|
|
|
## Architektur
|
|
|
|
```
|
|
RouteAuthorizationService
|
|
├── checkLegacyAuthAttribute()
|
|
├── checkNamespaceAccessPolicy() [NEU]
|
|
├── checkNamespaceIpRestrictions()
|
|
└── checkRouteIpAuthAttribute()
|
|
```
|
|
|
|
Der Service wird in der `RoutingMiddleware` **nach dem Routing** aufgerufen, sodass die gematchte Route bekannt ist.
|
|
|
|
## Konfiguration
|
|
|
|
### Initializer-basierte Konfiguration
|
|
|
|
**Location**: `src/Framework/Auth/RouteAuthorizationServiceInitializer.php`
|
|
|
|
```php
|
|
#[Initializer]
|
|
public function __invoke(Container $container): RouteAuthorizationService
|
|
{
|
|
$namespaceConfig = [
|
|
// Namespace Pattern => Configuration
|
|
'App\Application\Admin\*' => [
|
|
'visibility' => 'admin', // IP-based restriction
|
|
'access_policy' => NamespaceAccessPolicy::blocked()
|
|
],
|
|
];
|
|
|
|
return new RouteAuthorizationService(
|
|
config: $this->config,
|
|
namespaceConfig: $namespaceConfig
|
|
);
|
|
}
|
|
```
|
|
|
|
### Namespace Patterns
|
|
|
|
**Wildcard-basierte Patterns**:
|
|
- `App\Application\Admin\*` - Matched alle Admin-Controller
|
|
- `App\Application\Api\*` - Matched alle API-Controller
|
|
- `App\Application\*` - Matched alle Application-Controller
|
|
|
|
**Exact Match**:
|
|
- `App\Application\Admin\Dashboard` - Nur exakt dieser Namespace
|
|
|
|
## Use Cases
|
|
|
|
### 1. Admin-Bereich komplett blockieren
|
|
|
|
```php
|
|
$namespaceConfig = [
|
|
'App\Application\Admin\*' => [
|
|
'access_policy' => NamespaceAccessPolicy::blocked()
|
|
],
|
|
];
|
|
```
|
|
|
|
**Ergebnis**: Alle Admin-Controller werfen `RouteNotFound` (404)
|
|
|
|
### 2. Admin-Bereich mit Allowlist
|
|
|
|
```php
|
|
use App\Application\Admin\LoginController;
|
|
use App\Application\Admin\HealthCheckController;
|
|
|
|
$namespaceConfig = [
|
|
'App\Application\Admin\*' => [
|
|
'access_policy' => NamespaceAccessPolicy::blockedExcept(
|
|
LoginController::class,
|
|
HealthCheckController::class
|
|
)
|
|
],
|
|
];
|
|
```
|
|
|
|
**Ergebnis**:
|
|
- ✅ `LoginController` und `HealthCheckController` öffentlich erreichbar
|
|
- ❌ Alle anderen Admin-Controller blockiert
|
|
|
|
### 3. Kombination: IP-Restriction + Namespace-Blocking
|
|
|
|
```php
|
|
$namespaceConfig = [
|
|
'App\Application\Admin\*' => [
|
|
'visibility' => 'admin', // Nur Admin-IPs erlaubt
|
|
'access_policy' => NamespaceAccessPolicy::blockedExcept(
|
|
LoginController::class // Aber Login ist public
|
|
)
|
|
],
|
|
];
|
|
```
|
|
|
|
**Ergebnis**:
|
|
- ✅ `LoginController` - öffentlich erreichbar (trotz admin visibility)
|
|
- 🔒 Alle anderen Admin-Controller - nur von Admin-IPs
|
|
|
|
### 4. API-Bereich mit IP-Restriction (ohne Blocking)
|
|
|
|
```php
|
|
$namespaceConfig = [
|
|
'App\Application\Api\*' => [
|
|
'visibility' => 'local', // Nur localhost/private IPs
|
|
// Kein access_policy - keine Namespace-Blockierung
|
|
],
|
|
];
|
|
```
|
|
|
|
**Ergebnis**: API nur von localhost/private IPs erreichbar
|
|
|
|
### 5. Mehrere Namespace-Policies
|
|
|
|
```php
|
|
$namespaceConfig = [
|
|
// Admin komplett gesperrt
|
|
'App\Application\Admin\*' => [
|
|
'access_policy' => NamespaceAccessPolicy::blocked()
|
|
],
|
|
|
|
// API nur von localhost
|
|
'App\Application\Api\*' => [
|
|
'visibility' => 'local'
|
|
],
|
|
|
|
// Internal Tools nur admin IPs
|
|
'App\Application\Internal\*' => [
|
|
'visibility' => 'admin',
|
|
'access_policy' => NamespaceAccessPolicy::blocked()
|
|
],
|
|
];
|
|
```
|
|
|
|
## Value Objects
|
|
|
|
### NamespaceAccessPolicy
|
|
|
|
```php
|
|
// Alle Controller im Namespace blockieren
|
|
NamespaceAccessPolicy::blocked()
|
|
|
|
// Alle blockieren außer spezifische Controller
|
|
NamespaceAccessPolicy::blockedExcept(
|
|
LoginController::class,
|
|
HealthCheckController::class
|
|
)
|
|
|
|
// Alle erlauben (default)
|
|
NamespaceAccessPolicy::allowed()
|
|
|
|
// Prüfen ob Controller blockiert ist
|
|
$policy->isControllerBlocked(Dashboard::class) // true/false
|
|
```
|
|
|
|
## Visibility Modes (IP-Restrictions)
|
|
|
|
**Predefined Modes**:
|
|
- `public` - Keine IP-Restrictions
|
|
- `admin` - Nur Admin-IPs (WireGuard, etc.)
|
|
- `local` - Nur localhost/127.0.0.1
|
|
- `development` - Development-IPs
|
|
- `private` - Alias für `local`
|
|
- `custom` - Custom IP-Liste via Config
|
|
|
|
## Execution Order
|
|
|
|
1. **Legacy Auth Attribute** - Backward compatibility check
|
|
2. **Namespace Access Policy** - Block/Allow basierend auf Controller-Klasse
|
|
3. **Namespace IP Restrictions** - IP-basierte Zugriffskontrolle
|
|
4. **Route IP Auth Attribute** - Feinkörnige Route-Level IP-Kontrolle
|
|
|
|
Alle Checks werfen `RouteNotFound` bei Failure (versteckt Route-Existenz).
|
|
|
|
## Testing
|
|
|
|
### Unit Test Beispiel
|
|
|
|
```php
|
|
use App\Framework\Auth\RouteAuthorizationService;
|
|
use App\Framework\Auth\ValueObjects\NamespaceAccessPolicy;
|
|
|
|
it('blocks admin controllers except allowlist', function () {
|
|
$config = ['App\Application\Admin\*' => [
|
|
'access_policy' => NamespaceAccessPolicy::blockedExcept(
|
|
LoginController::class
|
|
)
|
|
]];
|
|
|
|
$service = new RouteAuthorizationService(
|
|
config: $this->config,
|
|
namespaceConfig: $config
|
|
);
|
|
|
|
// Should throw RouteNotFound for Dashboard
|
|
expect(fn() => $service->authorize($request, $dashboardRoute))
|
|
->toThrow(RouteNotFound::class);
|
|
|
|
// Should allow LoginController
|
|
expect(fn() => $service->authorize($request, $loginRoute))
|
|
->not->toThrow(RouteNotFound::class);
|
|
});
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Namespace-Blocking für Production
|
|
- Blockiere Admin/Internal-Bereiche in Production
|
|
- Nutze Allowlist nur für wirklich öffentliche Endpoints (Login, Health)
|
|
|
|
### 2. IP-Restrictions für Sensitive Bereiche
|
|
- Kombiniere Namespace-Blocking mit IP-Restrictions
|
|
- Nutze `visibility: 'admin'` für maximale Sicherheit
|
|
|
|
### 3. Graceful Error Handling
|
|
- Alle Checks werfen `RouteNotFound` (404)
|
|
- Versteckt Route-Existenz vor Angreifern
|
|
- Keine Information Leakage
|
|
|
|
### 4. Konfiguration via Initializer
|
|
- Zentrale Konfiguration in `RouteAuthorizationServiceInitializer`
|
|
- Environment-spezifische Configs möglich (dev vs. production)
|
|
- Type-safe via Value Objects
|
|
|
|
## Migration Guide
|
|
|
|
### Von altem System (RoutingMiddleware::withNamespaceConfig)
|
|
|
|
**Alt**:
|
|
```php
|
|
RoutingMiddleware::withNamespaceConfig(
|
|
$router, $dispatcher, $config, $performance, $container,
|
|
namespaceConfig: [
|
|
'App\Application\Admin\*' => ['visibility' => 'admin']
|
|
]
|
|
);
|
|
```
|
|
|
|
**Neu**:
|
|
```php
|
|
// In RouteAuthorizationServiceInitializer
|
|
$namespaceConfig = [
|
|
'App\Application\Admin\*' => [
|
|
'visibility' => 'admin',
|
|
'access_policy' => NamespaceAccessPolicy::blocked() // NEU
|
|
]
|
|
];
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Problem: Route wirft 404 obwohl sie erreichbar sein sollte
|
|
|
|
**Debugging**:
|
|
1. Prüfe `RouteAuthorizationServiceInitializer` Config
|
|
2. Check ob Controller-Namespace in `namespaceConfig` matched
|
|
3. Prüfe `access_policy` - ist Controller in Allowlist?
|
|
4. Check IP-Restrictions (`visibility`)
|
|
|
|
### Problem: Allowlist funktioniert nicht
|
|
|
|
**Ursache**: Controller-Klasse exakt mit `::class` angeben
|
|
|
|
```php
|
|
// ❌ Falsch
|
|
NamespaceAccessPolicy::blockedExcept('LoginController')
|
|
|
|
// ✅ Korrekt
|
|
NamespaceAccessPolicy::blockedExcept(
|
|
\App\Application\Admin\LoginController::class
|
|
)
|
|
```
|
|
|
|
## Framework Integration
|
|
|
|
- **Automatic Discovery**: Service wird via `#[Initializer]` automatisch registriert
|
|
- **DI Container**: Alle Dependencies werden automatisch injected
|
|
- **Type Safety**: Value Objects für alle Policies
|
|
- **Readonly Classes**: Unveränderliche Policies für Thread-Safety
|
|
- **Framework-konform**: Nutzt bestehende Patterns (IpAuthPolicy, RouteNotFound)
|