Skip to main content

Jira Integration for AlmaForge

AlmaForge can file a Jira issue for every access request in your cluster and keep that issue in step with the request's state. When a request is created in AlmaForge, a new issue appears in your Jira project. When the request is approved, denied, or expires, the matching issue is transitioned and a resolution comment is posted with the reviewer and the reason.

The integration is built into almad. You do not install a separate plugin, run a callback service, or expose a public URL to Jira. Configure it with a JiraConnector resource, either under Integrations in the Web UI or with alma apply. Both paths store the same resource.

TL;DR​

  1. Mint a Jira API token (Step 1).
  2. Note the Jira URL, project key, and issue type (Step 2).
  3. Apply the example JiraConnector from Step 3.
  4. File a test access request to confirm the issue lands in the project (Step 4).

Limitations​

The integration is currently one-way. It pushes access-request state into Jira, but approvals and denials still happen in AlmaForge, either in the Web UI or with alma request review.

Only one Jira integration is supported per cluster. The connector must be named jira. Any JiraConnector applied under a different name is accepted by the API but never read. The plugin only ever fetches the well-known name, so an extra connector is silent rather than logged.

Reporter attribution is best-effort. AlmaForge tries to set the Jira issue reporter to the AlmaForge user who filed the access request, but Jira Cloud hides email addresses from the user search API in many configurations. If the match is ambiguous, the issue is created without a reporter and the request body identifies the AlmaForge user by login name only. See Reporter attribution under Operations for the full matching rules.

Prerequisites​

Before you start, make sure you have:

  • A running AlmaForge cluster with an Auth Service that you can reach over the network and a working alma CLI pointed at it.

  • A requester allowed to request access and a different user allowed to review that request. See Just-in-Time Access.

  • Outbound HTTPS egress from almad to your Jira instance from every auth host. The integration makes no inbound connections, so no firewall or NAT rules on the AlmaForge side are required.

  • A Jira Cloud site or a self-hosted Jira Server / Data Center instance.

  • A Jira project that will hold the access-request issues. A fresh project dedicated to AlmaForge is recommended. The integration writes issues often, and mixing them with unrelated tracker work gets noisy.

  • A Jira issue workflow that covers the states below and allows single-step transitions from the initial state to each of the final states. State name matching is case-insensitive.

    Initial state: the state every new issue lands in, used while the access request is still awaiting a decision. Most Jira projects call this Pending, To Do, or Open. AlmaForge creates issues in whatever state your project's workflow uses for new issues. No extra configuration is needed.

    Final states: transitions from the initial state must reach each of these:

    • Approved: set when the access request is approved in AlmaForge.
    • Denied: set when the access request is denied in AlmaForge.
    • Expired: set when the access request expires without a decision.

    If any required final state is missing, the transition fails with cannot find a <status> status among possible transitions in the almad logs and the Jira issue stays in its pre-transition state.

  • Permission on the target project to Browse, Create issues, Transition issues, and Add comments. AlmaForge uses a single Jira account for everything it does. A dedicated service user keeps the audit log clean.

Step 1. Create an API token​

Sign in to Jira as the account you plan to use for the integration. On Jira Cloud, open Account settings → Security → Create and manage API tokens and mint a new token. On Jira Server or Data Center, use a personal access token issued from the user profile.

Store the token in your secret manager. Jira only shows it once. Access to stored connector secrets requires permission to read secrets.

Treat the API token as a password

Anyone with the API token can create issues, post comments, and transition existing issues as your service account. Store it in the same secret manager you use for production credentials. Do not commit it to Git.

Step 2. Confirm the project and issue type​

Open the target project in Jira and note three values:

  • The base URL, including the scheme. On Jira Cloud this is https://example.atlassian.net. On self-hosted it is your instance's own URL. The plugin refuses to start unless the value begins with https://, so a bare hostname will not do.
  • The project key, for example OPS, SEC, or ACCESS.
  • The issue type that AlmaForge should use when it creates issues. Task is the default and works for almost every project. Set it explicitly only if your workflow uses a custom type.

If your workflow renames the default statuses, confirm that the destination states for Approved, Denied, and Expired are reachable from the unresolved state as single-step transitions. AlmaForge does not follow multi-step workflow chains.

Step 3. Apply a JiraConnector​

Write a YAML file describing the connector:

jira.yaml:

examples/integrations/jira.yaml
apiVersion: almaforge.com/v1
kind: JiraConnector
metadata:
name: jira
spec:
# Replace every value below before applying.
url: https://example.atlassian.net
username: bot@example.com
apiToken: replace-me
project: OPS
issueType: Task

For a quick setup, keep apiToken inline as shown above. For production, keep the secret out of the manifest and point this field at a file or environment variable instead. See Secret management in this page's Operations section.

Replace:

  • The Jira URL, username, and token with the values from Step 1 and Step 2.
  • The project key and issue type with your own values.

Apply the connector:

Terminal
alma apply -f jira.yaml
One connector per cluster

Only one Jira integration is supported per cluster. The connector must be named jira. Any JiraConnector applied under a different name is ignored.

Step 4. Test end-to-end​

The plugin polls the JiraConnector resource once a minute and reconciles its state against what it observes. It starts on first appearance, restarts on resource-version change, and stops on delete. Apply, edit, and delete are all picked up within about 60 seconds with no daemon restart.

Tail the almad logs on your auth host and look for the plugin's start lines:

Terminal
journalctl -u almad -f | grep jira_service...  jira_service: starting plugin  name=jira  host=https://example.atlassian.net  project=OPS...  Plugin is ready

Now create a real access request and confirm a Jira issue appears in the target project:

Terminal
alma request create --roles access --nowait --reason "jira smoke test"

As a different user with permission to review this request, approve or deny it in AlmaForge. Use the request ID printed by the create command:

Terminal
alma request review <request-id> --approve --reason "smoke test ok"

The matching Jira issue transitions to the Approved or Denied state and receives a comment summarizing the approver, the reason, and the original AlmaForge request identifier.

Troubleshooting​

API token is wrong or the user lacks permission​

Unauthorized (HTTP 401) from Jira. The API token does not belong to the user named in username, or the user has not been granted access to the project. Mint a fresh token, confirm the user can browse the target project in the Jira UI, and re-apply the connector.

Project not found​

Project not found from Jira. The project key does not exist, or it points at a project the service user cannot browse. Project keys are case-sensitive. Copy the value directly from the project settings page.

Transition fails​

cannot find a <status> status among possible transitions in the auth journal. The Jira workflow does not allow a direct transition from the issue's current state to Approved, Denied, or Expired. Adjust the workflow in Jira to add single-step transitions, or rename the destination status to match what AlmaForge expects.

Token file cannot be read​

no such file or directory or permission denied on plugin start. The file named by a ${file:PATH} reference in apiToken does not exist or is not readable by root. A file over the 64 KiB cap is reported as exceeds 65536 bytes. Check file ownership and permissions on the auth host, and confirm the file is a plain text token with no leading or trailing whitespace.

Plugin starts and immediately exits​

The most common causes are an unreachable Jira instance (egress problem from the auth host), a wrong spec.url (missing scheme, wrong port), or an expired token. Tail the auth journal for the jira_service component to see the underlying error. The plugin retries on the next poll tick (about 60 seconds), so a transient network problem self-recovers.

Operations​

Lifecycle​

The Jira plugin lives inside the almad binary and is enabled by default on every process that runs the Auth Service. To turn it on or off for a specific host, pass --jira-service or --no-jira-service on the almad start command line, or set ALMA_JIRA_SERVICE to true or false. Both forms work under systemd drop-ins, container environments, and Kubernetes pod specs.

The connector is reloaded every 60 seconds. Applying it starts the plugin. Editing it triggers a restart on the next reload. Deleting it stops the plugin. None of these transitions require a almad restart.

High availability​

The plugin runs on every auth process, including in multi-node clusters. Each access request produces exactly one Jira issue regardless of how many auth processes are running, and resolution transitions work correctly even if the auth host that created the original issue has since restarted.

Egress requirements​

Auth hosts require outbound TCP/443 to your Jira instance. For Jira Cloud, that is *.atlassian.net. For self-hosted deployments, it is the hostname you put in spec.url. No inbound connectivity is required, and the integration does not open any listening sockets.

Sidecar deployment​

The plugin can also run as a dedicated sidecar process: a standalone almad instance that joins the existing cluster solely to bridge Jira. This topology is appropriate when the auth nodes themselves cannot reach Jira and a separate host is used as the egress point.

On the auth cluster, mint a join token that grants the Jira system role:

Terminal
alma create token --services=jira --expires=1h

On the sidecar host, start almad with the token and the Jira role enabled. No configuration file is required:

Terminal
export ALMA_CLIENT_SECRET=/path/to/client-secretalmad start \    --auth-server=auth.example.com:443 \    --client-id=<client-id> \    --jira-service

The same parameters can be supplied as environment variables for container or systemd deployments:

Terminal
export ALMA_AUTH_SERVER=auth.example.com:443export ALMA_CLIENT_ID=<client-id>export ALMA_CLIENT_SECRET=/path/to/client-secretexport ALMA_JIRA_SERVICE=truealmad start

The sidecar joins the cluster as system:jira, receives an identity certificate from the auth service, polls the JiraConnector/jira resource over the standard auth gRPC channel, and runs the plugin locally.

Secret management​

For production, keep the Jira API token outside the manifest. spec.apiToken accepts a literal value or a value loaded from the environment or a file. See Resource value expansion for the exact syntax and field support.

Rotate the token by updating the underlying file or environment variable and re-applying the connector. No almad restart is required.

Reporter attribution​

When AlmaForge files a Jira issue for an access request, it tries to attribute the issue to the Jira user who requested access, not to the service account in spec.username. The plugin takes the AlmaForge user's login name and searches Jira's /rest/api/2/user/search endpoint with that string. Matching rules, in order:

  1. If any returned user has an emailAddress that equals the AlmaForge login name (case-insensitive), that user becomes the issue reporter. This is the common path. If your AlmaForge users log in with email addresses that also exist in Jira, attribution works with no extra configuration.
  2. On Jira Cloud, email addresses are often hidden from the search API. When the search returns exactly one active user and no email match was possible, the plugin assumes that single result is the right match.
  3. If neither rule matches, the issue is still created but without a reporter. The request text in the issue body identifies the AlmaForge user by login name only.

If Jira returns an error or the lookup times out (the plugin caps it at 5 seconds), the issue is created with no reporter. Lookup is best-effort and never blocks issue creation.

Identity and permissions​

The Jira integration runs under a built-in system role called Jira. almad grants it the minimum set of permissions it needs and nothing more: list and read on ClusterName, list and readwithsecrets on JiraConnector so it can load its API token, read on CertificateAuthority, and list, read and update on AccessRequest and AccessPluginData. No hand-authored RBAC resources are required, and the role cannot be used to sign in as a human.

Each Jira issue is created by the API user named in spec.username. In the Jira audit log every action taken by the integration appears as that user. Pick a name that makes the source obvious, for example almaforge-bot@example.com.

Monitoring​

The auth service logs plugin lifecycle events (start, stop, restart on connector change) and Jira API errors under the jira_service component. Tail the journal with:

Terminal
journalctl -u almad -f | grep jira_service

A successful start prints starting plugin followed by Plugin is ready. Connector changes log connector changed; restarting plugin. Jira API errors are logged with the HTTP status code and the description Jira returned.

The integration does not emit Jira-specific audit events. Every AlmaForge access request and review already produces a structured audit event in the auth service journal, and the plugin lifecycle lines above are usually enough to confirm what the plugin did in response. Every Jira issue body includes the AlmaForge request identifier, so it is straightforward to correlate a Jira issue with a specific access request.

Removal​

Delete the connector resource:

Terminal
alma delete JiraConnector/jira

The plugin stops on the next polling tick, within about 60 seconds, with no almad restart. Existing Jira issues are left in place. The integration never deletes issues on its own.

To revoke the API token entirely, delete it in the Jira account settings.

References​