# Jira REST API Use Cases — STEAM Security Dashboard ## Overview The STEAM Security Dashboard is a self-hosted vulnerability management tool used by the NTS-AEO-STEAM and NTS-AEO-ACCESS-ENG teams. It integrates with Jira Data Center to create, track, and sync vulnerability remediation tickets linked to CVE records. All API calls are made from a single Node.js backend process. The integration uses Basic Auth with a service account and enforces Charter's posted rate limits client-side. --- ## Charter Compliance Summary | Requirement | Implementation | |---|---| | Authentication | Basic Auth with service account (`JIRA_API_USER` + `JIRA_API_TOKEN`) | | Rate limit — daily | Client-side enforced: 1 440 requests/day max | | Rate limit — burst | Client-side enforced: 60 requests/minute max | | Inter-request delay — GETs | 1 second minimum between GET requests | | Inter-request delay — writes | 2 seconds minimum between PUT/POST/DELETE requests | | Explicit field lists | Every GET includes `?fields=` parameter; `/rest/api/2/field` is blocked | | No bulk updates | Issues are updated one at a time; `/rest/api/2/issue/bulk` is blocked | | Bulk reads via JQL | Multi-ticket sync uses a single `GET /rest/api/2/search` with predefined key-based JQL query parameters, not per-issue GETs; no arbitrary JQL passthrough | | Single-issue fetch via JQL | `GET /rest/api/2/search?jql=key="KEY" AND project=&fields=...&maxResults=1` | | JQL scoping | All recurring JQL queries use predefined scoped patterns with `updated >= -72h` clause and `project = ` scoping; no arbitrary JQL passthrough | | `maxResults` cap | Search queries capped at 1 000 results per page | --- ## Use Cases ### 1. Connection Test | | | |---|---| | **Endpoint** | `GET /rest/api/2/myself` | | **Trigger** | Admin clicks "Test Connection" on the Jira settings panel | | **Frequency** | Manual, infrequent (a few times per day at most) | | **Purpose** | Verify service account credentials and connectivity | | **Fields requested** | Default (myself endpoint returns user profile) | ### 2. Create Issue | | | |---|---| | **Endpoint** | `POST /rest/api/2/issue` | | **Trigger** | User clicks "Create in Jira" from a CVE detail panel | | **Frequency** | Manual, estimated 5–20 per day | | **Purpose** | Create a vulnerability remediation ticket linked to a CVE/vendor pair | | **Fields sent** | `project.key`, `summary`, `issuetype.name`, `description` | | **Notes** | A local record is also created in the dashboard database linking the Jira key to the CVE | ### 3. Get Single Issue | | | |---|---| | **Endpoint** | `GET /rest/api/2/search?jql=key="ISSUE-KEY" AND project=&fields=summary,status,assignee,created,updated,priority,issuetype,project,resolution&maxResults=1` | | **Trigger** | User clicks "Sync" on a single Jira ticket row | | **Frequency** | Manual, estimated 10–30 per day | | **Purpose** | Refresh a single ticket's status and summary from Jira via JQL search | | **Notes** | Uses JQL-based lookup instead of single-issue GET per Charter compliance. Fields are always specified explicitly. | ### 4. Update Issue | | | |---|---| | **Endpoint** | `PUT /rest/api/2/issue/{issueKey}` | | **Trigger** | Future feature — local edits synced back to Jira | | **Frequency** | Manual, estimated 5–10 per day when enabled | | **Purpose** | Update issue summary or other fields from the dashboard | | **Notes** | Issues are updated one at a time; bulk PUT is not used | ### 5. Add Comment | | | |---|---| | **Endpoint** | `POST /rest/api/2/issue/{issueKey}/comment` | | **Trigger** | Dashboard adds audit trail comments to linked tickets | | **Frequency** | Automated on certain actions, estimated 5–15 per day | | **Purpose** | Maintain an audit trail on the Jira ticket for compliance visibility | ### 6. Get Transitions | | | |---|---| | **Endpoint** | `GET /rest/api/2/issue/{issueKey}/transitions` | | **Trigger** | Dashboard checks available workflow transitions before moving a ticket | | **Frequency** | Manual, paired with transition calls, estimated 5–10 per day | | **Purpose** | Discover valid status transitions for the issue's current workflow state | ### 7. Transition Issue | | | |---|---| | **Endpoint** | `POST /rest/api/2/issue/{issueKey}/transitions` | | **Trigger** | User moves a ticket to a new status from the dashboard | | **Frequency** | Manual, estimated 5–10 per day | | **Purpose** | Move ticket through workflow states (e.g., Open to In Progress to Closed) | ### 8. Scoped Bulk Sync via JQL | | | |---|---| | **Endpoint** | `GET /rest/api/2/search?jql=...&fields=...&maxResults=...&startAt=...` | | **Trigger** | Admin clicks "Sync All" on the Jira tickets panel | | **Frequency** | Manual, estimated 1–3 times per day | | **Purpose** | Bulk-refresh all tracked tickets in a single request instead of per-issue GETs | | **JQL pattern** | `key in ("KEY-1", "KEY-2", ...) AND updated >= -72h AND project = ` | | **Fields requested** | `summary, status, assignee, created, updated, priority, issuetype, project, resolution` | | **Batch size** | 100 keys per JQL query; multiple batches if needed | | **Notes** | Uses GET with URL-encoded query parameters per Charter compliance. JQL is predefined and scoped — constructed from known tracked issue keys, a fixed 72-hour window, and the configured project key. No arbitrary JQL is accepted from the frontend. Stops early if rate limit budget is running low (burst remaining <= 5 or daily remaining <= 10) | ### 9. Issue Lookup | | | |---|---| | **Endpoint** | `GET /rest/api/2/search?jql=key="ISSUE-KEY" AND project=&fields=...&maxResults=1` | | **Trigger** | User looks up a Jira issue by key from the dashboard search | | **Frequency** | Manual, estimated 5–15 per day | | **Purpose** | Quick lookup of any Jira issue to view its current state via JQL search | --- ## Estimated Daily API Usage | Operation | Estimated calls/day | Method | Delay enforced | |---|---|---|---| | Connection test | 2–5 | GET | 1s | | Create issue | 5–20 | POST | 2s | | Get single issue | 10–30 | GET | 1s | | Update issue | 5–10 | PUT | 2s | | Add comment | 5–15 | POST | 2s | | Get transitions | 5–10 | GET | 1s | | Transition issue | 5–10 | POST | 2s | | Scoped bulk sync | 1–5 | GET | 1s | | Issue lookup | 5–15 | GET | 1s | | **Total estimated** | **43–120** | | | Well within the 1 440/day limit. Burst usage stays under 60/minute due to enforced inter-request delays. --- ## Blocked Endpoints The integration explicitly blocks these endpoints to comply with Charter policy: - `/rest/api/2/field` — field metadata is never queried; fields are specified in code - `/rest/api/2/issue/bulk` — bulk updates are not used; issues are updated individually - `POST /rest/api/2/search` — arbitrary JQL search via POST is not used; all searches use `GET /rest/api/2/search` with URL-encoded query parameters and predefined scoped JQL patterns --- ## Error Handling - **429 responses**: Surfaced to the user as "Rate limit exceeded. Try again later." No automatic retry. - **5xx responses**: Surfaced as "Jira API error" with the response body for debugging. - **Network failures**: Caught and surfaced with the error message. - **Timeout**: 15 second timeout per request; surfaced as a timeout error. --- ## UAT Test Evidence The UAT test script (`backend/scripts/jira-uat-test.js`) exercises all use cases listed above and produces a log file at `backend/scripts/jira-uat-test.log`. This log can be attached to or referenced in the ATLSUP approval ticket. To run: ```bash cd backend node scripts/jira-uat-test.js ```