A thin shim that transparently injects opkssh into SSH workflows
Project description
opkssh-wrapper
A thin shim that transparently wires opkssh
into your normal ssh workflow. Alias it as ssh and forget it's there — the
wrapper silently ensures your ephemeral OpenPubKey identity is fresh before
every connection, then hands all arguments through to the real ssh unchanged.
How it works
When you run ssh user@host:
- The wrapper checks whether a valid, non-expired opkssh ephemeral key exists.
- If the key is missing or expired, it calls
opkssh login(opens a browser for OIDC authentication). - It prepends
-o IdentitiesOnly=yes -i <key_path>to your arguments. - It
execs the realsshbinary with your original arguments intact.
Your SSH experience is unchanged. Every flag, host pattern, and ~/.ssh/config
option continues to work exactly as before.
Usage
Use it exactly like ssh:
ssh user@host
ssh -p 2222 -A user@host
ssh -J bastion user@internal
git push origin main # works transparently via GIT_SSH / core.sshCommand
rsync -avz src/ user@host:dst/
If your key has expired and a terminal is available, you will be prompted to
authenticate. In non-interactive contexts (CI, rsync, git) the wrapper
exits with an error and tells you to run opkssh login first.
Installation
Prerequisites
- Python 3.10 or later
opksshinstalled and on$PATH
Install the package
pipx (recommended — keeps the tool isolated):
pipx install opkssh-wrapper
pip (system or virtual environment):
pip install opkssh-wrapper
Standalone binary (no Python required at runtime):
Pre-built binaries may be available on the
Releases page. Download, mark executable, and place on your
$PATH:
chmod +x opkssh-wrapper
mv opkssh-wrapper ~/.local/bin/
Set up the shell alias
The preferred way to use opkssh-wrapper is to alias ssh to it so that every
SSH invocation goes through the wrapper automatically.
Choose the section for your shell below. Add the shown snippet to your shell's
startup file, then open a new terminal (or source the file) to activate it.
bash
Add to ~/.bashrc:
alias ssh='opkssh-wrapper'
# Keep tab-completion working on the alias.
# bash-completion defines _ssh; redirect that spec to cover the alias name too.
if declare -F _ssh > /dev/null 2>&1; then
complete -F _ssh ssh
fi
Note: The
completeline above re-binds the_sshcompletion function to the alias. If bash-completion loads_sshlazily (common in many distributions), this line is a no-op on the first shell start but will take effect once_sshhas been loaded for the first time. To force it reliably, load the ssh completion before thecompletecall:alias ssh='opkssh-wrapper' # Eagerly load ssh completions, then apply to the alias _completion_loader ssh 2>/dev/null || true if declare -F _ssh > /dev/null 2>&1; then complete -F _ssh ssh fi
zsh
Add to ~/.zshrc:
alias ssh='opkssh-wrapper'
# Tell zsh to use ssh's completion spec for the alias.
# This must appear after compinit has run.
compdef opkssh-wrapper=ssh
If you use a framework such as Oh My Zsh or Prezto, place these lines
after the framework is sourced (e.g. after source $ZSH/oh-my-zsh.sh).
fish
Add to ~/.config/fish/config.fish:
alias ssh 'opkssh-wrapper'
Then create a completions file so that typing ssh <Tab> delegates to fish's
built-in SSH completions:
mkdir -p ~/.config/fish/completions
cat > ~/.config/fish/completions/opkssh-wrapper.fish <<'EOF'
# Reuse all SSH completions for opkssh-wrapper
complete -c opkssh-wrapper -w ssh
EOF
Because the fish alias command creates a shell function named ssh, fish
will automatically use existing ssh completions when you type ssh <Tab>.
The completions file above additionally provides completions when you invoke
opkssh-wrapper directly.
To persist the alias across sessions:
funcsave ssh
Optional: configuration file
Create ~/.config/opkssh-wrapper/config.toml to override defaults:
# Path to the opkssh binary (default: "opkssh", resolved via $PATH)
opkssh_path = "opkssh"
# Path to the real ssh binary (default: auto-detected, skipping the shim)
# ssh_path = "/usr/bin/ssh"
# Path to the ephemeral private key written by opkssh (default: ~/.ssh/id_ecdsa)
key_path = "~/.ssh/id_ecdsa"
# How many hours a freshly-issued key is considered valid (default: 24)
key_ttl_hours = 24
# Seconds to wait for the key file to appear on disk after login (default: 10)
key_wait_timeout = 10
# Seconds before opkssh login is forcibly killed (default: 120)
login_timeout = 120
# If true, attempt browser login even in non-interactive contexts (default: false)
aggressive_login = false
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opkssh_wrapper-0.1.0.tar.gz.
File metadata
- Download URL: opkssh_wrapper-0.1.0.tar.gz
- Upload date:
- Size: 29.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08455a5b0eed7cb2607a1f3b076f290342ddd345afa40cacfa82d372cb8fd386
|
|
| MD5 |
100531c19a9650b2741c5f2d8a21ca55
|
|
| BLAKE2b-256 |
c4ce1b4c1cfbe159d17404f200bbadd52ec4f8ae0d04eb9b642d5207280d0dec
|
Provenance
The following attestation bundles were made for opkssh_wrapper-0.1.0.tar.gz:
Publisher:
release.yml on rcmurphy/opkssh-wrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opkssh_wrapper-0.1.0.tar.gz -
Subject digest:
08455a5b0eed7cb2607a1f3b076f290342ddd345afa40cacfa82d372cb8fd386 - Sigstore transparency entry: 976431869
- Sigstore integration time:
-
Permalink:
rcmurphy/opkssh-wrapper@04ffb2528cb1389e1d2e69ac8bb6f43b64b1c6d6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rcmurphy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@04ffb2528cb1389e1d2e69ac8bb6f43b64b1c6d6 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file opkssh_wrapper-0.1.0-py3-none-any.whl.
File metadata
- Download URL: opkssh_wrapper-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
828b51f7d09c187ced629bf45dba3c8215478dc6f8cbb8967afd6677333d18d4
|
|
| MD5 |
28eed0268aae7bbc15b85b5e13c0d3ba
|
|
| BLAKE2b-256 |
0770508add591ba2379b1913a3348185d965b70dc093c15ad395762a576a4cfc
|
Provenance
The following attestation bundles were made for opkssh_wrapper-0.1.0-py3-none-any.whl:
Publisher:
release.yml on rcmurphy/opkssh-wrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opkssh_wrapper-0.1.0-py3-none-any.whl -
Subject digest:
828b51f7d09c187ced629bf45dba3c8215478dc6f8cbb8967afd6677333d18d4 - Sigstore transparency entry: 976431870
- Sigstore integration time:
-
Permalink:
rcmurphy/opkssh-wrapper@04ffb2528cb1389e1d2e69ac8bb6f43b64b1c6d6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/rcmurphy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@04ffb2528cb1389e1d2e69ac8bb6f43b64b1c6d6 -
Trigger Event:
workflow_dispatch
-
Statement type: