Skip to content

Jira integration: findings and tickets have no reference to each other #12448

Description

@manuelProwler

Summary

Tickets created by Prowler Cloud's Jira integration contain no machine-readable
reference back to the finding they came from, and Prowler retains no reference
to the ticket. That makes it impossible to answer "which finding is this ticket
for?" from Jira, or "which findings are already ticketed?" from Prowler.

Notably, prowler/lib/outputs/jira/jira.py already supports the pieces
needed for the first half — send_finding() and send_findings() both accept
issue_labels and finding_url — but the Cloud task never passes them.

Where it happens

api/src/backend/tasks/jobs/integrations.py, in send_findings_to_jira(), the
call to jira_integration.send_finding(...) passes check_id, check_title,
severity, resource fields, remediation, compliance, project_key and
issue_type — but omits issue_labels, finding_url and tenant_info, all of
which the SDK accepts and renders.

The result is an issue whose only link to the finding is the summary string
([Prowler] SEVERITY - check_id - resource_uid). That is identifiable by a
human reading it, but cannot be filtered, JQL'd, or automated against, and it
does not include the finding uid.

Impact

Reported by a customer using the integration to track finding resolution:

In Jira: tickets lack a direct reference, unique ID, or link back to the
specific Prowler finding.
In Prowler: we cannot see which findings have linked Jira tickets or track
their resolution status.

Proposed changes

1. Pass issue_labels (small, self-contained)

Populate labels from the finding — at minimum the finding uid, plus severity,
provider and check id. This alone makes tickets filterable and gives automation
a stable key to match on. Needs no new configuration.

Note the uid needs sanitising before use as a Jira label: uids routinely contain
/ (every Azure resource ID, and AWS uids such as
...-eu-west-1-hub/unknown). Whatever transformation is chosen has to be
applied consistently on both the write and any later read, or lookups silently
never match.

2. Pass finding_url (needs a design decision)

This one is larger than it looks: the API has no setting for the UI's base URL.
The only URL-ish settings today are the OAuth callbacks, so a new
DJANGO_UI_BASE_URL-style setting would be needed, with a sensible default for
Prowler Cloud and an override for self-hosted deployments. Happy to implement it
once maintainers decide how that should be configured.

Suggest linking by filter[uid] rather than the record id — findings are
stored per (finding x scan), so an id captured at ticket-creation time points
at a stale scan record later, while the uid remains valid for the life of the
ticket.

3. Optional — a reference from Prowler back to the ticket

Nothing in the data model currently stores a Jira issue key, so Prowler cannot
show that a finding is ticketed. The finding-triage API is a natural fit: it's
keyed on finding_uid and already supports notes and statuses, so recording the
issue key as a triage note (and reflecting ticket progress in the triage status)
would give the reverse direction without new schema.

Related

Also worth flagging separately: #11472 dropped the Jira idempotency table, so
repeated sends of the same finding produce duplicate tickets. That's fine for
the on-demand "send to Jira" flow, but customers using the integration on a
schedule to track resolution do hit it.

Willing to contribute

Happy to open a PR for (1) immediately. Raising (2) and (3) here first since
they involve configuration and data-model decisions that maintainers should own.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions