81

我在 Spinnaker 中配置了 jenkins,如下所示并设置了 spinnaker 管道。

 jenkins:
    # If you are integrating Jenkins, set its location here using the baseUrl
    # field and provide the username/password credentials.
    # You must also enable the "igor" service listed separately.
    #
    # If you have multiple jenkins servers, you will need to list
    # them in an igor-local.yml. See jenkins.masters in config/igor.yml.
    #
    # Note that jenkins is not installed with Spinnaker so you must obtain this
    # on your own if you are interested.
    enabled: ${services.igor.enabled:false}
    defaultMaster:
      name: default
      baseUrl: http://server:8080
      username: spinnaker
      password: password

但是我在尝试运行大三角帆管道时看到以下错误。

异常(启动 Jenkins 作业)403 请求中未包含有效的面包屑

4

22 回答 22

66

最后,这篇文章帮助我解决了 crumb 问题,但仍然保护 Jenkins 免受 CSRF 攻击。

请求问题中包含无效面包屑的解决方案

基本上,我们需要首先请求带有身份验证的 crumb,然后再次发出带有 crumb 作为标头的 POST api 调用以及身份验证。

我是这样弄的

curl -v -X GET http://jenkins-url:8080/crumbIssuer/api/json --user <username>:<password>

回应是,

{
"_class":"hudson.security.csrf.DefaultCrumbIssuer",
"crumb":"0db38413bd7ec9e98974f5213f7ead8b",
"crumbRequestField":"Jenkins-Crumb"
}

然后是 POST api,里面有上面的 crumb 信息。

curl -X POST http://jenkins-url:8080/job/<job-name>/build --user <username>:<password> -H 'Jenkins-Crumb: 0db38413bd7ec9e98974f5213f7ead8b'
于 2019-02-18T15:30:47.287 回答
39

该解决方案可以安全使用

当我们将 jenkins 更改为可通过反向代理访问时,出现了这个问题。

配置全局安全性”中有一个“启用代理兼容性”选项,这有助于解决我的问题。

在此处输入图像描述

其他解决方案

在 Github 有效负载 URL 中使您的 url 看起来像这样
https://jenkins:8080/github-webhook/ 不要忘记 / 在最后提及

于 2019-05-16T11:19:15.667 回答
38

为了解决这个问题,我取消了 jenkins.com/configureSecurity 部分中的“防止跨站点请求伪造攻击”,它开始工作。

防止跨站点请求伪造攻击

于 2017-06-24T04:19:52.920 回答
24

Crumb 只不过是访问令牌。下面是获取面包屑的api

https://jenkins.xxx.xxx.xxx/crumbIssuer/api/json // 用你的 jenkins url 替换它,并在你的邮递员或 rest-api 调用者中进行 GET 调用。

这将生成如下输出:

{
    "_class": "hudson.security.csrf.DefaultCrumbIssuer",
    "crumb": "ba4742b9d92606f4236456568a",
    "crumbRequestField": "Jenkins-Crumb"
}

以下是更多详细信息和相关链接: 如何为 jenkins Jenkins wiki 页面请求 Crumb 发行者: https ://wiki.jenkins-ci.org/display/jenkins/remote+access+api

如果您通过 rest-api 调用调用相同的,请查看下面的链接,其中解释了如何使用 jenkins-crumb 调用 rest 调用

https://blog.dahanne.net/2016/05/17/how-to-update-a-jenkins-job-posting-config-xml/

例子 :

curl -X POST http://anthony:anthony@localhost:8080/jenkins/job/pof/config.xml --data-binary "@config.xml" -data ".crumb=6bbabc426436b72ec35e5ad4a4344687"
于 2017-06-23T06:47:11.147 回答
19

对于 Jenkins 的新版本,您应该遵循以下解决方案:

https://jenkins.io/doc/upgrade-guide/2.176/#upgrading-to-jenkins-lts-2-176-3

升级到 Jenkins 2.176.2 改进的 CSRF 保护

安全-626

CSRF 令牌(碎屑)现在仅对创建它们的 Web 会话有效,以限制攻击者获取它们的影响。使用 /crumbIssuer/api URL 获取 crumb 的脚本现在将无法执行受 CSRF 保护的操作,除非脚本在后续请求中保留 Web 会话 ID。脚本可以改为使用 API 令牌,自 Jenkins 2.96 以来,它不再需要 CSRF 令牌(crumb)。

要禁用此改进,您可以将系统属性 hudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID 设置为 true。或者,您可以安装 Strict Crumb Issuer Plugin,它提供了更多选项来自定义 crumb 验证。它允许从验证标准中排除 Web 会话 ID,而是将其替换为基于时间的过期,以获得类似(甚至更好)的 CSRF 保护

在我的案例中,帮助安装了 Strict Crumb Issuer Plugin,重新启动了 jenkins,并按照供应商网站上的建议对 Jenkins 的 Web 界面应用了不那么严格的策略。

于 2020-03-11T10:20:18.060 回答
17

我通过使用API TOKEN作为基本身份验证密码解决了这个问题。这是如何

curl -v -X POST http://jenkins-url:8080/job/<job-name>/buildWithParameters?param=value --user <username>:<token>

注意:在 Accounts 图标 -> 配置 -> API Token -> 添加新令牌下创建API TOKEN

于 2020-07-31T12:03:03.080 回答
8

根据Jenkins Directive First,如果版本 < 2.176.2,您必须检查您的 Jenkins 版本,然后根据 Jenkins 指南,CSRF 令牌(碎屑)现在仅对创建它们的 Web 会话有效,以限制攻击者获取它们的影响。使用 /crumbIssuer/api URL 获取 crumb 的脚本现在将无法执行受 CSRF 保护的操作,除非脚本在后续请求中保留 Web 会话 ID。

或者,您可以安装 Strict Crumb Issuer Plugin,它提供了更多选项来自定义 crumb 验证。它允许从验证标准中排除 Web 会话 ID,而是将其替换为基于时间的过期,以实现类似(甚至更好)的 CSRF 保护。

脚步 :

  • 您必须安装名为“Strict Crumb Issuer”的插件
  • 安装完成后重启 jenkins 服务
  • 进入“管理 Jenkins”——>“配置全局安全”——>在 CSRF 保护下,从下拉列表中选择“严格的碎屑问题”——>点击高级并取消选中所有内容,但选择“防止违反攻击”选项。--> 应用并保存。
  • 现在运行你的 crumb 脚本。

它现在应该可以工作了。

检查此图像以供参考

于 2020-07-17T16:03:58.430 回答
5

当我使用 jenkins-client 库(即 com.offbytwo.jenkins)从 java 程序创建 jenkins 作业时,我确实收到了相同的“403 No valid crumb is included in request”错误。然后我在下面的代码中使用了 jenkins api 令牌而不是密码。现在,问题已解决。

JenkinsServer jServer = new JenkinsServer(new URI(jenkins_url), jnkn_username, jnkn_password);

我们可以从 Jenkins 控制台生成 API Token。配置文件 > 配置 > API 令牌(添加新令牌)

curl 也可以使用相同的 API 令牌代替密码。

curl -v -X POST http://jenkins-url:port/job/<job-name>/buildWithParameters?param=value --user <jen_username>:<jenkins_api_token>
于 2020-02-14T06:16:01.390 回答
5

我浪费了很多时间试图弄清楚这一点。最后,我刚刚安装了这个插件https://plugins.jenkins.io/build-token-root/并为匿名用户启用了构建权限。最后并不是真的,因为 jenkins 实例位于 VPN 后面,我正在使用https://smee.io将 webhook 转发到 Jenkins 实例。此外,Jenkins 实例位于反向代理后面,因此还选中了“启用代理兼容性”选项,并且在服务器级别的 Nginx 配置中将“ignore_invalid_headers”设置设置为关闭。分享我的解决方案,以防其他人也在苦苦挣扎。我确信有更好的方法可以做到这一点,但这是一种选择。

请注意,使用此插件,构建 url 设置为buildByToken/build?job=JobName&token=TokenValue并且令牌是在作业设置中生成的。

这是在 Jenkins 2.235.2 中,它没有禁用 CSRF 的选项。

于 2020-07-30T21:09:07.893 回答
3

您需要一个 2 步过程,首先从服务器获取面包屑,然后使用它。我正在使用这个 bash 脚本和 curl:

#!/bin/bash
# buildme.sh    Runs a build Jenkins build job that requires a crumb
# e.g.
# $ ./buildme.sh 'builderdude:monkey123' 'awesomebuildjob' 'http://paton.example.com:8080'
# Replace with your admin credentials, build job name and Jenkins URL
#
# More background:
# https://support.cloudbees.com/hc/en-us/articles/219257077-CSRF-Protection-Explained
USERPASSWORD=$1
JOB=$2
SERVER=$3
# File where web session cookie is saved
COOKIEJAR="$(mktemp)"
CRUMB=$(curl -f -u "$USERPASSWORD" --cookie-jar "$COOKIEJAR" "$SERVER/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)")
status=$?
if [[ $status -eq 0 ]] ; then
  curl -f -X POST -u "$USERPASSWORD" --cookie "$COOKIEJAR" -H "$CRUMB" "$SERVER"/job/"$JOB"/build
  status=$?
fi
rm "$COOKIEJAR"
exit $status

这是使用您需要的参数执行此脚本的示例:

$ ./buildme.sh 'builderdude:monkey123' 'awesomebuildjob' 'http://paton.example.com:8080'

如果 curl 命令之一因任何原因失败,此脚本将返回错误代码。

更多细节可以从cloudbees找到

于 2021-03-09T18:13:12.777 回答
2

由于这个问题是在 Google 中搜索“No valid crumb was included in the request”时的第一个 SO 链接,我认为值得一提的是,如果您省略/忘记 Authorization HTTP 标头或使用空白用户名/密码: 屏幕截图显示省略 Authorization HTTP 标头的错误

只有在传递值时才会生成与 Authorization 标头相关的错误消息: 显示与授权标头相关的错误的屏幕截图

而且,是的,第一个屏幕截图中传递的面包屑实际上是有效的;一切都使用正确的用户名/密码: 显示之前使用的 crumb 的屏幕截图是有效的

所以,不确定这是否是一个错误,但“请求中没有包含有效的 crumb”也可能意味着您不小心忘记了 Authorization 标头。

詹金斯 2.222.3,Ubuntu 服务器 20.04,Java 运行时 1.8.0_252-8u252-b09-1ubuntu1-b09

于 2020-05-22T07:25:27.747 回答
1

访问詹金斯https://...而不是http://...为我解决问题

于 2021-09-02T08:54:11.180 回答
0

对于访问 Jenkins API 的 java 代码,我会给出我的建议。

@Santhosh (https://stackoverflow.com/a/60221003/5940655)的答案确实解决了这个问题,这包括更改token的密码,但据我所知,token 现在是一种传统的方式来做到这一点. 所以我尝试了其他方式,并在java代码中找到了解决方案。

这里我是怎么做到的。在我的 java 代码中,我使用“ com.offbytwo.jenkins,我使用的类是“ JenkinsServer ”。

我的问题是在jenkins中创建工作,因为我收到错误:“ 403 No valid crumb is included in request

然后我找到了一个名为crumbFlag的布尔参数,并在其上传递了“ true ”,一切正常。

我的代码是这样的:

jenkins.createJob(job.getName(), config);

然后,我改变了这个ans就像一个魅力:

jenkins.createJob(job.getName(), config, true);

这个参数几乎在这个包的所有方法中,例如:

  • createJob(String jobName, String jobXml, Boolean crumbFlag)
  • updateJob(String jobName, String jobXml, boolean crumbFlag)
  • renameJob(String oldJobName, String newJobName, Boolean crumbFlag)
  • 其他。

代码里面的技术文档是:

@param crumbFlagtrue添加crumbIssuer * false否则。

我知道如果你为这个参数传递“ true ”,它会自动发出一个面包屑。

好吧,官方文档中有详细信息,如果您愿意,请看这里:

https://javadoc.io/doc/com.offbytwo.jenkins/jenkins-client/latest/com/offbytwo/jenkins/JenkinsServer.html

于 2020-10-07T13:44:49.593 回答
0

指南解释了如何生成 Jenkins crumb、保存 cookie 以及在需要身份验证的后续请求中同时使用 crumb 和保存的 cookie。这是 Jenkins V2.176.2 之后的必修课

于 2020-11-02T13:07:15.507 回答
0

我在尝试使用GitHub Pull Request Builder插件设置GitHub项目 时遇到了同样的问题

  • 这是我从Jenkins服务器获得的响应示例

在此处输入图像描述

  • 响应内容

在此处输入图像描述

  • 问题正在发生,因为我的Payload URL在末尾缺少正斜杠/

  • 在网址末尾添加正斜杠可以解决问题

  • 你的有效载荷 url 应该是这样的https://jenkins.host.com/ghprbhook/

  • 添加正斜杠后的示例

在此处输入图像描述

在此处输入图像描述

于 2021-01-26T09:17:03.560 回答
0

这是我对这个问题的解决方案(git hook to launch jenkins job behind a reverse proxy)

#从第一次调用中获取 CRUMB 并将 sessionid 存储在 cookie jar 中:

CRUMB=$(/usr/bin/curl --cookie-jar ./cookie -sX GET https://******.net/crumbIssuer/api/json|cut -d'"' -f8)

#启动作业:

/usr/bin/curl --cookie ./cookie -X POST https://******.net/job/PROJECTNAME/build -H "Jenkins-Crumb: $CRUMB"

于 2021-02-04T11:09:43.427 回答
0

对我来说,解决方案是按照手册的反向代理配置故障排除章节中的建议传递X-Forwarded-Host和标头。X-Forwarded-Port

HaProxy 配置,在该frontend部分内:

http-request set-header  X-Forwarded-Host  %[hdr(host)]
http-request set-header  X-Forwarded-Port  %[dst_port]
于 2021-04-22T09:59:19.793 回答
0

我也遇到了类似的问题,我使用的是密码而不是token. 更新后解决了我的问题,无需取消选中任何内容并使其不安全。以下是我遵循 jenkins CLI 工作的完整步骤-

步骤 -1:- 准备 ENV 变量

export JENKINS_URL=http://localhost:8080/
export JENKINS_USER=admin
export JENKINS_PASSWORD=b7f04f4efe5ee117912a1.....
export JENKINS_CRUMB=f360....
export FOLDER=test

获取令牌 as- 如何获取 Jenkins 的 API 令牌

获取 CRUMB 作为 - http://localhost:8080/crumbIssuer/api/json

step-2 :- 准备 XML 文件,文件名 creds.xml

<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>      
  <scope>GLOBAL</scope>                  
  <id>TEST-CLI</id>            
  <username>test</username>    
  <password>test123</password>
  <description>this secret if created confirms that jenkins-cli is working</description>        
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>

第 3 步:- 使用 curl 发布

curl -X POST -u $JENKINS_USER:$JENKINS_PASSWORD -H "Jenkins-Crumb:${JENKINS_CRUMB}" -H 'content-type:application/xml' -d @creds.xml "$JENKINS_URL/job/$FOLDER/credentials/store/folder/domain/_/createCredentials"
于 2021-05-19T11:38:40.003 回答
-1

前往管理 Jenkins => 配置全局安全性。

然后取消选中“防止跨站点请求伪造漏洞利用

于 2019-08-30T21:03:12.320 回答
-1

我正在使用带有 nignx 的反向代理运行。更改了“配置全局安全”中的詹金斯选项,即“启用代理兼容性”这解决了我的问题。

于 2020-08-09T17:38:36.823 回答
-1

首先通过转到用户-> API 令牌->添加新令牌来创建用户 API 令牌。

然后使用下面的脚本进行触发。

import jenkins,requests
job_name='sleep_job'
jenkins_url = "http://10.10.10.294:8080"
auth = ("jenkins","1143e7efc9371dde2e4f312345bec")
request_url = "{0:s}/job/{1:s}/buildWithParameters".format(jenkins_url, 
job_name, )
crumb_data = requests.get("{0:s}/crumbIssuer/api/json".format(jenkins_url), 
auth=auth, ).json()
headers = {'Jenkins-Crumb': crumb_data['crumb']}
jenkins_job_params={}
jenkins_job_params['NODE_NAME']='10_10_1_29'
jenkins_job_params['SLEEP_TIME']='1h'
response = requests.post(request_url, data=jenkins_job_params, auth=auth, )
response.raise_for_status()
于 2020-10-26T10:26:27.997 回答
-3

我遇到了同样的问题。我只刷新了我的浏览器,重新登录到 Jenkins,做同样的过程,一切正常。

于 2020-03-05T16:58:08.527 回答