IBM Bluemix® Track & Plan 服务主要是为开发用途而设计的。但是,应用程序也可以用它来报告自己的状态,包括已确认的安全违规。在本教程中,将学习如何让 Node.js Bluemix 应用程序自动联系 Track & Plan,使用 REST 接口报告问题。
尽管本教程是从安全角度进行编写的,但此技术的使用是没有限制的。应用程序可以使用它来报告错误条件,提醒资源不足,等等。
运行应用程序
获取代码
“ 在本教程中,将学习如何使用 IBM Devops Track & Plan 编写应用程序,在应用程序受到攻击时通知管理员。 ”
这个应用程序是一个登录屏幕。您可以作为合法用户 jdoe
使用密码 object00
进行登录。要生成可报告的安全事件,还可以使用错误的用户名或密码进行登录。还有一些用于 Track & Plan 配置的字段,以便可以将安全事件记录到一个系统中,您可以在该系统中查看它们。
备注: 有关这个步骤的更多详细说明,请参阅 将 Bluemix AppScan 结果放入 Bluemix Track & Plan 中 的第 1 步和第 2 步。
test #alert #security
,以创建 "alert" 和 "security" 作为标签。 下一步是获取 Track & Plan 数据,以便通过 REST 接口与服务器进行通信。您可以在 将 Bluemix AppScan 结果放入 Bluemix Track & Plan 中 的第 2 步中了解此操作,但我提供了一个 实用程序 来为您完成大部分工作。下图是这个实用程序的屏幕截图。
将 URL 输入到 Track & Plan 用户界面中(例如 https://hub.jazz.net/ccm19/quickplanner/jazzhub.html#items:planType=mywork&projectId=_CtzTlXn5EeWL9uPUvTiukg),然后输入您的 Track & Plan 用户名和密码。app.js 中的代码会推测剩余配置,并将它们存储在一个 index.html 代码可以读取的 cookie 中。
备注: 向 Track & Plan 发送警报不需要了解本节。您可以跳过它,将它提供的值硬编码到您的应用程序中。但是,它包含在这里以防您想要了解 app.js 如何推测配置。
下面的代码段声明了响应对 /getConf
的 post 请求(针对 util.html 表单的操作)的函数。 serverID
和 projectID
都在 Track & Plan URL 中,所以可使用正则表达式检索它们。与这些字段相反,检索类别需要向 Track & Plan 发出 REST 请求。函数主要构建该请求,然后解释它。
app.post("/getConf", function(req, res) { var serverID = RegExp("https://hub.jazz.net/(ccm[0-9]*)/").exec(req.body.url)[1]; var projectID = RegExp("projectId=(_[0-9A-Za-z]*)&").exec(req.body.url)[1];
以下 HTTPS 选项主要是可在 URL 中指定的标准信息,但也有一些例外。 auth
字段是用户名和密码。还有两个对 REST 请求至关重要的标头字段: Content-Type
指定请求类型(和额外数据的格式,如果有), Accept
指定响应的格式。
var httpsOpts = { hostname:'hub.jazz.net', port:443, path:"/" + serverID + "/oslc/contexts/" + projectID + "/workitems", method:'GET', auth: req.body.uid + ":"+ req.body.passwd, headers:{ Accept:"text/json", "Content-Type":"application/x-oslc-cm-change-request+json" } };
下面这段代码发出请求,并将函数声明为通过响应来调用。但是,此函数会在 Node.js 从服务器收到响应的标头后立即调用,该函数执行得太早了,所以没有用处。幸运的是,每次通过 TCP 收到 HTTP 主体的一部分时,响应都会发出一个数据事件。因此,为了获得完整的主体,我添加了来自所有这些事件的数据。
var httpsReq = https.request(httpsOpts, function(httpsRes) { var data = ""; httpsRes.on("data", function(d) { data += d.toString(); });
在交付整个主体后关闭 HTTP 连接时,响应会发出一个 end
事件。因为 Accept HTTP 标头指定 JSON 作为数据格式,所以要使用 JSON.parse()
来解释它。 oslc_cm:results
字段包含所有查询结果,所有工作项。第一个条目(编号为 0)是我们使用的条目,但在有多个条目时,其他任何条目也会有效。为了识别类别,可以在 rtc_cm:filedAgainst
结构中使用 rdf:resource
值。
httpsRes.on("end", function() { var categoryID = JSON.parse(data)["oslc_cm:results"][0]["rtc_cm:filedAgainst"]["rdf:resource"];
在生产环境中,我们会将所有这类信息都存储在一个数据库中,让用户登录某个帐户来使用它(而不是检索它,没有理由将它提供给浏览器)。但是,这不是生产环境。在本例中,我希望用户看到参数,并能够在他们自己的应用程序中使用这些参数。为了提供此信息,应用程序为这些参数设置了 cookie。(要了解 JavaScript 代码如何读取这些 cookie,请参阅 w3schools.com 网站上的 JavaScript Cookie 。)
res.setHeader("Set-Cookie", ["serverID=" + serverID, "projectID=" + projectID, "categoryID=" + categoryID, "userID=" + req.body.uid]); res.send('<a href="index.html">Configuration retrieved</a>'); });
最后一步是使用 REST 接口向 Track & Plan 发送警报。执行此操作的函数是 sendNotice(msg, conf)
。参数 conf
是配置,它会在向 /login 上的网页发送查询时提供。
下面这段代码显示了发送给 Track & Plan 的报告。没有 Track & Plan 类型与安全警报对应,所以我选择了最接近的类型 task
。 dc:subject
字段是任务的标签,在本例中它们是 security
和 alert
。
var report = { "dc:title":"Security violation", "dc:description": msg, "dc:type":"task", "dc:subject":"alert, security", "rtc_cm:filedAgainst":{ "rdf:resource": conf.categoryID } };
HTTPS 选项可以自述其身。我们正在创建一个新条目,所以 HTTP 方法是 POST。 auth
字段包含 Track & Plan 的身份验证信息。此值通常在代码中明确表示,或者是一个参数(参见“ 使用 Bluemix 和 MEAN 堆栈构建自助发表 Facebook 信息的应用程序,第 3 部分 ”中的第 5 步)。在本例中,它包含用户提供的配置项,所以您可以让应用程序登录您自己的 Track & Plan,您可以在这里查看结果,而不是登录我的 Track & Plan(您无法在这里查看结果)。
REST 中使用了两个额外的标头字段来描述请求的应用程序类型以及所请求的响应格式。
var httpsOpts = { hostname:'hub.jazz.net', port:443, path:"/" + conf.serverID + "/oslc/contexts/" + conf.projectID + "/workitems", method:'POST', auth: conf.ibm_uid + ":"+ conf.ibm_passwd, headers:{ Accept:"text/json", "Content-Type":"application/x-oslc-cm-change-request+json" } };
最后,下一节会向 Track & Plan 发出 HTTPS 请求。该请求没有回调,因为我们不关心响应。它只提供了我们创建的新工作项的细节。下一行采用 JSON 格式将报告写入 HTTP 请求的主体中。最后一行结束请求并发送它。
var httpsReq = https.request(httpsOpts); httpsReq.write(JSON.stringify(report)); httpsReq.end();
尝试使用错误的凭证登录到 测试应用程序 。您会看到一个错误消息。
然后,转到 IBM Bluemix DevOps Services 界面中的 TRACK & PLAN 并单击 INCOMING WORK 。单击新任务的标题来查看警报细节。
点击查看大图
关闭 [x]
自动分配工作项的所有者通常很有用。这样就有了负责人,而且此人会在该工作项打开时获得通知(就像对创建者所做的那样)。
unique_string @:<user name>
。 点击查看大图
关闭 [x]
https://hub.jazz.net/<Server ID>/oslc/contexts/<Project ID>/workitems
rtc_cm:ownedBy
,其中包含 rdf:resource
。您还可以看到,该值不仅是用户名,还是一个包含用户名和其他信息的 URL。记下此值。 点击查看大图
关闭 [x]
rtc_cm:ownedBy
字段(在第 9-10 行中添加该代码,并将资源替换为您自己的值): var report = { "dc:title":"Security violation", "dc:description": msg, "dc:type":"task", "dc:subject":"alert, security", "rtc_cm:filedAgainst":{ "rdf:resource": conf.categoryID }, "rtc_cm:ownedBy":{ "rdf:resource":"https://hub.jazz.net/jts19/users/oripomerantz" } };
点击查看大图