Jenkins“触发远程构建”>“身份验证令牌”选项丢失

27
我刚刚在Nginx反向代理后设置了Jenkins(最新版本-2.5),以便我可以通过HTTPS访问它。目前工作正常,但是我的多分支管道作业在主配置中不再具有“远程触发构建”选项。我认为我没有更改任何其他配置。您有什么想法,如何恢复此选项?以下是我想要的内容:

Screenshot of what I want back

6个回答

36

经过一段时间的搜索和思考,我相信我能够自信地回答自己的问题。

我认为答案在于安全设置。身份验证令牌的目的是允许未经授权的用户(开发人员)触发构建而无需登录 Jenkins(请参见https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clientshttps://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"

1
这个 Jenkins URL 周围的引号是故意的吗?这对我没有起作用。 - partydog
@val的帖子对我有用,我删除了引号并添加了-I。 - theeagle
谢谢您澄清这一点。我也认为我需要授权令牌。 - Foreever

28

免责声明

在阅读本答案之前,您必须知道,我只是在这个答案中累积了所有我在stackoverflow上找到的有用信息,所有功劳都应归于实际进行研究的人们。

我将链接内容从这个评论移动到stackoverflow上,仅仅是为了避免死链。

信息

我的作业名称是Football。我建议你创建一个专门的Jenkins用户名和密码,而不是像我在这个例子中使用的admin:admin。我的Jenkins GUI URL是http://192.168.99.20:8080,因为我在vagrant上。

创建作业

  1. 登录到http://192.168.99.20:8080地址的Jenkins。
  2. 创建一个名为“Football”的“Free Style”项目。
  3. 打开它的配置。
  4. 转到“Build Triggers”部分。
  5. 选中“远程触发构建(例如,来自脚本)”选项,只需注意其中写的文本并再次取消选中。文本显示为 使用以下URL远程触发生成:JENKINS_URL/job/Football/build?token=TOKEN_NAME或/buildWithParameters?token=TOKEN_NAME。可选地附加&cause=Cause+Text以提供将包含在记录的构建原因中的文本。
  6. 保存并退出。

获取API用户和令牌

  1. 登录到http://192.168.99.20:8080地址的Jenkins。
  2. 在页面右侧点击您的用户名(我的是admin)。
  3. 选择“配置”选项,它将带您进入http://192.168.99.20:8080/user/admin/configure页面。
  4. 在“API Token”部分点击“显示API令牌”按钮。
  5. 记下“User ID”和“API Token”,以便稍后在curl命令中使用。例如admin:85703fb68927f04968630e192e4927cb

获取crumb

有关更多信息,请访问远程访问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 ForbiddenError 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)')

谢谢!使用API令牌真的很有帮助。我改用它来让我顺利地转移到Google登录插件。非常有帮助。 - Josiah
似乎在DSL中,authorizationToken已被弃用。 - Daniel Hajduk
@DanielHajduk,谢谢。我不再在我的项目中使用Jenkins,所以现在无法更新我的帖子。但我会尽快尝试更新。 - VaL

8
有一个适用于1.565.3及更新版本的Jenkins插件,可以绕过基于矩阵的身份验证来触发构建任务。我在JENKINS-17764(涵盖了此特定问题)的评论中找到了这个信息,作者是Emil Dragu:
安装Build Token Root Plugin插件,然后将URL的上部分更改为相应的下部分(以列表形式呈现,更容易识别):
  • job/ProjectName/build?token=test
  • buildByToken/build?job=ProjectName&token=test
你仍然可以传递可选的cause参数。

3

同意。 当您单击右上角显示的用户名时,您可以找到API令牌。然后进入配置并单击“显示API令牌”。


2
我编写了这个 Python 脚本来提交作业。同时,它还允许上传文件到作业中。
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})


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接