-
Notifications
You must be signed in to change notification settings - Fork 2
NH-141840 Add Jira creation to image publish workflow if Critical/High risks #797
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tammy-baylis-swi
wants to merge
21
commits into
main
Choose a base branch
from
NH-141840-add-docker-scout-ticket
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
45b5eba
Add Jira creation to beta workflow
tammy-baylis-swi da41458
Temp test
tammy-baylis-swi f818933
Debug
tammy-baylis-swi a048a48
Create Description object and other type fixes
tammy-baylis-swi 67bd024
jq instead of yaml parse
tammy-baylis-swi 619ca26
More debug
tammy-baylis-swi 2c58ae0
Change to temp file approach
tammy-baylis-swi cdb49ff
Use http1.1
tammy-baylis-swi 2802717
--data-binary
tammy-baylis-swi b85e315
debug
tammy-baylis-swi af88f23
Add sanitation, more debug
tammy-baylis-swi f5d4a43
Trim down logging
tammy-baylis-swi 0d90253
Jira from template
tammy-baylis-swi 947984b
Revert test mode
tammy-baylis-swi 715cbb6
Add to prod image pub
tammy-baylis-swi b346213
refactor shared jira_vuln action
tammy-baylis-swi 76d45d6
Test again
tammy-baylis-swi ef5374b
Revert "Test again"
tammy-baylis-swi 48163e0
Potential fix for pull request finding
tammy-baylis-swi 4efac07
Potential fix for pull request finding
tammy-baylis-swi 537a034
Potential fix for pull request finding
tammy-baylis-swi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| name: 'Create JIRA Tickets for Docker Scout CVEs' | ||
| description: 'Parses Docker Scout SARIF output and creates JIRA tickets for critical/high vulnerabilities' | ||
| inputs: | ||
| image-tag: | ||
| description: 'Docker image tag that was scanned' | ||
| required: true | ||
| workflow-url: | ||
| description: 'GitHub Actions workflow URL' | ||
| required: true | ||
| commit-sha: | ||
| description: 'Git commit SHA' | ||
| required: true | ||
| jira-base-url: | ||
| description: 'JIRA base URL' | ||
| required: true | ||
| jira-user-email: | ||
| description: 'JIRA user email' | ||
| required: true | ||
| jira-api-token: | ||
| description: 'JIRA API token' | ||
| required: true | ||
| jira-team-field-id: | ||
| description: 'JIRA custom field ID for team' | ||
| required: false | ||
| default: '' | ||
| outputs: | ||
| vulnerability-count: | ||
| description: 'Number of vulnerabilities found' | ||
| value: ${{ steps.parse-cves.outputs.count }} | ||
| ticket-count: | ||
| description: 'Number of JIRA tickets created' | ||
| value: ${{ steps.create-tickets.outputs.ticket-count }} | ||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - name: Parse SARIF for Critical/High CVEs | ||
| id: parse-cves | ||
| shell: bash | ||
| run: | | ||
| # Extract CVEs from SARIF | ||
| jq -r '.runs[0].results[] | | ||
| select(.level == "error" or .level == "warning") | | ||
| @json' sarif.output.json > vulnerabilities.json | ||
|
|
||
| # Count vulnerabilities | ||
| echo "count=$(jq -s 'length' vulnerabilities.json)" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Create Jira tickets with actionable details | ||
| id: create-tickets | ||
| if: steps.parse-cves.outputs.count != '0' | ||
| shell: bash | ||
|
Copilot marked this conversation as resolved.
|
||
| env: | ||
| JIRA_BASE_URL: ${{ inputs.jira-base-url }} | ||
| JIRA_USER_EMAIL: ${{ inputs.jira-user-email }} | ||
| JIRA_API_TOKEN: ${{ inputs.jira-api-token }} | ||
| IMAGE_TAG: ${{ inputs.image-tag }} | ||
| WORKFLOW_URL: ${{ inputs.workflow-url }} | ||
| COMMIT_SHA: ${{ inputs.commit-sha }} | ||
| TEAM_ID: ${{ inputs.jira-team-field-id }} | ||
| run: | | ||
| set +e | ||
|
|
||
| TICKET_COUNT=0 | ||
| ERROR_COUNT=0 | ||
| CREATED_TICKETS=() | ||
|
|
||
| while IFS= read -r vuln; do | ||
| CVE=$(echo "$vuln" | jq -r '.ruleId') | ||
| PACKAGE=$(echo "$vuln" | jq -r '.locations[0].physicalLocation.artifactLocation.uri // "unknown"') | ||
| VERSION=$(echo "$vuln" | jq -r '.locations[0].physicalLocation.region.snippet.text // "unknown"') | ||
| RAW_MESSAGE=$(echo "$vuln" | jq -r '.message.text') | ||
| SEVERITY=$(echo "$vuln" | jq -r '.level') | ||
|
|
||
| # Sanitize MESSAGE: remove control characters but keep newlines/tabs | ||
| MESSAGE=$(echo "$RAW_MESSAGE" | tr -d '\000-\010\013\014\016-\037') | ||
|
|
||
| SEVERITY_TEXT=$([ "$SEVERITY" = "error" ] && echo "Critical" || echo "High") | ||
| REPORT_DATE=$(date +%Y-%m-%d) | ||
| VULN_COMPONENT="${PACKAGE}-${VERSION}" | ||
|
|
||
| # Build request from template | ||
| JIRA_REQUEST=$(jq \ | ||
| --arg cve "$CVE" \ | ||
| --arg pkg "$PACKAGE" \ | ||
| --arg ver "$VERSION" \ | ||
| --arg sev "$SEVERITY_TEXT" \ | ||
| --arg img "$IMAGE_TAG" \ | ||
| --arg msg "$MESSAGE" \ | ||
| --arg url "$WORKFLOW_URL" \ | ||
| --arg commit "$COMMIT_SHA" \ | ||
| --arg summary "${CVE}: Python - ${PACKAGE}" \ | ||
| --arg teamId "$TEAM_ID" \ | ||
| --arg reportDate "$REPORT_DATE" \ | ||
| --arg cveArray "[${CVE}]" \ | ||
| --arg vulnComponent "$VULN_COMPONENT" \ | ||
| ' | ||
| walk(if type == "string" then | ||
| gsub("\\$CVE"; $cve) | | ||
| gsub("\\$PACKAGE"; $pkg) | | ||
| gsub("\\$VERSION"; $ver) | | ||
| gsub("\\$SEVERITY"; $sev) | | ||
| gsub("\\$IMAGE"; $img) | | ||
| gsub("\\$MESSAGE"; $msg) | | ||
| gsub("\\$WORKFLOW_URL"; $url) | | ||
| gsub("\\$COMMIT"; $commit) | | ||
| gsub("\\$REPORT_DATE"; $reportDate) | | ||
| gsub("\\$CVE_ARRAY"; $cveArray) | | ||
| gsub("\\$VULN_COMPONENT"; $vulnComponent) | ||
| else . end) | | ||
| .fields.summary = $summary | | ||
| .fields.priority.name = $sev | | ||
| if $teamId != "" then | ||
|
Copilot marked this conversation as resolved.
|
||
| .fields.customfield_10001 = $teamId | ||
| else . end | ||
| ' .github/templates/jira-security-vuln.json) | ||
|
|
||
| TEMP_REQUEST=$(mktemp) | ||
| printf '%s\n' "$JIRA_REQUEST" > "$TEMP_REQUEST" | ||
|
|
||
| JIRA_RESPONSE=$(curl -s --http1.1 -w "\n%{http_code}" --connect-timeout 30 --max-time 90 \ | ||
| -X POST "${JIRA_BASE_URL}/rest/api/3/issue" \ | ||
| -u "${JIRA_USER_EMAIL}:${JIRA_API_TOKEN}" \ | ||
| -H "Content-Type: application/json; charset=utf-8" \ | ||
| -H "Accept: application/json" \ | ||
| --data-binary @"$TEMP_REQUEST") | ||
|
|
||
| HTTP_CODE=$(echo "$JIRA_RESPONSE" | tail -n1) | ||
| RESPONSE_BODY=$(echo "$JIRA_RESPONSE" | sed '$d') | ||
| rm -f "$TEMP_REQUEST" | ||
|
|
||
| # Process response | ||
| if [[ "$HTTP_CODE" =~ ^2[0-9][0-9]$ ]]; then | ||
| JIRA_KEY=$(echo "$RESPONSE_BODY" | jq -r '.key // "null"') | ||
| if [ "$JIRA_KEY" != "null" ] && [ -n "$JIRA_KEY" ]; then | ||
| CREATED_TICKETS+=("$JIRA_KEY") | ||
| ((TICKET_COUNT++)) | ||
| else | ||
| echo "❌ ${CVE}: Failed to parse ticket ID (HTTP ${HTTP_CODE})" | ||
| ((ERROR_COUNT++)) | ||
| fi | ||
| else | ||
| echo "❌ ${CVE}: HTTP ${HTTP_CODE}" | ||
| ((ERROR_COUNT++)) | ||
| fi | ||
|
|
||
| done < vulnerabilities.json | ||
|
|
||
| echo "=========================================" | ||
| if [ $TICKET_COUNT -gt 0 ]; then | ||
| TICKET_LIST=$(IFS=', '; echo "${CREATED_TICKETS[*]}") | ||
| echo "✅ Created ${TICKET_COUNT} tickets: ${TICKET_LIST}" | ||
| fi | ||
|
|
||
| echo "ticket-count=${TICKET_COUNT}" >> $GITHUB_OUTPUT | ||
|
|
||
| if [ $ERROR_COUNT -gt 0 ]; then | ||
| echo "❌ Failed to create ${ERROR_COUNT} tickets" | ||
| exit 1 | ||
| fi | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| { | ||
| "fields": { | ||
| "project": { | ||
| "key": "NH" | ||
| }, | ||
| "summary": "$SUMMARY", | ||
| "description": { | ||
| "version": 1, | ||
| "type": "doc", | ||
| "content": [ | ||
| { | ||
| "type": "heading", | ||
| "attrs": {"level": 2}, | ||
| "content": [{"type": "text", "text": "Security Vulnerability Detected"}] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "CVE: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$CVE"} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Package: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$PACKAGE"} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Version: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$VERSION"} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Severity: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$SEVERITY"} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Image: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$IMAGE"} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "heading", | ||
| "attrs": {"level": 3}, | ||
| "content": [{"type": "text", "text": "Description"}] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [{"type": "text", "text": "$MESSAGE"}] | ||
| }, | ||
| { | ||
| "type": "heading", | ||
| "attrs": {"level": 3}, | ||
| "content": [{"type": "text", "text": "Recommended Action"}] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [{"type": "text", "text": "Upgrade the vulnerable dependency to the latest secure version."}] | ||
| }, | ||
| { | ||
| "type": "heading", | ||
| "attrs": {"level": 3}, | ||
| "content": [{"type": "text", "text": "Detection Source"}] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Workflow Run: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$WORKFLOW_URL", "marks": [{"type": "link", "attrs": {"href": "$WORKFLOW_URL"}}]} | ||
| ] | ||
| }, | ||
| { | ||
| "type": "paragraph", | ||
| "content": [ | ||
| {"type": "text", "text": "Commit: ", "marks": [{"type": "strong"}]}, | ||
| {"type": "text", "text": "$COMMIT"} | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| "issuetype": { | ||
| "name": "Security Vuln" | ||
| }, | ||
| "components": [ | ||
| {"name": "Instrument Python"} | ||
| ], | ||
| "customfield_10369": "$REPORT_DATE", | ||
| "customfield_10374": ["$CVE"], | ||
| "customfield_10392": "$VULN_COMPONENT", | ||
|
Copilot marked this conversation as resolved.
|
||
| "labels": ["docker-scout"], | ||
| "priority": { | ||
| "name": "Critical" | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.