MCPcopy
hub / github.com/openpubkey/opkssh

github.com/openpubkey/opkssh @v0.15.0 sqlite

repository ↗ · DeepWiki ↗ · release v0.15.0 ↗
566 symbols 2,148 edges 105 files 229 documented · 40%
README

opkssh (OpenPubkey SSH)

Go Coverage

opkssh is a tool which enables ssh to be used with OpenID Connect allowing SSH access to be managed via identities like alice@example.com instead of long-lived SSH keys. It does not replace SSH, but instead generates SSH public keys containing PK Tokens and configures sshd to verify them. These PK Tokens contain standard OpenID Connect ID Tokens. This protocol builds on OpenPubkey which adds user public keys to OpenID Connect without breaking compatibility with existing OpenID Providers.

Currently opkssh is compatible with Google, Microsoft/Azure, GitLab, hello.dev, Authelia, Authentik, Keycloak, Zitadel, PocketID, AWS Cognito, and Kanidm OpenID Providers (OP). See below for the entire list. If you have a Gmail, Microsoft, or a GitLab account you can ssh with that account.

To ssh with opkssh you first need to download the opkssh binary and then run:

opkssh login

This opens a browser window where you can authenticate to your OpenID Provider. This will generate an SSH key in ~/.ssh/id_ecdsa which contains your OpenID Connect identity. Then you can ssh under this identity to any ssh server which is configured to use opkssh to authenticate users using their OpenID Connect identities.

ssh user@example.com

OpenPubkey Mailing List

For updates and announcements join the OpenPubkey mailing list.

Getting Started

To ssh with opkssh, Alice first needs to install opkssh using homebrew or manually downloading the binary.

Homebrew Install (macOS)

To install with homebrew run:

brew tap openpubkey/opkssh
brew install opkssh

Winget Install (Windows)

To install with winget run:

winget install openpubkey.opkssh

Chocolatey Install (Windows)

To install with Chocolatey run:

choco install opkssh -y

Nix Install

Use the opkssh nixpkg as normal, or test it via:

nix-shell -p opkssh

Manual Install (Windows, Linux, macOS)

To install manually, download the opkssh binary and run it:

Download URL
🐧 Linux (x86_64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-linux-amd64
🐧 Linux (ARM64/aarch64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-linux-arm64
🍎 macOS (x86_64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-osx-amd64
🍎 macOS (ARM64/aarch64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-osx-arm64
⊞ Win (x86_64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-windows-amd64.exe
⊞ Win (ARM64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-windows-arm64.exe

To install on Windows run:

curl https://github.com/openpubkey/opkssh/releases/latest/download/opkssh-windows-amd64.exe -o opkssh.exe

To install on macOS run:

curl -L https://github.com/openpubkey/opkssh/releases/latest/download/opkssh-osx-amd64 -o opkssh; chmod +x opkssh

To install on linux, run:

curl -L https://github.com/openpubkey/opkssh/releases/latest/download/opkssh-linux-amd64 -o opkssh; chmod +x opkssh

or for ARM

curl -L https://github.com/openpubkey/opkssh/releases/latest/download/opkssh-linux-arm64 -o opkssh; chmod +x opkssh

SSHing with opkssh

After downloading opkssh run:

opkssh login

This opens a browser window to select which OpenID Provider you want to authenticate against. After successfully authenticating opkssh generates an SSH public key in ~/.ssh/id_ecdsa which contains your PK Token. By default this ssh key expires after 24 hours and you must run opkssh login to generate a new ssh key.

Since your PK Token has been saved as an SSH key you can SSH as normal:

ssh root@example.com

This works because SSH sends the public key written by opkssh in ~/.ssh/id_ecdsa to the server and sshd running on the server will send the public key to the opkssh command to verify. This also works for other protocols that build on ssh like sftp or ssh tunnels.

sftp root@example.com

Logging out

To remove opkssh-generated SSH keys and certificates:

opkssh logout

This removes the SSH key pair that was generated by opkssh login. To remove a specific key:

opkssh logout -i ~/.ssh/opkssh_server_group1

Custom key name

Instructions

SSH command

Tell opkssh to store the name the key-pair opkssh_server_group1

opkssh login -i opkssh_server_group1

Tell ssh to use the generated key pair.

ssh -o "IdentitiesOnly=yes" -i ~/.ssh/opkssh_server_group1 root@example.com

We recommend specifying -o "IdentitiesOnly=yes" as it tells ssh to only use the provided key. Otherwise ssh will cycle through other keys in ~/.ssh first and may not get to the specified ones. Servers are configured to only allow 6 attempts by default the config key is MaxAuthTries 6.

Installing on a Linux Server

To configure a Linux server to use opkssh simply run (with root level privileges):

wget -qO- "https://raw.githubusercontent.com/openpubkey/opkssh/main/scripts/install-linux.sh" | sudo bash

This downloads the opkssh binary, installs it as /usr/local/bin/opkssh, and then configures ssh to use opkssh as an additional authentication mechanism.

Installing on a Windows Server

To configure a Windows server to use opkssh, download and run the installer script in an elevated PowerShell terminal:

Invoke-WebRequest -Uri "https://github.com/openpubkey/opkssh/releases/latest/download/Install-OpksshServer.ps1" -OutFile Install-OpksshServer.ps1
.\Install-OpksshServer.ps1

This downloads the opkssh binary, configures sshd_config for AuthorizedKeysCommand, sets up the correct NTFS ACLs on all configuration files, and restarts sshd.

To uninstall:

Invoke-WebRequest -Uri "https://github.com/openpubkey/opkssh/releases/latest/download/Uninstall-OpksshServer.ps1" -OutFile Uninstall-OpksshServer.ps1
.\Uninstall-OpksshServer.ps1

To validate the installation:

Invoke-WebRequest -Uri "https://github.com/openpubkey/opkssh/releases/latest/download/Test-OpksshInstallation.ps1" -OutFile Test-OpksshInstallation.ps1
.\Test-OpksshInstallation.ps1

On Windows, the configuration files are located at %ProgramData%\opk\ (typically C:\ProgramData\opk\).

To allow a user, alice@gmail.com, to ssh to your server as root, run:

sudo opkssh add root alice@gmail.com google

To allow a group, ssh-users, to ssh to your server as root, run:

sudo opkssh add root oidc:groups:ssh-users google

We can also enforce policy on custom claims. For instance to require that root access is only granted to users whose ID Token has a claim https://acme.com/groups with the value ssh-users run:

sudo opkssh add root oidc:\"https://acme.com/groups\":ssh-users google

which will add that line to your OPKSSH policy file.

How it works

We use two features of SSH to make this work. First we leverage the fact that SSH public keys can be SSH certificates and SSH Certificates support arbitrary extensions. This allows us to smuggle your PK Token, which includes your ID Token, into the SSH authentication protocol via an extension field of the SSH certificate. Second, we use the AuthorizedKeysCommand configuration option in sshd_config (see sshd_config manpage) so that the SSH server will send the SSH certificate to an installed program that knows how to verify PK Tokens.

What is supported

Client support

OS Supported Tested Version Tested
Linux Ubuntu 24.04.1 LTS
macOS macOS 15.3.2 (Sequoia)
Windows 11 Windows 11

Server support

OS Supported Tested Version Tested Possible Future Support
Linux Ubuntu 24.04.1 LTS -
Linux Centos 9 -
Linux Arch Linux -
Linux openSUSE Leap 16 -
macOS - Likely
Windows Server Windows Server 2022 -
Windows Server Windows Server 2025 -
Windows 11 Windows 11 ARM64 -

Server Configuration

All opkssh configuration files are space delimited and live on the server. On Linux, configuration files are stored under /etc/opk/. On Windows, they are stored under %ProgramData%\opk\ (typically C:\ProgramData\opk\). Below we discuss our basic policy system, to read how to configure complex policies rules see our documentation on our policy plugin system. Using the policy plugin system you can enforce any policy rule that can be computed on a Turing Machine.

/etc/opk/providers

/etc/opk/providers contains a list of allowed OPs (OpenID Providers), a.k.a. IDPs. This file functions as an access control list that enables admins to determine the OpenID Providers and Client IDs they wish to rely on.

  • Column 1: Issuer URI of the OP
  • Column 2: Client-ID, the audience claim in the ID Token
  • Column 3: Expiration policy, options are:
  • 12h - user's ssh public key expires after 12 hours,
  • 24h - user's ssh public key expires after 24 hours,
  • 48h - user's ssh public key expires after 48 hours,
  • 1week - user's ssh public key expires after 1 week,
  • oidc - user's ssh public key expires when the ID Token expires
  • oidc-refreshed - user's ssh public key expires when their refreshed ID Token expires.

By default we use 24h as it requires that the user authenticate to their OP once a day. Most OPs expire ID Tokens every one to two hours, so if oidc the user will have to sign multiple times a day. oidc-refreshed is supported but complex and not currently recommended unless you know what you are doing.

The default values for /etc/opk/providers are:

# Issuer Client-ID expiration-policy
https://accounts.google.com 206584157355-7cbe4s640tvm7naoludob4ut1emii7sf.apps.googleusercontent.com 24h
https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0 096ce0a3-5e72-4da8-9c86-12924b294a01 24h

/etc/opk/providers requires the following permissions (by default we create all configuration files with the correct permissions):

sudo chown root:opksshuser /etc/opk/providers
sudo chmod 640 /etc/opk/providers

/etc/opk/auth_id

/etc/opk/auth_id is the global authorized identities file. This is a server wide file where policies can be configured to determine which identities can assume what linux user accounts. Linux user accounts are typically referred to in SSH as principals and we continue the use of this terminology.

  • Column 1: The principal, i.e., the account the user wants to assume
  • Column 2: Email address or subject ID of the user (choose one)
  • Email - the email of the identity
  • Subject ID - an unique ID for the user set by the OP. This is the sub claim in the ID Token.
  • Group - the name of the group that the user is part of. This uses the groups claim which is presumed to be an array. The group identifier uses a structured identifier. I.e. oidc:groups:{groupId}. Replace the groupId with the id of your group. If your group contains a colon, escape it oidc:"https://acme.com/groups":{groupId}.
  • Column 3: Issuer URI
# email/sub principal issuer
alice alice@example.com https://accounts.google.com
guest alice@example.com https://accounts.google.com
root alice@example.com https://accounts.google.com
dev bob@microsoft.com https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0

# Group identifier
dev oidc:groups:developer https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0
dev oidc:"https://acme.com/groups":developer https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0

To add new rule run:

sudo opkssh add <user> <email/sub/group> <issuer>

These auth_id files can be edited by hand or you can use the add command to add new policies. For convenience you can use the shorthand google or azure rather than specifying the entire issuer. This is especially use

Extension points exported contracts — how you extend this code

ACLVerifier (Interface)
ACLVerifier verifies ACLs and ownership for a given path against expectations. Implementations are platform-specific (Un [4 …
policy/files/acl.go
UserLookup (Interface)
UserLookup defines the minimal interface to lookup users on the current system [2 implementers]
policy/policyloader.go
ProviderLoader (Interface)
ProviderLoader defines the interface for loading provider policies [2 implementers]
policy/providerloader.go
Source (Interface)
Source declares the minimal interface to describe the source of a fetched opkssh policy (i.e. where the policy is retrie [2 …
policy/policy.go
PolicyEnforcerFunc (FuncType)
PolicyEnforcerFunc returns nil if the supplied PK token is permitted to login as username. Otherwise, an error is return
commands/verify.go
CmdExecutor (FuncType)
(no doc)
policy/plugins/plugins.go
FilePermsOps (Interface)
FilePermsOps provides an abstraction for creating files/directories and setting permissions in a platform-aware way. [3 …
policy/files/fileperms_ops.go
OptionalLoader (FuncType)
(no doc)
policy/policyloader.go

Core symbols most depended-on inside this repo

Run
called by 66
commands/add.go
WriteFile
called by 62
policy/files/filesystem.go
Stat
called by 43
policy/files/filesystem.go
String
called by 41
commands/login.go
printf
called by 36
commands/inspect.go
ReadFile
called by 32
policy/files/filesystem.go
MkdirAll
called by 31
policy/files/filesystem.go
AddRow
called by 20
policy/providerloader.go

Shape

Function 275
Method 200
Struct 73
Interface 7
TypeAlias 7
FuncType 4

Languages

Go100%

Modules by API surface

policy/files/filesystem.go29 symbols
policy/enforcer_test.go24 symbols
commands/login.go24 symbols
test/integration/ssh_test.go23 symbols
policy/policyloader.go17 symbols
policy/files/fileperms_ops.go17 symbols
policy/policyloader_test.go16 symbols
policy/providerloader.go15 symbols
policy/plugins/plugins.go14 symbols
commands/permissions_mocks_test.go14 symbols
policy/files/fileperms_ops_windows_acl.go13 symbols
commands/logout.go13 symbols

Dependencies from manifests, versioned

dario.cat/mergov1.0.1 · 1×
filippo.io/bigmodv0.1.0 · 1×
github.com/Azure/go-ansitermv0.0.0-2021061722524 · 1×
github.com/Microsoft/go-winiov0.6.2 · 1×
github.com/awnumar/memcallv0.1.2 · 1×
github.com/awnumar/memguardv0.22.3 · 1×
github.com/bits-and-blooms/bitsetv1.24.1 · 1×
github.com/bmatcuk/doublestar/v4v4.9.0 · 1×
github.com/containerd/errdefsv1.0.0 · 1×
github.com/containerd/errdefs/pkgv0.3.0 · 1×
github.com/containerd/logv0.1.0 · 1×

For agents

$ claude mcp add opkssh \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact