secure(api-tokens): one-time token file delivery and redact token_hash in CLI output

- Add --write-token-file option to admin tokens create
- Write token file with restrictive 0600 permissions; print only 'Token written to file: <PATH>'
- Preserve optional one-time stdout display when file not provided (labelled)
- Sanitize token metadata and token list by replacing token_hash with [REDACTED]
- Update CLI tests to use --write-token-file and assert file content & permissions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
thakaresandCopilot committed 2026-08-16 17:09:07 +05:30
1 parent 2ac6c81dfe
commit 3c43b56e09
2 files changed
+136 -19

No files matched your search

+24 -2
View File
@@ -95,7 +95,13 @@ fn test_cli_admin_init_and_management() {
assert!(ok);
assert!(out.contains("Administrator password updated successfully"));
// Test API token creation
// Test API token creation (write one-time token to a restricted file)
let token_file = runner
._temp_dir
.path()
.join("admin_token.txt")
.to_string_lossy()
.to_string();
let (ok, out, _) = runner.run(&[
"admin",
"tokens",
@@ -104,10 +110,26 @@ fn test_cli_admin_init_and_management() {
"ci-deployer",
"--days",
"30",
"--write-token-file",
&token_file,
]);
assert!(ok);
assert!(out.contains("API Token Created"));
assert!(out.contains("Secret Token"));
assert!(out.contains("Token written to file"));
// Verify token file exists and contains the token once
let token_contents = std::fs::read_to_string(&token_file).expect("read token file");
assert!(token_contents.starts_with("nx9_"));
// verify restrictive permissions on unix systems
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = std::fs::metadata(&token_file)
.expect("stat")
.permissions()
.mode()
& 0o777;
assert_eq!(mode, 0o600);
}
// List tokens
let (ok, out, _) = runner.run(&["admin", "tokens", "list", "--format", "json"]);