Что такое credentials в jenkins
The following plugin provides functionality available through Pipeline-compatible steps. Read more about how to integrate steps into your Pipeline in the Steps section of the Pipeline Syntax page.
For a list of other such plugins, see the Pipeline Steps Reference page.
Credentials Binding Plugin
withCredentials : Bind credentials to variables
Allows various kinds of credentials (secrets) to be used in idiosyncratic ways. (Some steps explicitly ask for credentials of a particular kind, usually as a credentialsId parameter, in which case this step is unnecessary.) Each binding will define an environment variable active within the scope of the step. You can then use them directly from any other steps that expect environment variables to be set:
As another example (use Snippet Generator to see all options):
Note the use of single quotes to define the script (implicit parameter to sh ) in Groovy above. You want the secret to be expanded by the shell as an environment variable. The following idiom is potentially less secure, as the secret is interpolated by Groovy and so (for example) typical operating system process listings will accidentally disclose it:
At least on Linux, environment variables can be obtained by other processes running in the same account, so you should not run a job which uses secrets on the same node as a job controlled by untrusted parties. In any event, you should always prefer expansion as environment variables to inclusion in the command, since Jenkins visualizations such as Blue Ocean will attempt to detect step parameters containing secrets and refuse to display them.
Beware that certain tools mangle secrets when displaying them. As one example, Bash (as opposed to Ubuntu’s plainer Dash) does so with text containing ‘ in echo mode:
Mangled secrets can only be detected on a best-effort basis. By default, Jenkins will attempt to mask mangled secrets as they would appear in output of Bourne shell, Bash, Almquist shell and Windows batch. Without these strategies in place, mangled secrets would appear in plain text in log files. In the example above, this would result in:
This particular issue can be more safely prevented by turning off echo with set +x or avoiding the use of shell metacharacters in secrets.
For bindings which store a secret file, beware that
to ensure that the secrets are outside the workspace; or choose a different workspace entirely:
Also see the Limitations of Credentials Masking blog post for more background.
Using credentials
There are numerous 3rd-party sites and applications that can interact with Jenkins, for example, artifact repositories, cloud-based storage systems and services, and so on.
A systems administrator of such an application can configure credentials in the application for dedicated use by Jenkins. This would typically be done to «lock down» areas of the application’s functionality available to Jenkins, usually by applying access controls to these credentials. Once a Jenkins manager (i.e. a Jenkins user who administers a Jenkins site) adds/configures these credentials in Jenkins, the credentials can be used by Pipeline projects to interact with these 3rd party applications.
Note: The Jenkins credentials functionality described on this and related pages is provided by the Credentials Binding plugin.
Credentials stored in Jenkins can be used:
anywhere applicable throughout Jenkins (i.e. global credentials),
by a specific Pipeline project/item (read more about this in the Handling credentials section of Using a Jenkinsfile),
by a specific Jenkins user (as is the case for Pipeline projects created in Blue Ocean).
Jenkins can store the following types of credentials:
Docker Host Certificate Authentication credentials.
Credential security
To maximize security, credentials configured in Jenkins are stored in an encrypted form on the controller Jenkins instance (encrypted by the Jenkins instance ID) and are only handled in Pipeline projects via their credential IDs.
This minimizes the chances of exposing the actual credentials themselves to Jenkins users and hinders the ability to copy functional credentials from one Jenkins instance to another.
Configuring credentials
This section describes procedures for configuring credentials in Jenkins.
Credentials can be added to Jenkins by any Jenkins user who has the Credentials > Create permission (set through Matrix-based security). These permissions can be configured by a Jenkins user with the Administer permission. Read more about this in the Authorization section of Managing Security.
Otherwise, any Jenkins user can add and configure credentials if the Authorization settings of your Jenkins instance’s Configure Global Security settings page is set to the default Logged-in users can do anything setting or Anyone can do anything setting.
Adding new global credentials
To add new global credentials to your Jenkins instance:
If required, ensure you are logged in to Jenkins (as a user with the Credentials > Create permission).
From the Jenkins home page (i.e. the Dashboard of the Jenkins classic UI), click Manage Jenkins > Manage Credentials.
Under Stores scoped to Jenkins on the right, click on Jenkins.
Under System, click the Global credentials (unrestricted) link to access this default domain.
Click Add Credentials on the left.
Note: If there are no credentials in this default domain, you could also click the add some credentials link (which is the same as clicking the Add Credentials link).
From the Kind field, choose the type of credentials to add.
From the Scope field, choose either:
Add the credentials themselves into the appropriate fields for your chosen credential type:
Specify an optional Description for the credential/s.
Click OK to save the credentials.
Using a Jenkinsfile
This section builds on the information covered in Getting started with Pipeline and introduces more useful steps, common patterns, and demonstrates some non-trivial Jenkinsfile examples.
Code review/iteration on the Pipeline
Audit trail for the Pipeline
Single source of truth [2] for the Pipeline, which can be viewed and edited by multiple members of the project.
Creating a Jenkinsfile
As discussed in the Defining a Pipeline in SCM, a Jenkinsfile is a text file that contains the definition of a Jenkins Pipeline and is checked into source control. Consider the following Pipeline which implements a basic three-stage continuous delivery pipeline.
Not all Pipelines will have these same three stages, but it is a good starting point to define them for most projects. The sections below will demonstrate the creation and execution of a simple Pipeline in a test installation of Jenkins.
It is assumed that there is already a source control repository set up for the project and a Pipeline has been defined in Jenkins following these instructions.
Using a text editor, ideally one which supports Groovy syntax highlighting, create a new Jenkinsfile in the root directory of the project.
The Declarative Pipeline example above contains the minimum necessary structure to implement a continuous delivery pipeline. The agent directive, which is required, instructs Jenkins to allocate an executor and workspace for the Pipeline. Without an agent directive, not only is the Declarative Pipeline not valid, it would not be capable of doing any work! By default the agent directive ensures that the source repository is checked out and made available for steps in the subsequent stages`
The stages directive, and steps directives are also required for a valid Declarative Pipeline as they instruct Jenkins what to execute and in which stage it should be executed.
| The checkout step will checkout code from source control; scm is a special variable which instructs the checkout step to clone the specific revision which triggered this Pipeline run. |
Build
For many projects the beginning of «work» in the Pipeline would be the «build» stage. Typically this stage of the Pipeline will be where source code is assembled, compiled, or packaged. The Jenkinsfile is not a replacement for an existing build tool such as GNU/Make, Maven, Gradle, etc, but rather can be viewed as a glue layer to bind the multiple phases of a project’s development lifecycle (build, test, deploy, etc) together.
Jenkins has a number of plugins for invoking practically any build tool in general use, but this example will simply invoke make from a shell step ( sh ). The sh step assumes the system is Unix/Linux-based, for Windows-based systems the bat could be used instead.
| The sh step invokes the make command and will only continue if a zero exit code is returned by the command. Any non-zero exit code will fail the Pipeline. |
| archiveArtifacts captures the files built matching the include pattern ( **/target/*.jar ) and saves them to the Jenkins controller for later retrieval. |
Archiving artifacts is not a substitute for using external artifact repositories such as Artifactory or Nexus and should be considered only for basic reporting and file archival.
Running automated tests is a crucial component of any successful continuous delivery process. As such, Jenkins has a number of test recording, reporting, and visualization facilities provided by a number of plugins. At a fundamental level, when there are test failures, it is useful to have Jenkins record the failures for reporting and visualization in the web UI. The example below uses the junit step, provided by the JUnit plugin.
In the example below, if tests fail, the Pipeline is marked «unstable», as denoted by a yellow ball in the web UI. Based on the recorded test reports, Jenkins can also provide historical trend analysis and visualization.
| Using an inline shell conditional ( sh ‘make check || true’ ) ensures that the sh step always sees a zero exit code, giving the junit step the opportunity to capture and process the test reports. Alternative approaches to this are covered in more detail in the Handling failure section below. |
| junit captures and associates the JUnit XML files matching the inclusion pattern ( **/target/*.xml ). |
Deploy
Deployment can imply a variety of steps, depending on the project or organization requirements, and may be anything from publishing built artifacts to an Artifactory server, to pushing code to a production system.
At this stage of the example Pipeline, both the «Build» and «Test» stages have successfully executed. In essence, the «Deploy» stage will only execute assuming previous stages completed successfully, otherwise the Pipeline would have exited early.
Assuming everything has executed successfully in the example Jenkins Pipeline, each successful Pipeline run will have associated build artifacts archived, test results reported upon and the full console output all in Jenkins.
A Scripted Pipeline can include conditional tests (shown above), loops, try/catch/finally blocks and even functions. The next section will cover this advanced Scripted Pipeline syntax in more detail.
Working with your Jenkinsfile
The following sections provide details about handling:
specific Pipeline syntax in your Jenkinsfile and
features and functionality of Pipeline syntax which are essential in building your application or Pipeline project.
Using environment variables
The current build ID, identical to BUILD_NUMBER for builds created in Jenkins versions 1.597+
The current build number, such as «153»
String of jenkins-$
The URL where the results of this build can be found (for example http://buildserver/jenkins/job/MyJobName/17/ )
The unique number that identifies the current executor (among executors of the same machine) performing this build. This is the number you see in the «build executor status», except that the number starts from 0, not 1
If your job is configured to use a specific JDK, this variable is set to the JAVA_HOME of the specified JDK. When this variable is set, PATH is also updated to include the bin subdirectory of JAVA_HOME
Full URL of Jenkins, such as https://example.com:port/jenkins/ (NOTE: only available if Jenkins URL set in «System Configuration»)
Name of the project of this build, such as «foo» or «foo/bar».
The name of the node the current build is running on. Set to ‘master’ for the Jenkins controller.
The absolute path of the workspace
Referencing or using these environment variables can be accomplished like accessing any key in a Groovy Map, for example:
Setting environment variables
Setting an environment variable within a Jenkins Pipeline is accomplished differently depending on whether Declarative or Scripted Pipeline is used.
Declarative Pipeline supports an environment directive, whereas users of Scripted Pipeline must use the withEnv step.
Setting environment variables dynamically
Handling credentials
Credentials configured in Jenkins can be handled in Pipelines for immediate use. Read more about using credentials in Jenkins on the Using credentials page.
For secret text, usernames and passwords, and secret files
Jenkins’ declarative Pipeline syntax has the credentials() helper method (used within the environment directive) which supports secret text, username and password, as well as secret file credentials. If you want to handle other types of credentials, refer to the For other credential types section (below).
Secret text
The following Pipeline code shows an example of how to create a Pipeline using environment variables for secret text credentials.
Usernames and passwords
The following Pipeline code snippets show an example of how to create a Pipeline using environment variables for username and password credentials.
When setting the credential environment variable in the environment directive:
this actually sets the following three environment variables:
By convention, variable names for environment variables are typically specified in capital case, with individual words separated by underscores. You can, however, specify any legitimate variable name using lower case characters. Bear in mind that the additional environment variables created by the credentials() method (above) will always be appended with _USR and _PSW (i.e. in the format of an underscore followed by three capital letters).
The following code snippet shows the example Pipeline in its entirety:
| The following credential environment variables (defined in this Pipeline’s environment directive) are available within this stage’s steps and can be referenced using the syntax: |
For example, here you can authenticate to Bitbucket with the username and password assigned to these credential variables.
To maintain the security and anonymity of these credentials, if the job displays the value of these credential variables from within the Pipeline the same behavior described in the Secret text example above applies to these username and password credential variable types too.
This only reduces the risk of accidental exposure. It does not prevent a malicious user from capturing the credential value by other means. A Pipeline that uses credentials can also disclose those credentials. Don’t allow untrusted Pipeline jobs to use trusted credentials.
Secret files
A secret file is a credential which is stored in a file and uploaded to Jenkins. Secret files are used for credentials that are:
too unwieldy to enter directly into Jenkins, and/or
in binary format, such as a GPG file.
For other credential types
To access the Snippet Generator for your Pipeline project/item:
From the Jenkins home page (i.e. the Dashboard of Jenkins’ classic UI), click the name of your Pipeline project/item.
On the left, click Pipeline Syntax and ensure that the Snippet Generator link is in bold at the top-left. (If not, click its link.)
From the Sample Step field, choose withCredentials: Bind credentials to variables.
Under Bindings, click Add and choose from the dropdown:
Click Generate Pipeline Script and Jenkins generates a withCredentials( … ) < … >Pipeline step snippet for the credentials you specified, which you can then copy and paste into your Declarative or Scripted Pipeline code.
Notes:
The Credentials fields (above) show the names of credentials configured in Jenkins. However, these values are converted to credential IDs after clicking Generate Pipeline Script.
To combine more than one credential in a single withCredentials( … ) < … >Pipeline step, see Combining credentials in one step (below) for details.
SSH User Private Key example
The optional passphraseVariable and usernameVariable definitions can be deleted in your final Pipeline code.
Certificate example
The optional aliasVariable and passwordVariable variable definitions can be deleted in your final Pipeline code.
The following code snippet shows an example Pipeline in its entirety, which implements the SSH User Private Key and Certificate snippets above:
To maintain the security and anonymity of these credentials, if you attempt to retrieve the value of these credential variables from within these withCredentials( … ) < … >steps, the same behavior described in the Secret text example (above) applies to these SSH public/private key pair credential and certificate variable types too.
This only reduces the risk of accidental exposure. It does not prevent a malicious user from capturing the credential value by other means. A Pipeline that uses credentials can also disclose those credentials. Don’t allow untrusted Pipeline jobs to use trusted credentials.
When using the Sample Step field’s withCredentials: Bind credentials to variables option in the Snippet Generator, only credentials which your current Pipeline project/item has access to can be selected from any Credentials field’s list. While you can manually write a withCredentials( … ) < … >step for your Pipeline (like the examples above), using the Snippet Generator is recommended to avoid specifying credentials that are out of scope for this Pipeline project/item, which when run, will make the step fail.
You can also use the Snippet Generator to generate withCredentials( … ) < … >steps to handle secret text, usernames and passwords and secret files. However, if you only need to handle these types of credentials, it is recommended you use the relevant procedure described in the section above for improved Pipeline code readability.
The use of single-quotes instead of double-quotes to define the script (the implicit parameter to sh ) in Groovy above. The single-quotes will cause the secret to be expanded by the shell as an environment variable. The double-quotes are potentially less secure as the secret is interpolated by Groovy, and so typical operating system process listings will accidentally disclose it :
Combining credentials in one step
Using the Snippet Generator, you can make multiple credentials available within a single withCredentials( … ) < … >step by doing the following:
From the Jenkins home page (i.e. the Dashboard of Jenkins’ classic UI), click the name of your Pipeline project/item.
On the left, click Pipeline Syntax and ensure that the Snippet Generator link is in bold at the top-left. (If not, click its link.)
From the Sample Step field, choose withCredentials: Bind credentials to variables.
Click Add under Bindings.
Choose the credential type to add to the withCredentials( … ) < … >step from the dropdown list.
Specify the credential Bindings details. Read more above these in the procedure under For other credential types (above).
Repeat from «Click Add …» (above) for each (set of) credential/s to add to the withCredentials( … ) < … >step.
Click Generate Pipeline Script to generate the final withCredentials( … ) < … >step snippet.
String interpolation
Jenkins Pipeline uses rules identical to Groovy for string interpolation. Groovy’s String interpolation support can be confusing to many newcomers to the language. While Groovy supports declaring a string with either single quotes, or double quotes, for example:
Understanding how to use string interpolation is vital for using some of Pipeline’s more advanced features.
Interpolation of sensitive environment variables
Groovy string interpolation should never be used with credentials.
Groovy string interpolation can leak sensitive environment variables (i.e. credentials, see: Handling credentials). This is because the sensitive environment variable will be interpolated during Groovy evaluation, and the environment variable’s value could be made available earlier than intended, resulting in sensitive data leaking in various contexts.
For example, consider a sensitive environment variable passed to the sh step.
Should Groovy perform the interpolation, the sensitive value will be injected directly into the arguments of the sh step, which among other issues, means that the literal value will be visible as an argument to the sh process on the agent in OS process listings. Using single-quotes instead of double-quotes when referencing these sensitive environment variables prevents this type of leaking.
Injection via interpolation
Groovy string interpolation can inject rogue commands into command interpreters via special characters.
Credential mangling is another issue that can occur when credentials that contain special characters are passed to a step using Groovy interpolation. When the credential value is mangled, it is no longer valid and will no longer be masked in the console log.
Handling parameters
Declarative Pipeline supports parameters out-of-the-box, allowing the Pipeline to accept user-specified parameters at runtime via the parameters directive. Configuring parameters with Scripted Pipeline is done with the properties step, which can be found in the Snippet Generator.
If you configured your pipeline to accept parameters using the Build with Parameters option, those parameters are accessible as members of the params variable.
Настраиваем Continuous Integration для Jenkins и Bitbucket с werf
Утилита werf создана так, чтобы её было легко интегрировать с любыми CI/CD-системами. Подробнее об этом процессе в общем случае читайте в эпилоге этой статьи, но основное её содержимое — практический пример по организации CI в Jenkins и Bitbucket.
Подразумевается, что в результате наших действий мы ожидаем получить следующее:
Конфигурация Jenkins
Для реализации задуманного в статье будут задействованы:
Итак, подключаем: Manage Jenkins → Configure System → Global Pipeline Libraries.
Нужно указать имя, ветвь репозитория, из которой Jenkins будет забирать код библиотеки, а в Source Code Management указать адрес и доступ до репозитория (в нашем случае — SSH-ключ для доступа ReadOnly).
Структура Shared Library
Теперь приступим к описанию самой библиотеки. Структура очень проста и состоит всего из трёх директорий:
К тому же, хотелось бы, чтобы весь пайплайн был полностью описан внутри библиотеки, а в Jenkinsfile мы передавали только некоторые параметры деплоя, которые в 99,9% случаев вообще не будут меняться.
Реализуем методы
Итак, реализуем 2 метода.
Триггеры по коммитам из Bitbucket
По умолчанию Jenkins сам не умеет интегрироваться в Bitbucket. Для этого нужно установить уже упомянутые плагины:
Также требуется создать служебного пользователя с доступом к репозиториям, т.к. Jenkins будет обнаруживать весь репозиторий через API. Это касается настройки как для cloud-версии, так и для собственного Bitbucket-сервера.
Пример из глобальных настроек Jenkins:
Далее понадобится настроить source в Multibranch Pipeline, что происходит в интерактивном режиме. Это означает, что, когда вы добавите credentials (Bitbucket пользователя и имя команды или пользователя, с проектами которых мы будем работать), Jenkins найдет все доступные пользователю репозитории и позволит выбрать один из списка.
В самом репозитории мы полагались на поиск только определенных веток, т.к. не уверены, как много веток может быть, а Jenkins может надолго «задуматься», если начнет исследовать каждую ветку. Это накладывает определенные ограничения, т.к. теги тоже попадают под регулярное выражение. Однако Java Regular Expressions — довольно гибкие, так что большой проблемы нет.
Альтернативный путь: если есть желание совсем отделить теги от веток, можно добавить еще один абсолютно такой же Source в репозиторий и настроить его только на обнаружение тегов.
После этого Jenkins с помощью сервис-аккаунта сам сходит в Bitbucket и создаст webhook:
Теперь при каждом коммите Bitbucket будет триггерить пайплайны (но только для тех веток и тегов, что мы отфильтровали) и даже посылать статус пайплайна обратно в Bitbucket в последнем столбце коммита:
Статусы — кликабельные: при нажатии перекидывают в нужный пайплайн в Jenkins
Последний штрих — про Jenkins, который находится за nginx proxy и работает с определенного location. Тогда нужно в основных настройках исправить его location, чтобы он сам знал, как выглядит его endpoint:
Без этого ссылки на pipeline в Bitbucket будут генерироваться некорректно.
Заключение
В статье рассмотрен вариант настройки CI с использованием Jenkins, Bitbucket и werf. Это очень общий пример, который не является панацеей для организации процесса разработки, однако даёт представление о том, как вообще подойти к построению своего CI с использованием werf.
Важная деталь: даже учитывая, что статус пайплайна отдается в Bitbucket, нам всё равно приходится «ходить» в Jenkins, чтобы разобрать результат в случае неудачи. Выкат по тегу через webhook, очевидно, может отрабатывать только один раз: любой откат на предыдущий тег придется делать вручную из Jenkins.
У данного подхода также есть большой плюс — это гибкость. Мы буквально можем прописать в CI всё что угодно. Хотя и порог вхождения для того, чтобы понимать, как именно это сделать, чуть выше, чем у других CI-систем.
Эпилог: про werf и CI/CD в целом
Общий подход к интеграции werf с CI/CD-системами описан в документации. Вкратце рекомендуемые для любых проектов шаги сводятся к следующим:



