provisioning/docs/book/user/AUTHENTICATION_LAYER_GUIDE.html
Jesús Pérez 6a59d34bb1
chore: update provisioning configuration and documentation
Update configuration files, templates, and internal documentation
for the provisioning repository system.

Configuration Updates:
- KMS configuration modernization
- Plugin system settings
- Service port mappings
- Test cluster topologies
- Installation configuration examples
- VM configuration defaults
- Cedar authorization policies

Documentation Updates:
- Library module documentation
- Extension API guides
- AI system documentation
- Service management guides
- Test environment setup
- Plugin usage guides
- Validator configuration documentation

All changes are backward compatible.
2025-12-11 21:50:42 +00:00

690 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>