Authentication & Security Access Controls¶
This document details the two core security subsystems in DVFS: 1. User-Facing Google OAuth 2.0 & Session Architecture: The primary identity, session handshake, centralized authorization (PEP), and cluster mTLS subsystem governing file access across clients and servers. 2. Administrative Console Authentication & Data Redaction: The SHA-256 credential verification, session cookie management, and telemetry sanitization protecting the admin dashboard.
1. User-Facing Google OAuth 2.0 & Session Architecture¶
DVFS replaces legacy unauthenticated or per-RPC token verification models with a Single-Gate Session Handshake Protocol backed by Google OAuth 2.0, RFC 7636 PKCE S256, and high-performance Server Session Tokens (SST).
Architecture Topology & Handshake Flow¶
sequenceDiagram
autonumber
actor User as User / Terminal Shell
participant Client as DVFS Client Binary
participant Google as Google Identity Provider
participant Meta as MetaServer (Coordinator)
participant FS as FileServer (Storage Node)
Note over User,Client: 1. Native Desktop Sign-In (RFC 7636 PKCE)
Client->>Client: Generate PKCE (verifier + S256 challenge) & CSRF state
Client->>Client: Start loopback listener on 127.0.0.1:38485
Client->>User: Display consent URL & prompt for token
User->>Google: Authenticate & grant consent in web browser
Google->>Client: HTTP redirect to http://localhost:38485/logincallback
Client->>Client: Verify CSRF state nonce matches expected state
Client->>Google: Exchange auth code + code_verifier for ID Token
Client->>User: Render success page in browser
Note over Client,Meta: 2. Coordinator Routing Handshake
Client->>Meta: Navigate(Google ID Token, target_root)
Meta->>Google: Verify token once via Google tokeninfo / cache
Meta-->>Client: Routing metadata (FileServer address)
Note over Client,FS: 3. FileServer Session Handshake (Single Gate)
Client->>FS: RegisterClient(Bearer <Google ID Token>, client_id)
FS->>Google: Verify token once via tokeninfo & enforce aud == clientID
FS->>FS: Mint 256-bit CSPRNG Server Session Token (SST)
FS->>FS: Store SHA-256(SST) bound to peer IP (15m idle, abs exp)
FS-->>Client: RegisterClientResponse(session_token=sst_..., expires_at)
Note over Client,FS: 4. High-Speed Authorized Operations (Zero Tokeninfo Overhead)
Client->>FS: ReadFile / WriteFile / UploadFile (Bearer <SST>)
FS->>FS: Validate SST from in-memory store & verify peer IP
FS->>FS: Centralized PEP fs.Authorize(ctx, fid, PermRead/Write)
FS-->>Client: Authorized file chunk stream
Core Principles & Security Invariants¶
1. Native Desktop Authorization Code Flow with PKCE (internal/auth/pkce.go, internal/auth/google.go)¶
- RFC 7636 S256 PKCE: Before generating the OAuth URL, the client generates a 32-byte cryptographic random code verifier (
[A-Za-z0-9\-._~], 43–128 characters) and computes the SHA-256 code challenge (BASE64URL-ENCODE(SHA256(verifier))). - Authorization Request: The consent URL includes
code_challenge,code_challenge_method=S256,response_type=code,scope=openid email profile, and a cryptographically randomstatenonce. - Loopback Redirect Listener: The client binds a local HTTP server on
127.0.0.1:38485(/logincallback). Upon redirect: - The server validates that
r.URL.Query().Get("state")matches the expected nonce, mitigating CSRF and malicious local redirects. - The authorization code is exchanged with Google's token endpoint (
POST https://oauth2.googleapis.com/token) includingcode_verifier. - A responsive, user-friendly HTML confirmation page is rendered in the user's browser, displaying their authenticated email address.
- Headless Fallback: If running over headless SSH where a local browser cannot open, the CLI provides a copy-paste prompt (
Paste your token:).
2. Strict Token Verification & Audience Guard (internal/auth/google.go)¶
- Validation: Google ID tokens are verified against Google's tokeninfo API (
https://oauth2.googleapis.com/tokeninfo?id_token=...). - Strict Audience Enforcement: The token's
audclaim is validated using strict string equality againstGOOGLE_CLIENT_ID. IfGOOGLE_CLIENT_IDis unconfigured in production mode (DVFS_AUTH_MOCK=false), token verification immediately fails closed before making external network calls. - Verified Email: The
email_verifiedclaim must evaluate totrue(or boolean"true"). - Bounded In-Memory Cache: Successfully verified tokens are cached in-memory (
tokenCache) for up to their remaining token lifetime (exp) (capped at 2 hours). Mock tokens enforce a 5,000-entry capacity limit with automatic expired-entry eviction to prevent memory exhaustion under automated testing concurrency.
3. Single-Gate Handshake Protocol (RegisterClient)¶
- In legacy systems, verifying a Google ID token over HTTP on every single gRPC call introduced 150–400ms of synchronous latency and vulnerability to Google API rate-limiting.
- In DVFS, Google ID token verification occurs only once when the client initiates its session via
RegisterClient. - Upon successful verification, the FileServer:
- Mints a cryptographically secure 256-bit random Server Session Token (
sst_<43-character-base64url>) providing 256 bits of CSPRNG entropy encoded via unpadded URL-safe Base64 per NIST SP 800-63B. - Hashes the token using
SHA-256for storage indexing (ensuring raw session tokens are never stored in plaintext in memory). - Binds the session to the client's network IP (
p.Addr). - Returns the raw SST and absolute expiration timestamp to the client in
RegisterClientResponse.
4. High-Performance Session Subsystem (internal/fileserver/session/)¶
- Decoupled Concurrency: The session subsystem operates with a standalone
sync.RWMutexdecoupled from the filesystem inode lock (fs.mu). High-throughput chunk streaming never blocks session validation. - Sliding Idle Timeout: Sessions enforce a 15-minute sliding inactivity timeout. Active operations touch the session (
sess.Touch()) to reset the idle timer. - Chunk Stream Touch Discipline: Streaming transfers validate and refresh session state upon stream initiation via the gRPC stream interceptor. During streaming
UploadFileRPCs,sess.Touch()is actively refreshed inside each chunk receiving loop, ensuring prolonged multi-gigabyte uploads never time out regardless of duration. - Absolute Expiry Ceiling: Sessions cannot be extended indefinitely. An absolute expiration ceiling is established at session creation (configured to a 12-hour ceiling:
now + 12h). When reached, the session expires and the client must re-authenticate. - Cryptographic Transport & IP Binding: The FileServer extracts the client IP (
extractIP) usingnet.SplitHostPortand validates it on every request. If a request arrives with a valid SST from a different IP address, the FileServer triggers a security alert and rejects the request withcodes.PermissionDenied(ErrIPMismatch). - DoS Limits & Eviction:
- Per-User Limit: Hard cap of 5 concurrent sessions per user. Creating a 6th session automatically evicts the user's oldest session (FIFO).
- Global Limit: Bounded global table cap of 10,000 sessions.
- Background Sweeper: A background goroutine cleans expired sessions every 60 seconds.
5. Centralized Policy Enforcement Point (fs.Authorize) & IDOR Immunity¶
All FileServer gRPC handlers pass through a centralized Policy Enforcement Point (fs.Authorize(ctx, fid, perm)) in internal/fileserver/fileserver.go:
- Identity Resolution: Handlers never trust client-supplied protobuf fields such as req.RootUser or req.Username. The authenticated identity is extracted directly from the verified session context via session.UsernameFromContext(ctx).
- Permission Matrix:
| Permission Level | Enum Value | Permitted Inode Types | Access Rule |
|---|---|---|---|
| PermRead | 0 | File, Directory | Allowed if caller is Inode Owner OR listed in Inode ACL.Shared |
| PermWrite | 1 | File, Directory | Allowed if caller is Inode Owner OR listed in Inode ACL.Shared |
| PermDelete | 2 | File, Directory | Strict Ownership: Allowed only if caller is Inode Owner |
| PermAdmin | 3 | Any Resource | Allowed only if caller is configured cluster administrator |
- Protected RPCs:
- CreateFile, ReadFile, WriteFile, UploadFile, DownloadFile
- GetAttr, ListDir, ChangeDir
- DeleteFile, TrashFile, RestoreFile, ShowTrash
- Share, Unshare (validates caller ownership before recursively updating directory subtree ACLs)
6. Dual-Mode Administrative Quota Authorization¶
Modifying storage limits via SetQuota is restricted to authorized cluster administrators through two distinct mechanisms:
1. Password-Based Admin Authorization (Admin Web Console):
- When an administrator logged in via password updates quotas in the Admin Web Console, the backend invokes CallSetQuota over gRPC, attaching the x-admin-password-hash metadata header.
- The FileServer verifies the submitted hash in constant time (crypto/subtle.ConstantTimeCompare) against ADMIN_PASSWORD_HASH or ADMIN_PASSWORD.
2. Identity-Based Admin Authorization (CLI / Google Session):
- If invoked by an authenticated Google user via gRPC, session.UsernameFromContext(ctx) must match DVFS_ADMIN_EMAIL.
- Regular users (e.g. student@gmail.com) attempting to call SetQuota to self-escalate storage limits are rejected with SetQuotaResponse{Success: false, Error: "permission denied: only cluster administrators can modify quotas"}.
7. Cluster Control Plane Mutual TLS (mTLS)¶
Cluster daemon RPCs on the MetaServer are separated from end-user RPCs:
- User Plane RPCs (GetRoots, Navigate): Require a valid Google ID token.
- Cluster Control RPCs (RegisterFileServer, Heartbeat, RootShare, RootUnshare): Handled by verifyClusterPeer(ctx) in internal/metaserver/auth_google.go. In production mode (DVFS_AUTH_MOCK=false), requests are rejected with codes.Unauthenticated unless presented with a valid mutual TLS client certificate signed by the Root CA whose Subject Alternative Name (SAN) matches *.cluster.local, fileserver, or localhost.
8. Offline & Automated Testing Mock Mode (DVFS_AUTH_MOCK)¶
For local integration testing and CI environments without live Google credentials:
- Set DVFS_AUTH_MOCK=true or 1.
- auth.MockToken(email) generates a valid mock token prefixed with mock-jwt..
- In production mode (DVFS_AUTH_MOCK=false), any token with the mock-jwt. prefix is strictly rejected with a fatal security alert.
2. Administrative Console Authentication & Data Redaction¶
The administrative web console provides hardware observability, quota management, and remote cluster execution. It uses a dual-mode presentation model separating casual visitors from authenticated cluster operators.
[Unauthenticated Visitor] -------------> [Public Dashboard View]
- Node uptimes & hardware temps
- Cluster throughput & IOPS
- Redacted user identities & quotas
[Administrator + Password] ------------> [Admin Console Mode]
- User listing & dynamic quota editing
- Remote SSH commands (reboot, git, apt)
- Live journalctl log streaming
- Alert resolution
Core Security Invariants¶
- Zero Plaintext Passwords: Passwords are never stored in plaintext on disk or in source code. Verification compares submitted passwords strictly against a precomputed SHA-256 hash.
- Timing Attack Immunity: Hash comparisons use constant-time verification (
crypto/subtle.ConstantTimeCompare) to prevent side-channel timing attacks. - Data Redaction by Default: All API endpoints scrub user identities, active usernames, and quota details when accessed without valid administrative session credentials.
- Cookie-Based WebSocket Protection: Real-time operational streams authenticate via browser session cookies by default, preventing credentials from appearing in web server access logs.
Implementation Details (internal/admin/auth.go)¶
The SHA-256 Authentication Engine¶
type AuthManager struct {
hash string
sessions map[string]time.Time // Token -> Expiration
mu sync.RWMutex
}
- Configuration: Configured in
.envviaADMIN_PASSWORD_HASH: - Linux / macOS / WSL:
- Windows PowerShell:
- Session Tokens: On successful authentication (
POST /api/auth/login), the server generates a 32-byte cryptographically secure random token (crypto/rand) hex-encoded to a 64-character string. - Session TTL: Tokens remain valid for 12 hours.
- Cookie Delivery: Tokens are written to the browser via an
HttpOnly,Path=/,SameSite=Laxcookie nameddvfs_admin_token.
Protected Endpoints (RequireAuth Middleware)¶
Privileged endpoints require a valid session:
- GET /api/users (User quota directory)
- PUT /api/users/{username}/quota (Quota adjustments — invokes CallSetQuota on FileServer with x-admin-password-hash)
- POST /api/actions/* (Cluster command execution)
- GET /api/actions/presets & GET /api/actions/history
- POST /api/alerts/resolve and POST /api/alerts/resolve-all
- GET /api/logs/tail (Live journalctl log streaming)
- GET /ws/actions (WebSocket command stream)
Public Data Redaction (internal/admin/handlers.go)¶
When unauthenticated visitors access telemetry endpoints:
- GET /api/cluster & GET /api/cluster/summary: The users dictionary is sanitized to an empty map {} (total_users is set to 0), and per-node user storage/quota dictionaries are stripped. Hardware health, storage capacities, cluster throughput (MiB/s), and IOPS remain visible.
- GET /api/alerts: Suppresses all quota_exceeded alerts and strips user identity strings from alert messages.
3. Configuration Summary¶
| Variable | Target Component | Required | Default | Description |
|---|---|---|---|---|
GOOGLE_CLIENT_ID |
FileServer, MetaServer, Client | Yes (Prod) | "" |
OAuth 2.0 Client ID; strictly enforced against token aud |
GOOGLE_CLIENT_SECRET |
Client, Admin UI | Yes (Prod) | "" |
OAuth 2.0 Client Secret for code exchange |
GOOGLE_REDIRECT_URI |
Client, Admin UI | No | http://localhost:38485/logincallback |
Local loopback redirect URI |
DVFS_AUTH_MOCK |
FileServer, MetaServer, Client | No | false |
Enables mock token generation and verification for testing |
DVFS_ADMIN_EMAIL |
FileServer | No | "" |
Google account email authorized to call SetQuota via CLI |
ADMIN_PASSWORD_HASH |
Admin Console, FileServer | Yes (Admin) | 8c6976... ("admin") |
SHA-256 hash of cluster admin password |
USE_GOOGLE_AUTH |
Build Tag / Makefile | No | 1 |
Build flag enabling Google Auth interceptors in binaries |