Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Connecting Jira Align to Jira Data Center with Apigee as a Reverse Proxy

Purpose

This document will explain how to connect Jira Align SaaS to a Jira Data Center via Apigee with Basic Authentication (API Key) .

Given 1: The customer has selected Jira Align SaaS in either multi-tenant or dedicated VPC configuration. This does not directly apply for an on premise implementation of Jira Align.

Given 2: The customer hosts Jira Data Center behind a firewall, without currently exposing the Jira Data Center API ports externally

Given 3: The customer uses Apigee as an API Gateway for network edge security and REST API ingress.

Please review the following example and adjust for your organization's security policies, security posture, and security practices.

How It Works

Apigee.png

All REST API traffic will initiate from the Jira Connector for Jira Align.

The Jira Connector for Jira Align currently supports two authentication methods:

  • Basic Authentication

  • OAuth 1.0a.

The preferred authentication policy configuration for Apigee is the API Key, instead of Basic Authentication. This policy configuration allows Jira Align to send the API Key in the Basic Authentication header.

  • In the Jira Align administrator interface, the administrator would select Basic Auth and input the supported Apigee API key.

  • Using a custom Apigee integration, the Apigee tool would extract the API key from the Basic Auth header and validate it.

  • The next step in the custom Apigee integration would modify the inbound request to replace the Basic Authentication header with the Jira Service Account username and password, which is stored in an encrypted KVM and forward the request onto Jira Server/Data Center.

    • Note: At this point the Apigee solution would also perform the public to private DNS mapping.

    • Note 2: The Apigee service can also restrict the requests to the Jira endpoint.

We also highly recommend configuring Mutual TLS and/or IP Allow listing at the Apigee policy level to establish multi-factor authentication policy. A sample IP allow list policy is covered in this article. As always, please review and validate these policies with your Head of IT Security before configuring in your environment.

  • You’ll want one proxy for each Jira Align connector (Ex: Test and Prod).

Additional Notes

  • The following configurations are not supported between Apigee and Jira Align:

    • OAuth 1.0a

    • OAuth 2.0

    • Bearer token

  • Mutual TLS between Jira Align and Apigee is not covered in this article but enabling MFA is part of the User Compensating Control requirements of the Jira Align SOC 2 compliance.

Prerequisites

Configuration Steps

1.) Sign in to Apigee Edge and click on API Proxies.

apigee_1.png

2.) Click +Proxy to create a new Proxy.

apigee_2.png

3. Select Reverse proxy.

apigee_3.png

4.) Fill in the Proxy name, the base path, and Target API (Jira site).

You’ll need 2 base paths (one for prod, one for test) to connect Jira Align to your Production Jira DataCenter and Test Jira DataCenter.

apigee_4.png

5.) Select API Key in the Security: Authorization options.

  • Do not enable CORS

  • Quota configuration and design is not in scope for this document. For the purposes of establishing connections, please do not enable at this time.

apigee_5.png

6.) Select secure in the Virtual hosts options.

apigee_6.png

7.) Click Create.

apigee_7.png

Create Key Value Map Store

8.) In the Apigee Edge tool, go to Admin > Environments > Key Value Maps.

Make sure to select the correct environment.

We recommend to use the test environment first.

9.) Create Key Value Map.

Example:

kvm_store_1 (encrypted)

key: name, value: <jira-service-acct-username>

key: pass, value: <jira-service-acct-password>

apigee_9a.pngapigee_9b.pngapigee_9c.png

 

Policies

10) Navigate to Develop > API Proxies > Select your Proxy > Develop Tab.

11) Create these policies. You can paste the Verify API Key policy below over the existing one.

Type: AccessControl

This policy permits certain IPs (or IP ranges) to connect to the proxy.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AccessControl async="false" continueOnError="false" enabled="true" name="IP-Allow-List">
    <DisplayName>IP Allow List</DisplayName>
    <Properties/>
    <IPRules noRuleMatchAction="DENY">
        <MatchRule action="ALLOW">
            <SourceAddress mask="32"><Example-IP></SourceAddress>
</MatchRule> </IPRules> </AccessControl>

Type: BasicAuthentication

This policy decodes the inbound (to Apigee) Basic Auth Header and stores the decoded username and password in variables.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication name="Decode-Basic-Auth-Headers">
    <DisplayName>Decode Basic Auth Headers</DisplayName>
    <Operation>Decode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="request.header.username"/>
    <Password ref="request.header.password"/>
    <Source>request.header.Authorization</Source>
    <Set/>
</BasicAuthentication>

Type: BasicAuthentication

This policy encodes the outbound (to Jira Data Center) Basic Auth Header using the variables created in the KeyValueMapOperations policy (Get-KVM).

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication async="false" continueOnError="false" enabled="true" name="Encode-Basic-Auth-Headers">
    <DisplayName>Encode Basic Auth Headers</DisplayName>
    <Operation>Encode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="private.service.name"/>
    <Password ref="private.service.pass"/>
    <AssignTo createNew="true">request.header.Authorization</AssignTo>
    <Source>request.header.Authorization</Source>
</BasicAuthentication>

Type: KeyValueMapOperations

This policy places the Jira service username and password defined in the Key Value Map Store into private variables.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<KeyValueMapOperations async="false" continueOnError="false" enabled="true" name="Get-KVM" mapIdentifier="kvm_store_1">
    <DisplayName>Get KVM</DisplayName>
    <Properties/>
    <Get assignTo="private.service.name">
        <Key>
            <Parameter>name</Parameter>
        </Key>
    </Get>
    <Get assignTo="private.service.pass">
        <Key>
            <Parameter>pass</Parameter>
        </Key>
    </Get>
    <Scope>environment</Scope>
</KeyValueMapOperations>

Type: AssignMessage

This policy cleans up Basic Auth Headers that are no longer needed after decoding and extraction has been completed.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="Remove-Basic-Auth-Headers">
    <DisplayName>Remove Basic Auth Headers</DisplayName>
    <Properties/>
    <Remove>
        <Headers>
            <Header name="request.header.Authorization"/>
        </Headers>
    </Remove>
    <Remove>
        <Headers>
            <Header name="request.header.username"/>
        </Headers>
    </Remove>
    <Remove>
        <Headers>
            <Header name="request.header.password"/>
        </Headers>
    </Remove>
    <Remove>
        <Headers>
            <Header name="username"/>
        </Headers>
    </Remove>
    <Remove>
        <Headers>
            <Header name="password"/>
        </Headers>
    </Remove>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

Type: VerifyAPIKey

This policy takes the password decoded during "Decode-Basic-Auth-Headers" and validates it against the Apigee API Key.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key">
    <DisplayName>Verify API Key</DisplayName>
    <APIKey ref="request.header.password"/>
</VerifyAPIKey>

 

12) Place this in your Proxy Endpoint PreFlow and PostFlow after making any adjustments (such as BasePath).

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>IP-Allow-List</Name>
            </Step>
            <Step>
                <Condition>(proxy.pathsuffix != "/rest/api/2/serverInfo")</Condition>
                <Name>Decode-Basic-Auth-Headers</Name>
            </Step>
            <Step>
                <Condition>(proxy.pathsuffix != "/rest/api/2/serverInfo")</Condition>
                <Name>Verify-API-Key</Name>
            </Step>
            <Step>
                <Name>Remove-Basic-Auth-Headers</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>
    <Flows/>
    <PostFlow name="PostFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix != "/rest/api/2/serverInfo")</Condition>
                <Name>Get-KVM</Name>
            </Step>
            <Step>
                <Condition>(proxy.pathsuffix != "/rest/api/2/serverInfo")</Condition>
                <Name>Encode-Basic-Auth-Headers</Name>
            </Step>
        </Request>
        <Response/>
    </PostFlow>
    <HTTPProxyConnection>
        <BasePath>/Jira-Align-Test</BasePath>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

 

13) Validate that this in your Target Endpoint PreFlow and PostFlow. (Do not paste over the existing policy.)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
    <PreFlow name="PreFlow">
        <Request/>
        <Response/>
    </PreFlow>
    <Flows/>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <HTTPTargetConnection>
        <URL>https://<your Jira server></URL>
    </HTTPTargetConnection>
</TargetEndpoint>

 

14) Save and Deploy to Test (or Prod if you are skipping Test).

apigee_14.png

Note: Trace is a great way to test and troubleshoot.

 

Create API Product and App

15) Go to Publish > API Products. Create new API Product.

16.) Give the API Product a name, access, environment(s), and add the recently created API proxy.

17.) Click Save.

apigee_17.png

18.) Go to Publish > Apps. Create new App.

19.) Give the App a name and add the recently created API Product.

20.) Click Create.

21.) In the newly created app, you should see the Key. Note that key for later use.

apigee_21.png

 

Setup in Jira Align

22.) Sign in to Jira Align as a super administrator, and navigate to Admin > Jira Settings > Jira Connectors.

apigee_22.png

23.) Enter the Jira Base URL (+ /browse/{external} ) into Jira Link.

24.) Assign this connector a memorable name.

25.) Enter the Apigee API Endpoint and base path from step 6 and step 4 into Jira API URL. (ex: https://example.apigee.net/Jira-Align-Test )

26.) Select Basic with API token Authentication as Authentication Type and set the username to something random and password as Key from step 21.

27.) Click Save.

28.) Click Test Now. (Note: You’ll need to close and open this box to see the Test refresh.)

29.) Assuming the test was good, go ahead and press Activate and Save.

30.) Then you can proceed with Syncing a Project.

 

 

2 comments

Mark Cruth
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
March 18, 2021

Thanks for sharing this, @James McCulley ! I know lots of customers leverage Apigee and this will make it 1000% times easier for them to think about how they connect to Jira Align!

Like # people like this
Carlos Garcia Navarro
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 10, 2024

Great article, thanks for sharing so many details!

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events