Как настроить процесс подписания ключей SSH каждый раз при запуске какого-либо этапа Ansible? Или хотя бы с некоторым интервалом.
У меня есть конвейер, который создает виртуальные машины с Terraform, а затем запускает Ansible. На этапе cloud-init создаются и подписываются ключи хоста, а также настраивается открытый ключ CA пользователя. Полномочия CA клиента/хоста настраиваются/работают в HashiCorp Vault. Таким образом, на этом этапе, независимо от того, какие виртуальные машины предоставлены, я могу подключиться по SSH к каждой из них, поскольку у меня есть открытый ключ CA хоста, @cert-authority *.example.com ecdsa-sha2-nistp521 AAAAB3NzaC1yc2EAAA...
установленный глобально в /etc/ssh/ssh_known_hosts
. Все, что мне нужно сделать, это создать новый персональный ключ и подписать его, поскольку мой TTL довольно короткий.
Но это не работает в Jenkins. Jenkins хранит все ключи SSH в , /var/lib/jenkins/.ssh
и по умолчанию там ничего нет. Если только для целей тестирования я скопирую свои личные пользовательские (или сгенерированные) ключи и сертификат + файл конфигурации ssh в /var/lib/jenkins/.ssh
, то Jenkins сможет без проблем запустить Ansible. Но я не могу генерировать, подписывать и копировать ключи jenkins каждый раз, когда делаю какой-то коммит в своем infra-репозитории. Создание долгоживущих сертификатов тоже не пахнет хорошо.
Каков идиоматический автоматизированный рабочий процесс для подписания и ротации ключей SSH?
решение1
Я сам перечислю "ПЛОХИЕ" решения. Плохие, потому что там ротация ключей ручная и TTL, скорее всего, будет долгим, потому что мы ленивые.
В хранилище вам необходимо создать новую роль SSH «jenkins» с TTL, например:52w
Затем, в идеале, на самом хосте Jenkins вам нужно создать новые ключи.
ssh-keygen -t ecdsa -b 521 -f /var/lib/jenkins/.ssh/id_ecdsa -C "jenkins@jenkins-01"
Тогда пой это с Vault
vault write -field=signed_key ssh-client-signer/sign/jenkinsrole public_key=/var/lib/jenkins/.ssh/id_ecdsa.pub > /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
Это значит, что Vault должен быть в системе. ... это дилемма - хотите ли вы копировать ключи ssh (включая закрытые) по сети, что немного попахивает, или вы хотите установить Vault на машину Jenkins. Это на ваше усмотрение.
Получив id_ecdsa-cert.pub
сертификат, вы можете проверить его ssh-keygen -Lf /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
и убедиться в правильности срока действия, принципов и т. д.
Поскольку, скорее всего, в инфраструктуре будут наблюдаться перебои, статическое хранение конфигурации SSH в /var/lib/jenkins/.ssh/config
будет затруднительным.
Вместо этого вы можете создать ansible-ssh.cfg
файл с таким содержимым:
Host bastion
HostName bastion.example.com
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ecdsa
CertificateFile ~/.ssh/id_ecdsa-cert.pub
Port 22
Protocol 2
User ansible
LogLevel INFO
Этот файл может (должен) располагаться рядом с остальным кодом Ansible.
Затем в ansible.cfg
файле включите строфу SSH
[ssh_connection]
ssh_args = -F ./ansible-ssh.cfg
Таким образом, Ansible всегда будет получать актуальные конфигурации SSH.
Если вы используете Terraform, то можно динамически обновлять файл конфигурации SSH, включая новые хосты и т. д.
Это решение не привязано только к Vault. Это можно сделать довольно легко с ssh-keygen
самим Vault.
ОБНОВЛЕНИЕ: В конце концов я пришел к небольшому скрипту оболочки, который выполняет авторизацию с помощью approle, а затем подписывает сертификат. Служба Systemd и блок Timer выполняют скрипт оболочки, который выполняет ротацию сертификатов каждый день. Так что на этом этапе Jenkins использует собственные свежие сертификаты пользователя для запуска Terraform и Ansible. https://stackoverflow.com/a/65875997/6651080