Files
bot-bottle/tests/unit/test_pipelock_yaml.sh
T

91 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Unit: pipelock_write_yaml — produces a YAML config containing the
# expected top-level keys and per-bottle entries. We don't fully parse
# YAML (no yq dependency); we grep for content shape.
TEST_NAME="pipelock_yaml"
. "$(dirname "$0")/../lib/common.sh"
# shellcheck source=../../lib/log.sh
. "${REPO_ROOT}/lib/log.sh"
# shellcheck source=../../lib/pipelock.sh
. "${REPO_ROOT}/lib/pipelock.sh"
out_dir="$(mktemp -d)"
cleanup() { rm -rf "$out_dir"; }
trap cleanup EXIT
# --- minimal bottle (no egress, no ssh): only api_allowlist defaults ---
m_min="$(write_fixture fixture_minimal)"
yaml_min="${out_dir}/min.yaml"
pipelock_write_yaml "$m_min" dev "$yaml_min"
content="$(cat "$yaml_min")"
assert_contains "$content" "mode: strict" "min: mode strict"
assert_contains "$content" "enforce: true" "min: enforce true"
assert_contains "$content" "api_allowlist:" "min: api_allowlist block"
assert_contains "$content" "api.anthropic.com" "min: anthropic baked default"
assert_contains "$content" "raw.githubusercontent.com" "min: github raw baked default"
assert_contains "$content" "forward_proxy:" "min: forward_proxy block"
assert_contains "$content" "enabled: true" "min: forward_proxy enabled"
assert_contains "$content" "dlp:" "min: dlp block"
assert_contains "$content" "include_defaults: true" "min: dlp include_defaults"
assert_contains "$content" "scan_env: true" "min: dlp scan_env"
# No ssh entries in the manifest, so neither ssrf nor trusted_domains
# blocks should be emitted.
assert_not_contains "$content" "trusted_domains:" "min: no trusted_domains"
assert_not_contains "$content" "ssrf:" "min: no ssrf block"
rm -f "$m_min"
# --- ssh bottle: trusted_domains for hostname, ssrf.ip_allowlist for ipv4 ---
m_ssh="$(write_fixture fixture_with_ssh)"
yaml_ssh="${out_dir}/ssh.yaml"
pipelock_write_yaml "$m_ssh" dev "$yaml_ssh"
content="$(cat "$yaml_ssh")"
assert_contains "$content" "trusted_domains:" "ssh: trusted_domains block emitted"
assert_contains "$content" "github.com" "ssh: hostname in trusted_domains (or allowlist)"
assert_contains "$content" "ssrf:" "ssh: ssrf block emitted"
assert_contains "$content" "ip_allowlist:" "ssh: ip_allowlist key under ssrf"
assert_contains "$content" "100.78.141.42/32" "ssh: ipv4 host emitted as /32"
# Belt-and-suspenders: the ipv4 host should also be in api_allowlist
# (strict mode requires both).
assert_contains "$content" "100.78.141.42" "ssh: ipv4 host in api_allowlist too"
rm -f "$m_ssh"
# --- secret hygiene: env values from the manifest never enter the YAML ---
m_secret="$(mktemp)"
cat > "$m_secret" <<'JSON'
{
"bottles": {
"dev": {
"env": {
"MY_SECRET": "literal-value-should-not-appear",
"ANOTHER": "?prompt-message"
},
"egress": { "allowlist": ["github.com"] }
}
},
"agents": { "demo": { "skills": [], "prompt": "", "bottle": "dev" } }
}
JSON
yaml_sec="${out_dir}/secret.yaml"
pipelock_write_yaml "$m_secret" dev "$yaml_sec"
content="$(cat "$yaml_sec")"
assert_not_contains "$content" "literal-value-should-not-appear" "secret: literal env value not leaked"
assert_not_contains "$content" "MY_SECRET" "secret: env var name not leaked"
assert_not_contains "$content" "prompt-message" "secret: prompt sentinel not leaked"
rm -f "$m_secret"
# --- file mode is 600 ---
mode="$(stat -f '%p' "$yaml_min" 2>/dev/null || stat -c '%a' "$yaml_min")"
# macOS stat -f '%p' returns full mode like 100600; trim. Linux stat -c '%a' gives just 600.
mode="${mode: -3}"
assert_eq "600" "$mode" "yaml file mode is 600"
test_summary