Рабочий процесс сертификатов хоста/пользователя Jenkins SSH

Рабочий процесс сертификатов хоста/пользователя Jenkins SSH

Как настроить процесс подписания ключей 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

Связанный контент