Skip to content

Repository files navigation

rune-keychain

A small, code-signed macOS command-line tool for reading and writing Keychain items through Security.framework.

Status: early prototype. The four core operations work. The code talks to Security.framework and Core Foundation directly right now, which is a deliberate spike. A safe wrapper over those APIs is the next step, and the interface may still change.

Why

macOS ships the security CLI, but an item it creates can't be read back by a script without a Touch ID or password prompt, because the script isn't in the item's access-control list. rune-keychain is a signed binary, so it can be added to an item's trusted-application ACL and then read that item without prompting. It exists to replace the security calls in my dotfiles secrets setup, where reading a secret currently means a Touch ID tap or a typed password every time. The aim is to keep secrets encrypted on disk and let a trusted, signed binary decrypt them on demand, with no prompt in the way.

This is plumbing. One invocation does one thing: get, set, delete, or check a single item.

Requirements

  • macOS
  • A code-signing identity (self-signed is fine for local use)
  • go-task for the build and sign workflow

Build

Every build re-signs, since the signature is tied to the binary's hash.

cp .env.example .env      # set SIGNING_IDENTITY
task build                # cargo build --release + codesign

Usage

Service and account name the item. The subcommand picks the operation.

# read a password to stdout
rune-keychain --service my-service --account my-account get

# store one (pipe it in so the secret stays out of shell history)
printf '%s' "$SECRET" | rune-keychain -s my-service -a my-account set --stdin

# check existence (exit code only)
rune-keychain -s my-service -a my-account exists

# remove it
rune-keychain -s my-service -a my-account delete

--sync targets the iCloud keychain and --keychain <path> targets a specific keychain file. On set, --trust <path> adds a binary to the item's trusted-application ACL, and --create-only fails if the item already exists.

Roadmap

Working today: get, set, delete, and exists, with trusted-app ACLs and iCloud sync on set.

It's early, so the list is long. The near-term direction:

  • A safe wrapper over the Core Foundation and Security.framework calls, so the rest of the code stops handling raw pointers. This is the main reason the project paused.
  • Access-control constraints on stored items via SecAccessControl: Touch ID, passcode, Apple Watch, and an application password for the cases a signed ACL can't cover.
  • More operations: list to enumerate a service's items, inspect to dump an item's metadata and trust list, and migrate to move an item between the local and iCloud keychains.
  • Editing the trusted-application ACL on an existing item (--trust-add / --trust-remove), instead of only setting it at creation.
  • Pulling the keychain layer into its own crate once the patterns settle, so other tools can build on it. The first is a Touch ID pinentry for GPG: pinentry-touchid has been dormant for years and the pinentry-mac it builds on was archived in 2021, so a maintained replacement is worth having.

License

MIT. See LICENSE.

About

Code-signed replacement for the macOS security CLI: Security.framework CRUD, ACL access without Touch ID prompts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages