Public release release-01875e88a3e2
Source commit: 01875e88a3e25379c309489f9f057dd97c0d37de Public tree identity: sha256:8f37a1aa0cc8f408975daf9cabbe193f8f4c169c6d25e8795e67a3ed5083c76b
This commit is contained in:
commit
c1769967c1
210 changed files with 78680 additions and 0 deletions
271
crates/clusterflux-cli/src/key.rs
Normal file
271
crates/clusterflux-cli/src/key.rs
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
use anyhow::Result;
|
||||
use clusterflux_core::Digest;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use crate::client::{authenticated_or_local_trusted_request, JsonLineSession};
|
||||
use crate::config::StoredCliSession;
|
||||
use crate::{confirmation_required_report, KeyAddArgs, KeyListArgs, KeyRevokeArgs};
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn key_add_report(args: KeyAddArgs) -> Result<Value> {
|
||||
key_add_report_with_session(args, None)
|
||||
}
|
||||
|
||||
pub(crate) fn key_add_report_with_session(
|
||||
args: KeyAddArgs,
|
||||
stored_session: Option<&StoredCliSession>,
|
||||
) -> Result<Value> {
|
||||
let coordinator = effective_coordinator(&args.scope.coordinator, stored_session);
|
||||
if let Some(coordinator) = &coordinator {
|
||||
let tenant = effective_session_value(stored_session, &args.scope.tenant, |session| {
|
||||
&session.tenant
|
||||
});
|
||||
let project = effective_session_value(stored_session, &args.scope.project, |session| {
|
||||
&session.project
|
||||
});
|
||||
let user =
|
||||
effective_session_value(stored_session, &args.scope.user, |session| &session.user);
|
||||
let agent = args.agent.clone();
|
||||
let public_key_fingerprint = Digest::sha256(&args.public_key);
|
||||
let mut session = JsonLineSession::connect(coordinator)?;
|
||||
let response = session.request(authenticated_or_local_trusted_request(
|
||||
coordinator,
|
||||
stored_session,
|
||||
json!({
|
||||
"type": "register_agent_public_key",
|
||||
"agent": agent,
|
||||
"public_key": args.public_key,
|
||||
}),
|
||||
json!({
|
||||
"type": "register_agent_public_key",
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"agent": agent,
|
||||
"public_key": args.public_key,
|
||||
}),
|
||||
)?)?;
|
||||
let record = response.get("record").cloned().unwrap_or_else(|| {
|
||||
json!({
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"agent": agent,
|
||||
"public_key_fingerprint": public_key_fingerprint,
|
||||
"scopes": ["project:read", "project:run"],
|
||||
"human_account_creation_privilege": false,
|
||||
"browser_interaction_required_each_run": false,
|
||||
})
|
||||
});
|
||||
return Ok(json!({
|
||||
"command": "key add",
|
||||
"coordinator": coordinator,
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"agent": agent,
|
||||
"public_key_fingerprint": record
|
||||
.get("public_key_fingerprint")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| json!(public_key_fingerprint)),
|
||||
"credential_scope": {
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"actions": record
|
||||
.get("scopes")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| json!(["project:read", "project:run"])),
|
||||
"human_account_creation_privilege": record
|
||||
.get("human_account_creation_privilege")
|
||||
.cloned()
|
||||
.unwrap_or(json!(false)),
|
||||
},
|
||||
"browser_interaction_required_each_run": record
|
||||
.get("browser_interaction_required_each_run")
|
||||
.cloned()
|
||||
.unwrap_or(json!(false)),
|
||||
"attribution": {
|
||||
"registered_by_user": user,
|
||||
"agent": agent,
|
||||
"credential_kind": "public_key",
|
||||
},
|
||||
"response": response,
|
||||
"coordinator_session_requests": session.requests(),
|
||||
}));
|
||||
}
|
||||
Ok(json!({
|
||||
"command": "key add",
|
||||
"status": "planned_without_coordinator",
|
||||
"agent": args.agent,
|
||||
"public_key_fingerprint": Digest::sha256(args.public_key),
|
||||
"browser_interaction_required_each_run": false,
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn key_list_report(args: KeyListArgs) -> Result<Value> {
|
||||
key_list_report_with_session(args, None)
|
||||
}
|
||||
|
||||
pub(crate) fn key_list_report_with_session(
|
||||
args: KeyListArgs,
|
||||
stored_session: Option<&StoredCliSession>,
|
||||
) -> Result<Value> {
|
||||
let coordinator = effective_coordinator(&args.scope.coordinator, stored_session);
|
||||
if let Some(coordinator) = &coordinator {
|
||||
let tenant = effective_session_value(stored_session, &args.scope.tenant, |session| {
|
||||
&session.tenant
|
||||
});
|
||||
let project = effective_session_value(stored_session, &args.scope.project, |session| {
|
||||
&session.project
|
||||
});
|
||||
let user =
|
||||
effective_session_value(stored_session, &args.scope.user, |session| &session.user);
|
||||
let mut session = JsonLineSession::connect(coordinator)?;
|
||||
let response = session.request(authenticated_or_local_trusted_request(
|
||||
coordinator,
|
||||
stored_session,
|
||||
json!({
|
||||
"type": "list_agent_public_keys",
|
||||
}),
|
||||
json!({
|
||||
"type": "list_agent_public_keys",
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
}),
|
||||
)?)?;
|
||||
return Ok(json!({
|
||||
"command": "key list",
|
||||
"coordinator": coordinator,
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"records": response
|
||||
.get("records")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| json!([])),
|
||||
"credential_scope": {
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"listed_for_user": user,
|
||||
"human_account_creation_privilege": false,
|
||||
},
|
||||
"response": response,
|
||||
"coordinator_session_requests": session.requests(),
|
||||
}));
|
||||
}
|
||||
Ok(json!({
|
||||
"command": "key list",
|
||||
"status": "requires_coordinator",
|
||||
"records": [],
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn key_revoke_report(args: KeyRevokeArgs) -> Result<Value> {
|
||||
key_revoke_report_with_session(args, None)
|
||||
}
|
||||
|
||||
pub(crate) fn key_revoke_report_with_session(
|
||||
args: KeyRevokeArgs,
|
||||
stored_session: Option<&StoredCliSession>,
|
||||
) -> Result<Value> {
|
||||
if !args.yes {
|
||||
return Ok(confirmation_required_report(
|
||||
"key revoke",
|
||||
"revoke_agent_public_key",
|
||||
json!({
|
||||
"coordinator": args.scope.coordinator,
|
||||
"tenant": args.scope.tenant,
|
||||
"project": args.scope.project,
|
||||
"user": args.scope.user,
|
||||
"agent": args.agent,
|
||||
}),
|
||||
format!("clusterflux key revoke --agent {} --yes", args.agent),
|
||||
));
|
||||
}
|
||||
let coordinator = effective_coordinator(&args.scope.coordinator, stored_session);
|
||||
if let Some(coordinator) = &coordinator {
|
||||
let tenant = effective_session_value(stored_session, &args.scope.tenant, |session| {
|
||||
&session.tenant
|
||||
});
|
||||
let project = effective_session_value(stored_session, &args.scope.project, |session| {
|
||||
&session.project
|
||||
});
|
||||
let user =
|
||||
effective_session_value(stored_session, &args.scope.user, |session| &session.user);
|
||||
let agent = args.agent.clone();
|
||||
let mut session = JsonLineSession::connect(coordinator)?;
|
||||
let response = session.request(authenticated_or_local_trusted_request(
|
||||
coordinator,
|
||||
stored_session,
|
||||
json!({
|
||||
"type": "revoke_agent_public_key",
|
||||
"agent": agent,
|
||||
}),
|
||||
json!({
|
||||
"type": "revoke_agent_public_key",
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"agent": agent,
|
||||
}),
|
||||
)?)?;
|
||||
return Ok(json!({
|
||||
"command": "key revoke",
|
||||
"coordinator": coordinator,
|
||||
"requires_confirmation": !args.yes,
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"user": user,
|
||||
"agent": agent,
|
||||
"revoked": response
|
||||
.pointer("/record/revoked")
|
||||
.cloned()
|
||||
.unwrap_or(json!(true)),
|
||||
"credential_scope": {
|
||||
"tenant": tenant,
|
||||
"project": project,
|
||||
"revoked_for_user": user,
|
||||
"human_account_creation_privilege": false,
|
||||
},
|
||||
"attribution": {
|
||||
"revoked_by_user": user,
|
||||
"agent": agent,
|
||||
"credential_kind": "public_key",
|
||||
},
|
||||
"response": response,
|
||||
"coordinator_session_requests": session.requests(),
|
||||
}));
|
||||
}
|
||||
Ok(json!({
|
||||
"command": "key revoke",
|
||||
"status": "requires_coordinator",
|
||||
"requires_confirmation": !args.yes,
|
||||
"agent": args.agent,
|
||||
}))
|
||||
}
|
||||
|
||||
fn effective_coordinator(
|
||||
requested: &Option<String>,
|
||||
stored_session: Option<&StoredCliSession>,
|
||||
) -> Option<String> {
|
||||
requested.clone().or_else(|| {
|
||||
stored_session
|
||||
.filter(|session| session.session_secret.is_some())
|
||||
.map(|session| session.coordinator.clone())
|
||||
})
|
||||
}
|
||||
|
||||
fn effective_session_value(
|
||||
stored_session: Option<&StoredCliSession>,
|
||||
requested: &str,
|
||||
value: impl FnOnce(&StoredCliSession) -> &String,
|
||||
) -> String {
|
||||
stored_session
|
||||
.filter(|session| session.session_secret.is_some())
|
||||
.map(value)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| requested.to_owned())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue