Update public node enrollment report
This commit is contained in:
parent
298fbcca72
commit
c4d8d94f49
3 changed files with 150 additions and 11 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"kind": "disasmer-filtered-public-tree",
|
"kind": "disasmer-filtered-public-tree",
|
||||||
"source_commit": "57e56a24e60a3990d91c199548b96b6c1f0fe962",
|
"source_commit": "3313653a3d00fcd3fa5613e12cde2f76ae9a8ad0",
|
||||||
"release_name": "dryrun-57e56a24e60a",
|
"release_name": "dryrun-3313653a3d00",
|
||||||
"filtered_out": [
|
"filtered_out": [
|
||||||
"private/**",
|
"private/**",
|
||||||
"experiments/**",
|
"experiments/**",
|
||||||
|
|
|
||||||
|
|
@ -1335,32 +1335,98 @@ fn build_report(args: BuildArgs, cwd: PathBuf) -> Result<Value> {
|
||||||
|
|
||||||
fn node_enroll_report(args: NodeEnrollArgs) -> Result<Value> {
|
fn node_enroll_report(args: NodeEnrollArgs) -> Result<Value> {
|
||||||
if let Some(coordinator) = &args.scope.coordinator {
|
if let Some(coordinator) = &args.scope.coordinator {
|
||||||
|
let tenant = args.scope.tenant.clone();
|
||||||
|
let project = args.scope.project.clone();
|
||||||
|
let user = args.scope.user.clone();
|
||||||
|
let requested_grant = args.grant.clone();
|
||||||
|
let ttl_seconds = args.ttl_seconds;
|
||||||
let mut session = JsonLineSession::connect(coordinator)?;
|
let mut session = JsonLineSession::connect(coordinator)?;
|
||||||
let response = session.request(json!({
|
let response = session.request(json!({
|
||||||
"type": "create_node_enrollment_grant",
|
"type": "create_node_enrollment_grant",
|
||||||
"tenant": args.scope.tenant,
|
"tenant": tenant,
|
||||||
"project": args.scope.project,
|
"project": project,
|
||||||
"actor_user": args.scope.user,
|
"actor_user": user,
|
||||||
"grant": args.grant,
|
"grant": requested_grant,
|
||||||
"now_epoch_seconds": 0,
|
"now_epoch_seconds": 0,
|
||||||
"ttl_seconds": args.ttl_seconds,
|
"ttl_seconds": ttl_seconds,
|
||||||
}))?;
|
}))?;
|
||||||
|
let enrollment_grant = node_enrollment_grant_summary(
|
||||||
|
&response,
|
||||||
|
&tenant,
|
||||||
|
&project,
|
||||||
|
&user,
|
||||||
|
&requested_grant,
|
||||||
|
ttl_seconds,
|
||||||
|
);
|
||||||
return Ok(json!({
|
return Ok(json!({
|
||||||
"command": "node enroll",
|
"command": "node enroll",
|
||||||
|
"status": "created",
|
||||||
"coordinator": coordinator,
|
"coordinator": coordinator,
|
||||||
|
"tenant": tenant,
|
||||||
|
"project": project,
|
||||||
|
"user": user,
|
||||||
|
"private_website_required": false,
|
||||||
|
"enrollment_grant": enrollment_grant,
|
||||||
"response": response,
|
"response": response,
|
||||||
"coordinator_session_requests": session.requests(),
|
"coordinator_session_requests": session.requests(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
let enrollment_grant = json!({
|
||||||
|
"grant": args.grant,
|
||||||
|
"tenant": args.scope.tenant,
|
||||||
|
"project": args.scope.project,
|
||||||
|
"user": args.scope.user,
|
||||||
|
"scope": "node:attach",
|
||||||
|
"ttl_seconds": args.ttl_seconds,
|
||||||
|
"short_lived": true,
|
||||||
|
"exchange_for_persistent_node_identity": true,
|
||||||
|
"node_credentials_separate_from_user_session": true,
|
||||||
|
});
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"command": "node enroll",
|
"command": "node enroll",
|
||||||
"status": "planned_without_coordinator",
|
"status": "planned_without_coordinator",
|
||||||
"grant": args.grant,
|
"private_website_required": false,
|
||||||
"ttl_seconds": args.ttl_seconds,
|
"enrollment_grant": enrollment_grant,
|
||||||
"scope": "node:attach",
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_enrollment_grant_summary(
|
||||||
|
response: &Value,
|
||||||
|
tenant: &str,
|
||||||
|
project: &str,
|
||||||
|
user: &str,
|
||||||
|
requested_grant: &str,
|
||||||
|
ttl_seconds: u64,
|
||||||
|
) -> Value {
|
||||||
|
json!({
|
||||||
|
"grant": response
|
||||||
|
.get("grant")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| json!(requested_grant)),
|
||||||
|
"tenant": response
|
||||||
|
.get("tenant")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| json!(tenant)),
|
||||||
|
"project": response
|
||||||
|
.get("project")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| json!(project)),
|
||||||
|
"user": user,
|
||||||
|
"scope": response
|
||||||
|
.get("scope")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| json!("node:attach")),
|
||||||
|
"ttl_seconds": ttl_seconds,
|
||||||
|
"expires_at_epoch_seconds": response
|
||||||
|
.get("expires_at_epoch_seconds")
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Value::Null),
|
||||||
|
"short_lived": true,
|
||||||
|
"exchange_for_persistent_node_identity": true,
|
||||||
|
"node_credentials_separate_from_user_session": true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn node_list_report(args: NodeListArgs) -> Result<Value> {
|
fn node_list_report(args: NodeListArgs) -> Result<Value> {
|
||||||
node_descriptors_report("node list", args.scope, None)
|
node_descriptors_report("node list", args.scope, None)
|
||||||
}
|
}
|
||||||
|
|
@ -7534,6 +7600,65 @@ mod tests {
|
||||||
assert_eq!(report["diagnostics"][0]["code"], "missing_environment");
|
assert_eq!(report["diagnostics"][0]["code"], "missing_environment");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn node_enroll_reports_short_lived_public_api_grant() {
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
let addr = listener.local_addr().unwrap().to_string();
|
||||||
|
let server = std::thread::spawn(move || {
|
||||||
|
let (mut stream, _) = listener.accept().unwrap();
|
||||||
|
let mut reader = BufReader::new(stream.try_clone().unwrap());
|
||||||
|
let mut line = String::new();
|
||||||
|
reader.read_line(&mut line).unwrap();
|
||||||
|
assert!(line.contains(r#""type":"create_node_enrollment_grant""#));
|
||||||
|
assert!(line.contains(r#""tenant":"tenant""#));
|
||||||
|
assert!(line.contains(r#""project":"project""#));
|
||||||
|
assert!(line.contains(r#""actor_user":"user""#));
|
||||||
|
assert!(line.contains(r#""grant":"grant-live""#));
|
||||||
|
assert!(line.contains(r#""ttl_seconds":300"#));
|
||||||
|
stream
|
||||||
|
.write_all(
|
||||||
|
br#"{"type":"node_enrollment_grant_created","tenant":"tenant","project":"project","grant":"grant-live","scope":"node:attach","expires_at_epoch_seconds":300}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
stream.write_all(b"\n").unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let report = node_enroll_report(NodeEnrollArgs {
|
||||||
|
scope: CliScopeArgs {
|
||||||
|
coordinator: Some(addr),
|
||||||
|
tenant: "tenant".to_owned(),
|
||||||
|
project: "project".to_owned(),
|
||||||
|
user: "user".to_owned(),
|
||||||
|
json: false,
|
||||||
|
},
|
||||||
|
grant: "grant-live".to_owned(),
|
||||||
|
ttl_seconds: 300,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
server.join().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(report["command"], "node enroll");
|
||||||
|
assert_eq!(report["status"], "created");
|
||||||
|
assert_eq!(report["private_website_required"], false);
|
||||||
|
assert_eq!(report["tenant"], "tenant");
|
||||||
|
assert_eq!(report["project"], "project");
|
||||||
|
assert_eq!(report["user"], "user");
|
||||||
|
assert_eq!(report["enrollment_grant"]["grant"], "grant-live");
|
||||||
|
assert_eq!(report["enrollment_grant"]["scope"], "node:attach");
|
||||||
|
assert_eq!(report["enrollment_grant"]["ttl_seconds"], 300);
|
||||||
|
assert_eq!(report["enrollment_grant"]["expires_at_epoch_seconds"], 300);
|
||||||
|
assert_eq!(report["enrollment_grant"]["short_lived"], true);
|
||||||
|
assert_eq!(
|
||||||
|
report["enrollment_grant"]["exchange_for_persistent_node_identity"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
report["enrollment_grant"]["node_credentials_separate_from_user_session"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(report["coordinator_session_requests"], 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn node_enroll_and_process_commands_have_safe_plan_without_coordinator() {
|
fn node_enroll_and_process_commands_have_safe_plan_without_coordinator() {
|
||||||
let scope = CliScopeArgs {
|
let scope = CliScopeArgs {
|
||||||
|
|
@ -7550,7 +7675,15 @@ mod tests {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(enroll["status"], "planned_without_coordinator");
|
assert_eq!(enroll["status"], "planned_without_coordinator");
|
||||||
assert_eq!(enroll["scope"], "node:attach");
|
assert_eq!(enroll["private_website_required"], false);
|
||||||
|
assert_eq!(enroll["enrollment_grant"]["grant"], "grant");
|
||||||
|
assert_eq!(enroll["enrollment_grant"]["scope"], "node:attach");
|
||||||
|
assert_eq!(enroll["enrollment_grant"]["ttl_seconds"], 60);
|
||||||
|
assert_eq!(enroll["enrollment_grant"]["short_lived"], true);
|
||||||
|
assert_eq!(
|
||||||
|
enroll["enrollment_grant"]["exchange_for_persistent_node_identity"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
let cancel = process_cancel_report(ProcessCancelArgs {
|
let cancel = process_cancel_report(ProcessCancelArgs {
|
||||||
scope,
|
scope,
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,7 @@ for (const [name, pattern] of [
|
||||||
["CLI top-level logout alias coverage", /fn top_level_logout_alias_removes_only_cli_session_state\(\)/],
|
["CLI top-level logout alias coverage", /fn top_level_logout_alias_removes_only_cli_session_state\(\)/],
|
||||||
["CLI run rejection category coverage", /fn run_rejection_reports_machine_readable_error_category\(\)/],
|
["CLI run rejection category coverage", /fn run_rejection_reports_machine_readable_error_category\(\)/],
|
||||||
["node attach grant disclosure coverage", /fn node_attach_discloses_dangerous_capability_grants\(\)/],
|
["node attach grant disclosure coverage", /fn node_attach_discloses_dangerous_capability_grants\(\)/],
|
||||||
|
["node enroll public API grant coverage", /fn node_enroll_reports_short_lived_public_api_grant\(\)/],
|
||||||
["quota local status coverage", /fn quota_status_uses_project_config_and_generic_public_limits\(\)/],
|
["quota local status coverage", /fn quota_status_uses_project_config_and_generic_public_limits\(\)/],
|
||||||
["quota coordinator usage coverage", /fn quota_status_queries_public_coordinator_usage\(\)/],
|
["quota coordinator usage coverage", /fn quota_status_queries_public_coordinator_usage\(\)/],
|
||||||
["task event summary coverage", /fn process_task_log_and_artifact_reports_summarize_task_events\(\)/],
|
["task event summary coverage", /fn process_task_log_and_artifact_reports_summarize_task_events\(\)/],
|
||||||
|
|
@ -305,6 +306,11 @@ expect(
|
||||||
"CLI exposes node attach grant disclosures",
|
"CLI exposes node attach grant disclosures",
|
||||||
/struct CapabilityGrantDisclosure[\s\S]*coordinator_policy_limited[\s\S]*fn capability_grant_disclosures/
|
/struct CapabilityGrantDisclosure[\s\S]*coordinator_policy_limited[\s\S]*fn capability_grant_disclosures/
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI exposes normalized node enrollment grants",
|
||||||
|
/fn node_enroll_report[\s\S]*create_node_enrollment_grant[\s\S]*enrollment_grant[\s\S]*private_website_required[\s\S]*fn node_enrollment_grant_summary[\s\S]*short_lived[\s\S]*node_credentials_separate_from_user_session/
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
cli,
|
cli,
|
||||||
"CLI exposes task placement reasons",
|
"CLI exposes task placement reasons",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue