Skip to main content

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

Python Version Nox PyPI Version Downloads Downloads Downloads License PyPI Format Maintenance Codecov

🔐 A modern Python library for persistent SSH agent management across sessions.

Key FeaturesInstallationDocumentationExamplesContributing

✨ 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

  1. SSH Agent Issues

    # Check SSH agent status
    ssh-add -l
    
    # Start SSH agent manually
    eval $(ssh-agent -s)
    
  2. 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

persistent_ssh_agent-0.2.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

persistent_ssh_agent-0.2.0-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

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

Hashes for persistent_ssh_agent-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4d310d960c6ae87cc56e5afbf38840f36214a4503a5cee30c78a4db645ce84bd
MD5 5fa2e813ad2b02ac38a450c053dadcbe
BLAKE2b-256 9578c32a1feb44b99fe8d0ba403e5d8d576234b9ebe662641cb07971fd6d14e6

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file persistent_ssh_agent-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for persistent_ssh_agent-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71274b89af55cc4fcd9154ac7d52eff330e99a3e386b9da972e039e3d531bc5c
MD5 571d26c5d6ed70b59c8374bf772234cb
BLAKE2b-256 b1ec226e6bf523cd55f6c65aa6b6c09e7f6cc432616b39a39d5cd3a6589d701f

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page