We are under very early construction, so please indulge us.

OpenSSH

Key management

Key management is based on ssh-keygen responsible for securekey pair generation, ssh-agent to host these keys and act as an authentication agent, ssh-add to add private keys to the agent.

ssh-agent

The ssh-agent is a helper program that keeps track of user's identity keys and their passphrases. The agent can then use the keys to log into other servers without having the user type in a password or passphrase again. This implements a form of single sign-on (SSO).

Windows 10 setup of ssh-agent

Looks like it is using named pipes while Linux (WSL/Docker) is using sockets. That makes it useless.

Set-Service ssh-agent -StartupType Manual

Setup connection

ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/ansible_controller

Create key pair (Powershell)

$keyfile = "$PSScriptRoot/.vault/id_rsa"

If (Test-Path $keyfile) {
	Write-Host "Key $keyfile already exists"
	Exit
}

Remove-Item "$keyfile.pub" -ErrorAction SilentlyContinue

&ssh-keygen -t RSA -b 4096 -f $keyfile -C default -q

# Setup permissions for the owner only
$acl = Get-Acl $keyfile
$acl.SetAccessRuleProtection($True, $False) # Disable inheritance
$acl.Access | %{ $acl.RemoveAccessRule($_) | Out-Null } # Revoke all permissions

$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity.Name, "FullControl", "Allow")
$acl.SetAccessRule($rule) # Add permission for the current user

Set-Acl -Path $keyfile -AclObject $acl

Installing existing pair

Firstly put id_rsa and id_rsa.pub into ~/.ssh folder.

# Setup owner-only read-write permissions
sudo chmod 600 ~/.ssh/id_rsa
sudo chmod 600 ~/.ssh/id_rsa.pub

# Start the ssh-agent in the background
eval $(ssh-agent -s)

# Make ssh agent to actually use copied key
ssh-add ~/.ssh/id_rsa

Install public key on remote host

ssh-copy-id user_name@host_address.com

Пока не удалось найти красивого способоа копирования заданного ключа из ssh-agent и данная команда копирует все доступные. После такого копирования стоит зайти на этот хост (ssh user_name@host_address.com) и отредактировать файл ~/.ssh/authorized_keys, удалив все лишние ключи.

Инфраструктура KeePass/KeeAgent

В целом решение выглядит предельно удобным и гармоничным. Приложение KeePass используется для хранение секретной информации, его расширение KeeAgent выполняет роль SSH Agent, предоставляя информацию о ключах самым разным инструментам.

Windows

После утановки Keeagent заходим в Tools -> Options -> KeeAgent, устаналиваем настройки "Create Cygwin compatible socket file", скажем в C:\Users\my_user\.ssh\keeagent-cygwin.sock, "Create msysGit compatible socketfile" в C:\Users\my_user\.ssh\keeagent-msys.sock.

Далее генерируем ключ и прикрепляем оба сформированных файла к записи в KeePass. С свойствах этой записи открываем закладку KeeAgent и указываем "Private Key File Location" на прикрепленный файл, а пароль записи на пароль заданный при создании ключа (если таковой был).

После этого в меню Tools > KeeAgent мы должны увидеть запись о публикации нашего ключа.

После такой настройки практически сразу должны начать работать mRemoteNG, Kitty, Putty, Git bash. Возможно, единственной необходимой настройкой будет указание переменной среды SSH_AUTH_SOCK на один из созданных ранее сокетов. На примере Git bash:

$ export SSH_AUTH_SOCK=/c/Users/my_user/.ssh/keeagent-cygwin.sock
$ ssh-add -l
2048 SHA256:lxDdCEQTPhgzGdbC6OH2+gsvm5jqQb2UyAWO30W8vCc Default.pem (RSA)
4096 SHA256:OSH9zR5Qmp6D9Bwh0DJBztlhCuRIm7CZTGkfgk53exg admin@egopolis.net (RSA)
...

С настройкой гостевых систем вроде Docker будет немного сложнее. Создаваемы сокеты, на самом деле, являются не сокетами, а простыми текстовыми файлами, внутри которых, помимо прочего, содержится порт реального сокета. Чтобы транслировать потоки между сокетами хостовой и гостевой системы, можно воспользоваться утилитой socat.

# Передаём гостевой машине файл с информацией о сокете
> docker run --rm -it -v "$($Env:USERPROFILE)/.ssh/keeagent-msys.sock:/root/.ssh/keeagent.sock" ubuntu /bin/bash

# Извлекаем из файла информацию о сокете
$ export SSH_AUTH_KEEAGENT_PORT=`sed -r 's/!<socket >([0-9]*\b).*/\1/' ~/.ssh/keeagent.sock`

# Перенаправляем коммуникации между двумя сокетами
$ export SSH_AUTH_SOCK=~/.ssh/agent.sock
$ setsid socat UNIX-LISTEN:${SSH_AUTH_SOCK},mode=0600,fork,shut-down TCP:host.docker.internal:${SSH_AUTH_KEEAGENT_PORT},connect-timeout=2 2>&1 > /dev/null &

$ ssh-add -l
2048 SHA256:lxDdCEQTPhgzGdbC6OH2+gsvm5jqQb2UyAWO30W8vCc Default.pem (RSA)
4096 SHA256:OSH9zR5Qmp6D9Bwh0DJBztlhCuRIm7CZTGkfgk53exg admin@egopolis.net (RSA)

Contribution

Поскольку KeeAgent является проектом с исходнмы кодом, а Windows с недавнего времени поддерживает Unix sockets (AF_UNIX), можно расширить его возможности и реализовать сокет напрямую, без проксирования socket -> msys soscket -> socat -> Unix socket.

Первые эксперименты с UnixDomainSocketEndPoint привели к тому, что сокет был создан, но с эксклюзивным доступом и не получалось его прокинуть в docker.

В качестве отправной точки можно обратить внимание наmsysgit2unix-socket.py и msysgit2unix-socket.py.

Классы CygwinSocket/MsysSocket очень похожи. Можно провести рефакторинг и вынести в базовый класс, на основе которого выстроить и свою реализацию.

Можно провести миграцию на более современные версии .NET Framework, .NET Core, .NET Standard.

S