Jenkins 管道 - ssh 到不同的机器和存储凭据的位置(使用 ssh/SSHAgent plugin/etc...)
Jenkins pipeline - ssh to different machine and where to store credentials (using ssh/SSHAgent plugin/etc...)
TLDR:如何通过 ssh 连接不同的机器以及在 Jenkins 管道上将 ssh 凭据存储在何处(使用 ssh / SSHAgent 插件/等等...)?
问题: 在 Jenkins 管道中,我需要一个远程 ssh 到目标机器。
我的旧方法是使用“使用 ssh 在远程主机上执行 shell 脚本”。我想指定用户名和密码。
我读到 groovy 方法应该类似于
sshagent(['RemoteCredentials']) {
sh 'ssh -o StrictHostKeyChecking=no -l remoteusername remotetarget uname -a'
}
RemoteCredentials: 是带密码的私钥
有没有办法使用 username/password 远程凭证创建 ssh? sshagent 不支持 username/password auth
里卡多
很遗憾,你是对的。
看起来 ssh-agent-plugin 仅支持通过 Jenkins 中的凭据管理区域添加的存储用户、密码、public 密钥凭据。 See this unit test 验证 ssh-agent 是否基于 public 密钥正常工作。插件中不太可能有未经测试的功能来支持用户+密码身份验证。
如果可以,请切换到 Public 基于密钥的身份验证。如果由于某种原因你不能切换......你 可以 在你的 Jenkins 盒子上安装 sshpass ,但这通常被认为是不好的做法。
node {
stage 'Does sshpass work?'
sh 'sshpass -p \'password\' ssh user@host "ls; hostname; whois google.com;"'
}
加强您的游戏 运行在 Jenkins 代理上执行 ssh 任务,将使您的服务器更加安全。当您 运行 像 Ansible 这样的 ssh 任务时,Jenkins 是一个攻击媒介,并且需要控制发布。
改进/etc/sshd_config将阻止黑客的大量探测。
密码验证无
PubkeyAuthentication 是
PermitRootLogin 否
从 DSA 或 RSA 密钥对转移到更安全的 ed25519 椭圆曲线
对私钥文件进行暴力保护的密码学。
ssh-keygen -t ed25519 -o -a 300 -C Jenkins
因为私钥需要几百轮,每次使用都要几十秒,
这对于开发人员可能会四处窥探的构建代理来说是完美的。
我宁愿不将私钥作为凭证存储在 Jenkins 中,因为 Jenkins 是一个可插入的代码执行引擎,而是我只将密码短语存储为秘密文本凭证(在示例中名为 mySecretText)。我有专门的环境代理,每个代理都有自己的 ~/.ssh/id_ed25519 密钥文件,爆炸半径有限。密码用于启动 ssh-agent,更具体地说,用于为每个会话加载密钥。
下面的 Jenkinsfile 允许使用密钥对将标签推送到 git,但磁盘上没有明文。选择此实现是因为 ssh-agent 插件不允许 ssh-add。
node {
println("Checkout repository...")
checkout scm
}
pipeline {
agent {
label "linux"
}
options {
disableConcurrentBuilds()
}
stages {
stage('PushTheTag') {
steps {
script {
withCredentials([string(credentialsId: 'mySecretText', variable: 'SSH_PASSPHRASE')]) {
sh "echo 'echo $SSH_PASSPHRASE' > ~/.ssh/tmp && chmod 700 ~/.ssh/tmp"
sh "eval `ssh-agent -s` && cat ~/.ssh/id_ed25519|DISPLAY=None SSH_ASKPASS=~/.ssh/tmp ssh-add - && git tag ${env.BUILD_NUMBER} && git push --tags; kill -9 $SSH_AGENT_PID"
}
}
}
}
}
}
解决方案:您想在您的管道中对某台机器进行 ssh。我想提供一种更安全的不同方法(我希望能够在机器本身上管理我的 ssh 凭据)。确保您的 ssh 密钥已预先构建在 ~/.ssh/id_rsa
下的基础设施中(可以通过 ansible/chef/puppet 进行预先配置,或者仅在 aws/gcp/azure 云环境中使用一些映像快照)。您的管道应该在机器中加载 ssh 私钥凭据并连接到节点(里面有 public 密钥)。
_node(with private key) ---> testing/staging/production_node(with public key)
什么时候使用它? 例如用例 - 你想 run/stop 另一个节点中的某个进程,或者在实例 x 上部署应用程序和管道中的 y
简单示例 - 点对点 ( node -> destination_node
) 将是:
def ip-address=<some-ip-address>
sh """#!/bin/bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
ssh -o StrictHostKeyChecking=no ${ip-address} << 'EOF'
echo 'im in ...'
"""
复杂示例 - Bastion 使用堡垒云架构 (node -> vpc-endpoint -> destination-node
) 将是:
def vpc-endpoint-gw-ip=<some-ip-address>
def subnet-ip=<some-subnet-address>
sh """#!/bin/bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
ssh -At -o StrictHostKeyChecking=no ${vpc-endpoint-gw-ip} << 'EOF'
ssh -o StrictHostKeyChecking=no ${subnet-ip} << 'EOF2'
echo 'im in ...'
"""
TLDR:如何通过 ssh 连接不同的机器以及在 Jenkins 管道上将 ssh 凭据存储在何处(使用 ssh / SSHAgent 插件/等等...)?
问题: 在 Jenkins 管道中,我需要一个远程 ssh 到目标机器。 我的旧方法是使用“使用 ssh 在远程主机上执行 shell 脚本”。我想指定用户名和密码。
我读到 groovy 方法应该类似于
sshagent(['RemoteCredentials']) {
sh 'ssh -o StrictHostKeyChecking=no -l remoteusername remotetarget uname -a'
}
RemoteCredentials: 是带密码的私钥
有没有办法使用 username/password 远程凭证创建 ssh? sshagent 不支持 username/password auth
里卡多
很遗憾,你是对的。
看起来 ssh-agent-plugin 仅支持通过 Jenkins 中的凭据管理区域添加的存储用户、密码、public 密钥凭据。 See this unit test 验证 ssh-agent 是否基于 public 密钥正常工作。插件中不太可能有未经测试的功能来支持用户+密码身份验证。
如果可以,请切换到 Public 基于密钥的身份验证。如果由于某种原因你不能切换......你 可以 在你的 Jenkins 盒子上安装 sshpass ,但这通常被认为是不好的做法。
node {
stage 'Does sshpass work?'
sh 'sshpass -p \'password\' ssh user@host "ls; hostname; whois google.com;"'
}
加强您的游戏 运行在 Jenkins 代理上执行 ssh 任务,将使您的服务器更加安全。当您 运行 像 Ansible 这样的 ssh 任务时,Jenkins 是一个攻击媒介,并且需要控制发布。
改进/etc/sshd_config将阻止黑客的大量探测。
密码验证无
PubkeyAuthentication 是
PermitRootLogin 否
从 DSA 或 RSA 密钥对转移到更安全的 ed25519 椭圆曲线 对私钥文件进行暴力保护的密码学。
ssh-keygen -t ed25519 -o -a 300 -C Jenkins
因为私钥需要几百轮,每次使用都要几十秒, 这对于开发人员可能会四处窥探的构建代理来说是完美的。
我宁愿不将私钥作为凭证存储在 Jenkins 中,因为 Jenkins 是一个可插入的代码执行引擎,而是我只将密码短语存储为秘密文本凭证(在示例中名为 mySecretText)。我有专门的环境代理,每个代理都有自己的 ~/.ssh/id_ed25519 密钥文件,爆炸半径有限。密码用于启动 ssh-agent,更具体地说,用于为每个会话加载密钥。
下面的 Jenkinsfile 允许使用密钥对将标签推送到 git,但磁盘上没有明文。选择此实现是因为 ssh-agent 插件不允许 ssh-add。
node {
println("Checkout repository...")
checkout scm
}
pipeline {
agent {
label "linux"
}
options {
disableConcurrentBuilds()
}
stages {
stage('PushTheTag') {
steps {
script {
withCredentials([string(credentialsId: 'mySecretText', variable: 'SSH_PASSPHRASE')]) {
sh "echo 'echo $SSH_PASSPHRASE' > ~/.ssh/tmp && chmod 700 ~/.ssh/tmp"
sh "eval `ssh-agent -s` && cat ~/.ssh/id_ed25519|DISPLAY=None SSH_ASKPASS=~/.ssh/tmp ssh-add - && git tag ${env.BUILD_NUMBER} && git push --tags; kill -9 $SSH_AGENT_PID"
}
}
}
}
}
}
解决方案:您想在您的管道中对某台机器进行 ssh。我想提供一种更安全的不同方法(我希望能够在机器本身上管理我的 ssh 凭据)。确保您的 ssh 密钥已预先构建在 ~/.ssh/id_rsa
下的基础设施中(可以通过 ansible/chef/puppet 进行预先配置,或者仅在 aws/gcp/azure 云环境中使用一些映像快照)。您的管道应该在机器中加载 ssh 私钥凭据并连接到节点(里面有 public 密钥)。
_node(with private key) ---> testing/staging/production_node(with public key)
什么时候使用它? 例如用例 - 你想 run/stop 另一个节点中的某个进程,或者在实例 x 上部署应用程序和管道中的 y
简单示例 - 点对点 ( node -> destination_node
) 将是:
def ip-address=<some-ip-address>
sh """#!/bin/bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
ssh -o StrictHostKeyChecking=no ${ip-address} << 'EOF'
echo 'im in ...'
"""
复杂示例 - Bastion 使用堡垒云架构 (node -> vpc-endpoint -> destination-node
) 将是:
def vpc-endpoint-gw-ip=<some-ip-address>
def subnet-ip=<some-subnet-address>
sh """#!/bin/bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
ssh -At -o StrictHostKeyChecking=no ${vpc-endpoint-gw-ip} << 'EOF'
ssh -o StrictHostKeyChecking=no ${subnet-ip} << 'EOF2'
echo 'im in ...'
"""