A Python library for persistent SSH agent management with automatic key handling, focusing on Windows compatibility and seamless Git integration.
Project description
persistent-ssh-agent
🔐 A modern Python library for persistent SSH agent management across sessions.Key Features • Installation • Documentation • Examples • Contributing
✨ Key Features
- 🔄 Persistent SSH agent management across sessions
- 🔑 Automatic SSH key loading and caching
- 🪟 Windows-optimized implementation
- 🔗 Seamless Git integration
- 🌐 Cross-platform compatibility (Windows, Linux, macOS)
- 📦 No external dependencies beyond standard SSH tools
🚀 Installation
pip install persistent-ssh-agent
📋 Requirements
- Python 3.x
- OpenSSH (ssh-agent, ssh-add) installed and available in PATH
- Git (optional, for Git operations)
📖 Usage
Basic Usage
from persistent_ssh_agent import PersistentSSHAgent
# Create an instance
ssh_agent = PersistentSSHAgent()
# Set up SSH for a specific host
if ssh_agent.setup_ssh('github.com'):
print("✅ SSH authentication ready!")
GitPython Integration
from git import Repo
from persistent_ssh_agent import PersistentSSHAgent
import os
def clone_with_gitpython(repo_url: str, local_path: str, branch: str = None) -> Repo:
"""Clone a repository using GitPython with persistent SSH authentication."""
ssh_agent = PersistentSSHAgent()
# Extract hostname and set up SSH
hostname = ssh_agent._extract_hostname(repo_url)
if not hostname or not ssh_agent.setup_ssh(hostname):
raise RuntimeError("Failed to set up SSH authentication")
# Get SSH command and configure environment
ssh_command = ssh_agent.get_git_ssh_command(hostname)
if not ssh_command:
raise RuntimeError("Failed to get SSH command")
# Set up Git environment
env = os.environ.copy()
env['GIT_SSH_COMMAND'] = ssh_command
# Clone with GitPython
return Repo.clone_from(
repo_url,
local_path,
branch=branch,
env=env
)
# Example usage
try:
repo = clone_with_gitpython(
'git@github.com:username/repo.git',
'/path/to/local/repo',
branch='main'
)
print(f"✅ Repository cloned: {repo.working_dir}")
# Perform Git operations
repo.remotes.origin.pull()
repo.remotes.origin.push()
except Exception as e:
print(f"❌ Error: {e}")
Advanced GitPython Operations
def setup_git_operations():
"""Set up environment for Git operations."""
ssh_agent = PersistentSSHAgent()
hostname = "github.com"
if not ssh_agent.setup_ssh(hostname):
raise RuntimeError("SSH setup failed")
ssh_command = ssh_agent.get_git_ssh_command(hostname)
if not ssh_command:
raise RuntimeError("Failed to get SSH command")
os.environ['GIT_SSH_COMMAND'] = ssh_command
return True
# Example: Complex Git operations
def manage_git_workflow(repo_path: str):
if not setup_git_operations():
return False
repo = Repo(repo_path)
# Create and checkout new branch
new_branch = repo.create_head('feature/new-feature')
new_branch.checkout()
# Make changes
with open(os.path.join(repo_path, 'new_file.txt'), 'w') as f:
f.write('New content')
# Stage and commit
repo.index.add(['new_file.txt'])
repo.index.commit('Add new file')
# Push to remote
repo.remotes.origin.push(new_branch)
🔧 Common Use Cases
CI/CD Pipelines
import os
from persistent_ssh_agent import PersistentSSHAgent
def setup_ci_ssh():
"""Set up SSH for CI environment."""
ssh_agent = PersistentSSHAgent()
# Set up SSH key from environment
key_path = os.environ.get('SSH_PRIVATE_KEY_PATH')
if not key_path:
raise ValueError("SSH key path not provided")
if ssh_agent._start_ssh_agent(key_path):
print("✅ SSH agent started successfully")
return True
raise RuntimeError("Failed to start SSH agent")
Multi-Host Management
async def setup_multiple_hosts(hosts: list[str]) -> dict[str, bool]:
"""Set up SSH for multiple hosts concurrently."""
ssh_agent = PersistentSSHAgent()
results = {}
for host in hosts:
results[host] = ssh_agent.setup_ssh(host)
return results
# Usage
hosts = ['github.com', 'gitlab.com', 'bitbucket.org']
status = await setup_multiple_hosts(hosts)
💡 Best Practices
Key Management
- 🔑 Store SSH keys in standard locations (
~/.ssh/) - 🔒 Use Ed25519 keys for better security
- 📝 Maintain organized SSH config files
Error Handling
from typing import Optional
from pathlib import Path
def safe_git_operation(repo_url: str, local_path: Path) -> Optional[Repo]:
"""Safely perform Git operations with proper error handling."""
ssh_agent = PersistentSSHAgent()
try:
hostname = ssh_agent._extract_hostname(repo_url)
if not hostname:
raise ValueError("Invalid repository URL")
if not ssh_agent.setup_ssh(hostname):
raise RuntimeError("SSH setup failed")
return Repo.clone_from(repo_url, local_path)
except Exception as e:
logger.error(f"Git operation failed: {e}")
return None
🔍 Troubleshooting
Common Issues
-
SSH Agent Issues
# Check SSH agent status ssh-add -l # Start SSH agent manually eval $(ssh-agent -s)
-
Key Problems
# Fix key permissions chmod 600 ~/.ssh/id_ed25519 # Test SSH connection ssh -T git@github.com
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
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 persistent_ssh_agent-0.2.0.tar.gz.
File metadata
- Download URL: persistent_ssh_agent-0.2.0.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d310d960c6ae87cc56e5afbf38840f36214a4503a5cee30c78a4db645ce84bd
|
|
| MD5 |
5fa2e813ad2b02ac38a450c053dadcbe
|
|
| BLAKE2b-256 |
9578c32a1feb44b99fe8d0ba403e5d8d576234b9ebe662641cb07971fd6d14e6
|
Provenance
The following attestation bundles were made for persistent_ssh_agent-0.2.0.tar.gz:
Publisher:
python-publish.yml on loonghao/persistent_ssh_agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
persistent_ssh_agent-0.2.0.tar.gz -
Subject digest:
4d310d960c6ae87cc56e5afbf38840f36214a4503a5cee30c78a4db645ce84bd - Sigstore transparency entry: 157337939
- Sigstore integration time:
-
Permalink:
loonghao/persistent_ssh_agent@3d96bcdd9ae4c9f3433f7ee54e65c293138c97ca -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/loonghao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@3d96bcdd9ae4c9f3433f7ee54e65c293138c97ca -
Trigger Event:
push
-
Statement type:
File details
Details for the file persistent_ssh_agent-0.2.0-py3-none-any.whl.
File metadata
- Download URL: persistent_ssh_agent-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71274b89af55cc4fcd9154ac7d52eff330e99a3e386b9da972e039e3d531bc5c
|
|
| MD5 |
571d26c5d6ed70b59c8374bf772234cb
|
|
| BLAKE2b-256 |
b1ec226e6bf523cd55f6c65aa6b6c09e7f6cc432616b39a39d5cd3a6589d701f
|
Provenance
The following attestation bundles were made for persistent_ssh_agent-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on loonghao/persistent_ssh_agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
persistent_ssh_agent-0.2.0-py3-none-any.whl -
Subject digest:
71274b89af55cc4fcd9154ac7d52eff330e99a3e386b9da972e039e3d531bc5c - Sigstore transparency entry: 157337940
- Sigstore integration time:
-
Permalink:
loonghao/persistent_ssh_agent@3d96bcdd9ae4c9f3433f7ee54e65c293138c97ca -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/loonghao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@3d96bcdd9ae4c9f3433f7ee54e65c293138c97ca -
Trigger Event:
push
-
Statement type: