Skip to content

feat(agent_secrets): add 1Password as optional secret store backend#5

Merged
muscariello merged 7 commits intomainfrom
4-add-1password-as-optional-secret-store-backend
Mar 10, 2026
Merged

feat(agent_secrets): add 1Password as optional secret store backend#5
muscariello merged 7 commits intomainfrom
4-add-1password-as-optional-secret-store-backend

Conversation

@muscariello
Copy link
Member

Summary

Add 1Password as an alternative SecretStore backend, selectable at runtime via SHADI_SECRET_BACKEND=onepassword env var.

Currently agent_secrets only supports the macOS Keychain (via security-framework) with a no-op fallback on other platforms. This adds cross-platform secret management with team/shared vault support via 1Password.

Approach

  • New OnePasswordStore implementing the existing SecretStore trait
  • Uses the op CLI (std::process::Command) -- same proven pattern as cargo-credential-1password in the Rust toolchain (no official 1Password Rust SDK exists)
  • Items stored as Secure Notes with base64-encoded content, tagged shadi
  • Supports both interactive auth (1Password desktop app) and headless/CI (OP_SERVICE_ACCOUNT_TOKEN)
  • Gated behind onepassword Cargo feature flag
  • Fully backward compatible -- no env var means existing OS keychain behavior

Changes

  • New: crates/agent_secrets/src/platform/onepassword.rs -- OnePasswordStore with put/get/delete/list_keys via op CLI
  • Modified: crates/agent_secrets/Cargo.toml -- added onepassword feature gating serde, serde_json, base64
  • Modified: crates/agent_secrets/src/platform/mod.rs -- runtime backend selection via SHADI_SECRET_BACKEND env var
  • Modified: crates/agent_secrets/src/lib.rs -- conditional re-export of OnePasswordStore
  • Modified: crates/shadictl/Cargo.toml -- enabled onepassword feature
  • Modified: crates/shadi_py/Cargo.toml -- enabled onepassword feature

Configuration

Env var Description Default
SHADI_SECRET_BACKEND Backend selection (onepassword or keychain) keychain
SHADI_OP_VAULT 1Password vault name shadi
SHADI_OP_ACCOUNT 1Password account (for multi-account) auto

Testing

  • 27 tests pass (8 new unit tests for JSON parsing, error classification, construction)
  • Full workspace builds clean
  • Verified end-to-end: shadictl --list-keychain and shadictl -- get-secret --key against a real 1Password vault

Closes #4

Add OnePasswordStore implementing the SecretStore trait via the op CLI,
following the same pattern used by cargo-credential-1password.

- New platform/onepassword.rs with put/get/delete/list_keys via op CLI
- Items stored as Secure Notes with base64 content, tagged 'shadi'
- Runtime backend selection via SHADI_SECRET_BACKEND=onepassword env var
- Configurable vault (SHADI_OP_VAULT) and account (SHADI_OP_ACCOUNT)
- Gated behind 'onepassword' Cargo feature flag
- Feature enabled in shadictl and shadi_py
- Unit tests for JSON parsing, error classification, and construction

Closes #4

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
@muscariello muscariello linked an issue Mar 5, 2026 that may be closed by this pull request
6 tasks
@codecov-commenter
Copy link

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

@muscariello muscariello requested a review from msardara March 6, 2026 15:31
}

fn make_cmd(&self, args: &[&str]) -> Command {
let mut cmd = Command::new("op");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could also allow overriding the op path with an env variable, like SHADI_OP_PATH

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's already the case.

- Fix macOS Seatbelt sandbox: add sysctl-read, unrestricted mach-lookup
  for op daemon, ~/.slim write access for SLIM bindings, and resolve
  relative policy paths to absolute before emitting subpath rules
- Set default llm_provider to anthropic in secops.toml and import script
- Update import script to read LLM_PROVIDER env var with anthropic default
- Update launch scripts to forward SHADI_SECRET_BACKEND, SHADI_OP_VAULT,
  SHADI_OP_ACCOUNT and use uv run --no-project --python
- Add just build auto-install of shadi .so to venv
- Add -op Justfile targets for 1Password-backed demo workflow
- Update docs: README, architecture, security, cli, demo, scripts/README

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
- scripts/launch_slim.sh: remove --endpoint flag (conflicts with slimctl)
- scripts/launch_secops_a2a.sh: add SLIM TLS cert defaults, PYTHONUNBUFFERED,
  and pre-read all 1Password secrets into SHADI_SECRET_* env vars before the
  sandbox starts (op CLI hangs without a TTY in background processes)
- scripts/launch_avatar.sh: same pre-read block for avatar LLM + SLIM secrets
- agents/secops/skills.py: require_shadi_secret() checks SHADI_SECRET_<KEY>
  env var fallback before calling op; avoids sandbox op hang
- agents/avatar/adk_agent/agent.py: same env var fallback in
  require_shadi_secret_value(); fix send_message() to collect artifacts from
  all terminal states using state.value for correct enum comparison
- agents/secops/a2a_server.py: startup print, executor debug print
- crates/shadi_sandbox/src/platform/macos.rs: allow ~/.cache write for gh CLI
- Justfile: codesign .so after build; demo-start depends on demo-stop;
  op vault list preflight in demo-start-op/demo-avatar-op
- policies/demo/*.json: add litellm.prod.outshift.ai and github.com to net_allow
- tools/test_avatar_transport.py: diagnostic transport test script

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
- sandbox/macos: normalize resolve_path('.') to avoid trailing dot in
  Seatbelt subpath rules (was silently denying writes to sandboxed CWD)

- secops/memory: fix SqlCipherMemoryStore called with key name instead of
  resolved key value; pass actual secret as key= arg not key_name=

- secops/a2a_server: normalize labels list to comma-separated string
  before passing to skill_collect_security_issues

- secops/telemetry: fix service.name empty when OTEL_SERVICE_NAME='';
  use 'or' fallback instead of getenv default; forward OTEL vars via Justfile

- tools/shadi_prompt.py: fix pre-existing syntax corruption (require_slima2a_packages
  body interleaved with load_secops_config and stray parser.add_argument calls;
  create_prompt_session missing if-not-ok body and return)

- tools/test_avatar_transport.py: configurable timeout via CLI arg

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
@muscariello muscariello force-pushed the 4-add-1password-as-optional-secret-store-backend branch from 773aec2 to b531c54 Compare March 10, 2026 13:34
@muscariello muscariello merged commit 3ae096d into main Mar 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add 1Password as optional secret store backend

3 participants