- Add PUT /v1/policy/rule endpoint for updating policy rules; expose full policy CRUD through the web UI with a dedicated policy page - Add certificate revoke, delete, and get-cert to CA engine and wire REST + gRPC routes; fix missing interceptor registrations - Update ARCHITECTURE.md to reflect v2 gRPC as the active implementation, document ACME endpoints, correct CA permission levels, and add policy/cert management route tables - Add POLICY.md documenting the priority-based ACL engine design - Add web/templates/policy.html for policy management UI Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
109 lines
4.9 KiB
HTML
109 lines
4.9 KiB
HTML
{{define "title"}} - Policy{{end}}
|
|
{{define "content"}}
|
|
<div class="page-header">
|
|
<h2>Policy Rules</h2>
|
|
<div class="page-meta">
|
|
<a href="/dashboard" class="btn btn-ghost btn-sm">← Dashboard</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{if .Error}}<div class="error">{{.Error}}</div>{{end}}
|
|
|
|
<div class="card">
|
|
<div class="card-title">Active Rules</div>
|
|
{{if .Rules}}
|
|
<div class="table-wrapper">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Priority</th>
|
|
<th>Effect</th>
|
|
<th>Usernames</th>
|
|
<th>Roles</th>
|
|
<th>Resources</th>
|
|
<th>Actions</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .Rules}}
|
|
<tr>
|
|
<td><code>{{.ID}}</code></td>
|
|
<td>{{.Priority}}</td>
|
|
<td><span class="badge {{if eq .Effect "allow"}}badge-ok{{else}}badge-warn{{end}}">{{.Effect}}</span></td>
|
|
<td>{{if .Usernames}}{{range $i, $u := .Usernames}}{{if $i}}, {{end}}{{$u}}{{end}}{{else}}<em>any</em>{{end}}</td>
|
|
<td>{{if .Roles}}{{range $i, $r := .Roles}}{{if $i}}, {{end}}{{$r}}{{end}}{{else}}<em>any</em>{{end}}</td>
|
|
<td>{{if .Resources}}{{range $i, $r := .Resources}}{{if $i}}, {{end}}<code>{{$r}}</code>{{end}}{{else}}<em>any</em>{{end}}</td>
|
|
<td>{{if .Actions}}{{range $i, $a := .Actions}}{{if $i}}, {{end}}{{$a}}{{end}}{{else}}<em>any</em>{{end}}</td>
|
|
<td>
|
|
<form method="post" action="/policy/delete" style="display:inline">
|
|
<input type="hidden" name="id" value="{{.ID}}">
|
|
<button type="submit" class="btn-danger btn-sm" onclick="return confirm('Delete rule {{.ID}}?')">Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{else}}
|
|
<p>No policy rules defined. Admins always have full access. Non-admin users are denied by default unless a matching allow rule exists.</p>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-title">Create Rule</div>
|
|
<details>
|
|
<summary>Add a new policy rule</summary>
|
|
<form method="post" action="/policy">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="rule_id">Rule ID <span class="required">*</span></label>
|
|
<input type="text" id="rule_id" name="id" placeholder="allow-users-read" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="rule_priority">Priority</label>
|
|
<input type="number" id="rule_priority" name="priority" value="50" min="0" max="9999">
|
|
<small>Lower number = higher priority. Default: 50.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="rule_effect">Effect <span class="required">*</span></label>
|
|
<select id="rule_effect" name="effect" required>
|
|
<option value="allow">allow</option>
|
|
<option value="deny">deny</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="rule_usernames">Usernames</label>
|
|
<input type="text" id="rule_usernames" name="usernames" placeholder="alice, bob">
|
|
<small>Comma-separated. Leave blank to match any user.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="rule_roles">Roles</label>
|
|
<input type="text" id="rule_roles" name="roles" placeholder="user, guest">
|
|
<small>Comma-separated. Leave blank to match any role.</small>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="rule_resources">Resources</label>
|
|
<input type="text" id="rule_resources" name="resources" placeholder="engine/pki/*, engine/pki/list-certs">
|
|
<small>Comma-separated glob patterns. Leave blank to match any resource.</small>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="rule_actions">Actions</label>
|
|
<input type="text" id="rule_actions" name="actions" placeholder="read, write">
|
|
<small>Comma-separated: <code>read</code> or <code>write</code>. Leave blank to match any action.</small>
|
|
</div>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="submit">Create Rule</button>
|
|
</div>
|
|
</form>
|
|
</details>
|
|
</div>
|
|
{{end}}
|