Skip to content

Commit d772423

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 d772423

File tree

11 files changed

+2912
-0
lines changed

11 files changed

+2912
-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: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
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+
# Close CVEs and the parent task, with patch link on both
102+
python manage_task_cves.py OSASINFRA-12345 --close-task \
103+
--patch-url "https://github.com/org/repo/pull/123"
104+
```
105+
106+
### reset_cves.py - Reset Processed Labels
107+
108+
```bash
109+
# Dry run - see what would be reset
110+
python reset_cves.py --dry-run
111+
112+
# Actually remove labels
113+
python reset_cves.py
114+
115+
# Reset only a specific CVE
116+
python reset_cves.py --cve CVE-2024-1234
117+
118+
# Reset issues from a file
119+
python reset_cves.py -f issues.txt
120+
121+
# Also remove dependency and duplicate links
122+
python reset_cves.py -f issues.txt --remove-links
123+
124+
# Transition issues back to ASSIGNED status
125+
python reset_cves.py -f issues.txt --reassign
126+
127+
# Full reset: remove label, links, and reassign
128+
python reset_cves.py -f issues.txt --remove-links --reassign
129+
```
130+
131+
## Processing Flow
132+
133+
```
134+
┌─────────────────────────────────────────────────────────────┐
135+
│ 1. Query unprocessed CVEs │
136+
│ - Status: New or Assigned │
137+
│ - No processed label │
138+
│ - Matching configured downstream components │
139+
└─────────────────────────────────────────────────────────────┘
140+
141+
┌─────────────────────────────────────────────────────────────┐
142+
│ 2. Group by {component}:{cve_id} │
143+
└─────────────────────────────────────────────────────────────┘
144+
145+
┌─────────────────────────────────────────────────────────────┐
146+
│ 3. For each CVE group: │
147+
│ a. Find/create Epic in OSASINFRA │
148+
│ b. Query ALL CVEs for this CVE ID (version detection) │
149+
│ c. Calculate range: min(CVE versions) → max(available) │
150+
└─────────────────────────────────────────────────────────────┘
151+
152+
┌─────────────────────────────────────────────────────────────┐
153+
│ 4. For each version in range: │
154+
│ ├─ Create Task in OSASINFRA (with Epic Link) │
155+
│ ├─ If CVEs exist: │
156+
│ │ ├─ Link Task to CVEs (is caused by) │
157+
│ │ ├─ Set Target Backport Versions = Affects Version/s │
158+
│ │ └─ Add processed label to all CVEs │
159+
│ └─ If NO CVEs: │
160+
│ ├─ Create ON_QA Bug in OCPBUGS │
161+
│ └─ Link Task → is related to → Bug │
162+
└─────────────────────────────────────────────────────────────┘
163+
164+
┌─────────────────────────────────────────────────────────────┐
165+
│ 5. Create dependency chain (older depends on newer): │
166+
│ 4.12 → depends on → 4.13 → depends on → 4.14 │
167+
└─────────────────────────────────────────────────────────────┘
168+
```
169+
170+
## JQL Queries Used
171+
172+
### 1. Initial Query - Find Unprocessed CVEs
173+
174+
```sql
175+
project = OCPBUGS AND type = Vulnerability
176+
AND ("Downstream Component Name" ~ "comp1" OR "Downstream Component Name" ~ "comp2" ...)
177+
AND labels != "{cve_processed_label}"
178+
AND status IN (New, Assigned)
179+
AND "CVE ID" ~ "{cve_filter}" -- only if --cve flag provided
180+
```
181+
182+
### 2. Secondary Query - Find All Related CVEs
183+
184+
```sql
185+
project = OCPBUGS AND type = Vulnerability
186+
AND "CVE ID" ~ "{cve_id}"
187+
AND ("Downstream Component Name" ~ "comp1" OR ...)
188+
AND (status != Closed OR resolution IN (Duplicate, "Won't Do", "Not a Bug"))
189+
```
190+
191+
### 3. Find Existing Epic
192+
193+
```sql
194+
project = OSASINFRA AND type = Epic
195+
AND summary ~ "\"{cve_id} - {component}\""
196+
```
197+
198+
### 4. Find Existing Task
199+
200+
```sql
201+
project = OSASINFRA AND type = Task
202+
AND summary ~ "\"{cve_id} - {component} - {version}\""
203+
```
204+
205+
### 5. Find Existing Bug
206+
207+
```sql
208+
project = OCPBUGS AND type = Bug
209+
AND summary ~ "\"{cve_id} - {component} - {version}\""
210+
```
211+
212+
## Issue Structure Created
213+
214+
```
215+
OSASINFRA:
216+
├── Epic: CVE-2024-1234 - openstack-cinder
217+
│ ├── Task: CVE-2024-1234 - openstack-cinder - 4.12 (Epic Link)
218+
│ │ └── is caused by: CVE (Vulnerability) for 4.12
219+
│ ├── Task: CVE-2024-1234 - openstack-cinder - 4.13 (Epic Link)
220+
│ │ └── is caused by: CVE (Vulnerability) for 4.13
221+
│ ├── Task: CVE-2024-1234 - openstack-cinder - 4.14 (Epic Link)
222+
│ │ └── is related to: ON_QA Bug (no CVE reported)
223+
│ └── Task: CVE-2024-1234 - openstack-cinder - 4.15 (Epic Link)
224+
│ └── is related to: ON_QA Bug (no CVE reported)
225+
226+
OCPBUGS (only created where no CVE exists):
227+
├── Bug: CVE-2024-1234 - openstack-cinder - 4.14 (ON_QA)
228+
└── Bug: CVE-2024-1234 - openstack-cinder - 4.15 (ON_QA)
229+
230+
Dependency Chain (older depends on newer):
231+
CVE-4.12 → depends on → CVE-4.13 → depends on → Bug-4.14 → depends on → Bug-4.15
232+
```
233+
234+
## Link Types Used
235+
236+
| Source | Link Type | Target | Description |
237+
|--------|-----------|--------|-------------|
238+
| Task | Epic Link (field) | Epic | Tasks belong to the Epic |
239+
| Task | is related to | Bug (ON_QA) | Task linked to created bug |
240+
| Task | is caused by | CVE | Task is caused by the CVE |
241+
| Older issue | depends on | Newer issue | Dependency chain |
242+
243+
## Fields Set on Created Issues
244+
245+
### Epics (in OSASINFRA)
246+
247+
| Field | Value |
248+
|-------|-------|
249+
| Project | OSASINFRA |
250+
| Issue Type | Epic |
251+
| Summary | `{CVE ID} - {component}` |
252+
| Epic Name | `{CVE ID} - {component}` |
253+
| Security Level | Red Hat Employee |
254+
| Assignee | User running the script |
255+
| Description | `Grouping epic for bugs related to {CVE ID} - {component}` |
256+
257+
### Tasks (in OSASINFRA)
258+
259+
| Field | Value |
260+
|-------|-------|
261+
| Project | OSASINFRA |
262+
| Issue Type | Task |
263+
| Summary | `{CVE ID} - {component} - {version}` |
264+
| Security Level | Red Hat Employee |
265+
| Assignee | User running the script |
266+
| Epic Link | Link to parent Epic |
267+
268+
### ON_QA Bugs (in OCPBUGS)
269+
270+
| Field | Value |
271+
|-------|-------|
272+
| Project | OCPBUGS |
273+
| Issue Type | Bug |
274+
| Summary | `{CVE ID} - {component} - {version}` |
275+
| Component/s | Inherited from source CVE issues |
276+
| Target Version | `{version}.z` (e.g., 4.14.z) |
277+
| Security Level | Red Hat Employee |
278+
| Assignee | User running the script |
279+
| Status | Transitioned to ON_QA |
280+
281+
## Version Range Logic
282+
283+
- **Minimum version**: Lowest version with a reported CVE
284+
- **Maximum version**: Latest available target version in Jira
285+
- All versions in between get a Task in OSASINFRA
286+
- Versions without a CVE get an ON_QA Bug in OCPBUGS for QA verification
287+
288+
## Idempotency
289+
290+
The script can be run multiple times safely:
291+
292+
- **Existing Epics** are reused (searched by summary)
293+
- **Existing Tasks** are reused (searched by summary)
294+
- **Existing Bugs** are reused (searched by summary)
295+
- **Already-processed CVEs** are identified by the processed label and skipped
296+
297+
## Files
298+
299+
| File | Description |
300+
|------|-------------|
301+
| `dup_cve.py` | Main script for CVE processing |
302+
| `manage_task_cves.py` | Utility to manage CVEs linked to a task |
303+
| `inspect_issues.py` | Utility to inspect issue status and links |
304+
| `reset_cves.py` | Utility to remove processed labels |
305+
| `lib/jira_client.py` | Jira API client wrapper |
306+
| `lib/jira_formatter.py` | Field formatting utilities for Jira API requests |
307+
| `config.yaml` | Configuration file (component mappings, labels) |
308+
309+
## Configuration
310+
311+
The `config.yaml` file contains:
312+
313+
- **cve_processed_label**: Label applied to processed CVE issues
314+
- **repo_to_component**: Mapping of downstream repository names to component names
315+
316+
The script queries for Vulnerabilities matching the downstream components defined in `repo_to_component`.
317+
318+
To add support for new components, add entries to the `repo_to_component` section:
319+
320+
```yaml
321+
repo_to_component:
322+
openshift4/ose-new-component-rhel9: openshift/new-component
323+
```
324+
325+
## Example Output
326+
327+
```
328+
2025-01-15 10:30:00 - Loaded config from config.yaml
329+
2025-01-15 10:30:00 - Configured components: ['openshift4/ose-cloud-provider-openstack-rhel9', ...]
330+
2025-01-15 10:30:01 - Found 50 numeric target versions
331+
2025-01-15 10:30:01 - Querying Jira for Vulnerabilities...
332+
2025-01-15 10:30:05 - Found 7 unprocessed Vulnerabilities
333+
2025-01-15 10:30:05 - Found 2 CVE groups
334+
335+
2025-01-15 10:30:05 - Processing CVE group: openstack-cinder:CVE-2024-1234
336+
2025-01-15 10:30:05 - CVE: CVE-2024-1234, Component: openstack-cinder
337+
2025-01-15 10:30:05 - Found CVEs in versions: ['4.12', '4.13']
338+
2025-01-15 10:30:05 - Processing versions: ['4.12', '4.13', '4.14', '4.15', '4.16']
339+
2025-01-15 10:30:06 - Created Epic: OSASINFRA-99999
340+
2025-01-15 10:30:07 - Version 4.12:
341+
2025-01-15 10:30:07 - Created task: OSASINFRA-100000
342+
2025-01-15 10:30:07 - 2 CVEs (1 new)
343+
2025-01-15 10:30:07 - OCPBUGS-11111 (already processed)
344+
2025-01-15 10:30:08 - Linked: OCPBUGS-22222
345+
2025-01-15 10:30:09 - Version 4.13:
346+
2025-01-15 10:30:09 - Created task: OSASINFRA-100001
347+
2025-01-15 10:30:09 - 1 CVEs (1 new)
348+
2025-01-15 10:30:09 - Linked: OCPBUGS-33333
349+
2025-01-15 10:30:10 - Version 4.14:
350+
2025-01-15 10:30:10 - Created task: OSASINFRA-100002
351+
2025-01-15 10:30:10 - No CVEs, creating ON_QA bug
352+
2025-01-15 10:30:11 - Created bug: OCPBUGS-100003
353+
2025-01-15 10:30:11 - Transitioned OCPBUGS-100003 to ON_QA
354+
...
355+
356+
======================================================================
357+
SUMMARY (DRY RUN - no changes made)
358+
======================================================================
359+
360+
TOTALS
361+
----------------------------------------
362+
Epics: 2 (1 existing, 1 to create)
363+
Tasks: 10 (3 existing, 7 to create)
364+
Bugs: 6 (0 existing, 6 to create)
365+
CVEs: 5 to link
366+
367+
DETAILS BY CVE GROUP
368+
----------------------------------------
369+
[CVE-2024-1234] openstack-cinder
370+
Epic: OSASINFRA-99999
371+
Tasks (5): OSASINFRA-100000, OSASINFRA-100001, ... OSASINFRA-100004
372+
Bugs (3): OCPBUGS-100003, OCPBUGS-100004, OCPBUGS-100005
373+
CVEs (2): OCPBUGS-11111, OCPBUGS-22222
374+
375+
======================================================================
376+
```

0 commit comments

Comments
 (0)