An Add-on for OWASP ZAP to export alerts of a web application as Issues to JIRA — Part 2 Writing API methods for ZAP-API
In my previous post how I developed a jira plugin for zap. The main objective of this plugin was to integrate zap as a build step in jenkins so that the vulnerabilities found in the build process can be automatically exported to jira as issues based on their threat levels.
To run zap proxy as a build step in jenkins there is a plugin already available. (the plugin can be found here ) This plugin uses the zap-api methods available in zap which is running in daemon mode. So to integrate the functionality to jenkins I had expose my methods used in zap jira plugin through the zap api. The zap-api wiki can be found here.
As the wiki states under the implementation
- Have at least one class that extends org.parosproxy.paros.extension.Extension.java
- Add a class that extends org.zaproxy.zap.extension.api.ApiImplementor.java
So I wrote two files as JiraIsuueCreaterAPI.java which extends ApiImplementor class and ExtensionJiraIssueCreater.java which extends ExtensionAdaptor class .
Inside ExtensionJiraIssueCreater.java the new api method should be registered. This should be done inside the hook method. The code is as follows.
public void hook(ExtensionHook extensionHook) { super.hook(extensionHook); if (getView() != null) { // Register our top menu item, as long as we're not running as a daemon // Use one of the other methods to add to a different menu list extensionHook.getHookMenu().addReportMenuItem(getMenuExample()); extensionHook.getHookView().addStatusPanel(getStatusPanel()); } //register the api methods this.api=new JiraIssueCreaterAPI(this); API.getInstance().registerApiImplementor(api); }
I have implemented the api action in the same file and the code is as follows.
public void createJiraIssues(String jiraBaseURL, String jiraUserName, String jiraPassword, String projectKey,String asssignee, String high, String medium, String low, String filterIssuesByResourceType){ String project_key = projectKey; String issueList[]; JiraRestClient jira = new JiraRestClient(); int issueCount; String issue; try { String auth = new String(Base64.encode(jiraUserName+":"+jiraPassword)); String BASE_URL = jiraBaseURL; XmlDomParser xmlParser = new XmlDomParser(); if(high.equals("1")|| medium.equals("1")|| low.equals("1")) { issueList = xmlParser.parseXmlDoc(project_key, asssignee, stringToBool(high), stringToBool(medium), stringToBool(low), stringToBool(filterIssuesByResourceType)); issueCount = issueList.length; //get the issue count from the preset last index if (issueCount != 0) { //proceed if the issue count is > 1 for (int i = 0; i < issueCount; i++) { //create Issues in jira if(xmlParser.checkForIssueExistence(issueList[i],project_key)){ //update if the issue already exists xmlParser.updateExistingIssue(issueList[i],auth,BASE_URL,i); }else { //create a new issue if not issue = jira.invokePostMethod(auth, BASE_URL + "/rest/api/2/issue", issueList[i]); System.out.println("Created Issue : "+issue); } } } else { //abort if the issue count is = 0 System.out.println("No issues forund "); } }else{ System.out.println("No alert levels to create issues !!"); } } catch (AuthenticationException e) { //authentication faliure log.error(e.getMessage(), e); } }
Inside the JiraIssueCreaterAPI class the constructor should have the following method calls.
public JiraIssueCreaterAPI(ExtensionJiraIssueCreater extension){ super(); this.extension=extension; this.addApiAction(new ApiAction(ACTION_CREATE_JIRA_ISSUE, new String[] { ACTION_PARAM_BASEURL,ACTION_PARAM_JIRAUSERNAME, ACTION_PARAM_JIRAPASSWORD, ACTION_PARAM_PROJECTKEY,ACTION_PARAM_ASSIGNEE, ACTION_PARAM_HIGH,ACTION_PARAM_MEDIUM,ACTION_PARAM_LOW}, new String[] { ACTION_PARAM_FILTER_BY_FILE_TYPE })); }
In the first string array the mandatory action parameters are included while the optional parameters are included in the second string array.
In the APiActionHandler the method calls to handle the request should be included. The code is as follows.
@Override public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { if (log.isDebugEnabled()) { log.debug("Request for handleApiAction: " + name + " (params: " + params.toString() + ")"); } switch (name) { case ACTION_CREATE_JIRA_ISSUE: extension.createJiraIssues(params.getString(ACTION_PARAM_BASEURL),params.getString(ACTION_PARAM_JIRAUSERNAME), params.getString(ACTION_PARAM_JIRAPASSWORD),params.getString(ACTION_PARAM_PROJECTKEY), params.getString(ACTION_PARAM_ASSIGNEE), params.getString(ACTION_PARAM_HIGH), params.getString(ACTION_PARAM_MEDIUM), params.getString(ACTION_PARAM_LOW),params.getString(ACTION_PARAM_FILTER_BY_FILE_TYPE)); } return new ApiResponseElement(name,params.toString()); }
That’s it!! 🙂 Once the plugin has been installed the zap api can be accessed in the ui mode by your browser by typing in zap in the url and browsing into local api. (you will have to configure the browser proxy port to the same port which the zap is configured to)
If the plugin has been installed and the api methods have registered successfully they will be listed in the ui.
Once you click in and go to the method, you can see all the actions and the views listed and actions can be triggered by inserting the correct parameter values.
That is all from the zap part of this plugin. I had to customize the zap plugin for jenkins to include this functionality in the jenkings build step. I will publish that work in my next blog post.
Originally published at http://neatrick.wordpress.com on January 8, 2016.