Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #105 from JupiterOne/INT-6664-findings
Browse files Browse the repository at this point in the history
INT-6664: ingest GitLab vulnerability findings
  • Loading branch information
gastonyelmini authored Jun 15, 2023
2 parents 4fe71f5 + 9ac1214 commit a228911
Show file tree
Hide file tree
Showing 10 changed files with 1,700 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/jupiterone.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ The following entities are created:
| ------------- | ---------------------- | --------------------- |
| Account | `gitlab_account` | `Account` |
| Commit | `gitlab_commit` | `CodeCommit` |
| Finding | `gitlab_finding` | `Finding` |
| Group | `gitlab_group` | `Group` |
| Merge Request | `gitlab_merge_request` | `CodeReview`, `PR` |
| Project | `gitlab_project` | `CodeRepo`, `Project` |
Expand All @@ -101,6 +102,7 @@ The following relationships are created:
| `gitlab_group` | **HAS** | `gitlab_project` |
| `gitlab_group` | **HAS** | `gitlab_user` |
| `gitlab_merge_request` | **HAS** | `gitlab_commit` |
| `gitlab_project` | **HAS** | `gitlab_finding` |
| `gitlab_project` | **HAS** | `gitlab_merge_request` |
| `gitlab_project` | **HAS** | `gitlab_user` |
| `gitlab_user` | **APPROVED** | `gitlab_merge_request` |
Expand Down
12 changes: 12 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const Steps = {
PROJECTS: 'fetch-projects',
MERGE_REQUESTS: 'fetch-merge-requests',
COMMITS: 'fetch-mr-commits',
FINDINGS: 'fetch-vulnerability-findings',
BUILD_ACCOUNT_HAS_PROJECT: 'build-account-project-relationships',
BUILD_ACCOUNT_HAS_GROUP: 'build-account-group-relationships',
BUILD_PROJECT_HAS_USER: 'build-project-user-relationships',
Expand Down Expand Up @@ -34,6 +35,11 @@ export const Entities = {
_type: 'gitlab_group',
_class: 'Group',
},
FINDING: {
resourceName: 'Finding',
_type: 'gitlab_finding',
_class: ['Finding'],
},
MERGE_REQUEST: {
resourceName: 'Merge Request',
_type: 'gitlab_merge_request',
Expand Down Expand Up @@ -88,6 +94,12 @@ export const Relationships = {
_class: RelationshipClass.HAS,
targetType: Entities.PROJECT._type,
},
PROJECT_HAS_FINDING: {
_type: 'gitlab_project_has_finding',
sourceType: Entities.PROJECT._type,
_class: RelationshipClass.HAS,
targetType: Entities.FINDING._type,
},
PROJECT_HAS_PR: {
_type: 'gitlab_project_has_merge_request',
sourceType: Entities.PROJECT._type,
Expand Down
90 changes: 90 additions & 0 deletions src/converters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
GitLabMergeRequestApproval,
GitLabProject,
GitLabUser,
GitLabFinding,
} from '../provider/types';
import { getCommitWebLinkFromMergeRequest } from '../util/mergeRequest';

Expand Down Expand Up @@ -204,3 +205,92 @@ const COMMIT_ID_PREFIX = 'gitlab-commit';
export function createCommitIdentifier(id: number): string {
return `${COMMIT_ID_PREFIX}:${id}`;
}

export function createVulnerabilityFindingEntity(
finding: GitLabFinding,
): Entity {
const key = createFindingIdentifier(finding.id);

// For more Finding data model class required fields info please visit: https://github.com/JupiterOne/data-model/blob/main/src/schemas/Finding.json.
return createIntegrationEntity({
entityData: {
source: finding,
assign: {
_key: key,
_type: Entities.FINDING._type,
_class: Entities.FINDING._class,
// START: finding data model required fields
category: finding?.report_type,
severity: finding?.severity,
numericSeverity: getNumericSeverity(finding?.severity),
open: finding.state?.toLocaleLowerCase() === 'detected',
// END: finding data model required fields
id: String(finding.id),
reportType: finding.report_type,
name: finding.name,
confidence: finding.confidence,
'scanner.externalId': finding.scanner?.external_id,
'scanner.name': finding.scanner?.name,
'scanner.vendor': finding.scanner?.vendor,
identifiers: finding.identifiers?.map(
(identifier) => identifier.external_id,
),
projectFingerprint: finding.project_fingerprint,
uuid: finding.uuid,
createJiraIssueUrl: finding.create_jira_issue_url,
falsePositive: finding.false_positive,
createVulnerabilityFeedbackIssuePath:
finding.create_vulnerability_feedback_issue_path,
createVulnerabilityFeedbackMergeRequestPath:
finding.create_vulnerability_feedback_merge_request_path,
createVulnerabilityFeedbackDismissalPath:
finding.create_vulnerability_feedback_dismissal_path,
'project.id': finding.project?.id,
'project.name': finding.project?.name,
'project.fullPath': finding.project?.full_path,
'project.fullName': finding.project?.full_name,
dismissalFeedback: finding.dismissal_feedback,
issueFeedback: finding.issue_feedback,
mergeRequestFeedback: finding.merge_request_feedback,
description: finding.description,
links: finding.links?.map((link) => link.url),
'location.file': finding.location?.file,
'location.startLine': finding.location?.start_line,
'location.class': finding.location?.class,
'location.method': finding.location?.method,
'location.hostname': finding.location?.hostname,
solution: finding.solution,
evidence: finding.evidence,
state: finding.state,
blobPath: finding.blob_path,
'scan.type': finding.scan?.type,
'scan.status': finding.scan?.status,
'scan.startTime': parseTimePropertyValue(finding.scan?.start_time),
'scan.endTime': parseTimePropertyValue(finding.scan?.end_time),
},
},
});
}

const FINDING_ID_PREFIX = 'gitlab-finding';
export function createFindingIdentifier(id: number): string {
return `${FINDING_ID_PREFIX}:${id}`;
}

export function getNumericSeverity(severity: string | undefined) {
if (!severity) {
return 0;
} else if (/critical/i.test(severity)) {
return 10;
} else if (/high/i.test(severity)) {
return 7;
} else if (/medium/i.test(severity)) {
return 5;
} else if (/low/i.test(severity)) {
return 2;
} else if (/info/i.test(severity)) {
return 1;
} else if (/unknown/i.test(severity)) {
return undefined;
}
}
14 changes: 14 additions & 0 deletions src/provider/GitlabClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '@jupiterone/integration-sdk-core';

import {
GitLabFinding,
GitLabGroup,
GitLabMergeRequest,
GitLabMergeRequestApproval,
Expand Down Expand Up @@ -81,6 +82,19 @@ export class GitlabClient {
return this.makePaginatedRequest(HttpMethod.GET, '/groups');
}

async iterateProjectVulnerabilities(
projectId: string,
iteratee: ResourceIteratee<GitLabFinding>,
): Promise<void> {
return this.iterateResources(
`/projects/${projectId}/vulnerability_findings`,
iteratee,
{
params: { severity: ['medium', 'high', 'critical'] },
},
);
}

async iterateOwnedProjects(
iteratee: ResourceIteratee<GitLabProject>,
): Promise<void> {
Expand Down
64 changes: 64 additions & 0 deletions src/provider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,70 @@ export interface GitLabGroup {
file_template_project_id: number;
}

export interface GitLabFinding {
id: number;
report_type?: string;
name?: string;
severity?: string;
confidence?: string;
scanner?: {
external_id?: string;
name?: string;
vendor?: string;
};
identifiers?: [
{
external_type: string;
external_id: string;
name: string;
url: string;
},
];
project_fingerprint?: string;
uuid?: string;
create_jira_issue_url?: string;
false_positive?: boolean;
create_vulnerability_feedback_issue_path?: string;
create_vulnerability_feedback_merge_request_path?: string;
create_vulnerability_feedback_dismissal_path?: string;
project?: {
id?: number;
name?: string;
full_path?: string;
full_name?: string;
};
dismissal_feedback?: string;
issue_feedback?: string;
merge_request_feedback?: string;
description?: null;
links?: [{ url: string }];
location?: {
file?: string;
start_line?: number;
class?: string;
method?: string;
hostname?: string;
};
solution?: string;
evidence?: string;
details?: {
urls: { name?: string; type?: string };
discovered_at?: {
name?: string;
type?: string;
value?: string;
};
};
state?: string;
scan?: {
type?: string;
status?: string;
start_time?: string;
end_time?: string;
};
blob_path?: string;
}

export type GitLabProject = Opaque<any, 'GitLabProject'>;

export type GitLabMergeRequest = Opaque<any, 'GitLabMergeRequest'>;
Expand Down
Loading

0 comments on commit a228911

Please sign in to comment.