Total Pageviews

Sunday, 13 April 2025

OPKSSH开源:用单点登录重构SSH密钥的管理

 

Cloudflare宣布将OPKSSH(OpenPubkey SSH)代码库捐赠给Linux基金会旗下的OpenPubkey项目,推动这一创新方案全面开源。OPKSSH通过将OpenID Connect(OIDC)单点登录(SSO)技术与SSH协议深度结合,重构传统SSH密钥管理模式。

OPKSSH的核心机制

    从ID Token到PK Token
        传统OIDC流程中,身份提供商(如Google、Azure)颁发的ID Token仅包含用户身份信息(如邮箱),不含公钥。
        OpenPubkey协议在ID Token中嵌入用户公钥,生成PK Token,使其兼具身份认证与密钥绑定功能,无需修改现有OIDC协议。
    SSH协议的“无侵入”集成
        动态密钥生成:用户执行opkssh login后,工具自动生成短期有效的SSH密钥对(默认24小时失效),并将PK Token嵌入SSH公钥的证书扩展字段,通过标准SSH协议传输至服务器。
        服务端验证革新:SSH服务器通过AuthorizedKeysCommand调用OpenPubkey验证器,直接解析PK Token中的身份信息(如邮箱),替代传统静态公钥白名单。

OPKSSH结合身份提供商的MFA(多因素认证),实现SSH访问的细粒度控制,满足金融、医疗等行业合规要求。 PK Token中的身份信息(如邮箱、组织)为访问日志提供结构化数据,便于溯源异常行为。

官网消息来源:https://blog.cloudflare.com/open-sourcing-openpubkey-ssh-opkssh-integrating-single-sign-on-with-ssh/

源代码:https://github.com/openpubkey/opkssh

-----------------------------------------------------------

opkssh (OpenPubkey SSH)

eprint.iacr.org/2023/296 

 

opkssh (OpenPubkey SSH)

Go Coverage

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

Currently opkssh is compatible with Google, Microsoft/Azure and Gitlab OpenID Providers (OP). 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_ecdsas 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

Getting Started

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

Homebrew Install (OSX)

To install with homebrew run:

brew tap openpubkey/opkssh
brew install opkssh

Winget Install (Windows)

To install with winget run:

winget install openpubkey.opkssh

Manual Install (Windows, Linux, OSX)

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
🍎 OSX (x86_64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-osx-amd64
🍎 OSX (ARM64/aarch64) github.com/openpubkey/opkssh/releases/latest/download/opkssh-osx-arm64
⊞ Win github.com/openpubkey/opkssh/releases/latest/download/opkssh-windows-amd64.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 OSX 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_ecdsas 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 SSH public key opkssh wrote in ~/.ssh/id_ecdsas 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

Installing on a 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.

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

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 Possible Future Support
Linux Ubuntu 24.04.1 LTS -
OSX OSX 15.3.2 (Sequoia) -
Windows11 Windows 11 -

Server support

OS Supported Tested Version Tested Possible Future Support
Linux Ubuntu 24.04.1 LTS -
Linux Centos 9 -
Linux Arch Linux -
OSX - Likely
Windows11 - Likely

Configuration

All opkssh configuration files are space delimited and live on the server. We currently have no configuration files on the client.

/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:
    • 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.
  • 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

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 useful in the case of azure where the issuer contains a long and hard to remember random string. For instance:

sudo opkssh add dev bob@microsoft.com azure

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

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

~/.opk/auth_id

This is a local version of the auth_id file. It lives in the user's home directory (/home/{USER}/.opk/auth_id) and allows users to add or remove authorized identities without requiring root level permissions.

It can only be used for user/principal whose home directory it lives in. That is, if it is in /home/alice/.opk/auth_id it can only specify who can assume the principal alice on the server.

# email/sub principal issuer
alice alice@example.com https://accounts.google.com

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

It requires the following permissions:

chown {USER}:{USER} /home/{USER}/.opk/auth_id
chmod 600 /home/{USER}/.opk/auth_id

AuthorizedKeysCommandUser

We use a low privilege user for the SSH AuthorizedKeysCommandUser. Our install script creates this user and group automatically by running:

sudo groupadd --system opksshuser
sudo useradd -r -M -s /sbin/nologin -g opksshuser opksshuser

We then add the following lines to /etc/ssh/sshd_config

AuthorizedKeysCommand /usr/local/bin/opkssh verify %u %k %t
AuthorizedKeysCommandUser opksshuser

Custom OpenID Providers (Authentik, Authelia, Keycloak, Zitadel...)

To log in using a custom OpenID Provider, run:

opkssh login --provider={ISSUER},{CLIENT_ID}

or in the rare case that a client secret is required by the OpenID Provider:

opkssh login --provider={ISSUER},{CLIENT_ID},{CLIENT_SECRET}

where ISSUER, CLIENT_ID and CLIENT_SECRET correspond to the issuer client ID and client secret of the custom OpenID Provider.

For example if the issuer is https://authentik.local/application/o/opkssh/ and the client ID was ClientID123:

opkssh login --provider=https://authentik.local/application/o/opkssh/,ClientID123

Currently opkssh supports the following redirect URIs. Make sure to set them at your OpenID Provider:

http://localhost:3000/login-callback
http://localhost:10001/login-callback
http://localhost:11110/login-callback

Security Note: Create a new Client ID for opkssh

Do not reuse a client ID between opkssh and other OpenID Connect services. If the same client ID is used for opkssh as another OpenID Connect authentication service, then an SSH server could replay the ID Token sent in an opkssh SSH key to authenticate to that service. Such replay attacks can be ruled out by simply using a new client ID with opkssh.

Note that this requirement of using different client IDs for different audiences and uses is not unique to opkssh and is a best practice in OpenID Connect.

Server Configuration

In the /etc/opk/providers file, add the OpenID Provider as you would any OpenID Provider. For example:

https://authentik.local/application/o/opkssh/ ClientID123 24h

Then add identities to the policy to allow those identities SSH to the server:

opkssh add root alice@example.com https://authentik.local/application/o/opkssh/

Tested

OpenID Provider Tested Notes
Authelia Authelia Integration Guide
Authentik Do not add a certificate in the encryption section of the provider
Zitadel Check the UserInfo box on the Token Settings
PocketID Create a new OIDC Client and inside the new client, check "Public client" on OIDC Client Settings

Do not use Confidential/Secret mode only client ID is needed.

More information

We document how to manually install opkssh on a server here.

from  https://github.com/openpubkey/opkssh

 



No comments:

Post a Comment