通过脚本更新Jenkins凭据

通过脚本更新Jenkins凭据,jenkins,scripting,Jenkins,Scripting,我有一个运行在Windows上的Jenkins服务器。它在凭证插件中存储用户名:密码。这是一个定期更新密码的服务用户 我正在寻找一种运行脚本(最好是Powershell)的方法,该脚本将更新Jenkins密码存储中的凭据,以便在生成作业脚本中使用该凭据时始终保持最新 密码由Thycotic Secret Server安装管理,因此我应该能够自动更新此密码,但我几乎找不到实现此目的的线索,尽管编写凭据api的人的报告几乎完全提到了这个场景,然后继续链接到凭据插件的下载页面,但没有说明如何实际使用a

我有一个运行在Windows上的Jenkins服务器。它在凭证插件中存储用户名:密码。这是一个定期更新密码的服务用户

我正在寻找一种运行脚本(最好是Powershell)的方法,该脚本将更新Jenkins密码存储中的凭据,以便在生成作业脚本中使用该凭据时始终保持最新

密码由Thycotic Secret Server安装管理,因此我应该能够自动更新此密码,但我几乎找不到实现此目的的线索,尽管编写凭据api的人的报告几乎完全提到了这个场景,然后继续链接到凭据插件的下载页面,但没有说明如何实际使用api

更新

公认的答案非常有效,但rest方法调用示例使用的是curl,如果您使用的是windows,这并没有多大帮助。特别是当您试图调用RESTURL,但Jenkins服务器正在使用AD集成时。要实现这一点,可以使用以下脚本

通过转到人员>用户>配置>显示API令牌来查找用户ID和API令牌

$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

Jenkins支持使用Groovy语言编写脚本。通过在浏览器中打开Jenkins实例的URL
/script
,您可以获得一个。(即:)

Groovy语言(相对于powershell或其他任何语言)的优势在于,这些Groovy脚本在Jenkins中执行,并且可以访问所有内容(配置、插件、作业等)

然后,以下代码将用户“Billhert”的密码更改为“s3crEt!”:

import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
def changePassword={用户名,新密码->
def creds=com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
詹金斯实例
)
def c=creds.findResult{it.username==username?it:null}
如果(c){
println“找到用户名${c.username}的凭据${c.id}”
def credentials_store=Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
def result=credentials\u store.updateCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
C
新用户名PasswordCredentialSimpl(c.scope、c.id、c.description、c.username、新密码)
)
如果(结果){
println“更改了${username}的密码”
}否则{
println“更改${username}的密码失败”
}
}否则{
println“找不到${username}的凭据”
}
}
更改密码('BillHurt','s3crEt!')

经典自动化(
/scriptText
) 要自动执行此脚本,可以将其保存到文件(比如
/tmp/changepassword.groovy
)并运行以下curl命令:

curl-d“script=$(cat/tmp/changepassword.groovy)”http://localhost:8080/scriptText
应以
HTTP 200
状态和文本响应:

找到用户名Billhert的凭据801cf176-3455-4b6d-a461-457a288fd202

更改了Billhert的密码

使用Scriptler插件实现自动化 您还可以安装Jenkins并按如下步骤进行:

  • 在侧菜单中打开Scriptler工具

  • 填写第一个字段中的3个字段,注意将Id字段设置为
    changeCredentialPassword.groovy
  • 选中“定义脚本参数”复选框
  • 添加两个参数:
    username
    password
  • 粘贴以下脚本:
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
def changePassword={用户名,新密码->
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}
如果(c){
println“找到用户名${c.username}的凭据${c.id}”
def credentials_store=jenkins.model.jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
def result=credentials\u store.updateCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
C
新用户名PasswordCredentialSimpl(c.scope,null,c.description,c.username,new_password)
)
如果(结果){
println“更改了${username}的密码”
}否则{
println“更改${username}的密码失败”
}
}否则{
println“找不到${username}的凭据”
}
}
更改密码(“$username”,“$password”)
  • 然后单击提交按钮
现在,您可以调用以下URL来更改密码(替换
用户名
密码
参数):(注意需要修改参数的值)

或与卷曲:

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

资料来源:


搜索引擎提示:使用关键字
'Jenkins.instance.'
'com.cloudbees.plugins.credentials'
用户名密码CredentialsImpl

我从未找到让Groovy脚本停止更新凭据ID的方法,但我注意到,如果我使用web界面更新凭据,ID不会改变

考虑到这一点,下面的脚本实际上是脚本t
$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 
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}'"
}