201 lines
10 KiB
HTML
201 lines
10 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Enroll Security</title>
|
|
<meta name="description" content="Security posture and safe workflows for Enroll outputs.">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
|
|
<!-- Bootstrap -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
|
|
|
<link href="assets/css/site.css" rel="stylesheet">
|
|
|
|
</head>
|
|
<body>
|
|
|
|
<nav class="navbar navbar-expand-lg bg-white bg-opacity-75 sticky-top border-bottom" data-bs-theme="light">
|
|
<div class="container py-1">
|
|
<a class="navbar-brand fw-bold d-flex align-items-center gap-2" href="index.html">
|
|
<img class="brand-mark" src="assets/img/enroll.svg" alt="Enroll">
|
|
<span>Enroll</span>
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#nav" aria-controls="nav" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="nav">
|
|
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-2">
|
|
<li class="nav-item"><a class="nav-link" href="docs.html">Docs</a></li>
|
|
<li class="nav-item"><a class="nav-link" href="examples.html">Examples</a></li>
|
|
<li class="nav-item"><a class="nav-link" href="schema.html">Schema</a></li>
|
|
<li class="nav-item"><a class="nav-link" href="security.html">Security Design</a></li>
|
|
<li class="nav-item ms-lg-2">
|
|
<a class="btn btn-sm btn-outline-dark" href="https://git.mig5.net/mig5/enroll" target="_blank" rel="noreferrer">
|
|
<i class="bi bi-git"></i> Repo
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
<header class="py-5 hero">
|
|
<div class="container py-3">
|
|
<div class="kicker mb-3"><i class="bi bi-shield-lock"></i> Security</div>
|
|
<h1 class="display-6 fw-bold mb-2">Safe by default. Powerful when you opt in.</h1>
|
|
<p class="lead mb-0">Enroll can touch sensitive files. This page helps you use it confidently.</p>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="py-5">
|
|
<div class="container">
|
|
|
|
<div class="row g-4">
|
|
<div class="col-lg-8">
|
|
<div class="feature-card p-4">
|
|
<h2 class="h4 fw-bold mb-2">Default behavior</h2>
|
|
<p class="text-secondary mb-0">In normal mode, Enroll attempts to avoid harvesting likely secrets using a combination of path deny-lists, content sniffing, and size caps. This means you may see some files intentionally skipped.</p>
|
|
</div>
|
|
|
|
<div class="feature-card p-4 mt-4 border border-warning">
|
|
<div class="d-flex align-items-start gap-3">
|
|
<div class="icon-pill" style="background: rgba(255,193,7,0.20); border-color: rgba(255,193,7,0.45);"><i class="bi bi-exclamation-triangle"></i></div>
|
|
<div>
|
|
<h2 class="h4 fw-bold mb-2">The <code>--dangerous</code> flag</h2>
|
|
<p class="mb-2">This disables secret-safety checks. It can copy private keys, API tokens, DB passwords, TLS key material, etc.</p>
|
|
<p class="small text-secondary mb-0"><strong>Rule:</strong> if you use <code>--dangerous</code>, treat the output as sensitive data and plan secure storage before you run it. Don't store secrets in plaintext in a public place!</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="feature-card p-4 mt-4">
|
|
<h2 class="h4 fw-bold mb-2">Encrypt bundles at rest with SOPS</h2>
|
|
<p class="text-secondary">You can install <a href="https://github.com/getsops/sops" target="_blank" rel="noopener noreferrer">SOPS</a> on your <code>$PATH</code>, then use <code>--sops</code> to write a single encrypted <code>.tar.gz.sops</code> file for harvests and/or manifests. This is meant for storage-at-rest and backups.</p>
|
|
|
|
<div class="codeblock terminal">
|
|
<button class="btn btn-sm btn-outline-secondary copy-btn" data-copy-target="#sec-sops"><i class="bi bi-clipboard"></i> Copy</button>
|
|
<pre class="mb-0"><code id="sec-sops"><span class="prompt">$</span> enroll harvest --out /tmp/enroll-harvest --dangerous --sops <FINGERPRINT>
|
|
<span class="prompt">$</span> enroll manifest --harvest /tmp/enroll-harvest/harvest.tar.gz.sops \
|
|
--out /tmp/enroll-ansible --sops <FINGERPRINT></code></pre>
|
|
</div>
|
|
|
|
<div class="alert alert-secondary mt-3 mb-0">
|
|
<div class="fw-semibold">Important</div>
|
|
<div class="small mb-0">In manifest <code>--sops</code> mode, you'll need to decrypt and extract the bundle before running <code>ansible-playbook</code>.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-4">
|
|
<div class="callout p-4">
|
|
<div class="fw-semibold mb-2">Recommended workflow</div>
|
|
<ol class="small mb-0">
|
|
<li>Start with default mode (no <code>--dangerous</code>).</li>
|
|
<li>Add <code>--include-path</code> for a small set of extra files you genuinely want managed.</li>
|
|
<li>If you must capture secrets, use <code>--dangerous</code> <strong>and</strong> <code>--sops</code>.</li>
|
|
<li>Keep outputs out of public repos; review before committing.</li>
|
|
<li>Rotate credentials if you ever suspect they were captured or exposed.</li>
|
|
</ol>
|
|
</div>
|
|
|
|
<div class="callout p-4 mt-3">
|
|
<div class="fw-semibold mb-2">Storage ideas</div>
|
|
<ul class="small mb-0">
|
|
<li>Encrypted SOPS bundle stored in a password manager vault</li>
|
|
<li>Private git repo with additional encryption at rest</li>
|
|
<li>Offline backup in an encrypted volume</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="callout p-4 mt-3">
|
|
<div class="fw-semibold mb-2">Scope control</div>
|
|
<p class="small text-secondary mb-3">You can explicitly include or exclude paths. Excludes take precedence over includes.</p>
|
|
<div class="terminal"><pre class="mb-0"><code><span class="prompt">$</span> enroll harvest \
|
|
--out /tmp/enroll-harvest \
|
|
--include-path '/home/*/.profile' \
|
|
--exclude-path '/home/*/.ssh/**'</code></pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="my-5">
|
|
|
|
<div class="feature-card p-4">
|
|
<h2 class="h4 fw-bold mb-2">Threat model</h2>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<div class="fw-semibold">What Enroll tries to prevent</div>
|
|
<ul class="small mb-0">
|
|
<li>Accidentally copying obvious secrets in default mode</li>
|
|
<li>Harvesting huge/unbounded file sets by mistake</li>
|
|
<li>One host's difference causing problems for other hosts in terms of Ansible task steps (multi-site mode)</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="fw-semibold">What you still need to think about</div>
|
|
<ul class="small mb-0">
|
|
<li>Where outputs are stored and who can access them</li>
|
|
<li>Reviewing what was captured before committing/sharing</li>
|
|
<li>Choosing encryption and secret-management strategy</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
|
|
<footer class="py-5">
|
|
<div class="container">
|
|
<div class="row g-4 align-items-start">
|
|
<div class="col-lg-6">
|
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
<img class="brand-mark" src="assets/img/enroll.svg" alt="Enroll">
|
|
<div class="fw-bold">Enroll (a mig5 project)</div>
|
|
<span class="badge badge-soft rounded-pill">CLI</span>
|
|
<span class="badge badge-soft rounded-pill">Ansible</span>
|
|
</div>
|
|
<p class="smallprint mb-3">Reverse-engineering servers into Ansible.</p>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a class="btn btn-sm btn-outline-dark" href="https://git.mig5.net/mig5/enroll" target="_blank" rel="noreferrer"><i class="bi bi-git"></i> Repo</a>
|
|
<a class="btn btn-sm btn-outline-dark" href="https://pypi.org/project/enroll/" target="_blank" rel="noreferrer"><i class="bi bi-box"></i> PyPI</a>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3">
|
|
<div class="fw-semibold mb-2">Site</div>
|
|
<ul class="list-unstyled small mb-0">
|
|
<li><a class="link-secondary text-decoration-none" href="docs.html">Docs</a></li>
|
|
<li><a class="link-secondary text-decoration-none" href="examples.html">Examples</a></li>
|
|
<li><a class="link-secondary text-decoration-none" href="schema.html">Schema</a></li>
|
|
<li><a class="link-secondary text-decoration-none" href="security.html">Security Design</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-lg-3">
|
|
<div class="fw-semibold mb-2">Contact</div>
|
|
<ul class="list-unstyled small mb-0">
|
|
<li><a class="link-secondary text-decoration-none" href="https://nr.mig5.net/forms/mig5/contact" target="_blank" rel="noreferrer">Form</a></li>
|
|
<li><span class="text-secondary">Fediverse:</span> <a class="link-secondary text-decoration-none" href="https://goto.mig5.net/@mig5" target="_blank" rel="noreferrer">@mig5</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<hr class="my-4">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-2 small">
|
|
<div class="text-secondary">© <span id="year"></span> <a href="https://mig5.net" target="_blank" rel="noopener noreferrer">mig5 system administration</a></div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="assets/js/site.js"></script>
|
|
<script>document.getElementById('year').textContent = new Date().getFullYear();</script>
|
|
</body>
|
|
</html>
|
|
|