Предотвращение раскрытия переменных среды в параметрах задания Jenkins - PullRequest
0 голосов
/ 13 февраля 2019

Проблема

Я работаю над заданием Jenkins, которое принимает некоторые параметры от пользователя.Я сталкиваюсь с нежелательным поведением: Дженкинс, по-видимому, расширяет ссылки на переменные среды внутри переменных среды параметров, прежде чем мой сценарий сможет их прочитать.

Если пользователь вводит foo-$BUILD_NUMBER для параметра, каков мой сценарийна самом деле видит что-то вроде foo-123;переменная окружения раскрывается.Если введенное значение содержит $$, мой сценарий видит только один $.Однако, если он содержит $variable, который не существует в среде, значение остается неизменным (без возникновения каких-либо ошибок).

Это неудобно, потому что это даже происходит для полей пароля, и яобычно используют генератор паролей, который может содержать $ символов.Я не хочу, чтобы мои пароли были потенциально искажены.

Пример

Мой первоначальный тестовый пример был следующим, с использованием Jenkins Job Builder Groovy DSL.

new BaseJobBuilder(
    jobName: 'example',
    jobBuildName: 'example-${BUILD_NUMBER}',
).build(this).with {
    parameters {
        nonStoredPasswordParam('SERVICE_PASSWORD')
    }
    steps {
        shell('echo "$SERVICE_PASSWORD";')
    }
}

Однако для более сокращенного тестового примера я создал новую установку Jenkins из образа Docker jenkins/jenkins:lts, настроил ее без каких-либо плагинов (даже по умолчанию) и создал эквивалентное задание, используя веб-интерфейс.

Когда я запускаю любое из этих заданий со значением hello $BUILD_NUMBER $HOME world для моего параметра SERVICE_PASSWORD, выходные данные имеют расширенные переменные вместо желаемого литерального значения.

Started by user jeremy
Building in workspace /var/jenkins_home/workspace/jeremy
[jeremy] $ /bin/sh -xe /tmp/jenkins2451955822062381529.sh
+ echo hello 3 /var/jenkins_home world
hello 3 /var/jenkins_home world
Finished: SUCCESS

Вопрос

Есть ли способ получить доступ к исходным значениям параметров для Jenkins, прежде чем они будут подвергнуты расширению / интерполяции переменных, или иным образом отключить или обойти это поведение?

КакМогу ли я принять параметры необработанного текста, которые могут содержать $ долларовых символов, без риска их искажения?

Ссылки по теме

1 Ответ

0 голосов
/ 15 февраля 2019

В качестве обходного пути мы можем добавить начальный шаг сборки, который читает все параметры напрямую и кодирует их в base64 , а затем экспортирует закодированные значения в качестве новых переменных среды.Значения в кодировке Base64 не могут содержать никаких долларовых символов $, поэтому их можно безопасно прочитать на последующих этапах сборки, которые могут декодировать их для получения исходного значения без какого-либо расширения.

Мы реализуем это с помощью«System Groovy Script» шаг сборки из плагина Groovy , который запускает пользовательский скрипт Groovy с прямым доступом к состоянию сборки (спасибо за предложение daspilker ).Если вы используете DSL, вы можете добавить это с помощью systemGroovyCommand("""…""") вызова.

import hudson.EnvVars;
import hudson.model.Executor;
import hudson.model.Environment;

def build = Executor.currentExecutor().currentExecutable;

def newVariables = [:];
build.getBuildVariables().each { name, value ->
  def encodedName = name + "_B64";
  def encodedValue = value.bytes.encodeBase64().toString();
  newVariables.put(encodedName, encodedValue);
}

build.getEnvironments().add(Environment.create(new EnvVars(newVariables)))

Администратору Jenkins может потребоваться утвердить этот сценарий из In-страница подтверждения сценария при первой загрузке.Поскольку он уже кодирует все параметры, вам никогда не потребуется изменять его, и вы сможете повторно использовать его в других заданиях без повторного утверждения.

Последующие шаги «Выполнить оболочку» теперь смогут декодировать исходное значение.

set -eu +vx;

echo "directly from environment: $SERVICE_PASSWORD";

SERVICE_PASSWORD="$(echo "$SERVICE_PASSWORD_B64" | base64 --decode)";
echo "via base-64 encoded value: $SERVICE_PASSWORD";

Мы можем использовать наше первоначальное тестовое значение hello $BUILD_NUMBER $HOME world, чтобы подтвердить, что оно работает:

directly from environment: hello 12 /var/jenkins_home world
via base-64 encoded value: hello $BUILD_NUMBER $HOME world

Невозможно отключить расширение переменной, когда вычтение параметров из переменных среды.Это поведение не связано с параметрами конкретно, но с тем, как Дженкинс обрабатывает переменные среды в целом.После того, как метод hudson.model.AbstractBuild.getEnvironment(…) агрегирует все переменные среды для сборки, он применяет функцию hudson.EnvVars.resolve(…) для выполнения расширения взаимных переменных над содержимым всех переменных среды.В зависимости от точной конфигурации сборки, может также использовать hudson.EnvVars.overrideExpandingAll(…), что делает дополнительный шаг топологической сортировки переменных, чтобы гарантировать, что все нециклические ссылки развернуты в правильномпорядок.Фактическое манипулирование строками выполняется hudson.util.replaceMacro(…), в котором есть комментарий, объясняющий необычную обработку (не замену) несуществующих переменных:

В отличие от оболочки, неопределенные переменные остаютсякак есть (это поведение аналогично Ant.)

Эти расширения выполняются безоговорочно, поэтому невозможно отключить его без изменения или замены нескольких классов в Jenkins.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...