Skip to content

Commit 901a8b4

Browse files
eshulman2claude
andcommitted
Add CVE processing tools for Jira vulnerability management
Main script (dup_cve.py): - Query unprocessed CVE Vulnerabilities from OCPBUGS - Create Epic per CVE/component in OSASINFRA - Create Task per version in OSASINFRA (linked to Epic) - Create ON_QA Bug in OCPBUGS for versions without CVEs - Link Tasks to CVEs (is caused by) and add processed label - Link Tasks to created Bugs (is related to) - Create dependency chain between versions (older depends on newer) - Idempotent: reuses existing issues, skips processed CVEs Utility scripts: - manage_task_cves.py: Manage CVEs linked to a task - update fields (release notes, patch links), transition status, close task - inspect_issues.py: Show issue status and links - reset_cves.py: Remove processed labels, optionally remove links (depends on, duplicates, blocks), and reassign issues Library (lib/): - jira_client.py: Jira API client with field caching, link type lookup, remote links, and issue link management - jira_formatter.py: Field formatting utilities Configuration: - config.yaml: Component mappings and label settings - Supports dry-run mode for safe testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8c10ef8 commit 901a8b4

File tree

11 files changed

+3029
-0
lines changed

11 files changed

+3029
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66

77
# ignore cloud credentials
88
/bot/cloud-credentials.json
9+
10+
__pycache__/

cve-jira-processing/README.md

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
# CVE Jira Processing
2+
3+
Tools for processing CVE Vulnerability issues in Jira. Queries Jira for unprocessed CVEs, creates tracking structures, and establishes dependency chains across versions.
4+
5+
The script is **idempotent** - it can be run multiple times safely without creating duplicate issues.
6+
7+
## Setup
8+
9+
1. Install dependencies:
10+
```bash
11+
pip install -r requirements.txt
12+
```
13+
14+
2. Set environment variables:
15+
```bash
16+
export JIRA_API_TOKEN="your-api-token"
17+
export JIRA_SERVER="https://issues.redhat.com" # optional, this is the default
18+
```
19+
20+
## Scripts
21+
22+
| Script | Description |
23+
|--------|-------------|
24+
| `dup_cve.py` | Main script for CVE processing |
25+
| `manage_task_cves.py` | Manage CVEs linked to a task (update fields, close, set release notes) |
26+
| `inspect_issues.py` | Inspect issues - show status and links |
27+
| `reset_cves.py` | Remove processed labels to allow reprocessing |
28+
29+
## Usage
30+
31+
### dup_cve.py - Main Processing Script
32+
33+
```bash
34+
# Dry run - see what would be done without making changes
35+
python dup_cve.py --dry-run
36+
37+
# Process CVEs for real
38+
python dup_cve.py
39+
40+
# Process only a specific CVE
41+
python dup_cve.py --cve CVE-2024-1234
42+
43+
# Verbose output for debugging
44+
python dup_cve.py --dry-run -v
45+
46+
# Use a custom config file
47+
python dup_cve.py --config /path/to/config.yaml
48+
```
49+
50+
### inspect_issues.py - Inspect Issues
51+
52+
```bash
53+
# Inspect specific issues
54+
python inspect_issues.py OCPBUGS-12345 OSASINFRA-67890
55+
56+
# Inspect issues from a file
57+
python inspect_issues.py -f issues.txt
58+
59+
# Combine both
60+
python inspect_issues.py OCPBUGS-12345 -f more_issues.txt
61+
```
62+
63+
### manage_task_cves.py - Manage CVEs Linked to a Task
64+
65+
```bash
66+
# See what CVEs are linked to a task
67+
python manage_task_cves.py OSASINFRA-12345 --dry-run
68+
69+
# Close all linked CVEs with defaults (status=Closed, resolution=Done)
70+
python manage_task_cves.py OSASINFRA-12345
71+
72+
# Transition to a different status
73+
python manage_task_cves.py OSASINFRA-12345 --status ON_QA
74+
75+
# Close with custom comment and resolution
76+
python manage_task_cves.py OSASINFRA-12345 --comment "Fixed in OCPBUGS-99999" --resolution "Fixed"
77+
78+
# Set release note fields when closing (using defaults: type=CVE, status=Proposed)
79+
python manage_task_cves.py OSASINFRA-12345 \
80+
--release-note-text "This CVE was addressed upstream." \
81+
--release-note-type \
82+
--release-note-status
83+
84+
# Set release note fields with custom values
85+
python manage_task_cves.py OSASINFRA-12345 \
86+
--release-note-text "This CVE was addressed upstream." \
87+
--release-note-type "Bug Fix" \
88+
--release-note-status "Done"
89+
90+
# Update release notes without transitioning (no status change)
91+
python manage_task_cves.py OSASINFRA-12345 --no-transition \
92+
--release-note-text "This CVE was addressed upstream." \
93+
--release-note-type \
94+
--release-note-status
95+
96+
# Add a patch link to CVEs
97+
python manage_task_cves.py OSASINFRA-12345 \
98+
--patch-url "https://github.com/org/repo/pull/123" \
99+
--patch-title "Fix for CVE-2024-1234"
100+
101+
# Transition CVEs to POST and task to POST
102+
python manage_task_cves.py OSASINFRA-12345 --status POST --task-status POST
103+
104+
# Close CVEs and the parent task
105+
python manage_task_cves.py OSASINFRA-12345 --close-task
106+
107+
# Close CVEs and task with patch link on both
108+
python manage_task_cves.py OSASINFRA-12345 --close-task \
109+
--patch-url "https://github.com/org/repo/pull/123"
110+
111+
# Close task with custom resolution
112+
python manage_task_cves.py OSASINFRA-12345 \
113+
--task-status Closed --task-resolution "Won't Fix"
114+
115+
# Process only Bug issues (not Vulnerabilities)
116+
python manage_task_cves.py OSASINFRA-12345 --bugs-only --status POST
117+
```
118+
119+
### reset_cves.py - Reset Processed Labels
120+
121+
```bash
122+
# Dry run - see what would be reset
123+
python reset_cves.py --dry-run
124+
125+
# Actually remove labels
126+
python reset_cves.py
127+
128+
# Reset only a specific CVE
129+
python reset_cves.py --cve CVE-2024-1234
130+
131+
# Reset issues from a file
132+
python reset_cves.py -f issues.txt
133+
134+
# Also remove dependency and duplicate links
135+
python reset_cves.py -f issues.txt --remove-links
136+
137+
# Transition issues back to ASSIGNED status
138+
python reset_cves.py -f issues.txt --reassign
139+
140+
# Full reset: remove label, links, and reassign
141+
python reset_cves.py -f issues.txt --remove-links --reassign
142+
```
143+
144+
## Processing Flow
145+
146+
```
147+
┌─────────────────────────────────────────────────────────────┐
148+
│ 1. Query unprocessed CVEs │
149+
│ - Status: New or Assigned │
150+
│ - No processed label │
151+
│ - Matching configured downstream components │
152+
└─────────────────────────────────────────────────────────────┘
153+
154+
┌─────────────────────────────────────────────────────────────┐
155+
│ 2. Group by {component}:{cve_id} │
156+
└─────────────────────────────────────────────────────────────┘
157+
158+
┌─────────────────────────────────────────────────────────────┐
159+
│ 3. For each CVE group: │
160+
│ a. Find/create Epic in OSASINFRA │
161+
│ b. Query ALL CVEs for this CVE ID (version detection) │
162+
│ c. Determine version range: min → max CVE version │
163+
└─────────────────────────────────────────────────────────────┘
164+
165+
┌─────────────────────────────────────────────────────────────┐
166+
│ 4. For each version with CVEs: │
167+
│ ├─ Create Task in OSASINFRA (with Epic Link) │
168+
│ ├─ Link Task to CVEs (is caused by) │
169+
│ ├─ Set Target Backport Versions = Affects Version/s │
170+
│ └─ Add processed label to all CVEs │
171+
└─────────────────────────────────────────────────────────────┘
172+
173+
┌─────────────────────────────────────────────────────────────┐
174+
│ 5. Create VERIFIED bug for next version after max CVE: │
175+
│ ├─ Create Task in OSASINFRA (with Epic Link) │
176+
│ ├─ Create VERIFIED Bug in OCPBUGS │
177+
│ └─ Link Task → is related to → Bug │
178+
└─────────────────────────────────────────────────────────────┘
179+
180+
┌─────────────────────────────────────────────────────────────┐
181+
│ 6. Create dependency chain (older depends on newer): │
182+
│ 4.12 → depends on → 4.13 → depends on → 4.14 │
183+
└─────────────────────────────────────────────────────────────┘
184+
```
185+
186+
## JQL Queries Used
187+
188+
### 1. Initial Query - Find Unprocessed CVEs
189+
190+
```sql
191+
project = OCPBUGS AND type = Vulnerability
192+
AND ("Downstream Component Name" ~ "comp1" OR "Downstream Component Name" ~ "comp2" ...)
193+
AND labels != "{cve_processed_label}"
194+
AND status IN (New, Assigned)
195+
AND "CVE ID" ~ "{cve_filter}" -- only if --cve flag provided
196+
```
197+
198+
### 2. Secondary Query - Find All Related CVEs
199+
200+
```sql
201+
project = OCPBUGS AND type = Vulnerability
202+
AND "CVE ID" ~ "{cve_id}"
203+
AND ("Downstream Component Name" ~ "comp1" OR ...)
204+
AND (status != Closed OR resolution IN (Duplicate, "Won't Do", "Not a Bug"))
205+
```
206+
207+
### 3. Find Existing Epic
208+
209+
```sql
210+
project = OSASINFRA AND type = Epic
211+
AND summary ~ "\"{cve_id} - {component}\""
212+
```
213+
214+
### 4. Find Existing Task
215+
216+
```sql
217+
project = OSASINFRA AND type = Task
218+
AND summary ~ "\"{cve_id} - {component} - {version}\""
219+
```
220+
221+
### 5. Find Existing Bug
222+
223+
```sql
224+
project = OCPBUGS AND type = Bug
225+
AND summary ~ "\"{cve_id} - {component} - {version}\""
226+
```
227+
228+
## Issue Structure Created
229+
230+
```
231+
OSASINFRA:
232+
├── Epic: CVE-2024-1234 - openstack-cinder
233+
│ ├── Task: CVE-2024-1234 - openstack-cinder - 4.12 (Epic Link)
234+
│ │ └── is caused by: CVE (Vulnerability) for 4.12
235+
│ ├── Task: CVE-2024-1234 - openstack-cinder - 4.13 (Epic Link)
236+
│ │ └── is caused by: CVE (Vulnerability) for 4.13
237+
│ └── Task: CVE-2024-1234 - openstack-cinder - 4.14 (Epic Link)
238+
│ └── is related to: VERIFIED Bug (CVE fixed in earlier version)
239+
240+
OCPBUGS (one VERIFIED bug for next version after max CVE):
241+
└── Bug: CVE-2024-1234 - openstack-cinder - 4.14 (VERIFIED)
242+
243+
Dependency Chain (older depends on newer):
244+
CVE-4.12 → depends on → CVE-4.13 → depends on → Bug-4.14
245+
```
246+
247+
## Link Types Used
248+
249+
| Source | Link Type | Target | Description |
250+
|--------|-----------|--------|-------------|
251+
| Task | Epic Link (field) | Epic | Tasks belong to the Epic |
252+
| Task | is related to | Bug (ON_QA) | Task linked to created bug |
253+
| Task | is caused by | CVE | Task is caused by the CVE |
254+
| Older issue | depends on | Newer issue | Dependency chain |
255+
256+
## Fields Set on Created Issues
257+
258+
### Epics (in OSASINFRA)
259+
260+
| Field | Value |
261+
|-------|-------|
262+
| Project | OSASINFRA |
263+
| Issue Type | Epic |
264+
| Summary | `{CVE ID} - {component}` |
265+
| Epic Name | `{CVE ID} - {component}` |
266+
| Security Level | Red Hat Employee |
267+
| Assignee | User running the script |
268+
| Description | `Grouping epic for bugs related to {CVE ID} - {component}` |
269+
270+
### Tasks (in OSASINFRA)
271+
272+
| Field | Value |
273+
|-------|-------|
274+
| Project | OSASINFRA |
275+
| Issue Type | Task |
276+
| Summary | `{CVE ID} - {component} - {version}` |
277+
| Security Level | Red Hat Employee |
278+
| Assignee | User running the script |
279+
| Epic Link | Link to parent Epic |
280+
281+
### VERIFIED Bugs (in OCPBUGS)
282+
283+
| Field | Value |
284+
|-------|-------|
285+
| Project | OCPBUGS |
286+
| Issue Type | Bug |
287+
| Summary | `{CVE ID} - {component} - {version}` |
288+
| Component/s | Inherited from source CVE issues |
289+
| Target Version | `{version}.z` (e.g., 4.14.z) |
290+
| Security Level | Red Hat Employee |
291+
| Assignee | User running the script |
292+
| Status | Transitioned to VERIFIED |
293+
294+
## Version Range Logic
295+
296+
- **CVE versions**: Only versions with reported CVEs get processed
297+
- **VERIFIED bug**: One bug created for next version after max CVE version
298+
- This indicates the CVE was fixed in an earlier version
299+
300+
## Idempotency
301+
302+
The script can be run multiple times safely:
303+
304+
- **Existing Epics** are reused (searched by summary)
305+
- **Existing Tasks** are reused (searched by summary)
306+
- **Existing Bugs** are reused (searched by summary)
307+
- **Already-processed CVEs** are identified by the processed label and skipped
308+
309+
## Files
310+
311+
| File | Description |
312+
|------|-------------|
313+
| `dup_cve.py` | Main script for CVE processing |
314+
| `manage_task_cves.py` | Utility to manage CVEs linked to a task |
315+
| `inspect_issues.py` | Utility to inspect issue status and links |
316+
| `reset_cves.py` | Utility to remove processed labels |
317+
| `lib/jira_client.py` | Jira API client wrapper |
318+
| `lib/jira_formatter.py` | Field formatting utilities for Jira API requests |
319+
| `config.yaml` | Configuration file (component mappings, labels) |
320+
321+
## Configuration
322+
323+
The `config.yaml` file contains:
324+
325+
- **cve_processed_label**: Label applied to processed CVE issues
326+
- **repo_to_component**: Mapping of downstream repository names to component names
327+
328+
The script queries for Vulnerabilities matching the downstream components defined in `repo_to_component`.
329+
330+
To add support for new components, add entries to the `repo_to_component` section:
331+
332+
```yaml
333+
repo_to_component:
334+
openshift4/ose-new-component-rhel9: openshift/new-component
335+
```
336+
337+
## Example Output
338+
339+
```
340+
2025-01-15 10:30:00 - Loaded config from config.yaml
341+
2025-01-15 10:30:00 - Configured components: ['openshift4/ose-cloud-provider-openstack-rhel9', ...]
342+
2025-01-15 10:30:01 - Found 50 numeric target versions
343+
2025-01-15 10:30:01 - Querying Jira for Vulnerabilities...
344+
2025-01-15 10:30:05 - Found 7 unprocessed Vulnerabilities
345+
2025-01-15 10:30:05 - Found 2 CVE groups
346+
347+
2025-01-15 10:30:05 - Processing CVE group: openstack-cinder:CVE-2024-1234
348+
2025-01-15 10:30:05 - CVE: CVE-2024-1234, Component: openstack-cinder
349+
2025-01-15 10:30:05 - Found CVEs in versions: ['4.12', '4.13']
350+
2025-01-15 10:30:05 - Processing versions: ['4.12', '4.13', '4.14', '4.15', '4.16']
351+
2025-01-15 10:30:06 - Created Epic: OSASINFRA-99999
352+
2025-01-15 10:30:07 - Version 4.12:
353+
2025-01-15 10:30:07 - Created task: OSASINFRA-100000
354+
2025-01-15 10:30:07 - 2 CVEs (1 new)
355+
2025-01-15 10:30:07 - OCPBUGS-11111 (already processed)
356+
2025-01-15 10:30:08 - Linked: OCPBUGS-22222
357+
2025-01-15 10:30:09 - Version 4.13:
358+
2025-01-15 10:30:09 - Created task: OSASINFRA-100001
359+
2025-01-15 10:30:09 - 1 CVEs (1 new)
360+
2025-01-15 10:30:09 - Linked: OCPBUGS-33333
361+
2025-01-15 10:30:10 - Version 4.14:
362+
2025-01-15 10:30:10 - Created task: OSASINFRA-100002
363+
2025-01-15 10:30:10 - No CVEs, creating ON_QA bug
364+
2025-01-15 10:30:11 - Created bug: OCPBUGS-100003
365+
2025-01-15 10:30:11 - Transitioned OCPBUGS-100003 to ON_QA
366+
...
367+
368+
======================================================================
369+
SUMMARY (DRY RUN - no changes made)
370+
======================================================================
371+
372+
TOTALS
373+
----------------------------------------
374+
Epics: 2 (1 existing, 1 to create)
375+
Tasks: 10 (3 existing, 7 to create)
376+
Bugs: 6 (0 existing, 6 to create)
377+
CVEs: 5 to link
378+
379+
DETAILS BY CVE GROUP
380+
----------------------------------------
381+
[CVE-2024-1234] openstack-cinder
382+
Epic: OSASINFRA-99999
383+
Tasks (5): OSASINFRA-100000, OSASINFRA-100001, ... OSASINFRA-100004
384+
Bugs (3): OCPBUGS-100003, OCPBUGS-100004, OCPBUGS-100005
385+
CVEs (2): OCPBUGS-11111, OCPBUGS-22222
386+
387+
======================================================================
388+
```

0 commit comments

Comments
 (0)