经过一段时间的搜索和思考,我相信我能够自信地回答自己的问题。
我认为答案在于安全设置。身份验证令牌的目的是允许未经授权的用户(开发人员)触发构建而无需登录 Jenkins(请参见https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients和https://wiki.jenkins-ci.org/display/JENKINS/Quick+and+Simple+Security)。
因此,如果您正在使用基于矩阵的安全性(在“配置全局安全性”>>“授权”下),则“远程触发构建”选项将消失,因为假定您将使用 Jenkins 用户帐户对请求进行身份验证。
为了做到这一点,您可以使用用户名/密码(或更好的用户名/API 令牌)发出 HTTP 请求:
curl -X POST "https://username:api-token@JENKINS_URL/job/Example/build"
在阅读本答案之前,您必须知道,我只是在这个答案中累积了所有我在stackoverflow上找到的有用信息,所有功劳都应归于实际进行研究的人们。
我将链接内容从这个评论移动到stackoverflow上,仅仅是为了避免死链。
我的作业名称是Football
。我建议你创建一个专门的Jenkins用户名和密码,而不是像我在这个例子中使用的admin:admin
。我的Jenkins GUI URL是http://192.168.99.20:8080
,因为我在vagrant上。
http://192.168.99.20:8080
地址的Jenkins。 使用以下URL远程触发生成:JENKINS_URL/job/Football/build?token=TOKEN_NAME或/buildWithParameters?token=TOKEN_NAME。可选地附加&cause=Cause+Text以提供将包含在记录的构建原因中的文本。
http://192.168.99.20:8080
地址的Jenkins。http://192.168.99.20:8080/user/admin/configure
页面。admin:85703fb68927f04968630e192e4927cb
有关更多信息,请访问远程访问API页面。
$ wget -q --auth-no-challenge --user admin --password admin --output-document - 'http://192.168.99.20:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
这将为您提供类似 Jenkins-Crumb:44e7033af70da95a47403c3bed5c10f8
的东西。没有 crumb 信息,运行 curl 命令将导致示例错误,例如 HTTP/1.1 403 Forbidden
或 Error 403 No valid crumb was included in the request
。
$ curl -I -X POST http://admin:85703fb68927f04968630e192e4927cb@192.168.99.20:8080/job/Football/build -H "Jenkins-Crumb:44e7033af70da95a47403c3bed5c10f8"
HTTP/1.1 201 Created
Date: Fri, 02 Jun 2017 06:17:51 GMT
X-Content-Type-Options: nosniff
Location: http://192.168.99.20:8080/queue/item/17/
Content-Length: 0
Server: Jetty(9.2.z-SNAPSHOT)
除了上面的信息,我还找到了如何使用cli
获取Jenkins-Crumb的方法,来源于这个答案
CRUMB=$(curl -s 'http://USER:TOKEN@localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
job/
ProjectName/build?token=
testbuildByToken/build?job=
ProjectName&token=
testcause
参数。同意。 当您单击右上角显示的用户名时,您可以找到API令牌。然后进入配置并单击“显示API令牌”。
import os
import json
import requests
from glob import glob
from getpass import getpass
AUTH = (
os.environ.get('JENKIN_USER') or input('Jenkin username: '),
os.environ.get('JENKIN_PASSWORD') or getpass('Jenkin password: ')
)
TOKEN = os.environ.get('JENKIN_TOKEN') or input('Jenkin job token: ')
JENKIN_DOMAIN = 'https://jenkins'
REASON = 'Batch jenkin job'
JOB_URL = f'{JENKIN_DOMAIN}/view/some-job-url'
CRUM_ISSUER = f'{JENKIN_DOMAIN}/crumbIssuer/api/json'
session = requests.Session()
def get_crumb(auth=AUTH):
return session.get(CRUM_ISSUER, auth=auth).json()
def build_job(job_url, params=None, files=None, token=TOKEN, cause=REASON,
auth=AUTH):
crum = get_crumb()
payload = {}
if params:
job_url = f'{job_url}/buildWithParameters'
parameter = []
if files:
for key in files:
parameter.append({"name": key, "file": key})
for key, value in params.items():
parameter.append({"name": key, "value": str(value)})
payload.update(params)
payload['json'] = json.dumps({
'parameter': parameter,
'statusCode': "303",
'redirectTo': '.'
})
else:
job_url = f'{job_url}/build'
r = session.post(
job_url,
data=payload,
files=files,
params={"token": token, "cause": cause, crum['crumbRequestField']: crum['crumb']},
auth=auth,
headers={crum['crumbRequestField']: crum['crumb']}
)
return r
if __name__ == '__main__':
# Build job
build_job(JOB_URL, params={
'DO_SOMETHING': 'true', "DO_SOMETHING_ELSE"
})
# Build job with file upload
build_job(JOB_URL, params={'NO_HEADER': 'true'}, files={'UPLOAD_FILE_FIELD': f})