Goal
As a Fleet user, I want to use Fleet in my vulnerability ticketing workflow so that I don't have to manually create tickets for new vulnerabilities (CVEs) or configure the webhook to create them for me.
NOTE: We will only support Jira Cloud in this first iteration using the v2 API. We are choosing to integrate with the v2 API and not the v3 API because it is more likely that older hosted versions of Jira Server will support v2 API. In the future, we may upgrade to using the v3 API if we need one of the new features.
Related
- Epic: #4523
- Frontend (blocked): #2936
- Jira Cloud Setup (done) https://fleetdm.atlassian.net/: #4579
Figma
Integrations for vulnerability automations: https://www.figma.com/file/hdALBDsrti77QuDNSzLdkx/%F0%9F%9A%A7-Fleet-EE-(dev-ready%2C-scratchpad)?node-id=3905%3A218712
Jira ticket template
Summary (what Jira call's a name or title):
<CVE identifier> detected on <Number of affected hosts> hosts
Description:
See vulnerability (CVE) details in National Vulnerability Database (NVD) here: <Link to CVE details in NVD>
Affected hosts:
<Hostname1>: <Link to Host details page>
<Hostname2>: <Link to Host details page>
<Hostname3>: <Link to Host details page>
<Hostname4>: <Link to Host details page>
...
<Hostname50>: Link to Host details page>
View the affected software and more affected hosts:
1. Go to the **Software** page in Fleet: <Link to Software page in Fleet>
2. Above the list of software, in the **Search software** box, enter <CVE identifier>.
3. Hover over the affected software and select **View all hosts**.
--
This issue was created automatically by your Fleet to Jira integration.
## Tasks
### 1
- [x] Add support for a new `integrations` object in the `app_config_json` table.
- Use the following structure:
```json
{
"integrations": {
"jira": [
{
"url": "https://example.jira.com",
"username": "adminUser",
"password": "abc123",
"project_key": "PROJECT",
"enable_software_vulnerabilities": false
}
]
}
}
2
- [x] When a new software vulnerability automation is triggered, determine if either a Jira integration or webhook is enabled.
- Both configuration objects are stored in the
app_config_json
table using the following structure:
{
"integrations": {
"jira": [
{
"url": "https://example.jira.com",
"username": "adminUser",
"password": "abc123",
"project_key": "PROJECT",
"enable_software_vulnerabilities": false
}
]
}
"webhook_settings": {
"vulnerabilities_webhook": {
"enable_vulnerabilities_webhook":true,
"destination_url": "https://server.com",
"host_batch_size": 1000
}
},
}
- If
webhook_settings.vulnerabilities_webhook.enable_vulnerabilities_webhook: true
, send the notification through the existing webhook flow.
- If
integrations.jira[<index>].enable_software_vulnerabilities: true
, create a new ticket in the select Jira integration.
- Enforce that both webhook and Jira cannot both be enabled. We will only support one automation path at a time.
- Enforce that multiple Jira configurations can be added to the
integrations.jira
array, but only one can be set enable_software_vulnerabilities: true
.
3
- [x] Establish authenticated connection to Jira Server API using basic authentication.
- Use basic auth to authenticate with Jira Server API using user provided username and password.
- For the first iteration, the assumption is that basic auth is meaningfully faster to implement. In a future iteration, we will implement the more secure OAuth 2.0 method.
4
- [ ] ~~Retrieve project id from Jira Cloud API using project key.~~ Not required to create a ticket, project key is sufficient.
- Reference Get Project API docs.
- This assumes that both the project key and project id are needed to create the issue. If a project key alone will work, we can skip this step.
- This id should be cached if needed, we don't want to make this request after every vulnerability.
5
- [x] Create a Jira ticket using the Jira Cloud API.
- Reference Jira API Create Issue Docs for information about creating new issues.
- Retry up to five times.
- If issue create fails after five retries, fail silently for this first iteration. In future iterations, we will track the failure and notify the user.
6
- [x] Ensure newly added Jira configurations are valid.
- When a user adds a new Jira integration and associated credentials, we only want to save after we confirm the credentials work.
- Pick a simple Jira endpoint that we can hit as a "test" connection.
- On success, return 200 status code and save the new Jira integration.
- On failure, pass the status code and error message back to the Fleet UI via the
PATCH /api/v1/fleet/config
response and do not save the failing integration.
Architectural notes
Since we need to support retries and we want to support fleet restarting half way through, the vulnerability processing side of things should feed into a SQL table (could be redis, but it would be good to support storage) that reflects the status of each of the tickets created. That way, we have 2 separate parts: vulnerability processing, and jira ticket creation. One being slow doesn't affect the other.
These parts can use separate locks even, so that two instances are taking care of this in parallel.
The data stored should reflect the status of the ticket created, how many retries have been done, etc. We'll use all of this data to filter pending Jira tickets to be created.
We'll also use this table to understand what has happened in the system over time. We should cleanup old rows though, as it might not be useful to store that we created a ticket successfully a month ago.
While I'll leave the structure of the table to the developer that works on this, among the data that comes to mind would be useful to have I've got:
- created and updated at timestamps
- retries
- status
- cve it refers to
- error message received (could be null)
More things could be added if they are available and might be useful to store as well.