I'm trying to get access to the credentials stored in Jenkins without having to hardcode them in the script itself.
#!/usr/bin/env groovy
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'GroovyAWSScMgr', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
return ["${env.AWS_ACCESS_KEY_ID}"]
}
I've tried:
return [AWS_ACCESS_KEY_ID]
return [env.AWS_ACCESS_KEY_ID]
return ["${env.AWS_ACCESS_KEY_ID}"]
return ["${env.AWS_ACCESS_KEY_ID}"]
The result continues to be NULL
You can try this:
import jenkins.model.*
credentialsId = 'GroovyAWSScMgr'
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, Jenkins.instance, null, null ).find{
it.id == credentialsId}
return [creds.username]
You can use creds.usernameand creds.password in you script.
I'm not sure if it is secure.
I tried something similar in Active Choices Parameter for one of my jobs and nothing worked. I have instead used the below to prevent hardcoding credentials
Define your credentials, for ex. in your case AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY with appropriate values, as Environment variables in Manage Jenkins -> Configure System -> Global properties and retrieve them in your script
import jenkins.model.*
instance = Jenkins.getInstance()
globalNodeProperties = instance.getGlobalNodeProperties()
aws_access_key_id = ''
aws_secret_key = ''
globalNodeProperties.each {
envVars = it.getEnvVars()
if (envVars.get('AWS_ACCESS_KEY_ID') != null) {
aws_access_key_id = envVars.get('AWS_ACCESS_KEY_ID');
}
if (envVars.get('AWS_SECRET_ACCESS_KEY') != null) {
aws_secret_key = envVars.get('AWS_SECRET_ACCESS_KEY');
}
}
You can refer them in your script as ${aws_access_key_id} and ${aws_secret_key}
Related
I'm trying to set environment variables in a jenkins pipeline script.
I want to use the section "Prepare an environment for the run" in configure. So, in this section, I put the following groovy script:
instance = Jenkins.getInstance()
def globalNodeProperties = instance.getGlobalNodeProperties()
def envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
def newEnvVarsNodeProperty = null
def envVars = null
if ( envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0 ) {
newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
globalNodeProperties.add(newEnvVarsNodeProperty)
envVars = newEnvVarsNodeProperty.getEnvVars()
} else {
envVars = envVarsNodePropertyList.get(0).getEnvVars()
}
envVars.put("DEFCONFIG", "Name_of_Defconfig")
instance.save()
And, the pipeline script is shown below :
def get_name() {
return env.DEFCONFIG
}
pipeline {
agent {
node {
label 'BSP'
}
}
environment {
defconfig_name = get_name()
}
stages {
stage('test var') {
steps {
sh '''
echo ${defconfig_name}
echo "Hello word"
'''
}
}
}
}
But, instead of reading the value of DEFCONFIG I find "null" in the console:
[Pipeline] sh
+ echo null
null
Probably I am missing something but I cannot find what.
Any idea please?
I'd like to use a withCredentials() block in a shared-variable ("vars/") script rather than directly in the Jenkins pipeline because this is a lower-level semantic of a particular library, and also may or may not be required depending on the situation. However, withCredentials (or, at least, that signature of it) doesn't appear to be in scope.
script:
def credentials = [
[$class: 'UsernamePasswordMultiBinding', credentialsId: '6a55c310-aaf9-4822-bf41-5500cd82af4e', passwordVariable: 'GERRIT_PASSWORD', usernameVariable: 'GERRIT_USERNAME'],
[$class: 'StringBinding', credentialsId: 'SVC_SWREGISTRY_PASSWORD', variable: 'SVC_SWREGISTRY_PASSWORD']
]
withCredentials(credentials) {
// ...
}
Console:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: BuildagentInstallAndRun.withCredentials() is applicable for argument types: (java.util.ArrayList, org.jenkinsci.plugins.workflow.cps.CpsClosure2) values: [[[$class:UsernamePasswordMultiBinding, credentialsId:6a55c310-aaf9-4822-bf41-5500cd82af4e, ...], ...], ...]
Has anyone had any success with this?
I'm using a shared library rather than a shared variable, but I guess it is a similar situation.
I'm not using the $class parameter, but i'm calling directly one of the functions suggested by the pipeline snippet generator. You can have a list here. In the example below, I use the usernameColonPassword binding.
In the pipeline, I instantiate the class utilities and I pass this to the constructor. Then, in the library, I use the step object to access the pipeline steps (such as withCredentials or usernameColonPassword).
class Utilities implements Serializable {
def steps
Utilities(steps) {
this.steps = steps
}
def doArchiveToNexus(String credentials, String artifact, String artifact_registry_path){
try {
this.steps.withCredentials([steps.usernameColonPassword(credentialsId: credentials, variable: 'JENKINS_USER')]) {
this.steps.sh "curl --user " + '${JENKINS_USER}' + " --upload-file ${artifact} ${artifact_registry_path}"
}
} catch (error){
this.steps.echo error.getMessage()
throw error
}
}
}
You can try following:
import jenkins.model.*
credentialsId = '6a55c310-aaf9-4822-bf41-5500cd82af4e'
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, Jenkins.instance, null, null ).find{
it.id == credentialsId}
println creds.username
println creds.password
But it is not secure, everything will be in console log
I was able to obtain credentials inside the shared library with proper passwords masking with such code:
class Utilities implements Serializable {
def steps
Utilities(steps) {
this.steps = steps
}
def execute() {
this.steps.withCredentials(
bindings: [
this.steps.usernameColonPassword(
credentialsId: this.credentialsId,
variable: "unameColonPwd")
]) {
this.steps.sh "echo {this.steps.env.unameColonPwd}"
}
}
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
I am looking to set some configurations in Jenkins as part of a Docker build and using the init.groovy.d scripts to do so.
I am able to run the below code successfully when a Global Property already exists, but when there are no Global Properties in place the script is successful but the property is not added.
import jenkins.*
import jenkins.model.*
def instance = Jenkins.getInstance()
println "--> setting Global properties (Environment variables)..."
def globalProps = hudson.model.Hudson.instance.globalNodeProperties
def props = globalProps.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
for (prop in props) {
prop.envVars.put("PATH", "/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin")
}
instance.save()
println "--> setting Global properties (Environment variables)... done!"
How can I run this command in a Jenkins instance with no global properties already set?
This was caused by the for loop essentially looping over an empty array. Fixed by changing the code. No issue with Jenkins, just my implementation!
if ( envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0 ) {
newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
globalNodeProperties.add(newEnvVarsNodeProperty)
envVars = newEnvVarsNodeProperty.getEnvVars()
} else {
envVars = envVarsNodePropertyList.get(0).getEnvVars()
}
envVars.put("PATH", "/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin")
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)