🔐 一个用于跨会话持久化 SSH agent 管理的现代 Python 库。
- 🔄 跨会话的持久化 SSH agent 管理
- 🔑 自动 SSH 密钥加载和缓存
- 🪟 针对 Windows 优化的实现
- 🔗 无缝 Git 集成
- 🌐 跨平台兼容性 (Windows, Linux, macOS)
- 📦 除标准 SSH 工具外无外部依赖
- 🔒 安全的密钥管理和会话控制
- ⚡ 异步操作支持
- 🧪 完整的单元测试覆盖
- 📝 类型提示支持
pip install persistent-ssh-agent
- Python 3.8+
- OpenSSH (ssh-agent, ssh-add) 已安装且在 PATH 中可用
- Git (可选,用于 Git 操作)
from persistent_ssh_agent import PersistentSSHAgent
# 创建实例,可自定义过期时间(默认24小时)
ssh_agent = PersistentSSHAgent(expiration_time=86400)
# 为特定主机设置 SSH
if ssh_agent.setup_ssh('github.com'):
print("✅ SSH 认证就绪!")
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 创建自定义 SSH 配置
config = SSHConfig(
identity_file='~/.ssh/github_key', # 可选的指定身份文件
identity_passphrase='your-passphrase', # 可选的密码短语
ssh_options={ # 可选的 SSH 选项
'StrictHostKeyChecking': 'yes',
'PasswordAuthentication': 'no',
'PubkeyAuthentication': 'yes'
}
)
# 使用自定义配置和 agent 复用设置初始化
ssh_agent = PersistentSSHAgent(
config=config,
expiration_time=86400, # 可选:设置 agent 过期时间(默认24小时)
reuse_agent=True # 可选:控制 agent 复用行为(默认为 True)
)
# 设置 SSH 认证
if ssh_agent.setup_ssh('github.com'):
# 获取该主机的 Git SSH 命令
ssh_command = ssh_agent.get_git_ssh_command('github.com')
if ssh_command:
print("✅ Git SSH 命令已就绪!")
reuse_agent
参数控制 SSH agent 如何处理现有会话:
-
当
reuse_agent=True
(默认值)时:- 尝试复用现有的 SSH agent(如果可用)
- 减少 agent 启动和密钥添加的次数
- 通过避免不必要的 agent 操作来提高性能
-
当
reuse_agent=False
时:- 总是启动新的 SSH agent 会话
- 当您需要全新的 agent 状态时很有用
- 在某些对安全性要求较高的环境中可能更受欢迎
禁用 agent 复用的示例:
# 总是启动新的 agent 会话
ssh_agent = PersistentSSHAgent(reuse_agent=False)
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
def setup_ci_ssh():
"""为 CI 环境设置 SSH。"""
# 创建带有密钥内容的配置
config = SSHConfig(
identity_content=os.environ.get('SSH_PRIVATE_KEY'),
ssh_options={'BatchMode': 'yes'}
)
ssh_agent = PersistentSSHAgent(config=config)
if ssh_agent.setup_ssh('github.com'):
print("✅ SSH agent 启动成功")
return True
raise RuntimeError("SSH agent 启动失败")
from git import Repo
from persistent_ssh_agent import PersistentSSHAgent
import os
def clone_repo(repo_url: str, local_path: str) -> Repo:
"""使用持久化 SSH 认证克隆仓库。"""
ssh_agent = PersistentSSHAgent()
# 提取主机名并设置 SSH
hostname = ssh_agent._extract_hostname(repo_url)
if not hostname or not ssh_agent.setup_ssh(hostname):
raise RuntimeError("SSH 认证设置失败")
# 获取 SSH 命令并配置环境
ssh_command = ssh_agent.get_git_ssh_command(hostname)
if not ssh_command:
raise RuntimeError("获取 SSH 命令失败")
# 使用 GitPython 克隆
env = os.environ.copy()
env['GIT_SSH_COMMAND'] = ssh_command
return Repo.clone_from(
repo_url,
local_path,
env=env
)
-
SSH 密钥管理:
- 自动检测和加载 SSH 密钥(Ed25519、ECDSA、RSA)
- 支持密钥内容注入(适用于 CI/CD)
- 安全的密钥文件权限处理
- 可选的密码短语支持
-
配置安全:
- 严格的主机名验证
- 安全的默认设置
- 支持安全相关的 SSH 选项
-
会话管理:
- 安全的代理信息存储
- 平台特定的安全措施
- 自动清理过期会话
- 跨平台兼容性
该库为所有公共接口提供全面的类型提示:
from typing import Optional
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
def setup_ssh(hostname: str, key_file: Optional[str] = None) -> bool:
config = SSHConfig(identity_file=key_file)
agent = PersistentSSHAgent(config=config)
return agent.setup_ssh(hostname)
import os
from persistent_ssh_agent import PersistentSSHAgent
def setup_ci_ssh():
"""为 CI 环境设置 SSH。"""
ssh_agent = PersistentSSHAgent()
# 从环境变量获取 SSH 密钥
key_path = os.environ.get('SSH_PRIVATE_KEY_PATH')
if not key_path:
raise ValueError("未提供 SSH 密钥路径")
if ssh_agent.start_ssh_agent(key_path):
print("✅ SSH agent 启动成功")
return True
raise RuntimeError("SSH agent 启动失败")
from git import Repo
from persistent_ssh_agent import PersistentSSHAgent
import os
def clone_repo(repo_url: str, local_path: str, branch: str = None) -> Repo:
"""使用持久化 SSH 认证克隆仓库。"""
ssh_agent = PersistentSSHAgent()
# 从 URL 提取主机名并设置 SSH
hostname = ssh_agent.extract_hostname(repo_url)
if not hostname or not ssh_agent.setup_ssh(hostname):
raise RuntimeError("SSH 认证设置失败")
# 获取 SSH 命令并配置环境
ssh_command = ssh_agent.get_git_ssh_command(hostname)
if not ssh_command:
raise RuntimeError("获取 SSH 命令失败")
# 使用 GitPython 克隆
env = os.environ.copy()
env['GIT_SSH_COMMAND'] = ssh_command
return Repo.clone_from(
repo_url,
local_path,
branch=branch,
env=env
)
# 使用示例
try:
repo = clone_repo(
'git@github.com:username/repo.git',
'/path/to/local/repo',
branch='main'
)
print("✅ 仓库克隆成功")
except Exception as e:
print(f"❌ 错误: {e}")
该库提供全面的 SSH 配置验证功能,支持:
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 创建带验证的自定义 SSH 配置
config = SSHConfig()
# 添加包含各种选项的主机配置
config.add_host_config('github.com', {
# 连接设置
'IdentityFile': '~/.ssh/github_key',
'User': 'git',
'Port': '22',
# 安全设置
'StrictHostKeyChecking': 'yes',
'PasswordAuthentication': 'no',
'PubkeyAuthentication': 'yes',
# 连接优化
'Compression': 'yes',
'ServerAliveInterval': '60',
'ServerAliveCountMax': '3',
# 代理和转发
'ForwardAgent': 'yes'
})
# 使用经过验证的配置初始化
ssh_agent = PersistentSSHAgent(config=config)
支持的配置类别:
- 连接设置:端口、主机名、用户、身份文件
- 安全设置:严格主机密钥检查、批处理模式、密码认证
- 连接优化:压缩、连接超时、服务器保活间隔
- 代理和转发:代理命令、代理转发、X11转发
- 环境设置:TTY请求、环境变量发送
- 多路复用选项:控制主机、控制路径、控制持久化
详细的验证规则和支持的选项,请参见 SSH 配置验证
配置多个主机的 SSH:
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 创建带有通用选项的配置
config = SSHConfig(
ssh_options={
'BatchMode': 'yes',
'StrictHostKeyChecking': 'yes',
'ServerAliveInterval': '60'
}
)
# 初始化代理
agent = PersistentSSHAgent(config=config)
# 为多个主机设置 SSH
hosts = ['github.com', 'gitlab.com', 'bitbucket.org']
for host in hosts:
if agent.setup_ssh(host):
print(f"✅ SSH 已为 {host} 配置完成")
else:
print(f"❌ {host} 的 SSH 配置失败")
设置全局 SSH 选项:
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 创建带有全局选项的配置
config = SSHConfig(
# 设置身份文件(可选)
identity_file='~/.ssh/id_ed25519',
# 设置全局 SSH 选项
ssh_options={
'StrictHostKeyChecking': 'yes',
'PasswordAuthentication': 'no',
'PubkeyAuthentication': 'yes',
'BatchMode': 'yes',
'ConnectTimeout': '30'
}
)
# 使用全局配置初始化代理
agent = PersistentSSHAgent(config=config)
该库基于您的 SSH 配置自动管理 SSH 密钥:
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 使用指定的密钥
config = SSHConfig(identity_file='~/.ssh/id_ed25519')
agent = PersistentSSHAgent(config=config)
# 或让库自动检测并使用可用的密钥
agent = PersistentSSHAgent()
if agent.setup_ssh('github.com'):
print("✅ SSH 密钥已加载并就绪!")
该库支持以下密钥类型(按优先级排序):
- Ed25519(推荐,最安全)
- ECDSA
- 带安全密钥的 ECDSA
- 带安全密钥的 Ed25519
- RSA
- DSA(传统,不推荐)
from persistent_ssh_agent import PersistentSSHAgent
from persistent_ssh_agent.config import SSHConfig
# 创建配置实例
config = SSHConfig()
# 添加全局配置
config.add_global_config({
'AddKeysToAgent': 'yes',
'UseKeychain': 'yes'
})
# 添加主机特定配置
config.add_host_config('*.git.luolix.top', {
'User': 'git',
'IdentityFile': '~/.ssh/github_ed25519',
'PreferredAuthentications': 'publickey'
})
# 使用配置初始化 agent
agent = PersistentSSHAgent(config=config)
欢迎贡献!请随时提交 Pull Request。
- Fork 仓库
- 创建您的功能分支 (
git checkout -b feature/amazing-feature
) - 提交您的更改 (
git commit -m '添加了一个惊人的功能'
) - 推送到分支 (
git push origin feature/amazing-feature
) - 打开一个 Pull Request
本项目使用 MIT 许可证 - 请参阅 LICENSE 文件以获取详细信息。