provisioning/docs/book/user/AUTHENTICATION_LAYER_GUIDE.html

690 lines
34 KiB
HTML
Raw Normal View History

<!DOCTYPE HTML>
<html lang="en" class="ayu sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Authentication Layer Guide - Provisioning Platform Documentation</title>
<!-- Custom HTML head -->
<meta name="description" content="Complete documentation for the Provisioning Platform - Infrastructure automation with Nushell, KCL, and Rust">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "../";
const default_light_theme = "ayu";
const default_dark_theme = "navy";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('ayu')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Provisioning Platform Documentation</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/provisioning/provisioning-platform" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/provisioning/provisioning-platform/edit/main/provisioning/docs/src/user/AUTHENTICATION_LAYER_GUIDE.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="authentication-layer-implementation-guide"><a class="header" href="#authentication-layer-implementation-guide">Authentication Layer Implementation Guide</a></h1>
<p><strong>Version</strong>: 1.0.0
<strong>Date</strong>: 2025-10-09
<strong>Status</strong>: Production Ready</p>
<hr />
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
<p>A comprehensive authentication layer has been integrated into the provisioning system to secure sensitive operations. The system uses <code>nu_plugin_auth</code> for JWT authentication with MFA support, providing enterprise-grade security with graceful user experience.</p>
<hr />
<h2 id="key-features"><a class="header" href="#key-features">Key Features</a></h2>
<h3 id="-jwt-authentication"><a class="header" href="#-jwt-authentication"><strong>JWT Authentication</strong></a></h3>
<ul>
<li>RS256 asymmetric signing</li>
<li>Access tokens (15min) + refresh tokens (7d)</li>
<li>OS keyring storage (macOS Keychain, Windows Credential Manager, Linux Secret Service)</li>
</ul>
<h3 id="-mfa-support"><a class="header" href="#-mfa-support"><strong>MFA Support</strong></a></h3>
<ul>
<li>TOTP (Google Authenticator, Authy)</li>
<li>WebAuthn/FIDO2 (YubiKey, Touch ID)</li>
<li>Required for production and destructive operations</li>
</ul>
<h3 id="-security-policies"><a class="header" href="#-security-policies"><strong>Security Policies</strong></a></h3>
<ul>
<li><strong>Production environment</strong>: Requires authentication + MFA</li>
<li><strong>Destructive operations</strong>: Requires authentication + MFA (delete, destroy)</li>
<li><strong>Development/test</strong>: Requires authentication, allows skip with flag</li>
<li><strong>Check mode</strong>: Always bypasses authentication (dry-run operations)</li>
</ul>
<h3 id="-audit-logging"><a class="header" href="#-audit-logging"><strong>Audit Logging</strong></a></h3>
<ul>
<li>All authenticated operations logged</li>
<li>User, timestamp, operation details</li>
<li>MFA verification status</li>
<li>JSON format for easy parsing</li>
</ul>
<h3 id="-user-friendly-error-messages"><a class="header" href="#-user-friendly-error-messages"><strong>User-Friendly Error Messages</strong></a></h3>
<ul>
<li>Clear instructions for login/MFA</li>
<li>Distinct error types (platform auth vs provider auth)</li>
<li>Helpful guidance for setup</li>
</ul>
<hr />
<h2 id="quick-start"><a class="header" href="#quick-start">Quick Start</a></h2>
<h3 id="1-login-to-platform"><a class="header" href="#1-login-to-platform">1. Login to Platform</a></h3>
<pre><code class="language-bash"># Interactive login (password prompt)
provisioning auth login &lt;username&gt;
# Save credentials to keyring
provisioning auth login &lt;username&gt; --save
# Custom control center URL
provisioning auth login admin --url http://control.example.com:9080
</code></pre>
<h3 id="2-enroll-mfa-first-time"><a class="header" href="#2-enroll-mfa-first-time">2. Enroll MFA (First Time)</a></h3>
<pre><code class="language-bash"># Enroll TOTP (Google Authenticator)
provisioning auth mfa enroll totp
# Scan QR code with authenticator app
# Or enter secret manually
</code></pre>
<h3 id="3-verify-mfa-for-sensitive-operations"><a class="header" href="#3-verify-mfa-for-sensitive-operations">3. Verify MFA (For Sensitive Operations)</a></h3>
<pre><code class="language-bash"># Get 6-digit code from authenticator app
provisioning auth mfa verify --code 123456
</code></pre>
<h3 id="4-check-authentication-status"><a class="header" href="#4-check-authentication-status">4. Check Authentication Status</a></h3>
<pre><code class="language-bash"># View current authentication status
provisioning auth status
# Verify token is valid
provisioning auth verify
</code></pre>
<hr />
<h2 id="protected-operations"><a class="header" href="#protected-operations">Protected Operations</a></h2>
<h3 id="server-operations"><a class="header" href="#server-operations">Server Operations</a></h3>
<pre><code class="language-bash"># ✅ CREATE - Requires auth (prod: +MFA)
provisioning server create web-01 # Auth required
provisioning server create web-01 --check # Auth skipped (check mode)
# ❌ DELETE - Requires auth + MFA
provisioning server delete web-01 # Auth + MFA required
provisioning server delete web-01 --check # Auth skipped (check mode)
# 📖 READ - No auth required
provisioning server list # No auth required
provisioning server ssh web-01 # No auth required
</code></pre>
<h3 id="task-service-operations"><a class="header" href="#task-service-operations">Task Service Operations</a></h3>
<pre><code class="language-bash"># ✅ CREATE - Requires auth (prod: +MFA)
provisioning taskserv create kubernetes # Auth required
provisioning taskserv create kubernetes --check # Auth skipped
# ❌ DELETE - Requires auth + MFA
provisioning taskserv delete kubernetes # Auth + MFA required
# 📖 READ - No auth required
provisioning taskserv list # No auth required
</code></pre>
<h3 id="cluster-operations"><a class="header" href="#cluster-operations">Cluster Operations</a></h3>
<pre><code class="language-bash"># ✅ CREATE - Requires auth (prod: +MFA)
provisioning cluster create buildkit # Auth required
provisioning cluster create buildkit --check # Auth skipped
# ❌ DELETE - Requires auth + MFA
provisioning cluster delete buildkit # Auth + MFA required
</code></pre>
<h3 id="batch-workflows"><a class="header" href="#batch-workflows">Batch Workflows</a></h3>
<pre><code class="language-bash"># ✅ SUBMIT - Requires auth (prod: +MFA)
provisioning batch submit workflow.k # Auth required
provisioning batch submit workflow.k --skip-auth # Auth skipped (if allowed)
# 📖 READ - No auth required
provisioning batch list # No auth required
provisioning batch status &lt;task-id&gt; # No auth required
</code></pre>
<hr />
<h2 id="configuration"><a class="header" href="#configuration">Configuration</a></h2>
<h3 id="security-settings-configdefaultstoml"><a class="header" href="#security-settings-configdefaultstoml">Security Settings (<code>config.defaults.toml</code>)</a></h3>
<pre><code class="language-toml">[security]
require_auth = true # Enable authentication system
require_mfa_for_production = true # MFA for prod environment
require_mfa_for_destructive = true # MFA for delete operations
auth_timeout = 3600 # Token timeout (1 hour)
audit_log_path = "{{paths.base}}/logs/audit.log"
[security.bypass]
allow_skip_auth = false # Allow PROVISIONING_SKIP_AUTH env var
[plugins]
auth_enabled = true # Enable nu_plugin_auth
[platform.control_center]
url = "http://localhost:9080" # Control center URL
</code></pre>
<h3 id="environment-specific-configuration"><a class="header" href="#environment-specific-configuration">Environment-Specific Configuration</a></h3>
<pre><code class="language-toml"># Development
[environments.dev]
security.bypass.allow_skip_auth = true # Allow auth bypass in dev
# Production
[environments.prod]
security.bypass.allow_skip_auth = false # Never allow bypass
security.require_mfa_for_production = true
</code></pre>
<hr />
<h2 id="authentication-bypass-devtest-only"><a class="header" href="#authentication-bypass-devtest-only">Authentication Bypass (Dev/Test Only)</a></h2>
<h3 id="environment-variable-method"><a class="header" href="#environment-variable-method">Environment Variable Method</a></h3>
<pre><code class="language-bash"># Export environment variable (dev/test only)
export PROVISIONING_SKIP_AUTH=true
# Run operations without authentication
provisioning server create web-01
# Unset when done
unset PROVISIONING_SKIP_AUTH
</code></pre>
<h3 id="per-command-flag"><a class="header" href="#per-command-flag">Per-Command Flag</a></h3>
<pre><code class="language-bash"># Some commands support --skip-auth flag
provisioning batch submit workflow.k --skip-auth
</code></pre>
<h3 id="check-mode-always-bypasses-auth"><a class="header" href="#check-mode-always-bypasses-auth">Check Mode (Always Bypasses Auth)</a></h3>
<pre><code class="language-bash"># Check mode is always allowed without auth
provisioning server create web-01 --check
provisioning taskserv create kubernetes --check
</code></pre>
<p>⚠️ <strong>WARNING</strong>: Auth bypass should ONLY be used in development/testing environments. Production systems should have <code>security.bypass.allow_skip_auth = false</code>.</p>
<hr />
<h2 id="error-messages"><a class="header" href="#error-messages">Error Messages</a></h2>
<h3 id="not-authenticated"><a class="header" href="#not-authenticated">Not Authenticated</a></h3>
<pre><code>❌ Authentication Required
Operation: server create web-01
You must be logged in to perform this operation.
To login:
provisioning auth login &lt;username&gt;
Note: Your credentials will be securely stored in the system keyring.
</code></pre>
<p><strong>Solution</strong>: Run <code>provisioning auth login &lt;username&gt;</code></p>
<hr />
<h3 id="mfa-required"><a class="header" href="#mfa-required">MFA Required</a></h3>
<pre><code>❌ MFA Verification Required
Operation: server delete web-01
Reason: destructive operation (delete/destroy)
To verify MFA:
1. Get code from your authenticator app
2. Run: provisioning auth mfa verify --code &lt;6-digit-code&gt;
Don't have MFA set up?
Run: provisioning auth mfa enroll totp
</code></pre>
<p><strong>Solution</strong>: Run <code>provisioning auth mfa verify --code 123456</code></p>
<hr />
<h3 id="token-expired"><a class="header" href="#token-expired">Token Expired</a></h3>
<pre><code>❌ Authentication Required
Operation: server create web-02
You must be logged in to perform this operation.
Error: Token verification failed
</code></pre>
<p><strong>Solution</strong>: Token expired, re-login with <code>provisioning auth login &lt;username&gt;</code></p>
<hr />
<h2 id="audit-logging"><a class="header" href="#audit-logging">Audit Logging</a></h2>
<p>All authenticated operations are logged to the audit log file with the following information:</p>
<pre><code class="language-json">{
"timestamp": "2025-10-09 14:32:15",
"user": "admin",
"operation": "server_create",
"details": {
"hostname": "web-01",
"infra": "production",
"environment": "prod",
"orchestrated": false
},
"mfa_verified": true
}
</code></pre>
<h3 id="viewing-audit-logs"><a class="header" href="#viewing-audit-logs">Viewing Audit Logs</a></h3>
<pre><code class="language-bash"># View raw audit log
cat provisioning/logs/audit.log
# Filter by user
cat provisioning/logs/audit.log | jq '. | select(.user == "admin")'
# Filter by operation type
cat provisioning/logs/audit.log | jq '. | select(.operation == "server_create")'
# Filter by date
cat provisioning/logs/audit.log | jq '. | select(.timestamp | startswith("2025-10-09"))'
</code></pre>
<hr />
<h2 id="integration-with-control-center"><a class="header" href="#integration-with-control-center">Integration with Control Center</a></h2>
<p>The authentication system integrates with the provisioning platforms control center REST API:</p>
<ul>
<li><strong>POST /api/auth/login</strong> - Login with credentials</li>
<li><strong>POST /api/auth/logout</strong> - Revoke tokens</li>
<li><strong>POST /api/auth/verify</strong> - Verify token validity</li>
<li><strong>GET /api/auth/sessions</strong> - List active sessions</li>
<li><strong>POST /api/mfa/enroll</strong> - Enroll MFA device</li>
<li><strong>POST /api/mfa/verify</strong> - Verify MFA code</li>
</ul>
<h3 id="starting-control-center"><a class="header" href="#starting-control-center">Starting Control Center</a></h3>
<pre><code class="language-bash"># Start control center (required for authentication)
cd provisioning/platform/control-center
cargo run --release
</code></pre>
<p>Or use the orchestrator which includes control center:</p>
<pre><code class="language-bash">cd provisioning/platform/orchestrator
./scripts/start-orchestrator.nu --background
</code></pre>
<hr />
<h2 id="testing-authentication"><a class="header" href="#testing-authentication">Testing Authentication</a></h2>
<h3 id="manual-testing"><a class="header" href="#manual-testing">Manual Testing</a></h3>
<pre><code class="language-bash"># 1. Start control center
cd provisioning/platform/control-center
cargo run --release &amp;
# 2. Login
provisioning auth login admin
# 3. Try creating server (should succeed if authenticated)
provisioning server create test-server --check
# 4. Logout
provisioning auth logout
# 5. Try creating server (should fail - not authenticated)
provisioning server create test-server --check
</code></pre>
<h3 id="automated-testing"><a class="header" href="#automated-testing">Automated Testing</a></h3>
<pre><code class="language-bash"># Run authentication tests
nu provisioning/core/nulib/lib_provisioning/plugins/auth_test.nu
</code></pre>
<hr />
<h2 id="troubleshooting"><a class="header" href="#troubleshooting">Troubleshooting</a></h2>
<h3 id="plugin-not-available"><a class="header" href="#plugin-not-available">Plugin Not Available</a></h3>
<p><strong>Error</strong>: <code>Authentication plugin not available</code></p>
<p><strong>Solution</strong>:</p>
<ol>
<li>Check plugin is built: <code>ls provisioning/core/plugins/nushell-plugins/nu_plugin_auth/target/release/</code></li>
<li>Register plugin: <code>plugin add target/release/nu_plugin_auth</code></li>
<li>Use plugin: <code>plugin use auth</code></li>
<li>Verify: <code>which auth</code></li>
</ol>
<hr />
<h3 id="control-center-not-running"><a class="header" href="#control-center-not-running">Control Center Not Running</a></h3>
<p><strong>Error</strong>: <code>Cannot connect to control center</code></p>
<p><strong>Solution</strong>:</p>
<ol>
<li>Start control center: <code>cd provisioning/platform/control-center &amp;&amp; cargo run --release</code></li>
<li>Or use orchestrator: <code>cd provisioning/platform/orchestrator &amp;&amp; ./scripts/start-orchestrator.nu --background</code></li>
<li>Check URL is correct in config: <code>provisioning config get platform.control_center.url</code></li>
</ol>
<hr />
<h3 id="mfa-not-working"><a class="header" href="#mfa-not-working">MFA Not Working</a></h3>
<p><strong>Error</strong>: <code>Invalid MFA code</code></p>
<p><strong>Solutions</strong>:</p>
<ul>
<li>Ensure time is synchronized (TOTP codes are time-based)</li>
<li>Code expires every 30 seconds, get fresh code</li>
<li>Verify youre using the correct authenticator app entry</li>
<li>Re-enroll if needed: <code>provisioning auth mfa enroll totp</code></li>
</ul>
<hr />
<h3 id="keyring-access-issues"><a class="header" href="#keyring-access-issues">Keyring Access Issues</a></h3>
<p><strong>Error</strong>: <code>Keyring storage unavailable</code></p>
<p><strong>macOS</strong>: Grant Keychain access to Terminal/iTerm2 in System Preferences → Security &amp; Privacy</p>
<p><strong>Linux</strong>: Ensure <code>gnome-keyring</code> or <code>kwallet</code> is running</p>
<p><strong>Windows</strong>: Check Windows Credential Manager is accessible</p>
<hr />
<h2 id="architecture"><a class="header" href="#architecture">Architecture</a></h2>
<h3 id="authentication-flow"><a class="header" href="#authentication-flow">Authentication Flow</a></h3>
<pre><code>┌─────────────┐
│ User Command│
└──────┬──────┘
┌─────────────────────────────────┐
│ Infrastructure Command Handler │
│ (infrastructure.nu) │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ Auth Check │
│ - Determine operation type │
│ - Check if auth required │
│ - Check environment (prod/dev) │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ Auth Plugin Wrapper │
│ (auth.nu) │
│ - Call plugin or HTTP fallback │
│ - Verify token validity │
│ - Check MFA if required │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ nu_plugin_auth │
│ - JWT verification (RS256) │
│ - Keyring token storage │
│ - MFA verification │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ Control Center API │
│ - /api/auth/verify │
│ - /api/mfa/verify │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ Operation Execution │
│ (servers/create.nu, etc.) │
└──────┬──────────────────────────┘
┌─────────────────────────────────┐
│ Audit Logging │
│ - Log to audit.log │
│ - Include user, timestamp, MFA │
└─────────────────────────────────┘
</code></pre>
<h3 id="file-structure"><a class="header" href="#file-structure">File Structure</a></h3>
<pre><code>provisioning/
├── config/
│ └── config.defaults.toml # Security configuration
├── core/nulib/
│ ├── lib_provisioning/plugins/
│ │ └── auth.nu # Auth wrapper (550 lines)
│ ├── servers/
│ │ └── create.nu # Server ops with auth
│ ├── workflows/
│ │ └── batch.nu # Batch workflows with auth
│ └── main_provisioning/commands/
│ └── infrastructure.nu # Infrastructure commands with auth
├── core/plugins/nushell-plugins/
│ └── nu_plugin_auth/ # Native Rust plugin
│ ├── src/
│ │ ├── main.rs # Plugin implementation
│ │ └── helpers.rs # Helper functions
│ └── README.md # Plugin documentation
├── platform/control-center/ # Control Center (Rust)
│ └── src/auth/ # JWT auth implementation
└── logs/
└── audit.log # Audit trail
</code></pre>
<hr />
<h2 id="related-documentation"><a class="header" href="#related-documentation">Related Documentation</a></h2>
<ul>
<li><strong>Security System Overview</strong>: <code>docs/architecture/ADR-009-security-system-complete.md</code></li>
<li><strong>JWT Authentication</strong>: <code>docs/architecture/JWT_AUTH_IMPLEMENTATION.md</code></li>
<li><strong>MFA Implementation</strong>: <code>docs/architecture/MFA_IMPLEMENTATION_SUMMARY.md</code></li>
<li><strong>Plugin README</strong>: <code>provisioning/core/plugins/nushell-plugins/nu_plugin_auth/README.md</code></li>
<li><strong>Control Center</strong>: <code>provisioning/platform/control-center/README.md</code></li>
</ul>
<hr />
<h2 id="summary-of-changes"><a class="header" href="#summary-of-changes">Summary of Changes</a></h2>
<div class="table-wrapper"><table><thead><tr><th>File</th><th>Changes</th><th>Lines Added</th></tr></thead><tbody>
<tr><td><code>lib_provisioning/plugins/auth.nu</code></td><td>Added security policy enforcement functions</td><td>+260</td></tr>
<tr><td><code>config/config.defaults.toml</code></td><td>Added security configuration section</td><td>+19</td></tr>
<tr><td><code>servers/create.nu</code></td><td>Added auth check for server creation</td><td>+25</td></tr>
<tr><td><code>workflows/batch.nu</code></td><td>Added auth check for batch workflow submission</td><td>+43</td></tr>
<tr><td><code>main_provisioning/commands/infrastructure.nu</code></td><td>Added auth checks for all infrastructure commands</td><td>+90</td></tr>
<tr><td><code>lib_provisioning/providers/interface.nu</code></td><td>Added authentication guidelines for providers</td><td>+65</td></tr>
<tr><td><strong>Total</strong></td><td><strong>6 files modified</strong></td><td><strong>~500 lines</strong></td></tr>
</tbody></table>
</div>
<hr />
<h2 id="best-practices"><a class="header" href="#best-practices">Best Practices</a></h2>
<h3 id="for-users"><a class="header" href="#for-users">For Users</a></h3>
<ol>
<li><strong>Always login</strong>: Keep your session active to avoid interruptions</li>
<li><strong>Use keyring</strong>: Save credentials with <code>--save</code> flag for persistence</li>
<li><strong>Enable MFA</strong>: Use MFA for production operations</li>
<li><strong>Check mode first</strong>: Always test with <code>--check</code> before actual operations</li>
<li><strong>Monitor audit logs</strong>: Review audit logs regularly for security</li>
</ol>
<h3 id="for-developers"><a class="header" href="#for-developers">For Developers</a></h3>
<ol>
<li><strong>Check auth early</strong>: Verify authentication before expensive operations</li>
<li><strong>Log operations</strong>: Always log authenticated operations for audit</li>
<li><strong>Clear error messages</strong>: Provide helpful guidance for auth failures</li>
<li><strong>Respect check mode</strong>: Always skip auth in check/dry-run mode</li>
<li><strong>Test both paths</strong>: Test with and without authentication</li>
</ol>
<h3 id="for-operators"><a class="header" href="#for-operators">For Operators</a></h3>
<ol>
<li><strong>Production hardening</strong>: Set <code>allow_skip_auth = false</code> in production</li>
<li><strong>MFA enforcement</strong>: Require MFA for all production environments</li>
<li><strong>Monitor audit logs</strong>: Set up log monitoring and alerts</li>
<li><strong>Token rotation</strong>: Configure short token timeouts (15min default)</li>
<li><strong>Backup authentication</strong>: Ensure multiple admins have MFA enrolled</li>
</ol>
<hr />
<h2 id="license"><a class="header" href="#license">License</a></h2>
<p>MIT License - See LICENSE file for details</p>
<hr />
<p><strong>Last Updated</strong>: 2025-10-09
<strong>Maintained By</strong>: Security Team</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../user/troubleshooting-guide.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../user/AUTH_QUICK_REFERENCE.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../user/troubleshooting-guide.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../user/AUTH_QUICK_REFERENCE.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>