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
- Mint a Jira API token (Step 1).
- Note the Jira URL, project key, and issue type (Step 2).
- Apply the example
JiraConnectorfrom Step 3. - 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
almaCLI pointed at it. -
A requester allowed to request
accessand a different user allowed to review that request. See Just-in-Time Access. -
Outbound HTTPS egress from
almadto 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, orOpen. 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 transitionsin thealmadlogs 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.
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 withhttps://, so a bare hostname will not do. - The project key, for example
OPS,SEC, orACCESS. - The issue type that AlmaForge should use when it creates issues.
Taskis 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:
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:
alma apply -f jira.yamlOnly 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:
journalctl -u almad -f | grep jira_service... jira_service: starting plugin name=jira host=https://example.atlassian.net project=OPS... Plugin is readyNow create a real access request and confirm a Jira issue appears in the target project:
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:
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:
alma create token --services=jira --expires=1hOn the sidecar host, start almad with the token and the
Jira role enabled. No configuration file is required:
export ALMA_CLIENT_SECRET=/path/to/client-secretalmad start \ --auth-server=auth.example.com:443 \ --client-id=<client-id> \ --jira-serviceThe same parameters can be supplied as environment variables for container or systemd deployments:
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 startThe 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.