Add Kubernetes Status Updates and Authentication Event Tracking - #81
Merged
Conversation
This commit implements status tracking for Tenant CRDs in Kubernetes, displaying client count and active user sessions in kubectl output. Features: - Added status subresource to Tenant CRD with additionalPrinterColumns - Extended AuthCodeStorage with tenant-specific session counting - Implemented session tracking for interceptor mode logins - Automatic status updates on token creation, logout, and client changes - Added RBAC permissions for status subresource updates Fixes: - Fixed Redis session counting to handle mixed key types gracefully - RedisAuthCodeStorage.count() now skips LoginSession objects correctly Testing: - Added comprehensive TenantStatusUpdateTest suite with 4 test cases - Verified session counting accuracy across different scenarios
This commit fixes a critical issue where tenant session counts were not decremented after user logout, causing incorrect active session reporting in Kubernetes CRD status. Root Cause: - Redis wipe() and count() functions attempted to decode ALL Redis keys as AuthSession objects, including loginid~ keys which are LoginSession objects - LoginSession lacks the 'type' field, causing decoding to fail - Silent error handling prevented session deletion - Race condition: triggerStatusUpdate ran asynchronously Changes: - AuthCodeStorage+RedisImpl.swift: * Add prefix check to skip loginid~ keys before decoding * Add comprehensive debug logging for wipe and count operations * Track sessions being wiped and counted - AuthCodeStorage+MemoryImpl.swift: * Add debug logging for session storage, wipe, and count * Log session details (type, tenant, subject) for debugging - LogoutController.swift: * Add session count logging before and after wipe * Track session count changes during logout flow - EntityLoader.swift: * Make triggerStatusUpdate() async (was creating detached Task) * Ensure status update waits for wipe completion * Fix race condition between wipe and count Result: - Session counts now correctly decrement to 0 after logout - Kubernetes CRD status reflects accurate active session counts - All 344 tests pass
Implement comprehensive status tracking for Client CRDs, displaying: - Active session counts per client (based on audience claim) - Denied login attempts per client - Status phase and last update timestamp Changes: - Update Client CRD YAML with status subresource and printer columns - Added Tenant, Sessions, Denied, Status, Age columns to kubectl output - Defined status schema with phase, activeSessions, deniedAttempts fields - Add ClientStatus struct and StatusHavingResource conformance - Implement status update mechanism in EntityCRDLoader - Extract namespace from tenant name for K8s operations - Implement session counting by client identifier - Add count(client:type:) to AuthCodeStorageProtocol - Implement for both Memory and Redis storage backends - Match sessions by audience claim (client_id in OAuth2) - Support multiple clients in single session audience - Add denied login tracking system in EntityStorage - Track failed login attempts per client name - Provide increment and query methods - Trigger status updates when clients are added/modified - Update client status after creation - Update parent tenant status when client changes - Add comprehensive test suite (6 tests) - Session count increases after token creation - Session count is client-specific - Multiple clients in audience handling - Refresh vs authorization code filtering - Denied login attempts tracking - Client-specific denied attempts isolation All 789 tests passing. No linter violations.
Add status updates for all Kubernetes entities after authCodeStorage is set. Problem: - EntityLoader starts loading entities immediately on creation - authCodeStorage is set afterwards in configure.swift - Initial status updates fail because authCodeStorage is nil - Result: Client status columns remain empty on startup Solution: - Add updateAllKubernetesStatuses() method to EntityLoader - Triggered automatically when setAuthCodeStorage() is called - Iterates through all existing Kubernetes tenants and clients - Updates their status with current session counts and metrics Changes: - Add isKubernetes property to EntityResourceReference - Add updateAllKubernetesStatuses() to EntityLoader - Call status updates in setAuthCodeStorage() This ensures clients show correct session counts and status immediately after startup, not just after configuration changes.
Add unit tests to verify client status tracking works correctly: - Session counting per client based on audience claim - Denied login attempts tracking per client - Multiple clients with different session counts All 791 tests passing.
Allow keeping the Kubernetes cluster running after e2e tests complete for manual inspection and testing. Usage: ./tooling.sh e2e --dirty --fast --hold When --hold is used: - Tests run normally - Cluster stays up after tests complete - User gets instructions for kubectl commands - User must press ENTER to delete cluster This is useful for: - Debugging failed tests - Manual verification of deployments - Inspecting Kubernetes resources after tests - Testing kubectl commands against live cluster
The Uitsmijter service account needs permission to update the clients/status subresource in order to populate client metrics (sessions, denied, status). This adds clients/status to the ClusterRole alongside the existing tenants/status permission.
The count() method was incorrectly matching sessions by client.name instead of client_id (UUID). The audience in JWT payloads contains the client_id, not the client name. This fixes client session counting in both Memory and Redis implementations, which is required for displaying accurate SESSIONS counts in kubectl output. Fixed in: - AuthCodeStorage+MemoryImpl.swift - AuthCodeStorage+RedisImpl.swift
Remove verbose diagnostic logging that was added for debugging. Keep only essential INFO and DEBUG level logs.
Previously, status updates were only triggered for interceptor mode logins and only updated tenant status. Now: 1. Status updates are triggered for ALL login modes (both interceptor and OAuth) 2. Both tenant AND client status are updated on login/logout/token creation 3. Added convenience method triggerStatusUpdate(for:client:) to EntityLoader This ensures that client session counts are accurately reflected in kubectl output for all authentication flows. Changes: - EntityLoader.swift: Add triggerStatusUpdate(for:client:) overload - LoginController.swift: Move status update outside interceptor-only block - LogoutController.swift: Pass client to status update - TokenController+TokenGrantTypeRequestHandler.swift: Find and pass client
Use clientId: instead of withId:for: to match the actual method signature.
This commit introduces a new AuthEventActor that consolidates authentication event handling (login success/failure, logout) by combining Prometheus metrics recording and entity status updates into a single, reusable component. Changes: - Add AuthEventActor with three methods: - recordLoginSuccess(): Records login success metrics and triggers status updates - recordLoginFailure(): Records login failure metrics, increments denied attempts counter, and triggers client status updates - recordLogout(): Records logout metrics and triggers status updates - Add Application+AuthEventActor extension for dependency injection via Vapor's storage system - Refactor LoginController to use AuthEventActor: - Replace duplicate Prometheus + status update calls in canNotLoginResponse() - Replace duplicate calls in renderSuccess() - Refactor LogoutController to use AuthEventActor: - Replace Prometheus metric call in doLogout() - Add comprehensive unit tests in AuthEventActorTests covering all event types - Update CHANGELOG.md with feature documentation This eliminates code duplication across LoginController and LogoutController while ensuring consistent event tracking throughout the authentication flow. Fixes #78
This commit fixes test cases to use the correct client identifier (client_id/UUID) instead of client name when creating JWT payloads for session tracking. Changes: - Update ClientStatusInitializationTest to use client.config.ident.uuidString in audience claims - Update ClientStatusUpdateTest to use client.config.ident.uuidString in audience claims - Fix trailing whitespace in Cheese tenant YAML configuration The audience claim in JWT tokens must contain the client's UUID (client_id) rather than the client's name, as this is what the session counting logic uses to match sessions to clients.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds comprehensive Kubernetes status subresource support for both Tenant and Client CRDs, along with a centralized authentication event handling system. Key improvements include:
kubectl get tenantsshowing client count, active sessions, and tenant phasekubectl get clientsshowing active sessions, denied attempts, and last authentication timestampAuthEventActorconsolidates Prometheus metrics and status updates for login/logout eventsChanges
New Features
--holdoption for debugging failed testsBug Fixes
client_idinstead of nameClient.findcall with correct parameter nameInfrastructure
Test Plan
TenantStatusUpdateTest)ClientStatusUpdateTest)ClientStatusInitializationTest)AuthEventActorTests)kubectl get tenantsshows real-time metricskubectl get clientsshows real-time metricsDocumentation
Changelog entries added in CHANGELOG.md for version 0.10.2.
Files Changed
28 files changed with 1,916 insertions and 27 deletions:
AuthEventActor.swift- Centralized authentication event handlingAuthCodeStorage.swift- Protocol enhancements for session countingLoginController.swift,LogoutController.swift- Integrated with AuthEventActorEntityCRDLoader.swift,EntityLoader.swift- Status update logic