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 ...'
  """