Adding JIRA Integration to Policy Reporter for Kyverno
Introduction In Kyverno policy management, detecting policy violations is only half the battle. Acting on them efficiently is equally important. Today, I'm excited to share how we implemented JIRA integration in Policy Reporter, allowing Kyverno policy violations to be automatically converted into actionable JIRA tickets. The Feature The JIRA integration enables Policy Reporter to: Create JIRA issues from Kyverno policy violations detected in PolicyReports Format violations with detailed information including severity, resources affected, and remediation steps Customize issue types, fields, and project keys Filter violations by severity Implementation Approach Our implementation focused on three key areas: Configuration Structure We added JIRA configuration options to Policy Reporter's config structure: target: jira: enabled: true host: "https://your-instance.atlassian.net/" username: "your-email@example.com" apiToken: "your-jira-api-token" projectKey: "PRJ" issueType: "Task" # Default if not specified JIRA Client Implementation We created a specialized client to handle JIRA API interactions: package jira import ( "bytes" "encoding/json" "fmt" "net/http" "strings" "github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2" ) // Client for Jira REST API interactions type Client struct { host string username string apiToken string projectKey string issueType string // other fields } // Send creates a JIRA issue from a policy violation func (e *Client) Send(result v1alpha2.PolicyReportResult) { // Transform policy result into JIRA issue // POST to JIRA API } HTTP Request Handling The most challenging part was correctly formatting the HTTP request to JIRA: // Create JSON payload jsonBody, err := json.Marshal(issueData) if err != nil { return } // Create HTTP request req, err := http.NewRequest("POST", fmt.Sprintf("%s/rest/api/2/issue", strings.TrimRight(e.host, "/")), bytes.NewBuffer(jsonBody)) if err != nil { return } // JIRA API requires Content-Type to be exactly "application/json" (without charset) req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", "Policy-Reporter") // Set authentication req.SetBasicAuth(e.username, e.apiToken) Challenges and Solutions JIRA API Quirks JIRA's API is particular about request formatting. We encountered several issues: Content-Type header: JIRA requires exactly "application/json" without charset parameters URL formatting: Double slashes in URLs caused failures Issue type compatibility: Different JIRA instances have different available issue types Testing in Kubernetes Testing the integration locally was straightforward, but testing on Kubernetes presented challenges: Image building: Making sure the Docker image contained the binary at the correct path Configuration mapping: Properly passing JIRA credentials to the container Debugging: Using logs to diagnose API interaction issues Testing Locally To test the JIRA integration with Kyverno: Build the binary: make build Create a test config (config.yaml): target: jira: enabled: true host: "https://your-instance.atlassian.net/" username: "your-email@example.com" apiToken: "your-jira-api-token" projectKey: "PRJ" issueType: "Task" Run locally ./build/policyreporter run --config config.yaml Create a test Kyverno PolicyReport: kubectl apply -f -

Introduction
In Kyverno policy management, detecting policy violations is only half the battle. Acting on them efficiently is equally important. Today, I'm excited to share how we implemented JIRA integration in Policy Reporter, allowing Kyverno policy violations to be automatically converted into actionable JIRA tickets.
The Feature
The JIRA integration enables Policy Reporter to:
Create JIRA issues from Kyverno policy violations detected in
PolicyReports
Format violations with detailed information including severity, resources affected, and remediation steps
Customize issue types, fields, and project keys
Filter violations by severity
Implementation Approach
Our implementation focused on three key areas:
- Configuration Structure We added JIRA configuration options to Policy Reporter's config structure:
target:
jira:
enabled: true
host: "https://your-instance.atlassian.net/"
username: "your-email@example.com"
apiToken: "your-jira-api-token"
projectKey: "PRJ"
issueType: "Task" # Default if not specified
- JIRA Client Implementation We created a specialized client to handle JIRA API interactions:
package jira
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2"
)
// Client for Jira REST API interactions
type Client struct {
host string
username string
apiToken string
projectKey string
issueType string
// other fields
}
// Send creates a JIRA issue from a policy violation
func (e *Client) Send(result v1alpha2.PolicyReportResult) {
// Transform policy result into JIRA issue
// POST to JIRA API
}
- HTTP Request Handling The most challenging part was correctly formatting the HTTP request to JIRA:
// Create JSON payload
jsonBody, err := json.Marshal(issueData)
if err != nil {
return
}
// Create HTTP request
req, err := http.NewRequest("POST", fmt.Sprintf("%s/rest/api/2/issue", strings.TrimRight(e.host, "/")), bytes.NewBuffer(jsonBody))
if err != nil {
return
}
// JIRA API requires Content-Type to be exactly "application/json" (without charset)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Policy-Reporter")
// Set authentication
req.SetBasicAuth(e.username, e.apiToken)
Challenges and Solutions
JIRA API Quirks
JIRA's API is particular about request formatting. We encountered several issues:
Content-Type header: JIRA requires exactly "application/json" without charset parameters
URL formatting: Double slashes in URLs caused failures
Issue type compatibility: Different JIRA instances have different
available issue typesTesting in Kubernetes
Testing the integration locally was straightforward, but testing on Kubernetes presented challenges:
Image building: Making sure the Docker image contained the binary at the correct pathConfiguration mapping: Properly passing JIRA credentials to the container
Debugging: Using logs to diagnose API interaction issues
Testing Locally
To test the JIRA integration with Kyverno:
- Build the binary:
make build
- Create a test config (config.yaml):
target:
jira:
enabled: true
host: "https://your-instance.atlassian.net/"
username: "your-email@example.com"
apiToken: "your-jira-api-token"
projectKey: "PRJ"
issueType: "Task"
- Run locally
./build/policyreporter run --config config.yaml
- Create a test Kyverno PolicyReport:
kubectl apply -f - <
Best Practices
Through this implementation, we learned several best practices:
Direct HTTP Requests:
For complex APIs like JIRA, create HTTP requests directly rather than using utility functions, giving you precise control over headers and formatting.
Debug Logging:
Add detailed debug logging during development to understand exactly what's being sent and received.
URL Sanitization:
Always sanitize URLs before constructing requests, especially for trailing slashes.
Content-Type Headers:
Be precise with Content-Type headers, as some APIs are very particular about them.
Error Handling:
Provide detailed error information that includes both HTTP status codes and response bodies.
Conclusion
The JIRA integration for Policy Reporter bridges the gap between Kyverno policy violations and issue tracking, enabling teams to:
Automatically track Kyverno violations in their existing workflow
Ensure compliance issues don't fall through the cracks
Assign and prioritize remediation work
By connecting Kyverno policy management with team issue tracking, we enable smoother compliance workflows and better security governance in your Kyverno-protected clusters.