Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISOC-3693 Secret scanning alerts backfill #2335

Merged
merged 23 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
41bc2c1
initial checkin
Harminder84 Aug 1, 2023
bf33a17
inital checkin
Harminder84 Aug 2, 2023
6c5bb3f
Merge branch 'main' into ISOC-3776-installation-webhook
Harminder84 Aug 2, 2023
a2d44e1
Merge branch 'main' into ISOC-3776-installation-webhook
Harminder84 Aug 3, 2023
c5c6e71
Merge branch 'main' into ISOC-3776-installation-webhook
gxueatlassian Aug 3, 2023
55fdd1a
Merge branch 'main' into ISOC-3776-installation-webhook
Harminder84 Aug 3, 2023
a4ee049
refacored
Harminder84 Aug 3, 2023
5dc337c
Merge branch 'main' into ISOC-3776-installation-webhook
Harminder84 Aug 3, 2023
03503a0
Merge branch 'main' into ISOC-3776-installation-webhook
Harminder84 Aug 4, 2023
51281ca
update error message
Harminder84 Aug 4, 2023
3c934d0
adding identifiers for screcet scanning VULNs
Harminder84 Aug 6, 2023
3b04ff2
initial checkin
Harminder84 Aug 7, 2023
153af66
Merge branch 'main' into ISOC-3678-backill-dependabot-alerts
Harminder84 Aug 7, 2023
494651d
Merge branch 'main' into ISOC-3678-backill-dependabot-alerts
Harminder84 Aug 8, 2023
9c11e6b
inital checkin
Harminder84 Aug 8, 2023
220c7f5
Merge branch 'main' into ISOC-3693-secret-scanning-backfill-db-cols
Harminder84 Aug 8, 2023
a0190f7
initial sync
Harminder84 Aug 10, 2023
3f70385
Merge branch 'main' into ISOC-3693-secret-scanning-backfill
Harminder84 Aug 10, 2023
fcb503b
Merge branch 'main' into ISOC-3693-secret-scanning-backfill
Harminder84 Aug 10, 2023
cbf7343
code refacttored
Harminder84 Aug 11, 2023
a050130
Merge branch 'main' into ISOC-3693-secret-scanning-backfill
Harminder84 Aug 11, 2023
d37fa10
missed typing file
Harminder84 Aug 11, 2023
00a65c6
Merge branch 'main' into ISOC-3693-secret-scanning-backfill
Harminder84 Aug 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/github/client/github-client.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ export type GetPullRequestParams = {
page?: number;
}

export type GetSecretScanningAlertRequestParams = {
sort?: string;
direction?: string;
per_page?: number;
page?: number;
}

export type GraphQlQueryResponse<ResponseData> = {
data: ResponseData;
errors?: GraphQLError[];
Expand Down
9 changes: 9 additions & 0 deletions src/github/client/github-installation-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
ActionsListRepoWorkflowRunsResponseEnhanced,
CreateReferenceBody,
GetPullRequestParams,
GetSecretScanningAlertRequestParams,
PaginatedAxiosResponse,
ReposGetContentsResponse
} from "./github-client.types";
Expand All @@ -38,6 +39,7 @@ import { GithubClientError, GithubClientGraphQLError } from "~/src/github/client
import { cloneDeep } from "lodash";
import { BooleanFlags, booleanFlag } from "config/feature-flags";
import { logCurlOutputInChunks, runCurl } from "utils/curl/curl-utils";
import { SecretScanningAlertResponseItem } from "./secret-scanning-alert.types";

// Unfortunately, the type is not exposed in Octokit...
// https://docs.github.com/en/rest/pulls/review-requests?apiVersion=2022-11-28#get-all-requested-reviewers-for-a-pull-request
Expand Down Expand Up @@ -74,6 +76,13 @@ export class GitHubInstallationClient extends GitHubClient {
this.gitHubServerAppId = gshaId;
}


public async getSecretScanningAlerts(owner: string, repo: string, secretScanningAlertRequestParams: GetSecretScanningAlertRequestParams): Promise<AxiosResponse<SecretScanningAlertResponseItem[]>> {
return await this.get<SecretScanningAlertResponseItem[]>(`/repos/{owner}/{repo}/secret-scanning/alerts`, secretScanningAlertRequestParams, {
owner,
repo
});
}
/**
* Lists pull requests for the given repository.
*/
Expand Down
13 changes: 13 additions & 0 deletions src/github/client/secret-scanning-alert.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type SecretScanningAlertResponseItem = {
number: number,
created_at: string,
url: string,
html_url: string,
locations_url: string,
state: "open" | "resolved",
resolution?: string,
resolved_at?: string,
resolution_comment?: string,
secret_type: string,
secret_type_display_name: string
}
2 changes: 1 addition & 1 deletion src/github/installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const installationWebhookHandler = async (
);

} catch (err) {
logger.warn({ err }, "Failed to submit security workspace to Jira or trigger backfill via backfill");
logger.warn({ err }, "Failed to submit security workspace to Jira or trigger backfill");
const webhookReceived = context.webhookReceived;
webhookReceived && emitWebhookProcessedMetrics(
new Date(webhookReceived).getTime(),
Expand Down
20 changes: 17 additions & 3 deletions src/models/reposyncstate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,22 @@ export interface RepoSyncStateProperties {
buildStatus?: TaskStatus;
deploymentStatus?: TaskStatus;
dependabotAlertStatus?: TaskStatus;
secretScanningAlertStatus?: TaskStatus,
branchCursor?: string;
commitCursor?: string;
issueCursor?: string;
pullCursor?: string;
buildCursor?: string;
deploymentCursor?: string;
dependabotAlertCursor?: string;
secretScanningAlertCursor?: string;
commitFrom?: Date;
branchFrom?: Date;
pullFrom?: Date;
buildFrom?: Date;
deploymentFrom?: Date;
dependabotAlertFrom?: Date;
secretScanningAlertFrom?: Date;
forked?: boolean;
repoPushedAt: Date;
repoUpdatedAt: Date;
Expand Down Expand Up @@ -76,19 +79,22 @@ export class RepoSyncState extends Model implements RepoSyncStateProperties {
buildStatus?: TaskStatus;
deploymentStatus?: TaskStatus;
dependabotAlertStatus?: TaskStatus;
secretScanningAlertStatus?: TaskStatus;
branchCursor?: string;
commitCursor?: string;
issueCursor?: string;
pullCursor?: string;
buildCursor?: string;
deploymentCursor?: string;
dependabotAlertCursor?: string;
secretScanningAlertCursor?: string;
commitFrom?: Date;
branchFrom?: Date;
pullFrom?: Date;
buildFrom?: Date;
deploymentFrom?: Date;
dependabotAlertFrom?: Date;
secretScanningAlertFrom?: Date;
forked?: boolean;
repoPushedAt: Date;
repoUpdatedAt: Date;
Expand Down Expand Up @@ -135,7 +141,8 @@ export class RepoSyncState extends Model implements RepoSyncStateProperties {
commitStatus: "failed",
buildStatus: "failed",
deploymentStatus: "failed",
dependabotAlertStatus: "failed"
dependabotAlertStatus: "failed",
secretScanningAlertStatus: "failed"
}
}
});
Expand All @@ -152,7 +159,8 @@ export class RepoSyncState extends Model implements RepoSyncStateProperties {
commitStatus: "failed",
buildStatus: "failed",
deploymentStatus: "failed",
dependabotAlertStatus: "failed"
dependabotAlertStatus: "failed",
secretScanningAlertStatus: "failed"
}
}
}));
Expand Down Expand Up @@ -362,7 +370,10 @@ export class RepoSyncState extends Model implements RepoSyncStateProperties {
commitFrom: null,
dependabotAlertStatus: null,
dependabotAlertCursor: null,
dependabotAlertFrom: null
dependabotAlertFrom: null,
secretScanningAlertFrom: null,
secretScanningAlertStatus: null,
secretScanningAlertCursor: null
}, {
where: {
subscriptionId: subscription.id
Expand Down Expand Up @@ -410,19 +421,22 @@ RepoSyncState.init({
buildStatus: DataTypes.ENUM("pending", "complete", "failed"),
deploymentStatus: DataTypes.ENUM("pending", "complete", "failed"),
dependabotAlertStatus: DataTypes.ENUM("pending", "complete", "failed"),
secretScanningAlertStatus: DataTypes.ENUM("pending", "complete", "failed"),
branchCursor: STRING,
commitCursor: STRING,
issueCursor: STRING,
pullCursor: STRING,
buildCursor: STRING,
deploymentCursor: STRING,
dependabotAlertCursor: STRING,
secretScanningAlertCursor: STRING,
commitFrom: DATE,
branchFrom: DATE,
pullFrom: DATE,
buildFrom: DATE,
deploymentFrom: DATE,
dependabotAlertFrom: DATE,
secretScanningAlertFrom: DATE,
forked: BOOLEAN,
repoPushedAt: DATE,
repoUpdatedAt: DATE,
Expand Down
2 changes: 1 addition & 1 deletion src/routes/jira/sync/jira-sync-post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe("sync", () => {
installationId: installationIdForServer,
jiraHost,
commitsFromDate: commitsFromDate.toISOString(),
targetTasks: ["pull", "branch", "commit", "build", "deployment", "dependabotAlert"],
targetTasks: ["pull", "branch", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"],
gitHubAppConfig: expect.objectContaining({ gitHubAppId: gitHubServerApp.id, uuid: gitHubServerApp.uuid })
}), expect.anything(), expect.anything());
});
Expand Down
2 changes: 1 addition & 1 deletion src/routes/jira/sync/jira-sync-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,5 @@ const determineSyncTypeAndTargetTasks = async (syncTypeFromReq: string, subscrip
return { syncType: "full", targetTasks: undefined };
}

return { syncType: "partial", targetTasks: ["pull", "branch", "commit", "build", "deployment", "dependabotAlert"] };
return { syncType: "partial", targetTasks: ["pull", "branch", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"] };
};
8 changes: 5 additions & 3 deletions src/sync/installation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ describe("sync/installation", () => {

describe("getTargetTasks", () => {
it("should return all tasks if no target tasks present", async () => {
expect(getTargetTasks()).toEqual(["pull", "branch", "commit", "build", "deployment", "dependabotAlert"]);
expect(getTargetTasks([])).toEqual(["pull", "branch", "commit", "build", "deployment", "dependabotAlert"]);
expect(getTargetTasks()).toEqual(["pull", "branch", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"]);
expect(getTargetTasks([])).toEqual(["pull", "branch", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"]);
});

it("should return single target task", async () => {
Expand Down Expand Up @@ -566,7 +566,9 @@ describe("sync/installation", () => {
expect(repoSync.dependabotAlertFrom).toBeNull();
});

describe.each(["pull", "commit", "build", "deployment", "dependabotAlert"] as TaskType[])("Update jobs status for each tasks", (taskType: TaskType) => {
describe.each(
["pull", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"] as TaskType[]
)("Update jobs status for each tasks", (taskType: TaskType) => {
const colTaskFrom = `${taskType}From`;
const task: Task = {
task: taskType,
Expand Down
8 changes: 6 additions & 2 deletions src/sync/installation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { sendAnalytics } from "utils/analytics-client";
import { AnalyticsEventTypes, AnalyticsTrackEventsEnum } from "interfaces/common";
import { getNextTasks } from "~/src/sync/scheduler";
import { getDependabotAlertTask } from "./dependabot-alerts";
import { getSecretScanningAlertTask } from "./secret-scanning-alerts";

const tasks: TaskProcessors = {
repository: getRepositoryTask,
Expand All @@ -34,10 +35,11 @@ const tasks: TaskProcessors = {
commit: getCommitTask,
build: getBuildTask,
deployment: getDeploymentTask,
dependabotAlert: getDependabotAlertTask
dependabotAlert: getDependabotAlertTask,
secretScanningAlert: getSecretScanningAlertTask
};

const allTaskTypes: TaskType[] = ["pull", "branch", "commit", "build", "deployment", "dependabotAlert"];
const allTaskTypes: TaskType[] = ["pull", "branch", "commit", "build", "deployment", "dependabotAlert", "secretScanningAlert"];
const allTasksExceptBranch = without(allTaskTypes, "branch");

export const getTargetTasks = (targetTasks?: TaskType[]): TaskType[] => {
Expand Down Expand Up @@ -235,9 +237,11 @@ const sendPayloadToJira = async (task: TaskType, jiraClient, jiraPayload, reposi
});
break;
case "dependabotAlert":
case "secretScanningAlert":{
await jiraClient.security.submitVulnerabilities(jiraPayload, {
operationType: "BACKFILL"
});
}
break;
default:
await jiraClient.devinfo.repository.update(jiraPayload, {
Expand Down
33 changes: 31 additions & 2 deletions src/sync/scheduler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ describe("scheduler", () => {
expect(task.task).toEqual("commit");
});
});
it("should not filter by dependabot alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is off", async () => {
it("should filter dependabot alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is off", async () => {
when(booleanFlag).calledWith(BooleanFlags.ENABLE_GITHUB_SECURITY_IN_JIRA, expect.anything()).mockResolvedValue(false);
configureRateLimit(10000, 10000);
const repoSyncStates = await RepoSyncState.findAllFromSubscription(subscription);
Expand All @@ -255,7 +255,7 @@ describe("scheduler", () => {
expect(tasks.otherTasks.length).toEqual(0);
});

it("should not filter by dependabot alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is on", async () => {
it("should not filter dependabot alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is on", async () => {
when(booleanFlag).calledWith(BooleanFlags.ENABLE_GITHUB_SECURITY_IN_JIRA, expect.anything()).mockResolvedValue(true);
configureRateLimit(10000, 10000);
const repoSyncStates = await RepoSyncState.findAllFromSubscription(subscription);
Expand All @@ -271,4 +271,33 @@ describe("scheduler", () => {
expect(task.task).toEqual("dependabotAlert");
});
});
it("should filter secret scanning alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is off", async () => {
when(booleanFlag).calledWith(BooleanFlags.ENABLE_GITHUB_SECURITY_IN_JIRA, expect.anything()).mockResolvedValue(false);
configureRateLimit(10000, 10000);
const repoSyncStates = await RepoSyncState.findAllFromSubscription(subscription);
await Promise.all(repoSyncStates.map((record) => {
record.secretScanningAlertStatus = "pending";
return record.save();
}));
githubUserTokenNock(DatabaseStateCreator.GITHUB_INSTALLATION_ID);
const tasks = await getNextTasks(subscription, ["secretScanningAlert"], getLogger("test"));
expect(tasks.mainTask).toBeUndefined();
expect(tasks.otherTasks.length).toEqual(0);
});
it("should not filter secret scanning alerts task if ENABLE_GITHUB_SECURITY_IN_JIRA FF is on", async () => {
when(booleanFlag).calledWith(BooleanFlags.ENABLE_GITHUB_SECURITY_IN_JIRA, expect.anything()).mockResolvedValue(true);
configureRateLimit(10000, 10000);
const repoSyncStates = await RepoSyncState.findAllFromSubscription(subscription);
await Promise.all(repoSyncStates.map((record) => {
record.secretScanningAlertStatus = "pending";
return record.save();
}));

githubUserTokenNock(DatabaseStateCreator.GITHUB_INSTALLATION_ID);
const tasks = await getNextTasks(subscription, ["secretScanningAlert"], getLogger("test"));
expect(tasks.mainTask!.task).toEqual("secretScanningAlert");
tasks.otherTasks.forEach(task => {
expect(task.task).toEqual("secretScanningAlert");
});
});
});
2 changes: 1 addition & 1 deletion src/sync/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export const getNextTasks = async (subscription: Subscription, targetTasks: Task

let tasks = getTargetTasks(targetTasks);
if (!await booleanFlag(BooleanFlags.ENABLE_GITHUB_SECURITY_IN_JIRA, subscription.jiraHost)) {
tasks = without(tasks, "dependabotAlert");
tasks = without(tasks, "dependabotAlert", "secretScanningAlert");
}

const nSubTasks = await estimateNumberOfSubtasks(subscription, logger);
Expand Down
Loading