This project collects foundational Jira and Confluence access data and exports it in the BloodHound OpenGraph format using the bhopengraph Python library (gr33ts @p0dalirius). It should support both Atlassian Cloud and Data Center deployments (I dont have a on-prem to test against. PRs welcome lol)
- Jira collection: accounts, group membership, project leads, issues, attachments, and comments
- Confluence collection: spaces with principal permission assignments, page hierarchy, and attachments
AtlassianAccountAtlassianGroupConfluenceSpaceConfluencePageConfluenceAttachmentJiraProjectJiraIssueJiraAttachmentJiraComment
MemberOfJiraProjectLeadContainsIssueAssignedToIssueReportedIssueHasAttachmentAuthoredAttachmentHasCommentAuthoredCommentUpdatedCommentContainsPageParentPage- Space permission edges derived from Confluence operations
AdministerSpaceRestrictContentSpaceExportSpaceReadSpaceCreateAttachmentCreateBlogpostCreateCommentCreatePageDeleteSpaceDeleteAttachmentDeleteBlogpostDeletePageDeleteComment
Use these queries in BloodHound (or any Neo4j-compatible workspace) after importing the generated JSON.
// Jira Project Leads
MATCH p = (account:AtlassianAccount)-[:JiraProjectLead]->(project:JiraProject)
return p// Issues, comments, and attachments for a Jira Project
match p = (j:JiraProject {projectkey: "WERD"})-[*]->(m)
return p// Jira comments that mention passwords (provided example)
MATCH p = (c:JiraComment)
WHERE c.body CONTAINS "password"
RETURN p// Jira attachments with potentially sensitive file names
MATCH p = (issue:JiraIssue)-[:HasAttachment]->(attachment:JiraAttachment)
WHERE attachment.filename =~ '(?i).*(secret|credential|password).*'
RETURN p
LIMIT 50// Confluence attachments with sensitive filenames
MATCH p = (page:ConfluencePage)-[:HasAttachment]->(attachment:ConfluenceAttachment)
WHERE attachment.name =~ '(?i).*(secret|credential|password).*'
RETURN p
LIMIT 50// Confluence spaces not marked as personal
MATCH p = (s:ConfluenceSpace) where s.spaceType <> "personal"
RETURN p
match path = (p:ConfluencePage) where p.content CONTAINS "password"
return pathbhopengraph
ATLASSIAN_DEPLOYMENT:cloud(default) ordatacenter.ATLASSIAN_SITE_URL(preferred) orATLASSIAN_BASE_URL: base site URL without API paths (for example,https://your-domain.atlassian.net).ATLASSIAN_JIRA_SITE_URL(optional): overrides the Jira site if it lives on a different hostname.ATLASSIAN_CONFLUENCE_SITE_URL(optional): overrides the Confluence site. For Cloud, the code appends/wikiautomatically when missing.
Choose one of the supported flows:
- Session cookie (default when
TENANT_SESSION_TOKENis present)TENANT_SESSION_TOKEN: Atlassian session token.
- Basic / API token
- Set
ATLASSIAN_AUTH_TYPE=basic. - Provide credentials via
ATLASSIAN_USERNAME(orATLASSIAN_EMAIL) andATLASSIAN_PASSWORD(orATLASSIAN_API_TOKEN).
- Set
ATLASSIAN_JIRA_API_VERSION: override REST API version (3for cloud,2for data center by default).ATLASSIAN_JIRA_REST_PATH: custom REST path segment if your instance uses a non-standard context.ATLASSIAN_JIRA_ISSUE_JQL: custom bounded JQL used by the Jira issue collector (defaults toupdated >= -90d order by updated DESC).ATLASSIAN_CONFLUENCE_REST_PATH/ATLASSIAN_CONFLUENCE_V2_PATH: override Confluence REST or v2 API roots.BLOODHOUND_BEARER: static token for the BloodHound API. Alternatively, supplyBLOODHOUND_API_TOKEN_ID+BLOODHOUND_API_KEYto generate signed requests.
- Activate the virtual environment:
source .venv/bin/activate - Ensure the required environment variables are set (for example via
.env). - Run the collector:
python atlassianhound.py
- Add your Icons
python create_icons.py apply-defaults
The script writes output/atlassian_graph.json. Import this file into BloodHound