flowrs-engine/crates/flowrs-cli/tests/secrets.rs
flowRS 2b6f30d348 flowRS engine, cut from flowRS f907e0756a7c
Built alone from an empty CARGO_HOME, its tests passed, and flowrsc checked, ran and exported a
document from the conformance corpus; the export built alone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 08:54:33 -05:00

101 lines
3.3 KiB
Rust

//! `flowrsc` resolves a graph's `secret:NAME` from FLOWRS_SECRET_NAME and the file
//! FLOWRS_SECRETS names, refuses a credential file others can read, and prints no
//! credential: the readings and the report show the marker where one was.
use std::path::{Path, PathBuf};
use std::process::Command;
fn canary() -> String {
format!("{}-{}-{}", "flowrs", "canary", "cli-1b7e3d")
}
fn scratch(name: &str) -> PathBuf {
let d = std::env::temp_dir().join(format!("flowrsc-secrets-{}-{name}", std::process::id()));
std::fs::create_dir_all(&d).unwrap();
d
}
/// A Particle call holding `token`, its `auth` checked by `flowrsc test`.
fn graph(dir: &Path, token: &str) -> (PathBuf, PathBuf) {
let mut g = flowrs_core::Graph::new();
let n = g.add_node("cloud.particle.function", 0.0, 0.0);
g.nodes
.get_mut(&n)
.unwrap()
.properties
.insert("token".into(), token.into());
let doc = dir.join("g.flowrs");
std::fs::write(&doc, flowrs_core::graph::document::save(&g)).unwrap();
let expect = dir.join("expect.json");
std::fs::write(
&expect,
format!(
"{{\"{}.auth\": {:?}, \"{}.url\": \"https://api.particle.io/v1/devices/my_device/led\"}}",
n.0,
flowrs_core::graph::secret::MARKER,
n.0
),
)
.unwrap();
(doc, expect)
}
fn flowrsc(args: &[&Path], env: &[(&str, &str)]) -> (i32, String) {
let mut c = Command::new(env!("CARGO_BIN_EXE_flowrsc"));
c.arg("test").arg(args[0]).arg("--expect").arg(args[1]);
c.env_remove("FLOWRS_SECRETS");
for (k, v) in env {
c.env(k, v);
}
let out = c.output().unwrap();
(
out.status.code().unwrap_or(-1),
format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
),
)
}
#[test]
fn flowrsc_resolves_a_reference_and_prints_no_credential() {
let dir = scratch("env");
let (doc, expect) = graph(&dir, "secret:PARTICLE");
let value = canary();
let (code, text) = flowrsc(&[&doc, &expect], &[("FLOWRS_SECRET_PARTICLE", &value)]);
assert_eq!(code, 0, "{text}");
assert!(
!flowrs_core::graph::secret::holds(&text, &[value]),
"{text}"
);
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn a_credential_file_others_can_read_is_refused() {
let dir = scratch("file");
let (doc, expect) = graph(&dir, "secret:PARTICLE");
let file = dir.join("secrets");
std::fs::write(&file, format!("PARTICLE={}\n", canary())).unwrap();
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&file, std::fs::Permissions::from_mode(0o644)).unwrap();
let (code, text) = flowrsc(
&[&doc, &expect],
&[("FLOWRS_SECRETS", file.to_str().unwrap())],
);
assert_ne!(code, 0, "{text}");
assert!(text.contains("chmod 600"), "{text}");
assert!(!text.contains(&canary()), "{text}");
std::fs::set_permissions(&file, std::fs::Permissions::from_mode(0o600)).unwrap();
}
let (code, text) = flowrsc(
&[&doc, &expect],
&[("FLOWRS_SECRETS", file.to_str().unwrap())],
);
assert_eq!(code, 0, "{text}");
assert!(!text.contains(&canary()), "{text}");
let _ = std::fs::remove_dir_all(&dir);
}