pysnap.ssh package¶
ssh access to guests that have no console on COM1.
PySnap runs the system OpenSSH client (ssh) with its own key pair and its
own known_hosts files, so the user’s keys and ~/.ssh/known_hosts are
never read or changed.
Submodules¶
pysnap.ssh.client module¶
Run the system ssh client against a forwarded guest port.
Every call uses the PySnap key, the known_hosts file of the VM with
StrictHostKeyChecking=accept-new (the first key is trusted, a changed key
is refused) and no user configuration (-F with the null device), so the
behaviour does not depend on ~/.ssh. Non-interactive calls run in batch
mode: they never ask for a password.
- class pysnap.ssh.client.SshTarget(vm_name, vm_uuid, port, user)[source]¶
Bases:
objectDescribe where and as whom to connect.
- Parameters:
vm_name (str) – VM name, used in messages.
vm_uuid (str) – VM UUID, selects the known_hosts file.
port (int) – Host port forwarded to the guest ssh server.
user (str) – Guest user.
- vm_name: str¶
- vm_uuid: str¶
- port: int¶
- user: str¶
- class pysnap.ssh.client.AccessCheck(status, message='')[source]¶
Bases:
objectResult of a key login attempt.
- Parameters:
status (str) –
"ok","denied"(the server refused the key) or"unreachable"(no ssh server answered).message (str) – Error output of ssh.
- status: str¶
- message: str = ''¶
- pysnap.ssh.client.ssh_command(target, store, *, batch=True, tty=False, remote_command=None, extra=())[source]¶
Build an
sshcommand line.- Parameters:
target (SshTarget) – Connection target.
store (SshKeyStore) – PySnap key store.
batch (bool) – Use the PySnap key only and never ask for a password.
tty (bool) – Request a terminal on the guest (
-tt).remote_command (str | None) – Command for the guest shell; a login shell without.
extra (Sequence[str]) – Further ssh options placed before the destination.
- Returns:
Argument list.
- Return type:
list[str]
- pysnap.ssh.client.check_key_access(target, store)[source]¶
Try to log in with the PySnap key.
- Parameters:
target (SshTarget) – Connection target.
store (SshKeyStore) – PySnap key store.
- Returns:
Whether the key works, is refused or no server answers.
- Return type:
- pysnap.ssh.client.run_remote(target, store, command, *, timeout=None)[source]¶
Run one command on the guest with the PySnap key.
- Parameters:
target (SshTarget) – Connection target.
store (SshKeyStore) – PySnap key store.
command (str) – Shell command line for the guest.
timeout (float | None) – Seconds to wait.
- Returns:
Completed process with bytes output.
- Return type:
CompletedProcess
- async pysnap.ssh.client.open_terminal(target, store, *, columns, rows)[source]¶
Start an interactive guest shell on a pseudo terminal.
The guest terminal gets the given size first; output of ssh itself (errors) is merged into the stream.
- Parameters:
target (SshTarget) – Connection target.
store (SshKeyStore) – PySnap key store.
columns (int) – Terminal width.
rows (int) – Terminal height.
- Returns:
Reader, writer and the ssh process.
- Return type:
tuple[StreamReader, StreamWriter, Process]
- pysnap.ssh.client.install_script(public_key, *, with_root)[source]¶
Return the guest shell script that adds the PySnap key.
The key is appended to
~/.ssh/authorized_keysunless it is there already. Withwith_root, a user other than root then runs the same for root throughsu; the guest asks for the root password, and an empty or wrong one only skips root.- Parameters:
public_key (str) – Public key line.
with_root (bool) – Also install the key for root.
- Returns:
Script for
sh -c.- Return type:
str
- pysnap.ssh.client.install_key_interactively(target, store)[source]¶
Log in with a password in the current terminal and add the key.
ssh asks for the password of
target.user; the guest may ask for the root password. Nothing is captured, the user sees the whole dialogue.- Parameters:
target (SshTarget) – Connection target with the password login user.
store (SshKeyStore) – PySnap key store.
- Returns:
Exit status of ssh.
- Return type:
int
- pysnap.ssh.client.check_or_raise(target, store)[source]¶
Raise a helpful error unless the PySnap key logs in.
- Parameters:
target (SshTarget) – Connection target.
store (SshKeyStore) – PySnap key store.
- Raises:
PySnapError – When the key is refused or no server answers.
- Return type:
None
pysnap.ssh.keys module¶
The PySnap ssh key pair and per-VM known_hosts files.
Everything lives in ~/.pysnap/ssh (mode 0700): the key pair
pysnap_vm_access_ed25519 with its .pub file, created once by
ssh-keygen without a passphrase, and known_hosts.d/<VM UUID>, one
known_hosts file per VM. Both the directory and the file names are unique
to PySnap, and existing files are never overwritten.
- pysnap.ssh.keys.find_executable(name)[source]¶
Return the path of an OpenSSH program.
- Parameters:
name (str) –
sshorssh-keygen.- Returns:
Executable path.
- Raises:
PySnapError – When the program is not installed.
- Return type:
str
- class pysnap.ssh.keys.SshKeyStore(root=None)[source]¶
Bases:
objectLocate and create the PySnap key pair and known_hosts files.
- Parameters:
root (Path | None)
- known_hosts(vm_uuid)[source]¶
Return the known_hosts file of one VM, creating its directory.
- Parameters:
vm_uuid (str) – VirtualBox UUID of the VM.
- Returns:
File path; the file itself is written by ssh.
- Raises:
PySnapError – For an unusable UUID.
- Return type:
Path
- ensure_key()[source]¶
Return the private key, creating the key pair on first use.
- Returns:
Private key path.
- Raises:
PySnapError – When only one half of the pair exists, when a path is taken by something else or
ssh-keygenfails.- Return type:
Path