@enterprise-cmcs/macpro-security-hub-sync
Advanced tools
Comparing version 1.3.0 to 1.4.0
@@ -7,2 +7,3 @@ import { IssueObject } from "jira-client"; | ||
private static checkEnvVars; | ||
private static formatLabelQuery; | ||
getAllSecurityHubIssuesInJiraProject(identifyingLabels: string[]): Promise<IssueObject[]>; | ||
@@ -9,0 +10,0 @@ createNewIssue(issue: IssueObject): Promise<IssueObject>; |
@@ -39,3 +39,3 @@ "use strict"; | ||
this.jiraClosedStatuses = process.env.JIRA_CLOSED_STATUSES | ||
? process.env.JIRA_CLOSED_STATUSES.split(",") | ||
? process.env.JIRA_CLOSED_STATUSES.split(",").map((status) => status.trim()) | ||
: ["Done"]; | ||
@@ -64,18 +64,24 @@ this.jira = new jira_client_1.default({ | ||
} | ||
static formatLabelQuery(label) { | ||
return `labels = '${label}'`; | ||
} | ||
async getAllSecurityHubIssuesInJiraProject(identifyingLabels) { | ||
const labelQuery = identifyingLabels.reduce((accumulator, currentValue) => accumulator + `AND labels = ${currentValue} `, ""); | ||
const searchOptions = {}; | ||
const query = `project = ${process.env.JIRA_PROJECT} AND labels = security-hub ${labelQuery} AND status not in ("${this.jiraClosedStatuses.join('","')}")`; | ||
const labelQueries = [...identifyingLabels, "security-hub"].map((label) => Jira.formatLabelQuery(label)); | ||
const projectQuery = `project = '${process.env.JIRA_PROJECT}'`; | ||
const statusQuery = `status not in ('${this.jiraClosedStatuses.join("','" // wrap each closed status in single quotes | ||
)}')`; | ||
const fullQuery = [...labelQueries, projectQuery, statusQuery].join(" AND "); | ||
// We want to do everything possible to prevent matching tickets that we shouldn't | ||
if (!fullQuery.includes(Jira.formatLabelQuery("security-hub"))) { | ||
throw new Error("ERROR: Your query does not include the 'security-hub' label, and is too broad. Refusing to continue"); | ||
} | ||
if (!fullQuery.match(Jira.formatLabelQuery("[0-9]{12}"))) { | ||
throw new Error("ERROR: Your query does not include an AWS Account ID as a label, and is too broad. Refusing to continue"); | ||
} | ||
let totalIssuesReceived = 0; | ||
let allIssues = []; | ||
let results; | ||
const searchOptions = {}; | ||
do { | ||
// We want to do everything possible to prevent matching tickets that we shouldn't | ||
if (!query.includes("AND labels = security-hub ")) { | ||
throw "ERROR: Your query does not include the 'security-hub' label, and is too broad. Refusing to continue"; | ||
} | ||
if (!query.match(" AND labels = [0-9]{12}")) { | ||
throw "ERROR: Your query does not include an AWS Account ID as a label, and is too broad. Refusing to continue"; | ||
} | ||
results = await this.jira.searchJira(query, searchOptions); | ||
results = await this.jira.searchJira(fullQuery, searchOptions); | ||
allIssues = allIssues.concat(results.issues); | ||
@@ -89,3 +95,3 @@ totalIssuesReceived += results.issues.length; | ||
try { | ||
console.log("Creating Jira issue."); | ||
console.log("Creating Jira issue"); | ||
issue.fields.project = { key: process.env.JIRA_PROJECT }; | ||
@@ -105,3 +111,3 @@ const response = await this.jira.addNewIssue(issue); | ||
try { | ||
console.log("need to close jira issue:", issueKey); | ||
console.log("Need to close Jira issue:", issueKey); | ||
const transitions = await this.jira.listTransitions(issueKey); | ||
@@ -108,0 +114,0 @@ const doneTransition = transitions.transitions.find((t) => t.name === "Done"); |
@@ -9,2 +9,3 @@ import { SecurityHubFinding } from "./libs"; | ||
}; | ||
epicKey?: string; | ||
} | ||
@@ -16,2 +17,3 @@ export declare class SecurityHubJiraSync { | ||
private readonly region; | ||
private readonly epicKey; | ||
constructor(options?: SecurityHubJiraSyncOptions); | ||
@@ -18,0 +20,0 @@ sync(): Promise<void>; |
@@ -11,2 +11,3 @@ "use strict"; | ||
region; | ||
epicKey; | ||
constructor(options = {}) { | ||
@@ -18,2 +19,3 @@ const { region = "us-east-1", severities = ["MEDIUM", "HIGH", "CRITICAL"], customJiraFields = {}, } = options; | ||
this.customJiraFields = customJiraFields; | ||
this.epicKey = options.epicKey; | ||
} | ||
@@ -26,6 +28,2 @@ async sync() { | ||
const jiraIssues = await this.jira.getAllSecurityHubIssuesInJiraProject(identifyingLabels); | ||
// console.log( | ||
// "all current statuses on security hub issues:", | ||
// new Set(jiraIssues.map((i) => i.fields.status.name)) | ||
// ); | ||
// Step 2. Get all current findings from Security Hub | ||
@@ -121,4 +119,7 @@ const shFindings = await this.securityHub.getAllActiveFindings(); | ||
}; | ||
if (this.epicKey) { | ||
newIssueData.fields.parent = { key: this.epicKey }; | ||
} | ||
const newIssueInfo = await this.jira.createNewIssue(newIssueData); | ||
console.log("new Jira issue created:", newIssueInfo); | ||
console.log("New Jira issue created:", newIssueInfo); | ||
} | ||
@@ -125,0 +126,0 @@ createJiraIssuesForNewFindings(jiraIssues, shFindings, identifyingLabels) { |
@@ -7,3 +7,3 @@ { | ||
}, | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "NPM module to create Jira issues for all findings in Security Hub for the current AWS account..", | ||
@@ -10,0 +10,0 @@ "main": "./dist/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28521
441