Member tokens: reusable account credential authorizing key enrollment per node
This commit is contained in:
+41
-13
@@ -472,10 +472,11 @@ pub fn registry_approve(dir: &Path, id: &str, registry_url: Option<&str>) -> Res
|
||||
});
|
||||
Ok(())
|
||||
})?;
|
||||
let invite = registry::create_invite(dir, id, 24 * 3600)?;
|
||||
let token = registry::create_token(dir, id)?;
|
||||
let (_, signed) = open_registry(dir)?;
|
||||
println!("approved {id} ({class})");
|
||||
print_credential_block(id, &invite.token, registry_url, &signed.doc.ma_key);
|
||||
println!("member token — reusable for every node the member runs; keep private:");
|
||||
print_credential_block(id, &token, registry_url, &signed.doc.ma_key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -487,13 +488,33 @@ pub fn registry_invite(dir: &Path, id: &str, registry_url: Option<&str>) -> Resu
|
||||
return Err(anyhow!("no member named {id}"));
|
||||
}
|
||||
let invite = registry::create_invite(dir, id, 24 * 3600)?;
|
||||
println!("single-use handoff invite for {id} (valid 24h):");
|
||||
print_credential_block(id, &invite.token, registry_url, &signed.doc.ma_key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mints an additional member token (account credential) and prints the block.
|
||||
/// Returns the raw token for programmatic use.
|
||||
pub fn registry_token(dir: &Path, id: &str, registry_url: Option<&str>) -> Result<String> {
|
||||
let (_, signed) = open_registry(dir)?;
|
||||
if !signed.doc.members.iter().any(|member| member.id == id) {
|
||||
return Err(anyhow!("no member named {id}"));
|
||||
}
|
||||
let token = registry::create_token(dir, id)?;
|
||||
println!("member token for {id} — reusable for every node they run; keep private:");
|
||||
print_credential_block(id, &token, registry_url, &signed.doc.ma_key);
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
/// Revokes all of a member's tokens (e.g. after a leak); mint fresh with `registry token`.
|
||||
pub fn registry_revoke_token(dir: &Path, id: &str) -> Result<()> {
|
||||
let revoked = registry::revoke_tokens(dir, id)?;
|
||||
println!("revoked {revoked} token(s) for {id}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_credential_block(id: &str, token: &str, registry_url: Option<&str>, ma_key: &str) {
|
||||
let registry_url = registry_url.unwrap_or("<registry-url>");
|
||||
println!("hand this credential block to the member (single use, valid 24h):");
|
||||
println!("id={id} token={token} registry={registry_url} ma_key={ma_key}");
|
||||
}
|
||||
|
||||
@@ -741,12 +762,16 @@ async fn registry_enroll(
|
||||
.into_response();
|
||||
}
|
||||
};
|
||||
if let Err(error) = registry::redeem_invite(&server.dir, &request.id, &request.token) {
|
||||
return (
|
||||
StatusCode::FORBIDDEN,
|
||||
Json(serde_json::json!({ "error": error.to_string() })),
|
||||
)
|
||||
.into_response();
|
||||
if registry::redeem_invite(&server.dir, &request.id, &request.token).is_err() {
|
||||
let valid = registry::validate_token(&server.dir, &request.id, &request.token)
|
||||
.unwrap_or(false);
|
||||
if !valid {
|
||||
return (
|
||||
StatusCode::FORBIDDEN,
|
||||
Json(serde_json::json!({ "error": "unknown invite or member token" })),
|
||||
)
|
||||
.into_response();
|
||||
}
|
||||
}
|
||||
let result = mutate_registry(&server.dir, |doc| {
|
||||
let Some(member) = doc
|
||||
@@ -872,10 +897,10 @@ the MA for the membership contract — never published, never on the wire.</p>
|
||||
<h2>2. Download</h2>
|
||||
<div class="card">
|
||||
<p>Static Linux x86_64 binaries (musl — no runtime dependencies):</p>
|
||||
<pre class="cmd">curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.3/frxd-linux-amd64
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.3/frxd-linux-amd64.sha256
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.3/frx-linux-amd64
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.3/frx-linux-amd64.sha256</pre>
|
||||
<pre class="cmd">curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.4/frxd-linux-amd64
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.4/frxd-linux-amd64.sha256
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.4/frx-linux-amd64
|
||||
curl -LO https://git.federatedsearch.org/frx/frxd/releases/download/v0.1.4/frx-linux-amd64.sha256</pre>
|
||||
<p class="muted">All releases: <a href="https://git.federatedsearch.org/frx/frxd/releases">git.federatedsearch.org/frx/frxd/releases</a>.
|
||||
Source and spec (<code>rfc.txt</code>): <a href="https://git.federatedsearch.org/frx/frxd">git.federatedsearch.org/frx/frxd</a>.</p>
|
||||
</div>
|
||||
@@ -899,6 +924,9 @@ against the pinned MA key, and wires the federation relays — no domains, DNS,
|
||||
needed on your side.</li>
|
||||
<li>Index a directory and mark what you share:</li>
|
||||
</ol>
|
||||
<p class="muted">The credential block is reusable: run the wizard on every node you operate —
|
||||
each node binds its own key to your identifier. If the token leaks, the MA revokes it and
|
||||
issues a fresh one.</p>
|
||||
<pre class="cmd">frxd add ~/documents --name docs --shared --exposure metadata
|
||||
frxd serve</pre>
|
||||
<p class="muted">Search local-first with <code>frx search "..."</code>; broadcast to the federation with
|
||||
|
||||
Reference in New Issue
Block a user