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.1.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.1-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: persistent_ssh_agent-0.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 3a0ab073984a6d63c34c52a47067ebee4c065f49cc88a9767717d4ede20a9378
MD5 b1ff964e1bd31e6ff5c0d6579c5babe5
BLAKE2b-256 56aa2abd56a85e579a681e965b56686622328a66e94cd11cb9f1d3385d6fb4cd

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for persistent_ssh_agent-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cb1195067165a13085b79458b857a5b92be6a35ef5e68f20d277766646c34480
MD5 1000fdd1a3410206cf3fd5dc40467134
BLAKE2b-256 23285470a91f4d0f9d3c87777d840ad3a29aba8f7170f79bd8e6226ce57b8273

See more details on using hashes here.

Provenance

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