TL;DR: prmana is a PAM module and agent that replaces static SSH keys with short-lived OIDC tokens, bound to proof-of-possession via DPoP (RFC 9449). Rust, Apache-2.0. No proxy, no SSH CA — just your IdP and your Linux hosts.
Static SSH keys are the problem
Every org with more than a handful of Linux servers has the same issue: SSH keys everywhere, rotated never.
That key a developer generated in 2021? Still works on production. The contractor who left six months ago? Their authorized_keys entry is probably still on a dozen servers. Your security team mandates MFA for email, but root access to your database server? Static key on a laptop.
The usual solutions:
- Access platforms — proxy or gateway in front of everything
- SSH certificate authorities — new CA infrastructure to operate
- PAM/OIDC modules — SSO but still bearer tokens (interceptable)
Each solves part of the problem. Each adds operational complexity.
prmana: direct-to-host OIDC with DPoP
prmana brings OIDC authentication directly to the Linux host via PAM, and binds every token to a cryptographic proof that it hasn't been stolen.
Your Machine Linux Server
┌─────────────────┐ ┌──────────────────┐
│ prmana-agent │ SSH │ pam_prmana.so │
│ (OIDC + DPoP) │ ──────────────▶ │ (validate + bind)│
└─────────────────┘ └──────────────────┘
│ │
▼ ▼
Your IdP JWKS verification
(Keycloak/Okta/ + DPoP proof check
Azure AD/Auth0) + replay protection
- The agent gets a short-lived token from your identity provider
- It generates a DPoP proof — a signed JWT proving you hold the private key
- On SSH, the server's PAM module validates the token, checks expiry, verifies DPoP binding
- If it all checks out and the username maps to a local account, you're in
No gateway. No SSH CA. No static keys.
Why DPoP matters
Most OIDC-for-SSH approaches use bearer tokens. If someone intercepts the token — from a log, a compromised proxy, a memory dump — they can replay it from anywhere.
DPoP (RFC 9449) changes that. Every authentication includes a proof signed by an ephemeral key pair. The token carries a thumbprint of the public key. The server verifies the proof matches. Token leaks? Useless without the key.
{
"sub": "alice",
"iss": "https://idp.company.com",
"cnf": {
"jkt": "NKnABZgU1F7M5JW5uFrETiYx..."
}
}
That cnf.jkt field binds the token to a specific key pair. No key, no access.
The name "prmana" comes from Sanskrit (प्रमाण) — "proof" and "means of knowledge." Felt appropriate for a tool whose whole point is cryptographic proof of possession.
Hardware key support
DPoP proofs are signed by a key pair. By default that's a software key. prmana also supports:
- YubiKey — PKCS#11 via PIV slot
- TPM 2.0 — platform TPM on Linux
When the DPoP key lives on hardware, the private key can't be exported. Compromised laptop? They have the token but can't sign a valid proof.
prmana-agent login --signer yubikey:9a
# touch the key when it blinks, then SSH normally
ssh server.example.com
What's in the repo
Three Rust crates:
| Crate | Purpose |
|---|---|
prmana-core |
OIDC discovery, JWKS caching |
pam-prmana |
PAM module — validation, DPoP verification, replay protection, break-glass |
prmana-agent |
Client — token acquisition (device flow, auth code + PKCE), DPoP signing, credential storage |
Plus cross-language DPoP libraries in Go, Python, Java, and Rust.
The PAM module plugs into OpenSSH's existing stack. No patches to sshd. Standard ssh on the client, standard sshd on the server.
What it's not
prmana does SSH login. It's not a session recorder, not a proxy, not a privileged access management suite. One job, done well.
Getting started
git clone https://github.com/prodnull/prmana.git
cd prmana && cargo build --workspace
# Install PAM module
sudo cp target/release/libpam_prmana.so /lib/security/pam_prmana.so
# Point to your IdP
sudo mkdir -p /etc/prmana
cat << 'EOF' | sudo tee /etc/prmana/policy.yaml
issuers:
- url: https://your-idp.com/realms/your-realm
client_id: prmana
audiences: ["prmana"]
break_glass:
enabled: true
users: ["emergency-admin"]
EOF
# Login and SSH
prmana-agent login --issuer https://your-idp.com/realms/your-realm
ssh user@server
Docs cover setup for Keycloak, Entra ID, and Auth0.
Feedback welcome
github.com/prodnull/prmana — Apache-2.0.
What we'd find most useful:
- Security review — it's a PAM module. Poke holes.
- IdP testing — tested against Keycloak, Auth0, Google, Entra ID. If yours does something unexpected with DPoP or device flow, we want to know.
- Platform testing — Ubuntu 22.04/24.04 primary. RHEL, Rocky, Debian reports welcome.
GitHub Discussions for questions and ideas.
Top comments (0)