v0.1.23 - Make role-as-password the default authorization model; remove interactive approval prompts from wizard; add Makefile guard to direct agents to build_static.sh; optimize build_static.sh with content-hash skip and fix .dockerignore to exclude 1.3GB of unnecessary files from Docker context
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# Plan: Role-as-Password as the Default Authorization Model
|
||||
|
||||
## Status: Draft — ready for review
|
||||
|
||||
## Problem
|
||||
|
||||
The signer currently defaults to requiring interactive approval for every request, even for the default "main" role. This contradicts the intended design where **knowing the role name is sufficient authorization** (role-as-password). Users running v0.1.21 are prompted to approve requests when they should be authorized automatically.
|
||||
|
||||
## Root cause
|
||||
|
||||
Three places in the code set `requires_approval = 1` by default:
|
||||
|
||||
| Location | Context | Current value |
|
||||
|---|---|---|
|
||||
| [`src/main.c:3816`](../src/main.c:3816) | Default "main" role (non-interactive mode) | `requires_approval = 1` |
|
||||
| [`src/main.c:2374`](../src/main.c:2374) | Wizard role creation prompt | Default `1` (Y/n) |
|
||||
| [`src/main.c:2223`](../src/main.c:2223) | Wizard OTP role creation prompt | Default `1` (Y/n) |
|
||||
|
||||
## Changes required
|
||||
|
||||
### 1. Default "main" role — non-interactive mode
|
||||
|
||||
**File:** [`src/main.c:3816`](../src/main.c:3816)
|
||||
|
||||
Change:
|
||||
```c
|
||||
role.requires_approval = 1;
|
||||
```
|
||||
To:
|
||||
```c
|
||||
role.requires_approval = 0; /* role-as-password: knowing the role name is sufficient */
|
||||
```
|
||||
|
||||
This is the most critical fix — it affects every user running in non-interactive mode (e.g., `--listen unix`, `--listen tcp`, `--listen qrexec`).
|
||||
|
||||
### 2. Wizard role creation — remove approval prompt
|
||||
|
||||
**File:** [`src/main.c:2359-2377`](../src/main.c:2359)
|
||||
|
||||
Currently the wizard asks:
|
||||
```
|
||||
Require interactive approval for each request? [Y/n]:
|
||||
```
|
||||
|
||||
With role-as-password as the default, this prompt should be **removed entirely**. The role is created with `requires_approval = 0`. If a user wants approval, they can use `--preapprove` or manually edit the role after creation.
|
||||
|
||||
Remove the prompt block (lines 2359-2377) and set:
|
||||
```c
|
||||
int requires_approval = 0; /* role-as-password by default */
|
||||
```
|
||||
|
||||
### 3. Wizard OTP role creation — remove approval prompt
|
||||
|
||||
**File:** [`src/main.c:2208-2226`](../src/main.c:2208)
|
||||
|
||||
Same change as #2. Remove the approval prompt for OTP roles and default to `requires_approval = 0`.
|
||||
|
||||
### 4. Policy table default — no change needed
|
||||
|
||||
**File:** [`src/policy.c:1097-1113`](../src/policy.c:1097)
|
||||
|
||||
The current default policy is `* → PROMPT_EVERY_REQUEST`. This is correct because:
|
||||
|
||||
- For roles with `requires_approval = 0`, [`policy_check_with_role()`](../src/policy.c:1305) returns `POLICY_ALLOW` **before** consulting the policy table.
|
||||
- For roles with `requires_approval = 1`, the policy table prompt still fires as expected.
|
||||
|
||||
No change needed here.
|
||||
|
||||
### 5. `--allow-all` flag — retain as-is
|
||||
|
||||
**File:** [`src/main.c:3678`](../src/main.c:3678)
|
||||
|
||||
The `--allow-all` flag sets `g_prompt_always_allow`, which bypasses prompts for algorithm-based verbs (sign, verify, encapsulate, etc.) that don't go through the role system. This is still useful for testing and non-interactive scenarios. No change needed.
|
||||
|
||||
## Authorization flow after changes
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Client sends request with role name] --> B{Role found?}
|
||||
B -- No --> C[Reject: unknown_role]
|
||||
B -- Yes --> D{requires_approval?}
|
||||
D -- No --> E[Authorize immediately - role-as-password]
|
||||
D -- Yes --> F[Check policy table]
|
||||
F --> G{Policy match?}
|
||||
G -- Allow --> H[Authorize]
|
||||
G -- Prompt --> I[Show interactive prompt]
|
||||
G -- Deny --> J[Reject: policy_denied]
|
||||
I --> K{User choice}
|
||||
K -- y --> H
|
||||
K -- a/e --> L[Add session grant] --> H
|
||||
K -- n --> J
|
||||
```
|
||||
|
||||
## Test impact
|
||||
|
||||
- [`tests/test_n_signer_client.sh`](../tests/test_n_signer_client.sh) — may need updates if tests relied on the old approval-required default
|
||||
- [`tests/test_integration.c`](../tests/test_integration.c) — verify no tests break from the default change
|
||||
- The `NSIGNER_TEST_FORCE_PROMPT` env var ([`src/main.c:3063`](../src/main.c:3063)) can be used to force prompts in tests that need to exercise the approval path
|
||||
|
||||
## Files to modify
|
||||
|
||||
| File | Lines | Change |
|
||||
|---|---|---|
|
||||
| [`src/main.c`](../src/main.c) | 3816 | `requires_approval = 1` → `0` |
|
||||
| [`src/main.c`](../src/main.c) | 2359-2377 | Remove approval prompt, default to `0` |
|
||||
| [`src/main.c`](../src/main.c) | 2208-2226 | Remove approval prompt, default to `0` |
|
||||
|
||||
## Summary
|
||||
|
||||
Three one-line changes (plus removing two prompt blocks) to make role-as-password the default. The mechanism already exists in the code — it's just not the default.
|
||||
Reference in New Issue
Block a user