initial upload
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
{{define "login.html"}}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}}</title>
|
||||
<link rel="stylesheet" href="/static/app.css">
|
||||
</head>
|
||||
<body class="login-page">
|
||||
<main class="login-shell">
|
||||
<section class="login-card">
|
||||
<div class="brand-mark">TAPM</div>
|
||||
<p class="eyebrow">Technician authorization</p>
|
||||
<h1>Deployment Access</h1>
|
||||
<p class="lede">
|
||||
Create time-limited access for protected packages without placing
|
||||
permanent credentials on customer infrastructure.
|
||||
</p>
|
||||
<a class="button primary wide" href="{{.GiteaLoginURL}}">Continue with Gitea</a>
|
||||
<p class="fine-print">Authorized TAI technicians only. Activity is audited.</p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -0,0 +1,213 @@
|
||||
{{define "portal.html"}}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}} · TAPM</title>
|
||||
<link rel="stylesheet" href="/static/app.css">
|
||||
<script src="/static/app.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<header class="topbar">
|
||||
<div>
|
||||
<span class="wordmark">TAPM</span>
|
||||
<span class="product-name">Deployment Access</span>
|
||||
</div>
|
||||
<div class="operator">
|
||||
<span>{{.Technician.DisplayName}}</span>
|
||||
<form action="/auth/logout" method="post">
|
||||
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||
<button class="text-button" type="submit">Sign out</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="page">
|
||||
{{if .NewCode}}
|
||||
<section class="code-reveal" aria-live="polite">
|
||||
<div>
|
||||
<p class="eyebrow">Deployment authorization created</p>
|
||||
<h2 id="new-code">{{.NewCode}}</h2>
|
||||
<p>Share this code only with the technician performing the deployment.</p>
|
||||
</div>
|
||||
<button class="button light" type="button" data-copy="#new-code">Copy code</button>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{if .Notice}}<div class="notice">{{.Notice}}</div>{{end}}
|
||||
|
||||
<section class="hero">
|
||||
<div>
|
||||
<p class="eyebrow">Controlled package delivery</p>
|
||||
<h1>Open a deployment window.</h1>
|
||||
<p>
|
||||
Authorize a limited number of hosts for selected packages. Access
|
||||
closes automatically at the end of the window.
|
||||
</p>
|
||||
</div>
|
||||
<div class="policy-card">
|
||||
<span>Default policy</span>
|
||||
<strong>{{.DefaultHostLimit}} hosts</strong>
|
||||
<strong>{{.DefaultDuration}} hours</strong>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="content-grid">
|
||||
<section class="panel create-panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<p class="eyebrow">New authorization</p>
|
||||
<h2>Create deployment code</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="/portal/authorizations" method="post" class="stack">
|
||||
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||
<label>
|
||||
Customer or deployment label
|
||||
<input name="customer_label" maxlength="255" placeholder="Example: Acme cluster refresh">
|
||||
</label>
|
||||
|
||||
<div class="field-row">
|
||||
<label>
|
||||
Maximum hosts
|
||||
<input name="host_limit" type="number" min="1" max="25" value="{{.DefaultHostLimit}}" required>
|
||||
</label>
|
||||
<label>
|
||||
Duration in hours
|
||||
<input name="duration_hours" type="number" min="1" max="24" value="{{.DefaultDuration}}" required>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset>
|
||||
<legend>Allowed packages</legend>
|
||||
{{range .Packages}}
|
||||
{{if .Enabled}}
|
||||
<label class="package-choice">
|
||||
<input type="checkbox" name="package_id" value="{{.ID}}">
|
||||
<span>
|
||||
<strong>{{.DisplayName}}</strong>
|
||||
<small>{{.PackageVersion}}</small>
|
||||
</span>
|
||||
</label>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="empty">No packages have been enabled yet.</p>
|
||||
{{end}}
|
||||
</fieldset>
|
||||
|
||||
<button class="button primary" type="submit">Create 3-hour code</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Recent activity</p>
|
||||
<h2>Deployment authorizations</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="authorization-list">
|
||||
{{range .Authorizations}}
|
||||
<article class="authorization {{if isActive .}}active{{else}}closed{{end}}">
|
||||
<div class="authorization-top">
|
||||
<div>
|
||||
<strong>{{if .CustomerLabel}}{{.CustomerLabel}}{{else}}Unlabeled deployment{{end}}</strong>
|
||||
<span class="status">{{if isActive .}}Active{{else}}Closed{{end}}</span>
|
||||
</div>
|
||||
<span class="code-hint">•••••{{.CodeHint}}</span>
|
||||
</div>
|
||||
<dl>
|
||||
<div><dt>Hosts</dt><dd>{{.HostCount}} / {{.HostLimit}}</dd></div>
|
||||
<div><dt>Expires</dt><dd>{{formatTime .ExpiresAt}}</dd></div>
|
||||
<div><dt>Packages</dt><dd>{{.Packages}}</dd></div>
|
||||
<div><dt>Created by</dt><dd>{{.CreatedBy}}</dd></div>
|
||||
</dl>
|
||||
{{if isActive .}}
|
||||
<form action="/portal/authorizations/{{.ID}}/revoke" method="post">
|
||||
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
||||
<button class="text-button danger" type="submit">Revoke now</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</article>
|
||||
{{else}}
|
||||
<p class="empty">No deployment authorizations have been created.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="panel package-admin">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Registry catalog</p>
|
||||
<h2>Protected packages</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="package-layout">
|
||||
<div class="package-table">
|
||||
{{range .Packages}}
|
||||
<div class="package-row">
|
||||
<div>
|
||||
<strong>{{.DisplayName}}</strong>
|
||||
<small>{{.Slug}} · {{.PackageVersion}}</small>
|
||||
</div>
|
||||
<span class="status {{if .Enabled}}enabled{{end}}">{{if .Enabled}}Enabled{{else}}Disabled{{end}}</span>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="empty">Add the first package after publishing it to Gitea.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<form action="/portal/packages" method="post" class="stack compact">
|
||||
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||
<label>Slug <input name="slug" placeholder="sentinelone-linux" pattern="[a-z0-9_-]+" required></label>
|
||||
<label>Display name <input name="display_name" placeholder="SentinelOne Linux Agent" required></label>
|
||||
<div class="field-row">
|
||||
<label>Registry package <input name="package_name" placeholder="sentinelone-linux" required></label>
|
||||
<label>Version <input name="package_version" placeholder="26.1.1.31" required></label>
|
||||
</div>
|
||||
<label>Filename <input name="file_name" placeholder="SentinelAgent_linux_x86_64.deb" required></label>
|
||||
<label>SHA-256 <input name="sha256" minlength="64" maxlength="64" placeholder="64 hexadecimal characters" required></label>
|
||||
<label class="toggle"><input type="checkbox" name="enabled" value="1"> Enable for new authorizations</label>
|
||||
<button class="button secondary" type="submit">Save package metadata</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel audit-panel">
|
||||
<div class="panel-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Audit trail</p>
|
||||
<h2>Latest security events</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="audit-table">
|
||||
{{range .AuditEvents}}
|
||||
<div class="audit-row">
|
||||
<div>
|
||||
<strong>{{.EventType}}</strong>
|
||||
<small>{{formatTime .CreatedAt}}</small>
|
||||
</div>
|
||||
<div>
|
||||
{{if .Actor}}<span>{{.Actor}}</span>{{end}}
|
||||
{{if .Hostname}}<span>{{.Hostname}}</span>{{end}}
|
||||
{{if .PackageSlug}}<span>{{.PackageSlug}}</span>{{end}}
|
||||
</div>
|
||||
<div>
|
||||
<span>{{.SourceIP}}</span>
|
||||
{{if .Details}}<small>{{.Details}}</small>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="empty audit-empty">No security events have been recorded.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user