Conditionally selecting credentials in withcredentials in jenkins - jenkins

I have a jenkins stage which requires different credentials based on some parameters. The contents stays the same for each stage, the only change is the credentials, so I could achieve this by just having multiple stages with single credentials then just using those, but obviously not ideal.
I'm trying it essentially like this but jenkins doesn't like it
stage('test execute') {
steps {
withCredentials([
if (params.Env == 'env1') {
usernamePassword(credentialsId: 'creds1', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')
} else if (params.Env == 'env2') {
usernamePassword(credentialsId: 'creds2', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')
}
])
}
}
I get the below error though
WorkflowScript: 25: unexpected token: if # line 25, column 21.
if (params.Env == 'env1') {
^
so I'm not sure if there's any way to add conditional logic to withcredentials, or if I just have to have multiple stages with essentially the same code

I got around this by storing the credentialsId in an environment variable, and then using that env variable in the usernamePassword() statement.
def getDeploymentCreds(envName)
{
switch(envName) {
case ~/^Dev/: return 'MY_DEV_CREDS'
case ~/^QA/: return 'MY_QA_CREDS'
case ~/^Beta/: return 'MY_BETA_CREDS'
}
}
// ...
script {
env.DEPLOY_CREDS_ID = getDeploymentCreds(env.TARGET_ENVIRONMENT)
}
// ...
withCredentials([
usernamePassword(credentialsId: env.DEPLOY_CREDS_ID, passwordVariable: 'DEPLOY_PASS', usernameVariable: 'DEPLOY_USER')
])

Related

Jenkins declarative pipeline load parameters in pre condition

in jenkins declarative pipeline is there a way to execute pre condition whereby it should load build parameters from a file. In Jenkins there is an option whereby we can restart individual stage. Therefore, i wish for each stage to load the parameters from groovy file.
Currently is
pipeline {
agent any
stage("Grep the values") {
steps {
load "${WORKSPACE}/file-parameter.groovy"
}
}
stage("Perform Deploynment) {
when {
expression { "${Perform_Deployment}" == "true" }
}
steps {
withCredentials([
usernamePassword(credentialsId: "LoginID", passwordVariable: "LoginPassword", usernameVariable: "LoginUser")
]) {
ansiblePlaybook (
playbook: "${WORKSPACE}/ansible-playbook.yml",
forks: 5,
extraVars: [
loginUser: "${LoginUser}",
loginPassword: "${LoginPassword}"
]
)
}
}
}
}
}
How can i load "${WORKSPACE}/file-parameter.groovy" in teh stage before when condition. My expectation should be somethign as below
pipeline {
agent any
stage("Grep the values") {
steps {
load "${WORKSPACE}/file-parameter.groovy"
}
}
stage("Perform Deploynment) {
load "${WORKSPACE}/file-parameter.groovy"
when {
expression { "${Perform_Deployment}" == "true" }
}
steps {
withCredentials([
usernamePassword(credentialsId: "LoginID", passwordVariable: "LoginPassword", usernameVariable: "LoginUser")
]) {
ansiblePlaybook (
playbook: "${WORKSPACE}/ansible-playbook.yml",
forks: 5,
extraVars: [
loginUser: "${LoginUser}",
loginPassword: "${LoginPassword}"
]
)
}
}
}
}
}
The load step returns whatever the groovy script returned when it was executed, so you need to store it in a variable
file-parameter.groovy could either look like this:
return [
performDeployment: true,
// other variables
]
or like this
performDeployment = true
// other variables and methods
return this
In both cases you could use it in your pipeline like so:
stage("Grep the values") {
steps {
script {
fileParams = load("${WORKSPACE}/file-parameter.groovy")
}
}
}
stage("Perform Deploynment) {
when {
expression { fileParams.performDeployment }
}
I am pretty sure there is no need for the string comparison you are doing and you could use just the boolean value instead.

Jenkins - translate withCredentials into declarative style syntax

I have a jenkins pipeline which is written using a scripted syntax and I need to make this into a new pipeline using a declarative style.
This is my fist project with jenkins and I am stuck at how to translate the withCredentials syntax in declarative jenkins.
The original(scripted) pipeline looks something like this:
stage('stage1') {
steps {
script {
withCredentials([usernamePassword(credentialsId: CredentialsAWS, passwordVariable: 'AWS_SECRET_ACCESS_KEY', usernameVariable: 'AWS_ACCESS_KEY_ID')]) {
parallel (
something: {
sh 'some commands where there is no reference to the above credentials'
}
)
}
}
}
}
So far, I have set the credentials in question as an environment variable but since in the original pipeline these are not referenced in the command but they just wrap around the command as 'withCredentials', I am not sure how to achieve the same result. Any idea how to do this?
First of all take a look at official documentation
For your case pipeline will look like:
pipeline {
agent any
environment {
YOUR_CRED = credentials('CredentialsAWS')
}
stages {
stage('Call username and password from YOUR_CRED') {
steps {
echo "To call username use ${YOUR_CRED_USR}"
echo "To call password use ${YOUR_CRED_PSW}"
}
}
}
}
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
parameters {
string(name: 'STATEMENT', defaultValue: 'hello; ls /', description: 'What should I say?')
}
stages {
stage('Example') {
steps {
/* CORRECT */
sh('echo ${STATEMENT}')
}
}
}
}
visit here

How to create withXCredentials that wraps Jenkins withCredentials using Closure in Jenkins shared variable?

I want to have this code with exactly this syntax in my pipeline script:
withXCredentials(id: 'some-cred-id', usernameVar: 'USER', passwordVar: 'PASS') {
//do some stuff with $USER and $PASS
echo "${env.USER} - ${env.PASS}"
}
Note that you can put any code within withXCredenitals to be executed. withXCredentials.groovy resides in my Jenkins shared library under vars folder and it will use
Jenkins original withCredentials:
//withXCredentials.groovy
def userVar = params.usernameVar
def passwordVar = params.passwordVar
def credentialsId = params.credentialsId
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: credentialsId, usernameVariable: usernameVar, passwordVariable: passwordVar]]) {
body()
}
I am still learning advanced groovy stuff but I can't work out how to do this.
Please note:
My question is more about the syntax in groovy and using Closure and the answer here is not what I am after. With that solution, I need to instantiate the class first and then call the method. So I'm trying to avoid doing something like this:
new WithXCredentials(this).doSomthing(credentialsId, userVar, passwordVar)
In Jenkins documentation it has an example of using closure:
// vars/windows.groovy
def call(Closure body) {
node('windows') {
body()
}
}
//the above can be called like this:
windows {
bat "cmd /?"
}
But it doesn't explain how to pass parameters like this
windows(param1, param2) {
bat "cmd /?"
}
See here
So after digging internet I finally found the answer. In case anyone needs the same thing. The following code will work:
// filename in shared lib: /vars/withXCredentials.groovy
def call(map, Closure body) {
def credentialsId = map.credentialsId
def passwordVariable = map.passwordVariable
def usernameVariable = map.usernameVariable
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: credentialsId, usernameVariable: usernameVariable, passwordVariable: passwordVariable]]) {
echo 'INSIDE withXCredentials'
echo env."${passwordVariable}"
echo env."${usernameVariable}"
body()
}
}
With this you can have the following in your pipeline:
node('name') {
withXCredentials([credentialsId: 'some-credential', passwordVariable: 'my_password',
usernameVariable: 'my_username']) {
echo 'Outside withXCredenitals'
checkout_some_code username: "$env.my_username", password: "$env.my_password"
}
}

Jenkins : use withCredentials in global environment section

I have a Jenkins pipeline with multiple stages that all require the same environment variables, I run this like so:
script {
withCredentials([usernamePassword(credentialsId: 'COMPOSER_REPO_MAGENTO', passwordVariable: 'MAGE_REPO_PASS', usernameVariable: 'MAGE_REPO_USER')]) {
def composerAuth = """{
"http-basic": {
"repo.magento.com": {
"username": "${MAGE_REPO_USER}",
"password": "${MAGE_REPO_PASS}"
}
}
}""";
// do some stuff here that uses composerAuth
}
}
I don't want to have to re-declare composerAuth every time, so I want to store the credentials in a global variable, so I can do something like:
script {
// do some stuff here that uses global set composerAuth
}
I've tried putting it in the environment section:
environment {
DOCKER_IMAGE_NAME = "magento2_website_sibo"
withCredentials([usernamePassword(credentialsId: 'COMPOSER_REPO_MAGENTO', passwordVariable: 'MAGE_REPO_PASS', usernameVariable: 'MAGE_REPO_USER')]) {
COMPOSER_AUTH = """{
"http-basic": {
"repo.magento.com": {
"username": "${MAGE_REPO_USER}",
"password": "${MAGE_REPO_PASS}"
}
}
}""";
}
}
But (groovy noob as I am) that doesn't work. So what's the best approach on setting a globally accessible variable with credentials but only have to declare it once?
You can use credentials helper method of the environment section. For "Username and passwrd" type of credentials it assigns 2 additional environment variables. Example:
environment {
MAGE_REPO_CREDENTIALS = credentials('COMPOSER_REPO_MAGENTO')
COMPOSER_AUTH = """{
"http-basic": {
"repo.magento.com": {
"username": "${env.MAGE_REPO_CREDENTIALS_USR}",
"password": "${env.MAGE_REPO_CREDENTIALS_PSW}"
}
}
}"""
}
Read more
After a lot of search (and struggle), i came up with an easy workaround:
As better explained in the jenkins docs for Handling Credentials, when injecting a usernamePassword type credential into an environment variable named VAR_NAME, jenkins automatically generates two other variables ending with _USR and _PSW respectively for usernameVariable and passwordVariable parameters.
What i did was to inject my variables with the values from both USR and PSW new variables.
In #Giel Berkers case, it should be something like this:
environment {
DOCKER_IMAGE_NAME = "magento2_website_sibo"
COMPOSER_REPO_MAGENTO_CREDENTIAL = credentials('COMPOSER_REPO_MAGENTO')
COMPOSER_AUTH = """{
"http-basic": {
"repo.magento.com": {
"username": "${COMPOSER_REPO_MAGENTO_CREDENTIAL_USR}",
"password": "${COMPOSER_REPO_MAGENTO_CREDENTIAL_PSW}"
}
}
}""";
}
Here is how you can accomplish that
pipeline {
agent any
stages {
stage('first') {
steps {
script {
withCredentials([usernamePassword(credentialsId: 'COMPOSER_REPO_MAGENTO', passwordVariable: 'MAGE_REPO_PASS', usernameVariable: 'MAGE_REPO_USER')]) {
def user = env.MAGE_REPO_USER
def password = env.MAGE_REPO_PASS
//Initializing a global variable. Notice there is no def here
composerAuth = """{
"http-basic": {
"repo.magento.com": {
"username": "${user}",
"password": "${password}"
}
}
}"""
}
}
}
}
stage('second') {
steps {
script {
println composerAuth
}
}
}
}
}
I found this and it is helpful:
Source: https://wiki.jenkins.io/display/JENKINS/Credentials+Binding+Plugin
// Basic example
withCredentials([usernamePassword(credentialsId: 'amazon',
usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
//available as an env variable, but will be masked if you try to print it out any which way
sh 'echo $PASSWORD'
echo "${env.USERNAME}"
}
// You can also request multiple credentials in a single call
withCredentials([usernamePassword(credentialsId: 'amazon',
usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',
variable: 'SLACK_URL'),]) {
sh 'echo $PASSWORD'
echo "${env.SLACK_URL}"
}
// Older code might not use the new syntax (usernamePassword, string, ...) yet, and directly call the class:
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'amazon',
usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
//available as an env variable, but will be masked if you try to print it out any which way
sh 'echo $PASSWORD'
echo "${env.USERNAME}"
}
You may need to deal with multi-field credentials or vendor-specific credential types that the plugin does not (yet) support.
In this situation you have a couple of choices:
Use the closest standard multi-field credential (e.g. Username With Password) that fits your requirements.
Use a string credential, serialize all the fields into the secret value (e.g. as JSON or as a delimited string), and parse them in the job script. (This is a last resort when other methods don't work, e.g. when secret rotation would cause multiple fields to change.)
Example: Jenkins authenticates to Secrets Manager using the primary AWS credential (from the environment). You have a job that performs a particular AWS operation in a different account, which uses a secondary AWS credential. You choose to encode the secondary AWS credential as JSON in the string credential foo:
node {
withCredentials([string(credentialsId: 'foo', variable: 'secret')]) {
script {
def creds = readJSON text: secret
env.AWS_ACCESS_KEY_ID = creds['accessKeyId']
env.AWS_SECRET_ACCESS_KEY = creds['secretAccessKey']
env.AWS_REGION = 'us-east-1' // or whatever
}
sh "aws sts get-caller-identity" // or whatever
}
}
A typical example of a username password type credential (example from here) would look like:
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
// available as an env variable, but will be masked if you try to print it out any which way
// note: single quotes prevent Groovy interpolation; expansion is by Bourne Shell, which is what you want
sh 'echo $PASSWORD'
// also available as a Groovy variable
echo USERNAME
// or inside double quotes for string interpolation
echo "username is $USERNAME"
}
ReadMore1
ReadMore2

Jenkins withCredentials in dynamic selected parameters

could you help me with a litle throuble?
I tried find solution with jenkins and your wonderful plugin: uno-choice, but I couldn't it.
I have very simple script:
#!/usr/bin/env groovy
def sout = new StringBuffer(), serr = new StringBuffer()
def proc ='/var/lib/jenkins/script.sh location'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
def credential(name) {
def v;
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: name, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
v = "${env.USERNAME}"
}
return v
}
def key = credential('aws_prod_api')
String str = sout.toString()
String s = str.trim()
String[] items = s.split(",");
def v1 = Arrays.asList(items)
return v1
In general I want get AWS Credentional which save in Jenkins from bash script and with it do something.
I want use withCredentials in block which make selected list, but I don't understand how I can do it.
Could you help me with it?
I will very appreciate it
I tried using withCredentials inside groovy, but I got error:
Fallback to default script... groovy.lang.MissingMethodException: No
signature of method: Script1.withCredentials() is applicable for
argument types: (java.util.ArrayList, Script1$_credential_closure1)
values: [[[$class:UsernamePasswordMultiBinding,
credentialsId:aws_prod_api, ...]], ...] at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:81)
at
It's because withCredentials does not exist in the scope of Script1. It exists in the scope of the Jenkinsfile DSL. You need to pass it in.
I suggest converting your script to functions. Then passing the Jenkinsfile DSL through to your Groovy code.
def doAwsStuff(dsl) {
...
def key = credential(dsl, 'aws_prod_api')
...
}
def credential(dsl, name) {
def v;
dsl.withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: name, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
v = "${env.USERNAME}"
}
return v
}
and then call it from your Jenkinsfile with:
def result = MyAwsStuff.doAwsStuff(this)

Resources