Spike: Investigate and capture options on how to integrate, deploy and iterate the GraphQL version of the modal
Description
This spike's goal is to capture our options (and outline the work that is required for each) we have around integrating, deploying, and iterating on the GraphQL migration of the MR- and pipeline security modal.
The following options should be considered and their pros, cons, and rough effort captured:
- Build a new modal component
- Migrate all functionality to GraphQL and Apollo (including state management, which is currently handled by Vuex)
- Copy the existing modal component (including Vuex) and replace parts - for example, the vulnerability details component, which is due to be completed soon)
- Iteratively replace components of the existing modal (for example the details component, as mentioned above)
Steps
- Capture as much of the current modal's functionality and data, which includes various data sources and differences between the MR widget and pipeline modal (for example the MR modal is fetching vulnerability feedback from a separate endpoint and then adds it to each vulnerability object).
The output should include diagrams of components, their data flow, and how events propagate through the system. It should also include a list of used REST endpoints and the data that is consumed. - Look at the options listed above and capture their impact
- Create a rough roadmap for each option
Raw Findings
Components Overview
Current implementation
1) Vulnerability Details
- Migration is captured here: &8910 (closed)
- TODO:
- Refine Generic report: #382726 (closed)
2) Solution Card
Summary
- Display's
vulnerability.solutionHtml
or falls back tovulnerability.solution
orvulnerability.remediations\[0\].summary
- If there is not an existing MR for the given finding and a patch can be downloaded then show an extra message with instructions to create an MR or download the patch
Data dependencies
-
vulnerability.solutionHtml
missing but currently not used for vuex modal version orvulnerability.solution
- that means for the MVP this should not be needed -
vulnerability.remediations\[0\]
missing -
vulnerability.hasMergeRequest
missing
Endpoints
Pipeline
GET /api/v4/projects/34/vulnerability_findings
MR Widget
Same as Pipeline
Notes
- There are two versions of the card:
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card.vue
-
ee/app/assets/javascripts/vue_shared/security_reports/components/solution_card_vuex.vue
👈 used on current modal
Screenshots
3) Issue Notes
Summary
- Displays information about issues that were created for the given finding. This includes the creation date, details about the author and a link to the issue.
Props
feedback
{
author: {
id: '1',
name: 'Dave',
username: 'davepies',
path: 'davpies.me',
is_gitlab_employee: true,
},
created_at: '2022-11-17T09:33:07.971Z',
issue_url: 'http://foo.bar',
issue_iid: '111',
}
project
{
url: '/foo/bar',
value: 'Foo / Bar',
}
Endpoints
- Pipeline:
GET /api/v4/projects/34/vulnerability_findings?pipeline_id=1
->vulnerability.issue_feedback
- MR Widget:
GET /http://gdk.test:3000/security/security-reports/-/vulnerability_feedback?category=sast
(fetches for each category) andGET /security/security-reports/-/merge_requests/5/sast_reports
-> Vuex adds the data to what we get fromvulnerability_findings
from above
Screenshots
4) Merge Request Note
Summary
- Displays information about MRs that were created for the given finding. This includes the creation date, details about the author, and a link to the MR.
- Feedback is in
vulnerability.merge_request_feedback
Props
feedback
{
author: {
id: '1',
name: 'Dave',
username: 'davepies',
path: 'davpies.me',
is_gitlab_employee: true,
},
created_at: '2022-11-17T09:33:07.971Z',
merge_request_path: '/merge/foo',
merge_request_iid: 1,
}
project
{
url: '/foo/bar',
value: 'Foo / Bar',
}
Endpoints
- Pipeline:
GET /api/v4/projects/34/vulnerability_findings?pipeline_id=1
- MR Widget:
GET /security/security-reports/-/merge_requests/5/sast_reports
(for reach report type)
Screenshots
5) Dismissal Note
Summary
Displays information about a finding's dismissal (if present). This includes comments and information about the author.
Props
feedback
{
author: {
id: 1,
name: 'Author name',
username: 'author username',
path: 'author/path',
is_git_gitlab_employee: true,
},
// optional
comment_details: {
comment_author: {
id: '1',
name: 'Dave',
username: 'davepies',
path: 'davpies.me',
is_gitlab_employee: true,
},
comment_timestamp: '2022-11-17T09:33:07.971Z',
comment: 'foo is bar!',
},
created_at: '2022-11-17T09:33:07.971Z',
project: {
url: 'http://foo.bar',
value: 'project value',
},
// optional
pipeline: {
id: 1,
path: 'pipeline/path',
},
};
project
{
url: 'http://project/url',
value: 'project value'
}
Endpoints
- Pipeline:
GET /api/v4/projects/34/vulnerability_findings?pipeline_id=1&scope=dismissed
- MR Widget: e.g:
GET /security/security-reports/-/vulnerability_feedback?category=sast
and/security/security-reports/-/merge_requests/5/sast_reports
(requests for each report type and data gets combined, like mentioned above)
Screenshots
6) Dismissal Comment Box
Summary
- Renders textbox to enter a dismissal comment
- Gets displayed when there is a dismissal and no comment yet, or when the existing comment is being edited
- Lets a user add, edit and delete a comment
- Displays any error message that might have been triggered when trying to post the comment to the BE
Props
dismissal-comment
The placeholder text:
'this is a comment'
is-active
Set to true if the user is currently commenting
true | false
Error message
Any messages from errors that happened when trying to fetch or post data.
'message describing what went wrong'
Endpoints
Read
- Pipeline:
GET /api/v4/projects/34/vulnerability_findings?pipeline_id=1&scope=dismissed
- MR Widget:
GET /security/security-reports/-/vulnerability_feedback?category=sast
and/security/security-reports/-/merge_requests/5/sast_reports
(requests for each report type and data gets combined, like mentioned above)
Write (indirectly)
Pipeline:
POST /security/security-reports-fresh/-/vulnerability_feedback
payload
{ "vulnerability_feedback": { "category": "dependency_scanning", "comment": "test", "feedback_type": "dismissal", "pipeline_id": 1420, "project_fingerprint": "a5b166f93b07f2ead1c16552af374ebfda7fc7d0", "finding_uuid": "8b404791-53fc-5801-81c7-05d0d505a04e", "vulnerability_data": { "id": "client_14", "report_type": "dependency_scanning", "name": "Path Traversal in rubyzip", "severity": "critical", "confidence": "unknown", "scanner": { "external_id": "gemnasium", "name": "Gemnasium", "vendor": "GitLab" }, "identifiers": \[ { "external_type": "gemnasium", "external_id": "99f8ccec-097c-4147-9cd0-2a8cd3a354a4", "name": "Gemnasium-99f8ccec-097c-4147-9cd0-2a8cd3a354a4", "url": "``https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/blob/master/gem/rubyzip/CVE-2018-1000544.yml``" }, { "external_type": "cve", "external_id": "CVE-2018-1000544", "name": "CVE-2018-1000544", "url": "``https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000544``" } \], "project_fingerprint": "a5b166f93b07f2ead1c16552af374ebfda7fc7d0", "uuid": "8b404791-53fc-5801-81c7-05d0d505a04e", "create_jira_issue_url": null, "false_positive": false, "create_vulnerability_feedback_issue_path": "/security/security-reports-fresh/-/vulnerability_feedback", "create_vulnerability_feedback_merge_request_path": "/security/security-reports-fresh/-/vulnerability_feedback", "create_vulnerability_feedback_dismissal_path": "/security/security-reports-fresh/-/vulnerability_feedback", "project": { "id": 34, "name": "Security Reports - Fresh", "full_path": "/security/security-reports-fresh", "full_name": "Security / Security Reports - Fresh" }, "dismissal_feedback": null, "issue_feedback": { "id": 169, "created_at": "2022-11-24T13:39:31.705Z", "project_id": 34, "author": { "id": 1, "username": "root", "name": "Administrator", "state": "active", "avatar_url": "``https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon``", "web_url": "``http://gdk.test:3000/root``", "show_status": false, "path": "/root" }, "finding_uuid": "8b404791-53fc-5801-81c7-05d0d505a04e", "issue_iid": 1, "issue_url": "``http://gdk.test:3000/security/security-reports-fresh/-/issues/1``", "category": "dependency_scanning", "feedback_type": "issue", "branch": null, "project_fingerprint": "a5b166f93b07f2ead1c16552af374ebfda7fc7d0", "dismissal_reason": null }, "merge_request_feedback": null, "description": "The gem rubyzip contains a Directory Traversal vulnerability in Zip::File component that can result in write arbitrary files to the filesystem. This attack appear to be exploitable via If a site allows uploading of .zip files, an attacker can upload a malicious file that contains symlinks or files with absolute pathnames .. to write arbitrary files to the filesystem.", "description_html": "
The gem rubyzip contains a Directory Traversal vulnerability in Zip::File component that can result in write arbitrary files to the filesystem. This attack appear to be exploitable via If a site allows uploading of .zip files, an attacker can upload a malicious file that contains symlinks or files with absolute pathnames .. to write arbitrary files to the filesystem.", "links": \[{ "url": "``https://nvd.nist.gov/vuln/detail/CVE-2018-1000544``" }\], "location": { "file": "dependency-scanning-files/Gemfile.lock", "dependency": { "package": { "name": "rubyzip" }, "version": "1.2.1" } }, "remediations": null, "solution": "Upgrade to version 1.2.2 or above.", "evidence": null, "request": null, "response": null, "evidence_source": null, "supporting_messages": null, "assets": \[\], "details": { "vulnerablePackage": { "type": "text", "name": "Vulnerable Package", "value": "rubyzip:1.2.1" } }, "state": "detected", "scan": { "type": "dependency_scanning", "status": "success", "start_time": "2022-11-22T08:52:43", "end_time": "2022-11-22T08:52:46" }, "blob_path": "/security/security-reports-fresh/-/blob/225fa090f92d057854a68e9f8e071f86523be984/dependency-scanning-files/Gemfile.lock", "hasIssue": true, "hasMergeRequest": false, "isDismissed": false, "category": "dependency_scanning" } } }
MR Widget
Same as Pipeline
Delete (indirectly)
Pipeline
PATCH /security-reports-fresh/-/vulnerability_feedback/164
MR Widget
Same as Pipeline
Screenshots
7) Error Alert
Summary
Renders error message that gets displayed when dismissal or comment deletion results in an error.
Endpoints
- Dismissal and comment deletion
Screenshots
8) Dismiss / Undo Dismiss
Summary
Endpoints
Pipeline
Undo: DELETE 0/security/security-reports-fresh/-/vulnerability_feedback/164
MR Widget
Same as pipeline
Screenshots
9) Create Issue (GitLab / Jira)
Summary
If either a path* for creating a gitlab or jira issue is given, then it renders a "Create Issue" or "Create Jira Issue" button. If both are present then Jira issues take precedence. If there is an existing issue the button also won't render.
\*
vulnerability.create_vulnerability_feedback_issue_path
/ vulnerability.create_jira_issue_url
Endpoints
Pipeline
POST /security/security-reports-fresh/-/vulnerability_feedback
MR Widget
Same as Pipeline
Notes
Both data fields currently missing.
When there are more than one action buttons available, they get moved into a split-button (see screenshots below).
Screenshots
Default
Goes here
10) Download Patch
Summary
Uses the remediation's diff's data * to dynamically create a download link (using: \~/lib/utils/downloader
)
\*
vulnerability.remediations\[0\].diff
Endpoints
Pipeline
GET /api/v4/projects/34/vulnerability_findings?pipeline_id=1
MR Widget
Same as Pipeline
11) Resolve with MR
Summary
If the given vulnerability is not resolved, doesn't have an existing MR associated and has remedidation data, then the button to create an MR gets shown.
Endpoints
Pipeline
POST /security/security-reports/-/vulnerability_feedback
MR Widget
Same as Pipeline
What do we need for the migration
-
Solution Card
- Data we need
- remediations - Add remediations field to PipelineSecurityRepor... (#384508 - closed) (in progress)
-
mergeRequest (following the
Vulnerability
type) - Add mergeRequest field to PipelineSecurityRepor... (#384509 - closed) (in review) - solutionHtml (nice to have - currently not showing on Vuex version of modal but used on details page) - Add solutionHtml field to PipelineSecurityRepor... (#384510 - closed)
- Data we need
-
Issue notes
- Data we need
-
issueFeedback(Currently via REST invulnerability.issue_feedback
and thevulnerability_feedback
endpoint) -
issueLinks - Add issueLinks field to PipelineSecurityReportF... (#384867 - closed) (in review)
- Previously used feedback, we'll now respond directly with issues
-
- Data we need
-
MR notes
- Data we need
-
merge_request_feedback(Note: Might be available through themergeRequest
field, noted above) - This will be available via
mergeRequest
field
-
- Data we need
-
Resolve via MR
- Mutation we need
- Create MR that resolves finding (can we use existing one? To investigate)
- Mutation we need
-
Download Patch
- Data we need
-
remediations - currently we are using
remediations\[0\].diff
to dynamically generate a download on the client side
-
Dismissal Notes
- Data we need
- dismissal_feedback
- Data we need
-
Dismissal
- Create - No additional work needed.
- Notes
- Existing mutation:
securityFindingDismiss
- Existing mutation:
- Notes
- Undo
- Mutation we need
- Vulnerabilities use
vulnerabilityRevertToDetected
- Vulnerabilities use
- Undo / delete dismissal
- Mutation we need
- Comment
- Create
- Notes
- Existing mutation
securityFindingDismiss
(viacomment
field on input)
- Existing mutation
- Notes
- Edit
- Mutation we need
- Edit a dismissal comment
- Mutation we need
- Delete
- Mutation we need
- Delete a dismissal comment
- Mutation we need
- Create
- Create - No additional work needed.
-
Issue Creation
- GitLab
-
Mutation we needCreate an issue for a finding (maybe we can usecreateIssue
for this? To investigate)
- We have this mutation available at securityFindingCreateIssue. It is behind the :deprecate_vulnerability_feedback feature flag right now. Also, the issues are not being properly populated at this time (SecurityFinding::CreateIssueService does not pr... (#385616 - closed))
-
- Jira
- Notes
- Can use
vulnerabilityExternalIssueLinkCreate
mutation ? To investigate
- Can use
- Notes
- GitLab