IBM Security AppScan Dynamic Analyzer 通过检测如今的许多最常见的安全漏洞,帮助保护部署在 IBM Bluemix 上的 Web 应用程序。在本教程中,我将介绍如何使用 AppScan Analyzer 扫描您的 Bluemix 应用程序,然后将结果发送给 Bluemix DevOps Services Track & Plan 缺陷跟踪服务。
备注:源代码包含一个不安全的应用程序,您需要将它安装在 Bluemix 上并执行扫描。参见第 1 步。
“在本教程中,您将学习如何使用 AppScan Dynamic Analyzer 扫描您 Bluemix 应用程序,然后将扫描结果发送给 Track & Plan 缺陷跟踪服务。”
现在您已能从用户界面使用 Track & Plan,是时候通过 REST 接口从程序使用它了。
ccm08
和
_cqZlJx7LEeWrnMDj3ue0kw
。 curl
,请安装它。curl -k https://[uid:password]@hub.jazz.net/[server ID]/ oslc/contexts/[project ID]/workitems -H "Content-Type: application/ x-oslc-cm-change-request+json" -H "Accept: text/json" > x.html
<HTML> <BODY> <SCRIPT> var obj = JSON.parse('<curl result goes here>'); // Double quotes are used in the result, so we need to use the single quotes. document.write(obj["oslc_cm:results"][0]["rtc_cm:filedAgainst"]["rdf:resource"]); </SCRIPT> </BODY> </HTML>
{ "dc:title":"Test work item", "dc:description":"Description goes here", "dc:type": "defect", "rtc_cm:filedAgainst": { "rdf:resource": "<result of substep 5 goes here>" } }
curl -k https://[uid:password]@hub.jazz.net/[server ID]/oslc/contexts/ [project ID]/workitems -v -X POST -d @workitem.json -H "Content-Type: application/x-oslc-cm-change-request+json" -H "Accept: text/json"
Bluemix AppScan 服务提供的扫描报告是 PDF 格式的。该格式非常便于阅读并与人们分享,但不太适合计算机处理。要将报告转换为更容易使用的格式,可以使用 Adobe Acrobat Reader 11(或更高版本)打开它,选择 File > Save As Other > Text。
查看该文本文件,可以注意到所有问题在第 2 行都拥有 “Severity:<high、medium 或
low>
”。在问题末尾,有一行以 TOC
结尾,随后是一个空格。这应该足以拆分这些问题并创建工作项。
您可以将这些结果与 第 2 步 相结合来实际发送结果。这无法从浏览器完成,因为在浏览器中运行的 JavaScript 仅能够连接在相同域上运行的 REST API,或者宣称可从其他来源使用代码调用自己的 API。Track & Plan API 不属于二者。
我提供了一个 Python 程序来完成此任务。您需要使用您自己的配置来修改前几行,请参见 第 2 步 中的解释。备注:您可以从 IBM DevOps Services 中本教程的代码项目的 client_side 文件夹下载 Python 脚本。
#! /usr/bin/python # Send the results of an IBM Bluemix AppScan Dynamic Analyzer scan, # saved as text by Acrobat Reader, to IBM Bluemix Devops Track & Plan import re import urllib.request import base64 import json # Configuration #################################### # Your devops credentials uid = "oripomerantz"; passwd = "Nice-try"; # Get these values from Step 2.1. serverID = "ccm08"; projectID = "_cqZlJx7LEeWrnMDj3ue0kw"; # Get this value from Steps 2.3-5 filedAgainst = "https://hub.jazz.net/ccm08/resource/" filedAgainst += "itemOid/com.ibm.team.workitem.Category/_dLm0sB7LEeWrnMDj3ue0kw"; # The report file reportFile = "report.txt" # Read and parse the report ############################ # Read the report into a list of lines. report = open(reportFile).read().split("/n") # This array will include all the issues. issues = [] inIssue = False startOfIssue = re.compile("Severity:") # Actually, line #2 of it endOfIssue = re.compile("TOC$") # This is the syntax for a for loop in Python for i in range(len(report)): # If we're not in an issue and we find Severity: in this # line, start the issue with the previous line. if not inIssue and startOfIssue.search(report[i]): issue = report[i-1] + "/n" inIssue = True # If we are in an issue and we see TOC at the end of # if inIssue and endOfIssue.search(report[i]): inIssue = False issues.append(issue) issue = "" if inIssue: # Use //n to convert to /n which will be converted # to a newline by Track & Plan issue += report[i] + "//n"; # The HTTP configuration ################################################# # Basic authentication to get access to the API. Python can do HTTP # basic authentication for us, but this is much simpler. auth = base64.b64encode(bytes(uid + ":" + passwd, 'utf-8')).decode("utf-8") # The URL to access the API url = "https://hub.jazz.net/" + serverID url += "/oslc/contexts/" + projectID + "/workitems" # Header fields headers = { 'Content-Type': 'application/x-oslc-cm-change-request+json', 'Accept': 'text/json', 'Authorization': 'Basic ' + str(auth) + '==' } # Send the issues as work items ######################################## for issue in issues: # /n is the delimiter between the heading and the content (heading, content) = issue.split("/n") # The heading has some spaces before it. Remove them. heading = heading.lstrip() # Create the JSON request to send request = '{/n/t"dc:title": "' + heading + '",/n' # Escape any apostrophes in the work item content. Double escaping is # needed because it becomes single escaping in the JSON and then # gets interpreted correctly by the server. request += "/t'dc:description': '" + content.replace("'", "//'") + "',/n" request += '/t"dc:type": "defect",/n' # The filed against value. To figure this value you need to run some # curl, as explained in step 2 in the tutorial request += '/t"rtc_cm:filedAgainst": {/n' request += '/t/t"rdf:resource": "' + filedAgainst + '"/n' request += '/t}/n' request += '}/n' # Send the request req = urllib.request.Request(url, bytes(request, 'utf-8'), headers) response = urllib.request.urlopen(req) resp = json.loads(response.read().decode("utf-8")) # The response includes many fields. One of them is the # work item number. You can print it out to see the others if you # need them. print ("Created work item #" + str(resp["dc:identifier"]) + " for " + heading)
运行此程序,您会看到为您创建了相关的工作项:
本教程中讨论的程序非常简单。更复杂的程序可从描述中读取更多字段,比如严重级别,并将它们放在工作项中的相关字段中。这样的程序可能还拥有针对不同 URL
的不同类别,将工作项标记为自动扫描所检测到的漏洞。要创建包含这些功能的程序,让解析更加复杂,可以将 issue
从一个字符串更改为一种结构,并在 JSON request
中设置更多字段。您可以查看您从 Track & Plan 收到的
resp
变量来查看有哪些可用字段。
Track & Plan 服务:链接计划和代码,以便计划与开发团队的进度保持同步。