Трубопровод Дженкинса: SSHAgent удаленный SSH

В конвейере Jenkins2.0 мне нужен удаленный ssh ​​для целевой машины. Мой старый подход состоял в том, чтобы использовать "Выполнение сценариев оболочки на удаленном хосте с использованием ssh". Я хотел бы указать имя пользователя и пароль.

Я читал, что отличный подход должен быть что-то вроде

sshagent(['RemoteCredentials']) {
    sh 'ssh -o StrictHostKeyChecking=no -l remoteusername remotetarget uname -a'
  }

RemoteCredentials: это закрытый ключ с парольной фразой

Есть ли способ сделать SSH с именем пользователя / паролем удаленных учетных данных? Sshagent не поддерживает аутентификацию имени пользователя / пароля

Riccardo

3 ответа

Решение

Так что, к сожалению, вы правы.

Похоже, плагин ssh-agent-plugin поддерживает только сохраненные учетные данные пользователя, парольной фразы и открытого ключа, добавленные через область управления учетными данными в Jenkins. Посмотрите этот модульный тест, который проверяет, что ssh-agent работает правильно, основываясь на открытом ключе. Маловероятно, что в плагине есть непроверенная функциональность для поддержки аутентификации пользователя + пароль.

Если можете, переключитесь на аутентификацию на основе открытого ключа. Если по какой-то причине вы не можете переключиться... вы МОЖЕТЕ установить sshpass на свою коробку Jenkins, но это обычно считается плохой практикой.

node {
    stage 'Does sshpass work?'
    sh 'sshpass -p \'password\' ssh user@host "ls; hostname; whois google.com;"'
}

Решение: вы хотите использовать ssh для какой-либо машины в вашем конвейере. Я хочу предложить другой подход, более безопасный (я хочу иметь возможность управлять своими учетными данными ssh на самой машине). Убедитесь, что ваши ключи ssh предварительно встроены в вашу инфраструктуру под ~/.ssh/id_rsa(можно предварительно настроить через ansible/chef/puppet или просто использовать моментальный снимок изображения в облачной среде aws/gcp/azure). ваш конвейер должен загрузить учетные данные закрытого ключа ssh на машину и подключиться к узлу (с открытым ключом внутри).

      _node(with private key) ---> testing/staging/production_node(with public key)

Когда вы его используете? Например, вариант использования: вы хотите запустить/остановить какой-либо процесс на другом узле или развернуть приложение на экземплярах 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 , использующий облачную архитектуру 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 ...'
  """

Активизация вашей игры, запускающей задачи ssh на агентах Jenkins, сделает ваши серверы более безопасными. Jenkins - это вектор атаки, когда вы запускаете задачи ssh, такие как Ansible, и желательно контролировать выпуски.

  • Улучшение / etc / sshd_config остановит множество атак хакеров.

    Пароль Аутентификация нет

    PubkeyAuthentication да

    PermitRootLogin нет

  • Переходите от пар ключей DSA или RSA к более безопасной криптографии на основе эллиптических кривых ed25519 с защитой от перебора секретного файла ключей.

    ssh-keygen -t ed25519 -o -a 300 -C Дженкинс

    Поскольку закрытый ключ требует сотен раундов, каждое использование займет десятки секунд, что является идеальным вариантом для агента сборки, где разработчики могут следить.

Я предпочитаю не хранить закрытый ключ в качестве учетных данных в Jenkins, потому что Jenkins - это подключаемый механизм выполнения кода, вместо этого я сохраняю только кодовую фразу в качестве секретных текстовых учетных данных (в примере с именем mySecretText). У меня есть специальные агенты для сред, каждый из которых имеет собственный файл ключей ~/.ssh/id_ed25519 с ограниченным радиусом взрыва. Кодовая фраза используется для запуска ssh-agent, а именно для загрузки ключа за сеанс.

Приведенный ниже файл Jenkins позволяет использовать пару ключей для отправки тега в 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"
                    }
                }
            }
        }
    }
}
Другие вопросы по тегам