Groovy's interpolation doc explains that why I am getting an insecure warning for my httpRequest. I used this:
withCredentials([usernamePassword(credentialsId: 'myKeys', usernameVariable: 'user', passwordVariable: 'password')]) {
def response = httpRequest url: "https://someurl",
requestBody:"grant_type=password&username=${user}&password=${password}&client_id=id4&client_secret=secret4"
}
I think my attempted fix only applies to shell commands or something but as per the doc, I tried replacing the requestBody with:
requestBody:'grant_type=password&username=$user&password=$password&client_id=id4&client_secret=secret4'
...Which returns a 401 error, implying that the $user and $password were just interpreted as non variables. Not sure how I can securely use the withCredentials method without interpolation. Thank you for the help.
Related
I am trying to run a script to dictate whether a Jenkins step runs. This script needs credentials, which we access by calling withCredentials.
Here's a slightly reduced example:
stage('Sample test stage') {
when {
expression {
withCredentials([usernamePassword(credentialsId: 'MY_CREDENTIALS_ID', usernameVariable: 'MY_USERNAME', passwordVariable: 'MY_TOKEN')]) {
return sh([returnStdout: true, script: 'node bin/my-script ${MY_TOKEN}']).trim().startsWith('success')
}
}
}
steps {
echo 'I should only run when the script passes'
}
}
However, this doesn't work. Jenkins returns the error: "syntax error: bad substitution."
I'm assuming it's down to the syntax used when trying to pass in the credentials. I've tried a couple of variations, such as returning withCredentials and wrapping the whole expression in withCredentials, but both of them had fairly dramatic errors.
I cannot find any documentation on this, which makes me wonder if it's illegal
I feel quite silly. There's a difference between " and ' in Groovy. Within single quotes, only Bash substitutions will work. Within double quotes, both Groovy and Bash substitutions will work.
I have checked many suggestions regarding the issue, but didn't find a suitable solution.
Initially my pipeline code was working fine but with a Jenkins security warning The following steps that have been detected may have insecure interpolation of sensitive variables. sh: [pass, user]
My code is as below:
withCredentials([usernamePassword(credentialsId: 'Jenkins-Nexus-tech', passwordVariable: 'pass', usernameVariable: 'user')]){
sh "wget --user=$user --password=$pass 'https://nexus.mycompany.io/repository/updated-maven-releases/com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war' "
}
Warning:
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [pass, user]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
To avoid the Jenkins security warning as suggested in https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#interpolation-of-sensitive-environment-variables , I have modified my code as below. But with different permutation and combination of single and double quotes it is not working. It is throwing Bad substitution error:
withCredentials([usernamePassword(credentialsId: 'Jenkins-Nexus-tech', passwordVariable: 'pass', usernameVariable: 'user')]){
sh 'wget --user=$user --password=$pass \"https://nexus.mycompany.io/repository/updated-maven-releases/com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war\" '
}
I have tried with 3 single quotes. with this I am not getting the warning but it is unable to substitute the variables in the wget URL:
withCredentials([usernamePassword(credentialsId: 'Jenkins-Nexus-tech', passwordVariable: 'pass', usernameVariable: 'user')]){
sh '''wget --user=$user --password=$pass 'https://nexus.mycompany.io/repository/updated-maven-releases/com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war' '''
}
Error is as below as it can't substitute the values of the variable
[Pipeline] sh
+ wget --user=**** --password=**** https://nexus.mycompany.io/repository/updated-maven-releases/com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war
HTTP request sent, awaiting response... 404 com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war
ERROR 404: com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war.
It would be really great if someone can assist here.
The suggestion outlined in the page you mention suggests you do not use Groovy string interpolation to pass sensitive data to sh steps. The suggestion is to let the sh script instead get the values from the environment.
However, in your case you still need the value held in the params.AuthorizationServerVersion in your sh step.
Groovy string interpolation is only used when the string is within double quotes. String interpolation is turned off when the string is in single quotes.
When a string is in double quotes, you can escape $s using a backslash. This will prevent inserting the contents of a variable into the string when you don't want this to occur.
What you can do, then, is use double quotes, escape the $s on the variables you want to read from the environment, and leave the $s un-escaped on the variables you want to access directly from your Groovy code.
An example, using the withCredentials plugin:
withCredentials([string(credentialsId: 'mytoken', variable: 'THE_TOKEN')]) {
sh "some_command --that-uses \$THE_TOKEN --as-an-environment-variable --and-also-uses $params.A_PARAMETER"
}
Here, the token is injected into the environment as a secret, and is used in the sh script by escaping the $. This means the actual Unix shell (bash, zsh, or whatever) will get the literal $ and expand it as specified by that shell language.
The $ for $params.A_PARAMETER is not escaped, and is within double quotes, so Groovy will perform string interpolation and replace $params.A_PARAMETER with the value of the parameter at runtime as the string is constructed in memory, before the string is passed as an argument to the sh step.
In your specific case, this is what you can use (within your withCredentials block, of course):
sh "wget --user=\$user --password=\$pass 'https://nexus.mycompany.io/repository/updated-maven-releases/com/mycompany/project/authorization-server/${params.AuthorizationServerVersion}/authorization-server-${params.AuthorizationServerVersion}.war'"
Note that the $ on $user and $pass are escaped, but the $ on ${params.AuthorizationServerVersion} is not escaped.
In my pipeline script I want to execute the following sh command including a password (e.g. 123$ABC) with special characters:
withCredentials([sshUserPrivateKey(credentialsId: 'id', keyFileVariable: 'keyFile', passphraseVariable: '', usernameVariable: 'user')]) {
sh "ssh -i $keyFile ${user}#${virtualMachine} -C \"CONTAINER_NAME=${dockerContainerName} DOCKER_TAG=${dockerImageTag} JASYPT_MASTER_PASSWORD='${JASYPT_MASTER_PW}' docker-compose -f /tmp/docker-compose-jenkins.yml up\""
}
How must the command look like to obtain the special characters in my password?
I have the same issue, the possible solution is to decode the password variable, something like:
def encodedPassword = URLEncoder.encode("$JASYPT_MASTER_PW",'UTF-8')
and then use the encodedPassword variable instead of JASYPT_MASTER_PW
Let's try
I am retrieving the username password from the credentials plugin.
The values are then saved as environmental variables. I am using the password in later stages of the pipeline, in sh block as an argument for curl.
At this point the password is displayed in plaintext in the build logs. Is there a way to avoid this? I assumed by using the credentials plugin the password will be masked.
pipeline {
stages {
stage ('One') {
steps {
withCredentials([userNamePassword(credentialsId: 'my_cred', userNameVariable: 'User_Name', passwordVariable: 'Password')]){
env.User_Name = User_Name
env.Password = Password
}
}
}
stage ('Two') {
sh '''
curl -v -u ${User_Name}:${Password} ...
'''
}
}
}
Note: I am using the curl to upload a file to a remote host.
Thats true. The password will be displayed in plaintext.
The best way for your request, ist to use the HTTP Request Plugin.
You can pass credentials in "Authorization" in the Header inestead of URL.
I ended up using the curl inside the withCredentialsblock.
withCredentials([userNamePassword(credentialsId: 'my_cred', userNameVariable: 'User_Name', passwordVariable: 'Password')]){
sh '''
curl -v -u ${User_Name}:${Password} ...
'''
}
i am trying to use jenkins scripted pipeline to invoke config file provider plugin along with fetching credentials from jenkins for the username and password, but the below doesn't seem to work.
node {
def mvnHome
def mvnSettings
stage('Prepare') {
mvnHome = tool 'maven-3.5.4'
}
stage('Checkout') {
checkout scm
}
stage('Deploy'){
def usernameLocal, passwordLocal, usr, psw
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'xyz', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME']]) {
usernameLocal = env.USERNAME
passwordLocal = env.PASSWORD
}
configFileProvider(
[configFile(fileId: '*********', variable: 'MAVEN_SETTINGS', replaceTokens: true)])
{
usr="${usernameLocal}"
psw="${passwordLocal}"
sh "echo $usr"
sh "'${mvnHome}/bin/mvn' -s $MAVEN_SETTINGS deploy -Dserver.username="${usernameLocal}" -Dserver.password="${passwordLocal}""
}
}
}
where server.username and server.password are defined as properties under settings.xml server section for username and password.
Looks like i found out the issue and its nothing to do with withCredentials used here rather to do with the config file provider plugin. So i am able to print the credentials username correctly but somehow the config file provider is unable to substitute the variable value in the settings.xml.
so i don't get any error anymore, its just that the deployment doesn't go through with 401 unauthorized since the below in my settings.xml never gets the correct values :-
<server>
<id>snapshot</id>
<username>${server.username}</username>
<password>${server.password}</password>
</server>
Could you please advise how to resolve this?
The variables created by withCredentials are Groovy variables not environment variables. Try the following:
stage('Deploy'){
withCredentials([usernamePassword(credentialsId:'xyz', passwordVariable: 'Password', usernameVariable: 'Username')]) {
configFileProvider([configFile(fileId: 'abcde', variable:'MAVEN_SETTINGS')]) {
sh "'${mvnHome}/bin/mvn' -s $MAVEN_SETTINGS deploy -Dserver.username=${Username} -Dserver.password=${Password}"
}
}
}
Ok I figured out the solution, declare the configFileProvider entire section under the block of withCredentials and pass:
-Dserver.username='${usernameLocal}' -Dserver.password='${passwordLocal}'
(Please note single quotes). This way the values also get substituted and are outputted in the logs as masked.