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.1.0.tar.gz (10.6 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.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file persistent_ssh_agent-0.1.0.tar.gz.

File metadata

  • Download URL: persistent_ssh_agent-0.1.0.tar.gz
  • Upload date:
  • Size: 10.6 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.1.0.tar.gz
Algorithm Hash digest
SHA256 768a5d07c2956c953b8388897d8b61c18b8af5bf43411bec9dec1977bc30a368
MD5 bb31e2b2603b212b8e2bb6a8cb3f61df
BLAKE2b-256 f385e394e073771b9fb6313483e63b30c0c33294b1813b25b9ed9d7061007008

See more details on using hashes here.

Provenance

The following attestation bundles were made for persistent_ssh_agent-0.1.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.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for persistent_ssh_agent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 528a1c84dab6cbb5ec45565ee2047aae67e06206b4faf3b9509320d963e52d7c
MD5 d9dce8accae8c94d49397868404e104c
BLAKE2b-256 424ecd9e08cf2348aa8bfc9e5efd6ce855f3248029e443257ce2ae1b213eb4ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for persistent_ssh_agent-0.1.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