jenkins - Jenkins SSH 主机/用户证书工作流程
问题描述
每次 Ansible 阶段运行时如何设置 SSH 证书签名过程?我有使用 Terraform 创建 VM 然后运行 Ansible 的管道。在 cloud-init 阶段,会创建和签署主机密钥,并配置公共用户 CA 密钥。客户端/主机 CA 权限在 HashiCorp Vault 中配置。因此,此时,无论配置什么 VM,我都可以通过 SSH 连接到它们中的每一个,就像我@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了。但是,每次我在我的 infra repo 中进行一些提交时,我都无法生成、签名和复制 jenkins 密钥。创建长寿证书也不好闻。
SSH 证书签名和轮换的惯用工作流程是什么?
解决方案
我想到了其他解决方案。
创建 bash 脚本/etc/vault/sign-jenkins-cert.sh
#cat <<EOT >> /etc/vault/sign-jenkins-cert.sh
#!/bin/bash
set -eu -o pipefail
VAULT_ADDR='https://vault.example.com'
SSH_PUB_KEY_PATH='/var/lib/jenkins/.ssh/id_ecdsa.pub'
SSH_CERT_PATH='/var/lib/jenkins/.ssh/id_ecdsa-cert.pub'
ROLE_ID='<jenkins-role-id>' # At cloud-init/kickstart stage this should be baked in
SECRET_ID='<jenkins-secret-id>' # At cloud-init/kickstart stage this should be baked in
main () {
local VAULT_TOKEN=$(vault_signin "${ROLE_ID}" "${SECRET_ID}")
local SSH_PUB_KEY=$(cat "${SSH_PUB_KEY_PATH}")
sign_ssh_cert "${VAULT_TOKEN}" "${SSH_PUB_KEY}" "${SSH_CERT_PATH}"
chmod 0640 "${SSH_CERT_PATH}"
}
vault_signin () {
local ROLE_ID=$1
local SECRET_ID=$2
local RES=$(curl -s --request POST \
--data '{"role_id": "'"${ROLE_ID}"'", "secret_id": "'"${SECRET_ID}"'"}' \
${VAULT_ADDR}/v1/auth/approle/login | jq -r .auth.client_token)
local RT=$?
if [ "$RT" == "0" ]; then
echo $RES
else
echo "Login with role $ROLE_ID failed. RT:$RT $RES"
echo ""
fi
}
sign_ssh_cert () {
local VAULT_TOKEN="$1";
local PUB_KEY="$2";
local CERT_PATH="$3";
curl -s \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--request POST \
--data '{"public_key": "'"${PUB_KEY}"'", "cert_type": "user"}' \
${VAULT_ADDR}/v1/ssh-client-signer/sign/clientrole | jq -r .data.signed_key > "${CERT_PATH}"
}
main "$@"; exit
#EOT
然后将权限设置为0644
和 root 所有权。
sudo chown root. /etc/vault/sign-jenkins-cert.sh && sudo chmod 0644 /etc/vault/sign-jenkins-cert.sh
然后创建 Systemd 单元/etc/systemd/system/sign-jenkins-certificate.service
#cat <<EOT >> /etc/systemd/system/sign-jenkins-certificate.service
[Unit]
Description=Sign a new host cert on boot, then daily
[Service]
ExecStart=/bin/sh /etc/vault/sign-jenkins-cert.sh
Restart=on-failure
RestartSec=20
Type=forking
#EOT
还要设置权限0644
和 root 所有权。
然后创建定时器单元/etc/systemd/system/sign-jenkins-certificate.timer
#cat <<EOT >> /etc/systemd/system/sign-jenkins-certificate.timer
[Unit]
Description=Sign a new host cert on boot, then daily
[Timer]
OnCalendar=daily
Persistent=true
Unit=sign-jenkins-certificate.service
[Install]
WantedBy=timers.target
#EOT
https://www.freedesktop.org/software/systemd/man/systemd.time.html#Calendar%20Events
核实
systemd-analyze verify /etc/systemd/system/sign-jenkins-certificate.timer
启用和启动计时器
systemctl enable sign-jenkins-certificate.timer && \
systemctl start sign-jenkins-certificate.timer && \
systemctl status sign-jenkins-certificate.timer
对于那些坐在强化代理后面的人,请确保您的代理不会阻止curl
Vault ACL 中的用户代理。
该解决方案使用 Vault AppRole 进行身份验证,使用 Systemd 运行签名服务,Jenkins 主机上不需要 Vault 代理。
这可能是有效的解决方案。但也许有更好的东西?
推荐阅读
- java - In Hibernate/JPA how to tell if the ConstraintViolationException is a PK, a FK, or a unique key violation?
- java - 如何在 Firebase 数据库 Android 的子列表中搜索?
- c - Semantic versioning: minor or major change?
- python - Anchor 的值在 tkinter,python3.7 中看起来颠倒了
- html - 滚动卡在 iOS 上
- python - 在 Zapier 中使用 Python 获取图像
- android - PhoneGap Admob, external links... Can't get either one to work
- python - For循环在应该分配两个值时分配一个值
- android - 单击提交按钮时我的应用程序崩溃
- python - 获取给定地理区域的地点(代码优化)