993 lines
41 KiB
HTML
993 lines
41 KiB
HTML
|
|
<!DOCTYPE HTML>
|
|||
|
|
<html lang="en" class="ayu sidebar-visible" dir="ltr">
|
|||
|
|
<head>
|
|||
|
|
<!-- Book generated using mdBook -->
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<title>Nushell Plugins 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/NUSHELL_PLUGINS_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="nushell-plugins-for-provisioning-platform"><a class="header" href="#nushell-plugins-for-provisioning-platform">Nushell Plugins for Provisioning Platform</a></h1>
|
|||
|
|
<p>Complete guide to authentication, KMS, and orchestrator plugins.</p>
|
|||
|
|
<h2 id="overview"><a class="header" href="#overview">Overview</a></h2>
|
|||
|
|
<p>Three native Nushell plugins provide high-performance integration with the provisioning platform:</p>
|
|||
|
|
<ol>
|
|||
|
|
<li><strong>nu_plugin_auth</strong> - JWT authentication and MFA operations</li>
|
|||
|
|
<li><strong>nu_plugin_kms</strong> - Key management (RustyVault, Age, Cosmian, AWS, Vault)</li>
|
|||
|
|
<li><strong>nu_plugin_orchestrator</strong> - Orchestrator operations (status, validate, tasks)</li>
|
|||
|
|
</ol>
|
|||
|
|
<h2 id="why-native-plugins"><a class="header" href="#why-native-plugins">Why Native Plugins?</a></h2>
|
|||
|
|
<p><strong>Performance Advantages</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>10x faster</strong> than HTTP API calls (KMS operations)</li>
|
|||
|
|
<li><strong>Direct access</strong> to Rust libraries (no HTTP overhead)</li>
|
|||
|
|
<li><strong>Native integration</strong> with Nushell pipelines</li>
|
|||
|
|
<li><strong>Type safety</strong> with Nushell’s type system</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Developer Experience</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>Pipeline friendly</strong> - Use Nushell pipes naturally</li>
|
|||
|
|
<li><strong>Tab completion</strong> - All commands and flags</li>
|
|||
|
|
<li><strong>Consistent interface</strong> - Follows Nushell conventions</li>
|
|||
|
|
<li><strong>Error handling</strong> - Nushell-native error messages</li>
|
|||
|
|
</ul>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="installation"><a class="header" href="#installation">Installation</a></h2>
|
|||
|
|
<h3 id="prerequisites"><a class="header" href="#prerequisites">Prerequisites</a></h3>
|
|||
|
|
<ul>
|
|||
|
|
<li>Nushell 0.107.1+</li>
|
|||
|
|
<li>Rust toolchain (for building from source)</li>
|
|||
|
|
<li>Access to provisioning platform services</li>
|
|||
|
|
</ul>
|
|||
|
|
<h3 id="build-from-source"><a class="header" href="#build-from-source">Build from Source</a></h3>
|
|||
|
|
<pre><code class="language-bash">cd /Users/Akasha/project-provisioning/provisioning/core/plugins/nushell-plugins
|
|||
|
|
|
|||
|
|
# Build all plugins
|
|||
|
|
cargo build --release -p nu_plugin_auth
|
|||
|
|
cargo build --release -p nu_plugin_kms
|
|||
|
|
cargo build --release -p nu_plugin_orchestrator
|
|||
|
|
|
|||
|
|
# Or build individually
|
|||
|
|
cargo build --release -p nu_plugin_auth
|
|||
|
|
cargo build --release -p nu_plugin_kms
|
|||
|
|
cargo build --release -p nu_plugin_orchestrator
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="register-with-nushell"><a class="header" href="#register-with-nushell">Register with Nushell</a></h3>
|
|||
|
|
<pre><code class="language-bash"># Register all plugins
|
|||
|
|
plugin add target/release/nu_plugin_auth
|
|||
|
|
plugin add target/release/nu_plugin_kms
|
|||
|
|
plugin add target/release/nu_plugin_orchestrator
|
|||
|
|
|
|||
|
|
# Verify registration
|
|||
|
|
plugin list | where name =~ "provisioning"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="verify-installation"><a class="header" href="#verify-installation">Verify Installation</a></h3>
|
|||
|
|
<pre><code class="language-bash"># Test auth commands
|
|||
|
|
auth --help
|
|||
|
|
|
|||
|
|
# Test KMS commands
|
|||
|
|
kms --help
|
|||
|
|
|
|||
|
|
# Test orchestrator commands
|
|||
|
|
orch --help
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="plugin-nu_plugin_auth"><a class="header" href="#plugin-nu_plugin_auth">Plugin: nu_plugin_auth</a></h2>
|
|||
|
|
<p>Authentication plugin for JWT login, MFA enrollment, and session management.</p>
|
|||
|
|
<h3 id="commands"><a class="header" href="#commands">Commands</a></h3>
|
|||
|
|
<h4 id="auth-login-username-password"><a class="header" href="#auth-login-username-password"><code>auth login <username> [password]</code></a></h4>
|
|||
|
|
<p>Login to provisioning platform and store JWT tokens securely.</p>
|
|||
|
|
<p><strong>Arguments</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>username</code> (required): Username for authentication</li>
|
|||
|
|
<li><code>password</code> (optional): Password (prompts interactively if not provided)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--url <url></code>: Control center URL (default: <code>http://localhost:9080</code>)</li>
|
|||
|
|
<li><code>--password <password></code>: Password (alternative to positional argument)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Interactive password prompt (recommended)
|
|||
|
|
auth login admin
|
|||
|
|
|
|||
|
|
# Password in command (not recommended for production)
|
|||
|
|
auth login admin mypassword
|
|||
|
|
|
|||
|
|
# Custom URL
|
|||
|
|
auth login admin --url http://control-center:9080
|
|||
|
|
|
|||
|
|
# Pipeline usage
|
|||
|
|
"admin" | auth login
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Token Storage</strong>:
|
|||
|
|
Tokens are stored securely in OS-native keyring:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>macOS</strong>: Keychain Access</li>
|
|||
|
|
<li><strong>Linux</strong>: Secret Service (gnome-keyring, kwallet)</li>
|
|||
|
|
<li><strong>Windows</strong>: Credential Manager</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Success Output</strong>:</p>
|
|||
|
|
<pre><code>✓ Login successful
|
|||
|
|
User: admin
|
|||
|
|
Role: Admin
|
|||
|
|
Expires: 2025-10-09T14:30:00Z
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="auth-logout"><a class="header" href="#auth-logout"><code>auth logout</code></a></h4>
|
|||
|
|
<p>Logout from current session and remove stored tokens.</p>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Simple logout
|
|||
|
|
auth logout
|
|||
|
|
|
|||
|
|
# Pipeline usage (conditional logout)
|
|||
|
|
if (auth verify | get active) { auth logout }
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Success Output</strong>:</p>
|
|||
|
|
<pre><code>✓ Logged out successfully
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="auth-verify"><a class="header" href="#auth-verify"><code>auth verify</code></a></h4>
|
|||
|
|
<p>Verify current session and check token validity.</p>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Check session status
|
|||
|
|
auth verify
|
|||
|
|
|
|||
|
|
# Pipeline usage
|
|||
|
|
auth verify | if $in.active { echo "Session valid" } else { echo "Session expired" }
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Success Output</strong>:</p>
|
|||
|
|
<pre><code class="language-json">{
|
|||
|
|
"active": true,
|
|||
|
|
"user": "admin",
|
|||
|
|
"role": "Admin",
|
|||
|
|
"expires_at": "2025-10-09T14:30:00Z",
|
|||
|
|
"mfa_verified": true
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="auth-sessions"><a class="header" href="#auth-sessions"><code>auth sessions</code></a></h4>
|
|||
|
|
<p>List all active sessions for current user.</p>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># List sessions
|
|||
|
|
auth sessions
|
|||
|
|
|
|||
|
|
# Filter by date
|
|||
|
|
auth sessions | where created_at > (date now | date to-timezone UTC | into string)
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">[
|
|||
|
|
{
|
|||
|
|
"session_id": "sess_abc123",
|
|||
|
|
"created_at": "2025-10-09T12:00:00Z",
|
|||
|
|
"expires_at": "2025-10-09T14:30:00Z",
|
|||
|
|
"ip_address": "192.168.1.100",
|
|||
|
|
"user_agent": "nushell/0.107.1"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="auth-mfa-enroll-type"><a class="header" href="#auth-mfa-enroll-type"><code>auth mfa enroll <type></code></a></h4>
|
|||
|
|
<p>Enroll in MFA (TOTP or WebAuthn).</p>
|
|||
|
|
<p><strong>Arguments</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>type</code> (required): MFA type (<code>totp</code> or <code>webauthn</code>)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Enroll TOTP (Google Authenticator, Authy)
|
|||
|
|
auth mfa enroll totp
|
|||
|
|
|
|||
|
|
# Enroll WebAuthn (YubiKey, Touch ID, Windows Hello)
|
|||
|
|
auth mfa enroll webauthn
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>TOTP Enrollment Output</strong>:</p>
|
|||
|
|
<pre><code>✓ TOTP enrollment initiated
|
|||
|
|
|
|||
|
|
Scan this QR code with your authenticator app:
|
|||
|
|
|
|||
|
|
████ ▄▄▄▄▄ █▀█ █▄▀▀▀▄ ▄▄▄▄▄ ████
|
|||
|
|
████ █ █ █▀▀▀█▄ ▀▀█ █ █ ████
|
|||
|
|
████ █▄▄▄█ █ █▀▄ ▀▄▄█ █▄▄▄█ ████
|
|||
|
|
...
|
|||
|
|
|
|||
|
|
Or enter manually:
|
|||
|
|
Secret: JBSWY3DPEHPK3PXP
|
|||
|
|
URL: otpauth://totp/Provisioning:admin?secret=JBSWY3DPEHPK3PXP&issuer=Provisioning
|
|||
|
|
|
|||
|
|
Backup codes (save securely):
|
|||
|
|
1. ABCD-EFGH-IJKL
|
|||
|
|
2. MNOP-QRST-UVWX
|
|||
|
|
...
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="auth-mfa-verify---code-code"><a class="header" href="#auth-mfa-verify---code-code"><code>auth mfa verify --code <code></code></a></h4>
|
|||
|
|
<p>Verify MFA code (TOTP or backup code).</p>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--code <code></code> (required): 6-digit TOTP code or backup code</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Verify TOTP code
|
|||
|
|
auth mfa verify --code 123456
|
|||
|
|
|
|||
|
|
# Verify backup code
|
|||
|
|
auth mfa verify --code ABCD-EFGH-IJKL
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Success Output</strong>:</p>
|
|||
|
|
<pre><code>✓ MFA verification successful
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="environment-variables"><a class="header" href="#environment-variables">Environment Variables</a></h3>
|
|||
|
|
<div class="table-wrapper"><table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody>
|
|||
|
|
<tr><td><code>USER</code></td><td>Default username</td><td>Current OS user</td></tr>
|
|||
|
|
<tr><td><code>CONTROL_CENTER_URL</code></td><td>Control center URL</td><td><code>http://localhost:9080</code></td></tr>
|
|||
|
|
</tbody></table>
|
|||
|
|
</div>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="error-handling"><a class="header" href="#error-handling">Error Handling</a></h3>
|
|||
|
|
<p><strong>Common Errors</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># "No active session"
|
|||
|
|
Error: No active session found
|
|||
|
|
→ Run: auth login <username>
|
|||
|
|
|
|||
|
|
# "Invalid credentials"
|
|||
|
|
Error: Authentication failed: Invalid username or password
|
|||
|
|
→ Check username and password
|
|||
|
|
|
|||
|
|
# "Token expired"
|
|||
|
|
Error: Token has expired
|
|||
|
|
→ Run: auth login <username>
|
|||
|
|
|
|||
|
|
# "MFA required"
|
|||
|
|
Error: MFA verification required
|
|||
|
|
→ Run: auth mfa verify --code <code>
|
|||
|
|
|
|||
|
|
# "Keyring error" (macOS)
|
|||
|
|
Error: Failed to access keyring
|
|||
|
|
→ Check Keychain Access permissions
|
|||
|
|
|
|||
|
|
# "Keyring error" (Linux)
|
|||
|
|
Error: Failed to access keyring
|
|||
|
|
→ Install gnome-keyring or kwallet
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="plugin-nu_plugin_kms"><a class="header" href="#plugin-nu_plugin_kms">Plugin: nu_plugin_kms</a></h2>
|
|||
|
|
<p>Key Management Service plugin supporting multiple backends.</p>
|
|||
|
|
<h3 id="supported-backends"><a class="header" href="#supported-backends">Supported Backends</a></h3>
|
|||
|
|
<div class="table-wrapper"><table><thead><tr><th>Backend</th><th>Description</th><th>Use Case</th></tr></thead><tbody>
|
|||
|
|
<tr><td><code>rustyvault</code></td><td>RustyVault Transit engine</td><td>Production KMS</td></tr>
|
|||
|
|
<tr><td><code>age</code></td><td>Age encryption (local)</td><td>Development/testing</td></tr>
|
|||
|
|
<tr><td><code>cosmian</code></td><td>Cosmian KMS (HTTP)</td><td>Cloud KMS</td></tr>
|
|||
|
|
<tr><td><code>aws</code></td><td>AWS KMS</td><td>AWS environments</td></tr>
|
|||
|
|
<tr><td><code>vault</code></td><td>HashiCorp Vault</td><td>Enterprise KMS</td></tr>
|
|||
|
|
</tbody></table>
|
|||
|
|
</div>
|
|||
|
|
<h3 id="commands-1"><a class="header" href="#commands-1">Commands</a></h3>
|
|||
|
|
<h4 id="kms-encrypt-data---backend-backend"><a class="header" href="#kms-encrypt-data---backend-backend"><code>kms encrypt <data> [--backend <backend>]</code></a></h4>
|
|||
|
|
<p>Encrypt data using KMS.</p>
|
|||
|
|
<p><strong>Arguments</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>data</code> (required): Data to encrypt (string or binary)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--backend <backend></code>: KMS backend (<code>rustyvault</code>, <code>age</code>, <code>cosmian</code>, <code>aws</code>, <code>vault</code>)</li>
|
|||
|
|
<li><code>--key <key></code>: Key ID or recipient (backend-specific)</li>
|
|||
|
|
<li><code>--context <context></code>: Additional authenticated data (AAD)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Auto-detect backend from environment
|
|||
|
|
kms encrypt "secret data"
|
|||
|
|
|
|||
|
|
# RustyVault
|
|||
|
|
kms encrypt "data" --backend rustyvault --key provisioning-main
|
|||
|
|
|
|||
|
|
# Age (local encryption)
|
|||
|
|
kms encrypt "data" --backend age --key age1xxxxxxxxx
|
|||
|
|
|
|||
|
|
# AWS KMS
|
|||
|
|
kms encrypt "data" --backend aws --key alias/provisioning
|
|||
|
|
|
|||
|
|
# With context (AAD)
|
|||
|
|
kms encrypt "data" --backend rustyvault --key provisioning-main --context "user=admin"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code>vault:v1:abc123def456...
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="kms-decrypt-encrypted---backend-backend"><a class="header" href="#kms-decrypt-encrypted---backend-backend"><code>kms decrypt <encrypted> [--backend <backend>]</code></a></h4>
|
|||
|
|
<p>Decrypt KMS-encrypted data.</p>
|
|||
|
|
<p><strong>Arguments</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>encrypted</code> (required): Encrypted data (base64 or KMS format)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--backend <backend></code>: KMS backend (auto-detected if not specified)</li>
|
|||
|
|
<li><code>--context <context></code>: Additional authenticated data (AAD, must match encryption)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Auto-detect backend
|
|||
|
|
kms decrypt "vault:v1:abc123def456..."
|
|||
|
|
|
|||
|
|
# RustyVault explicit
|
|||
|
|
kms decrypt "vault:v1:abc123..." --backend rustyvault
|
|||
|
|
|
|||
|
|
# Age
|
|||
|
|
kms decrypt "-----BEGIN AGE ENCRYPTED FILE-----..." --backend age
|
|||
|
|
|
|||
|
|
# With context
|
|||
|
|
kms decrypt "vault:v1:abc123..." --backend rustyvault --context "user=admin"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output</strong>:</p>
|
|||
|
|
<pre><code>secret data
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="kms-generate-key---spec-spec"><a class="header" href="#kms-generate-key---spec-spec"><code>kms generate-key [--spec <spec>]</code></a></h4>
|
|||
|
|
<p>Generate data encryption key (DEK) using KMS.</p>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--spec <spec></code>: Key specification (<code>AES128</code> or <code>AES256</code>, default: <code>AES256</code>)</li>
|
|||
|
|
<li><code>--backend <backend></code>: KMS backend</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Generate AES-256 key
|
|||
|
|
kms generate-key
|
|||
|
|
|
|||
|
|
# Generate AES-128 key
|
|||
|
|
kms generate-key --spec AES128
|
|||
|
|
|
|||
|
|
# Specific backend
|
|||
|
|
kms generate-key --backend rustyvault
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">{
|
|||
|
|
"plaintext": "base64-encoded-key",
|
|||
|
|
"ciphertext": "vault:v1:encrypted-key",
|
|||
|
|
"spec": "AES256"
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="kms-status"><a class="header" href="#kms-status"><code>kms status</code></a></h4>
|
|||
|
|
<p>Show KMS backend status and configuration.</p>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Show status
|
|||
|
|
kms status
|
|||
|
|
|
|||
|
|
# Filter to specific backend
|
|||
|
|
kms status | where backend == "rustyvault"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">{
|
|||
|
|
"backend": "rustyvault",
|
|||
|
|
"status": "healthy",
|
|||
|
|
"url": "http://localhost:8200",
|
|||
|
|
"mount_point": "transit",
|
|||
|
|
"version": "0.1.0"
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="environment-variables-1"><a class="header" href="#environment-variables-1">Environment Variables</a></h3>
|
|||
|
|
<p><strong>RustyVault Backend</strong>:</p>
|
|||
|
|
<pre><code class="language-bash">export RUSTYVAULT_ADDR="http://localhost:8200"
|
|||
|
|
export RUSTYVAULT_TOKEN="your-token-here"
|
|||
|
|
export RUSTYVAULT_MOUNT="transit"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Age Backend</strong>:</p>
|
|||
|
|
<pre><code class="language-bash">export AGE_RECIPIENT="age1xxxxxxxxx"
|
|||
|
|
export AGE_IDENTITY="/path/to/key.txt"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>HTTP Backend (Cosmian)</strong>:</p>
|
|||
|
|
<pre><code class="language-bash">export KMS_HTTP_URL="http://localhost:9998"
|
|||
|
|
export KMS_HTTP_BACKEND="cosmian"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>AWS KMS</strong>:</p>
|
|||
|
|
<pre><code class="language-bash">export AWS_REGION="us-east-1"
|
|||
|
|
export AWS_ACCESS_KEY_ID="..."
|
|||
|
|
export AWS_SECRET_ACCESS_KEY="..."
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="performance-comparison"><a class="header" href="#performance-comparison">Performance Comparison</a></h3>
|
|||
|
|
<div class="table-wrapper"><table><thead><tr><th>Operation</th><th>HTTP API</th><th>Plugin</th><th>Improvement</th></tr></thead><tbody>
|
|||
|
|
<tr><td>Encrypt (RustyVault)</td><td>~50ms</td><td>~5ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Decrypt (RustyVault)</td><td>~50ms</td><td>~5ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Encrypt (Age)</td><td>~30ms</td><td>~3ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Decrypt (Age)</td><td>~30ms</td><td>~3ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Generate Key</td><td>~60ms</td><td>~8ms</td><td><strong>7.5x faster</strong></td></tr>
|
|||
|
|
</tbody></table>
|
|||
|
|
</div>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="plugin-nu_plugin_orchestrator"><a class="header" href="#plugin-nu_plugin_orchestrator">Plugin: nu_plugin_orchestrator</a></h2>
|
|||
|
|
<p>Orchestrator operations plugin for status, validation, and task management.</p>
|
|||
|
|
<h3 id="commands-2"><a class="header" href="#commands-2">Commands</a></h3>
|
|||
|
|
<h4 id="orch-status---data-dir-dir"><a class="header" href="#orch-status---data-dir-dir"><code>orch status [--data-dir <dir>]</code></a></h4>
|
|||
|
|
<p>Get orchestrator status from local files (no HTTP).</p>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--data-dir <dir></code>: Data directory (default: <code>provisioning/platform/orchestrator/data</code>)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Default data dir
|
|||
|
|
orch status
|
|||
|
|
|
|||
|
|
# Custom dir
|
|||
|
|
orch status --data-dir ./custom/data
|
|||
|
|
|
|||
|
|
# Pipeline usage
|
|||
|
|
orch status | if $in.active_tasks > 0 { echo "Tasks running" }
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">{
|
|||
|
|
"active_tasks": 5,
|
|||
|
|
"completed_tasks": 120,
|
|||
|
|
"failed_tasks": 2,
|
|||
|
|
"pending_tasks": 3,
|
|||
|
|
"uptime": "2d 4h 15m",
|
|||
|
|
"health": "healthy"
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="orch-validate-workflowk---strict"><a class="header" href="#orch-validate-workflowk---strict"><code>orch validate <workflow.k> [--strict]</code></a></h4>
|
|||
|
|
<p>Validate workflow KCL file.</p>
|
|||
|
|
<p><strong>Arguments</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>workflow.k</code> (required): Path to KCL workflow file</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--strict</code>: Enable strict validation (all checks, warnings as errors)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Basic validation
|
|||
|
|
orch validate workflows/deploy.k
|
|||
|
|
|
|||
|
|
# Strict mode
|
|||
|
|
orch validate workflows/deploy.k --strict
|
|||
|
|
|
|||
|
|
# Pipeline usage
|
|||
|
|
ls workflows/*.k | each { |file| orch validate $file.name }
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">{
|
|||
|
|
"valid": true,
|
|||
|
|
"workflow": {
|
|||
|
|
"name": "deploy_k8s_cluster",
|
|||
|
|
"version": "1.0.0",
|
|||
|
|
"operations": 5
|
|||
|
|
},
|
|||
|
|
"warnings": [],
|
|||
|
|
"errors": []
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Validation Checks</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li>KCL syntax errors</li>
|
|||
|
|
<li>Required fields present</li>
|
|||
|
|
<li>Dependency graph valid (no cycles)</li>
|
|||
|
|
<li>Resource limits within bounds</li>
|
|||
|
|
<li>Provider configurations valid</li>
|
|||
|
|
</ul>
|
|||
|
|
<hr />
|
|||
|
|
<h4 id="orch-tasks---status-status---limit-n"><a class="header" href="#orch-tasks---status-status---limit-n"><code>orch tasks [--status <status>] [--limit <n>]</code></a></h4>
|
|||
|
|
<p>List orchestrator tasks.</p>
|
|||
|
|
<p><strong>Flags</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>--status <status></code>: Filter by status (<code>pending</code>, <code>running</code>, <code>completed</code>, <code>failed</code>)</li>
|
|||
|
|
<li><code>--limit <n></code>: Limit number of results (default: 100)</li>
|
|||
|
|
<li><code>--data-dir <dir></code>: Data directory (default from <code>ORCHESTRATOR_DATA_DIR</code>)</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>Examples</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># All tasks
|
|||
|
|
orch tasks
|
|||
|
|
|
|||
|
|
# Pending tasks only
|
|||
|
|
orch tasks --status pending
|
|||
|
|
|
|||
|
|
# Running tasks (limit to 10)
|
|||
|
|
orch tasks --status running --limit 10
|
|||
|
|
|
|||
|
|
# Pipeline usage
|
|||
|
|
orch tasks --status failed | each { |task| echo $"Failed: ($task.name)" }
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>Output Format</strong>:</p>
|
|||
|
|
<pre><code class="language-json">[
|
|||
|
|
{
|
|||
|
|
"task_id": "task_abc123",
|
|||
|
|
"name": "deploy_kubernetes",
|
|||
|
|
"status": "running",
|
|||
|
|
"priority": 5,
|
|||
|
|
"created_at": "2025-10-09T12:00:00Z",
|
|||
|
|
"updated_at": "2025-10-09T12:05:00Z",
|
|||
|
|
"progress": 45
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="environment-variables-2"><a class="header" href="#environment-variables-2">Environment Variables</a></h3>
|
|||
|
|
<div class="table-wrapper"><table><thead><tr><th>Variable</th><th>Description</th><th>Default</th></tr></thead><tbody>
|
|||
|
|
<tr><td><code>ORCHESTRATOR_DATA_DIR</code></td><td>Data directory</td><td><code>provisioning/platform/orchestrator/data</code></td></tr>
|
|||
|
|
</tbody></table>
|
|||
|
|
</div>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="performance-comparison-1"><a class="header" href="#performance-comparison-1">Performance Comparison</a></h3>
|
|||
|
|
<div class="table-wrapper"><table><thead><tr><th>Operation</th><th>HTTP API</th><th>Plugin</th><th>Improvement</th></tr></thead><tbody>
|
|||
|
|
<tr><td>Status</td><td>~30ms</td><td>~3ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Validate</td><td>~100ms</td><td>~10ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
<tr><td>Tasks List</td><td>~50ms</td><td>~5ms</td><td><strong>10x faster</strong></td></tr>
|
|||
|
|
</tbody></table>
|
|||
|
|
</div>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="pipeline-examples"><a class="header" href="#pipeline-examples">Pipeline Examples</a></h2>
|
|||
|
|
<h3 id="authentication-flow"><a class="header" href="#authentication-flow">Authentication Flow</a></h3>
|
|||
|
|
<pre><code class="language-nushell"># Login and verify in one pipeline
|
|||
|
|
auth login admin
|
|||
|
|
| if $in.success { auth verify }
|
|||
|
|
| if $in.mfa_required { auth mfa verify --code (input "MFA code: ") }
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="kms-operations"><a class="header" href="#kms-operations">KMS Operations</a></h3>
|
|||
|
|
<pre><code class="language-nushell"># Encrypt multiple secrets
|
|||
|
|
["secret1", "secret2", "secret3"]
|
|||
|
|
| each { |data| kms encrypt $data --backend rustyvault }
|
|||
|
|
| save encrypted_secrets.json
|
|||
|
|
|
|||
|
|
# Decrypt and process
|
|||
|
|
open encrypted_secrets.json
|
|||
|
|
| each { |enc| kms decrypt $enc }
|
|||
|
|
| each { |plain| echo $"Decrypted: ($plain)" }
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="orchestrator-monitoring"><a class="header" href="#orchestrator-monitoring">Orchestrator Monitoring</a></h3>
|
|||
|
|
<pre><code class="language-nushell"># Monitor running tasks
|
|||
|
|
while true {
|
|||
|
|
orch tasks --status running
|
|||
|
|
| each { |task| echo $"($task.name): ($task.progress)%" }
|
|||
|
|
sleep 5sec
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="combined-workflow"><a class="header" href="#combined-workflow">Combined Workflow</a></h3>
|
|||
|
|
<pre><code class="language-nushell"># Complete deployment workflow
|
|||
|
|
auth login admin
|
|||
|
|
| auth mfa verify --code (input "MFA: ")
|
|||
|
|
| orch validate workflows/deploy.k
|
|||
|
|
| if $in.valid {
|
|||
|
|
orch tasks --status pending
|
|||
|
|
| where priority > 5
|
|||
|
|
| each { |task| echo $"High priority: ($task.name)" }
|
|||
|
|
}
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="troubleshooting"><a class="header" href="#troubleshooting">Troubleshooting</a></h2>
|
|||
|
|
<h3 id="auth-plugin"><a class="header" href="#auth-plugin">Auth Plugin</a></h3>
|
|||
|
|
<p><strong>“No active session”</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell">auth login <username>
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“Keyring error” (macOS)</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li>Check Keychain Access permissions</li>
|
|||
|
|
<li>Security & Privacy → Privacy → Full Disk Access → Add Nushell</li>
|
|||
|
|
</ul>
|
|||
|
|
<p><strong>“Keyring error” (Linux)</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Install keyring service
|
|||
|
|
sudo apt install gnome-keyring # Ubuntu/Debian
|
|||
|
|
sudo dnf install gnome-keyring # Fedora
|
|||
|
|
|
|||
|
|
# Or use KWallet
|
|||
|
|
sudo apt install kwalletmanager
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“MFA verification failed”</strong>:</p>
|
|||
|
|
<ul>
|
|||
|
|
<li>Check time synchronization (TOTP requires accurate clocks)</li>
|
|||
|
|
<li>Use backup codes if TOTP not working</li>
|
|||
|
|
<li>Re-enroll MFA if device lost</li>
|
|||
|
|
</ul>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="kms-plugin"><a class="header" href="#kms-plugin">KMS Plugin</a></h3>
|
|||
|
|
<p><strong>“RustyVault connection failed”</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Check RustyVault running
|
|||
|
|
curl http://localhost:8200/v1/sys/health
|
|||
|
|
|
|||
|
|
# Set environment
|
|||
|
|
export RUSTYVAULT_ADDR="http://localhost:8200"
|
|||
|
|
export RUSTYVAULT_TOKEN="your-token"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“Age encryption failed”</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Check Age keys
|
|||
|
|
ls -la ~/.age/
|
|||
|
|
|
|||
|
|
# Generate new key if needed
|
|||
|
|
age-keygen -o ~/.age/key.txt
|
|||
|
|
|
|||
|
|
# Set environment
|
|||
|
|
export AGE_RECIPIENT="age1xxxxxxxxx"
|
|||
|
|
export AGE_IDENTITY="$HOME/.age/key.txt"
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“AWS KMS access denied”</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Check AWS credentials
|
|||
|
|
aws sts get-caller-identity
|
|||
|
|
|
|||
|
|
# Check KMS key policy
|
|||
|
|
aws kms describe-key --key-id alias/provisioning
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h3 id="orchestrator-plugin"><a class="header" href="#orchestrator-plugin">Orchestrator Plugin</a></h3>
|
|||
|
|
<p><strong>“Failed to read status”</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Check data directory exists
|
|||
|
|
ls provisioning/platform/orchestrator/data/
|
|||
|
|
|
|||
|
|
# Create if missing
|
|||
|
|
mkdir -p provisioning/platform/orchestrator/data
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“Workflow validation failed”</strong>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Use strict mode for detailed errors
|
|||
|
|
orch validate workflows/deploy.k --strict
|
|||
|
|
</code></pre>
|
|||
|
|
<p><strong>“No tasks found”</strong>:</p>
|
|||
|
|
<pre><code class="language-bash"># Check orchestrator running
|
|||
|
|
ps aux | grep orchestrator
|
|||
|
|
|
|||
|
|
# Start orchestrator
|
|||
|
|
cd provisioning/platform/orchestrator
|
|||
|
|
./scripts/start-orchestrator.nu --background
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="development"><a class="header" href="#development">Development</a></h2>
|
|||
|
|
<h3 id="building-from-source"><a class="header" href="#building-from-source">Building from Source</a></h3>
|
|||
|
|
<pre><code class="language-bash">cd provisioning/core/plugins/nushell-plugins
|
|||
|
|
|
|||
|
|
# Clean build
|
|||
|
|
cargo clean
|
|||
|
|
|
|||
|
|
# Build with debug info
|
|||
|
|
cargo build -p nu_plugin_auth
|
|||
|
|
cargo build -p nu_plugin_kms
|
|||
|
|
cargo build -p nu_plugin_orchestrator
|
|||
|
|
|
|||
|
|
# Run tests
|
|||
|
|
cargo test -p nu_plugin_auth
|
|||
|
|
cargo test -p nu_plugin_kms
|
|||
|
|
cargo test -p nu_plugin_orchestrator
|
|||
|
|
|
|||
|
|
# Run all tests
|
|||
|
|
cargo test --all
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="adding-to-cicd"><a class="header" href="#adding-to-cicd">Adding to CI/CD</a></h3>
|
|||
|
|
<pre><code class="language-yaml">name: Build Nushell Plugins
|
|||
|
|
|
|||
|
|
on: [push, pull_request]
|
|||
|
|
|
|||
|
|
jobs:
|
|||
|
|
build:
|
|||
|
|
runs-on: ubuntu-latest
|
|||
|
|
steps:
|
|||
|
|
- uses: actions/checkout@v3
|
|||
|
|
|
|||
|
|
- name: Install Rust
|
|||
|
|
uses: actions-rs/toolchain@v1
|
|||
|
|
with:
|
|||
|
|
toolchain: stable
|
|||
|
|
|
|||
|
|
- name: Build Plugins
|
|||
|
|
run: |
|
|||
|
|
cd provisioning/core/plugins/nushell-plugins
|
|||
|
|
cargo build --release --all
|
|||
|
|
|
|||
|
|
- name: Test Plugins
|
|||
|
|
run: |
|
|||
|
|
cd provisioning/core/plugins/nushell-plugins
|
|||
|
|
cargo test --all
|
|||
|
|
|
|||
|
|
- name: Upload Artifacts
|
|||
|
|
uses: actions/upload-artifact@v3
|
|||
|
|
with:
|
|||
|
|
name: plugins
|
|||
|
|
path: provisioning/core/plugins/nushell-plugins/target/release/nu_plugin_*
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="advanced-usage"><a class="header" href="#advanced-usage">Advanced Usage</a></h2>
|
|||
|
|
<h3 id="custom-plugin-configuration"><a class="header" href="#custom-plugin-configuration">Custom Plugin Configuration</a></h3>
|
|||
|
|
<p>Create <code>~/.config/nushell/plugin_config.nu</code>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Auth plugin defaults
|
|||
|
|
$env.CONTROL_CENTER_URL = "https://control-center.example.com"
|
|||
|
|
|
|||
|
|
# KMS plugin defaults
|
|||
|
|
$env.RUSTYVAULT_ADDR = "https://vault.example.com:8200"
|
|||
|
|
$env.RUSTYVAULT_MOUNT = "transit"
|
|||
|
|
|
|||
|
|
# Orchestrator plugin defaults
|
|||
|
|
$env.ORCHESTRATOR_DATA_DIR = "/opt/orchestrator/data"
|
|||
|
|
</code></pre>
|
|||
|
|
<h3 id="plugin-aliases"><a class="header" href="#plugin-aliases">Plugin Aliases</a></h3>
|
|||
|
|
<p>Add to <code>~/.config/nushell/config.nu</code>:</p>
|
|||
|
|
<pre><code class="language-nushell"># Auth shortcuts
|
|||
|
|
alias login = auth login
|
|||
|
|
alias logout = auth logout
|
|||
|
|
|
|||
|
|
# KMS shortcuts
|
|||
|
|
alias encrypt = kms encrypt
|
|||
|
|
alias decrypt = kms decrypt
|
|||
|
|
|
|||
|
|
# Orchestrator shortcuts
|
|||
|
|
alias status = orch status
|
|||
|
|
alias validate = orch validate
|
|||
|
|
alias tasks = orch tasks
|
|||
|
|
</code></pre>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="security-best-practices"><a class="header" href="#security-best-practices">Security Best Practices</a></h2>
|
|||
|
|
<h3 id="authentication"><a class="header" href="#authentication">Authentication</a></h3>
|
|||
|
|
<p>✅ <strong>DO</strong>: Use interactive password prompts
|
|||
|
|
✅ <strong>DO</strong>: Enable MFA for production environments
|
|||
|
|
✅ <strong>DO</strong>: Verify session before sensitive operations
|
|||
|
|
❌ <strong>DON’T</strong>: Pass passwords in command line (visible in history)
|
|||
|
|
❌ <strong>DON’T</strong>: Store tokens in plain text files</p>
|
|||
|
|
<h3 id="kms-operations-1"><a class="header" href="#kms-operations-1">KMS Operations</a></h3>
|
|||
|
|
<p>✅ <strong>DO</strong>: Use context (AAD) for encryption when available
|
|||
|
|
✅ <strong>DO</strong>: Rotate KMS keys regularly
|
|||
|
|
✅ <strong>DO</strong>: Use hardware-backed keys (WebAuthn, YubiKey) when possible
|
|||
|
|
❌ <strong>DON’T</strong>: Share Age private keys
|
|||
|
|
❌ <strong>DON’T</strong>: Log decrypted data</p>
|
|||
|
|
<h3 id="orchestrator"><a class="header" href="#orchestrator">Orchestrator</a></h3>
|
|||
|
|
<p>✅ <strong>DO</strong>: Validate workflows in strict mode before production
|
|||
|
|
✅ <strong>DO</strong>: Monitor task status regularly
|
|||
|
|
✅ <strong>DO</strong>: Use appropriate data directory permissions (700)
|
|||
|
|
❌ <strong>DON’T</strong>: Run orchestrator as root
|
|||
|
|
❌ <strong>DON’T</strong>: Expose data directory over network shares</p>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="faq"><a class="header" href="#faq">FAQ</a></h2>
|
|||
|
|
<p><strong>Q: Why use plugins instead of HTTP API?</strong>
|
|||
|
|
A: Plugins are 10x faster, have better Nushell integration, and eliminate HTTP overhead.</p>
|
|||
|
|
<p><strong>Q: Can I use plugins without orchestrator running?</strong>
|
|||
|
|
A: <code>auth</code> and <code>kms</code> work independently. <code>orch</code> requires access to orchestrator data directory.</p>
|
|||
|
|
<p><strong>Q: How do I update plugins?</strong>
|
|||
|
|
A: Rebuild and re-register: <code>cargo build --release --all && plugin add target/release/nu_plugin_*</code></p>
|
|||
|
|
<p><strong>Q: Are plugins cross-platform?</strong>
|
|||
|
|
A: Yes, plugins work on macOS, Linux, and Windows (with appropriate keyring services).</p>
|
|||
|
|
<p><strong>Q: Can I use multiple KMS backends simultaneously?</strong>
|
|||
|
|
A: Yes, specify <code>--backend</code> flag for each operation.</p>
|
|||
|
|
<p><strong>Q: How do I backup MFA enrollment?</strong>
|
|||
|
|
A: Save backup codes securely (password manager, encrypted file). QR code can be re-scanned.</p>
|
|||
|
|
<hr />
|
|||
|
|
<h2 id="related-documentation"><a class="header" href="#related-documentation">Related Documentation</a></h2>
|
|||
|
|
<ul>
|
|||
|
|
<li><strong>Security System</strong>: <code>docs/architecture/ADR-009-security-system-complete.md</code></li>
|
|||
|
|
<li><strong>JWT Auth</strong>: <code>docs/architecture/JWT_AUTH_IMPLEMENTATION.md</code></li>
|
|||
|
|
<li><strong>Config Encryption</strong>: <code>docs/user/CONFIG_ENCRYPTION_GUIDE.md</code></li>
|
|||
|
|
<li><strong>RustyVault Integration</strong>: <code>RUSTYVAULT_INTEGRATION_SUMMARY.md</code></li>
|
|||
|
|
<li><strong>MFA Implementation</strong>: <code>docs/architecture/MFA_IMPLEMENTATION_SUMMARY.md</code></li>
|
|||
|
|
</ul>
|
|||
|
|
<hr />
|
|||
|
|
<p><strong>Version</strong>: 1.0.0
|
|||
|
|
<strong>Last Updated</strong>: 2025-10-09
|
|||
|
|
<strong>Maintained By</strong>: Platform Team</p>
|
|||
|
|
|
|||
|
|
</main>
|
|||
|
|
|
|||
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|||
|
|
<!-- Mobile navigation buttons -->
|
|||
|
|
<a rel="prev" href="../user/extension-development.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/PLUGIN_INTEGRATION_GUIDE.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/extension-development.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/PLUGIN_INTEGRATION_GUIDE.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>
|