Update Jenkins credentials on script

I have a Jenkins server running on Windows. It stores the username: password in the credential plugin. This is a user of the service who regularly updates his password.

I am looking for a way to run a script, preferably Powershell, that will update these credentials in the Jenkins password store so that it always updates when I use it in the script build job.

The password is controlled by the installation of Thycotic Secret Server, so I should be able to automate the process of updating this password, but I almost did not find how to do it, even if the blog post from the guy who wrote the api credentials mentions almost this script and then goes over to just a link to the credentials plugin download page, which reads: nothing about how to actually use the api.

Update

The accepted answer works fine, but an example of calling the rest method is to use curl, which if you use windows helps a little. Especially if you are trying to call a REST URL, but your Jenkins server uses AD Integration. You can use the following script for this.

Find the userId token and API by choosing People> User> Preferences> Show API Token.

$user = "UserID" $pass = "APIToken" $pair = "${user}:${pass}" $bytes = [System.Text.Encoding]::ASCII.GetBytes($pair) $base64 = [System.Convert]::ToBase64String($bytes) $basicAuthValue = "Basic $base64" $headers = @{ Authorization = $basicAuthValue } Invoke-WebRequest ` -uri "http://YourJenkinsServer:8080/scriptler/run/changeCredentialPassword.groovy?username=UrlEncodedTargetusername&password=URLEncodedNewPassword" ` -method Get ` -Headers $headers 
+6
source share
3 answers

Jenkins supports Groovy scripts. You can get the script console by opening the URL /script your Jenkins instance in the browser. (i.e. http: // localhost: 8080 / script )

The advantage of Groovy (over the file system or something else) is that these Groovy scripts run in Jenkins and have access to everything (config, plugins, tasks, etc.).

Then the following code will change the password for the user "BillHurt" to "s3crEt!":

 import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl def changePassword = { username, new_password -> def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, Jenkins.instance ) def c = creds.findResult { it.username == username ? it : null } if ( c ) { println "found credential ${c.id} for username ${c.username}" def credentials_store = Jenkins.instance.getExtensionList( 'com.cloudbees.plugins.credentials.SystemCredentialsProvider' )[0].getStore() def result = credentials_store.updateCredentials( com.cloudbees.plugins.credentials.domains.Domain.global(), c, new UsernamePasswordCredentialsImpl(c.scope, c.id, c.description, c.username, new_password) ) if (result) { println "password changed for ${username}" } else { println "failed to change password for ${username}" } } else { println "could not find credential for ${username}" } } changePassword('BillHurt', 's3crEt!') 

Classical Automation ( /scriptText )

To automate the execution of this script, you can save it in a file (let /tmp/changepassword.groovy ) and run the following curl command:

 curl -d "script=$(cat /tmp/changepassword.groovy)" http://localhost:8080/scriptText 

which should respond with HTTP 200 status HTTP 200 and text:

credentials found 801cf176-3455-4b6d-a461-457a288fd202 for username BillHurt

password changed for BillHurt

Automation with Scriptler Plugin

You can also install the Jenkins Scriptler plugin and proceed as follows:

enter image description here

  • Open the Scriptler tool in the side menu

enter image description here

  • fill in the 3rd first field, taking care to set the Id field to changeCredentialPassword.groovy
  • check the Define script checkbox.
  • add 2 parameters: username and password
  • paste the following script:
  import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl def changePassword = { username, new_password -> def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class, jenkins.model.Jenkins.instance ) def c = creds.findResult { it.username == username ? it : null } if ( c ) { println "found credential ${c.id} for username ${c.username}" def credentials_store = jenkins.model.Jenkins.instance.getExtensionList( 'com.cloudbees.plugins.credentials.SystemCredentialsProvider' )[0].getStore() def result = credentials_store.updateCredentials( com.cloudbees.plugins.credentials.domains.Domain.global(), c, new UsernamePasswordCredentialsImpl(c.scope, null, c.description, c.username, new_password) ) if (result) { println "password changed for ${username}" } else { println "failed to change password for ${username}" } } else { println "could not find credential for ${username}" } } changePassword("$username", "$password") 
  • and click Submit

Now you can call the following URL to change the password (replacing the username and password ): http: // localhost: 8080 / scriptler / run / changeCredentialPassword.groovy? Username = BillHurt & password = s3crEt% 21 (note the need for urlencode values parameters)

or with curl:

 curl -G http://localhost:8080/scriptler/run/changeCredentialPassword.groovy --data-urlencode 'username=BillHurt' --data-urlencode "password=s3crEt!" 

Sources:

Search engine: use the keywords 'Jenkins.instance.' , 'com.cloudbees.plugins.credentials' and UsernamePasswordCredentialsImpl

+13
source

I did not find a way to get the Groovy script to stop updating the identifier identifier, but I noticed that if I used the web interface to update credentials, the identifier did not change.

Based on this script, the Jenkins web UI script will be used below to perform updates.

Just for clarification, the reason is that it is important, because if you use something like a credential binding plugin to use credentials in your task, updating the identifier with credentials will break this link and your work will fail. Please excuse the use of $ args, not param (), as this is just an ugly hack, which I will clarify later.

Note the addition of the json payload to the form fields. I found that it is necessary in this particular format or the form message will not be executed.

 $username = $args[0] $password = $args[1] Add-Type -AssemblyName System.Web #1. Log in and capture the session. $homepageResponse = Invoke-WebRequest -uri http://Servername.domain.com/login?from=%2F -SessionVariable session $loginForm = $homepageResponse.Forms['login'] $loginForm.Fields.j_username = $username $loginForm.Fields.j_password = $password $loginResponse = Invoke-WebRequest ` -Uri http://Servername.domain.com/j_acegi_security_check ` -Method Post ` -Body $loginForm.Fields ` -WebSession $session #2. Get Credential ID $uri = "http://Servername.domain.com/credential-store/domain/_/api/xml" foreach($id in [string]((([xml](Invoke-WebRequest -uri $uri -method Get -Headers $headers -WebSession $session).content)).domainWrapper.Credentials | Get-Member -MemberType Property).Name -split ' '){ $id = $id -replace '_','' $uri = "http://Servername.domain.com/credential-store/domain/_/credential/$id/api/xml" $displayName = ([xml](Invoke-WebRequest -uri $uri -method Get -Headers $headers -WebSession $session).content).credentialsWrapper.displayName if($displayName -match $username){ $credentialID = $id } } #3. Get Update Form $updatePage = Invoke-WebRequest -Uri "http://Servername.domain.com/credential-store/domain/_/credential/$credentialID/update" -WebSession $session $updateForm = $updatePage.Forms['update'] $updateForm.Fields.'_.password' = $password #4. Submit Update Form $json = @{"stapler-class" = "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"; "scope"="GLOBAL";"username"="domain\$username";"password"=$password;"description"="";"id"=$id} | ConvertTo-Json $updateForm.Fields.Add("json",$json) Invoke-WebRequest ` -Uri "http://Servername.domain.com/credential-store/domain/_/credential/$credentialID/updateSubmit" ` -Method Post ` -Body $updateForm.Fields ` -WebSession $session 
+1
source

I decided to write a new answer, although this is mainly an update for @Tomasleveil:

  • removal of obsolete calls (thanks to jenkins wiki , for other listing options see the plugin user guide )
  • add comments
  • save credential identifier to avoid breaking existing tasks.
  • check credentials for descriptions because user names are rarely unique (the reader can easily change this to search for IDs)

Here he is:

 credentialsDescription = "my credentials description" newPassword = "hello" // list credentials def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( // com.cloudbees.plugins.credentials.common.StandardUsernameCredentials to catch all types com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials.class, Jenkins.instance, null, null ); // select based on description (based on ID might be even better) cred = creds.find { it.description == credentialsDescription} println "current values: ${cred.username}:${cred.password} / ${cred.id}" // not sure what the other stores would be useful for, but you can list more stores by // com.cloudbees.plugins.credentials.CredentialsProvider.all() credentials_store = jenkins.model.Jenkins.instance.getExtensionList( 'com.cloudbees.plugins.credentials.SystemCredentialsProvider' )[0].getStore() // replace existing credentials with a new instance updated = credentials_store.updateCredentials( com.cloudbees.plugins.credentials.domains.Domain.global(), cred, // make sure you create an instance from the correct type new com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl(cred.scope, cred.id, cred.description, cred.username, newPassword) ) if (updated) { println "password changed for '${cred.description}'" } else { println "failed to change password for '${cred.description}'" } 
+1
source

All Articles