ShiftLeft Engineering — Integrating your Go services with JIRA

ShiftLeft Engineering — Integrating your Go services with JIRA

How did ShiftLeft Engineering integrate its Go Services with JIRA to create a stable bidirectional JIRA based workflow

At ShiftLeft, we decided on an aim to empower developers to manage the security findings (discovered by our tool in their apps). We also decided to do it without stepping out of their traditional JIRA based workflow. With this blog, I describe the engineering approach that helped us achieve that goal by connecting our Go Based services with JIRA (cloud) infrastructure.

Photo by Markus Spiske on Unsplash

If you are interested to try out free ShiftLeft Code Analysis offering, please visit this link.

First, Atlassian Connect

In recent times Atlassian has been migrating their proposed usage of their product from a hybrid system of cloud/on-premise to pure play cloud based infrastructure.

The move to cloud has also had an effect on the way plug-ins are developed. As part of this new architecture they proposed a self hosted model powered by their Atlassian connect framework.

Connect style plugins allow the developer to express the capabilities of their product in a declarative format. Furthermore, interaction with JIRA is done through secure channels by using web-hooks, callbacks and snippet inserted in their UI. This novel approach allows each party to concentrate in their own strengths. Atlassian displays and manages their customers workflow and process. On the other hand the plugin developer augments Atlassian product’s information with their own, and in turn, keep their side up to date by getting feedback out of it.

The security aspects

The whole process is quite air tight. On the plugin side, Atlassian initiates communication with signed requests. Validity of security efficacy can be asserted against their verified servers and subsequent communication is signed with short lived tokens. The signatures can be checked against “user” bound keys. On the end user side they are presented with information about the kind of permissions the plugin wants and get pretty comprehensive information on what they are allowing.

ShiftLeft’s use case

For our case this is an excellent match, we present DevSecOps profiles with the relevant finding information in our UI. We facilitate for them to “send” the relevant bits to JIRA in the form of new Issues/Bugs to be addressed as part of their regular development cycle. Users seeing one of these Issues would be presented with augmented fields. These contain the detail of the security flaw detected and a way to go dive more into it at the ShiftLeft screen if necessary.

On our side, once we link a finding to a JIRA Issue/Bug we keep track of their changes. The operator of our system is always informed of the process of resolution of the vulnerability without having to alter their daily workflow to go track the development one.

Some Background — ShiftLeft services, existing tools, existing plugin

We built most of our API backend on top of Go.We leverage gorilla mux and use JWT tokens as a means of authentication. Naturally we thought that, given the presence of all the right ingredients, we could easily join both worlds.

Photo by Clint Patterson on Unsplash

Atlassian provides a Node.js Express and Spring Boot implementations of their framework. The existing offering allows developers to quickly create a plugin by implementing the security aspects and offering various hook points. The offering simplifies implementing functionality without having to dive in the internals of their pipeline.

Initially one of our expert teams in Node decided to create our plugin taking advantage of Atlassian Connect Express ACE. This served as a great first step and allowed us to validate that the proposed workflow suited both our users and they way they expected to interact with JIRA. We took this time to get some feedback, reduce friction in all possible surfaces and polish a well rounded product.

So why new plugin design?

As it is natural in every software project, once it works and end users are happy, the next step is to try and make it more efficient and better integrated. We decided on following re-architecture goals.

  • We wanted to reduce roundtrip times: having a service talk to both us and JIRA added some latency. In cases of intense use it added potential failure points and latency.
  • Too many hands in a bowl: Even though a lot of the aspects of this plugin were of relevance for our API team, addressing every issue/feature we worked on, as one maintained the plugin and the other the API.
  • Repeated functionality: We were starting to see a trend of repeating functionality and writing pass through endpoints in the plugin to support already implemented API parts.
  • Expertise: We have people well versed with Node.js in the company. Despite this, at the area in charge of the core functionality of our API we are more proficient in Go. Even though we understood the codebase well enough, we knew that our output on it would never be as on point as the other team. This was not ideal if we were to take the maintenance responsibility.
  • JIRA as a first class citizen: We see JIRA as a first class citizen of our system. Our aim is to add progressively more integration. Having it live as part of our core functionality is a must. We add features with JIRA in mind so it is only natural to have it be part of our core API.

Our solution

We really liked Atlasssian’s approach with ACE, so we based our own development on it. Sadly there was not a tool in their list of third party resources that allowed us to integrate the concept with Go. We intended to both support the main features: adding various panels, hook listeners, custom fields, etc. In short give enough tools to allow a developer to approach creating a new plugin in an almost declarative way.

We created atlassian-connect-go which permits the programming of a fully functional plugin by just instantiating a Go struct and calling a few methods in it to set up the various listeners.

We provided a series of auto generated types for ease of handling requests and callbacks. We also included a very simple storage interface for users to implement their own persistence backend and have the right information supplied to it.

We integrate with gorilla mux . This allows to add the plugin endpoints to an existing router. You can have the plug-in declaration and it’s endpoints be instantly served but also allow for extension for more on point cases. We facilitated what we use most but since Atlassian Connect plugins can reach a very deep level of integration we made it in a way that a developer is not limited to the concrete helpers.

The Security Aspect

In aspects of Security, a very important point for us, we based our framework strongly on the one provided by Atlassian. We provide a standalone function for developers to verify requests made by a third party against stored Atlassian credentials. We also added, for good measure, a wrapper that will take a handler function defined by us and return a standard `http.HandlerFunc` which will check every request to ensure proper credentials.

A developer creating handlers for Atlassian plugin endpoints just needs to create them as `func(jii *storage.JiraInstallInformation, store storage.Store, w http.ResponseWriter, r *http.Request)` and invoke `Plugin{}.VerifiedHandleFunc(yourHandler)`. The result is a handler whose request is verified before invocation and that gets passed all the relevant information to process the request.

Ultimately you can call the verifier function yourself as a way to securely retrieve user information from your storage.

We also added a few extra helpers to make secure properly signed calls to the apicommunication package. This package contains a way to create secure clients, the same way as ACE. It also allows to make calls as a given user (provided one has the right token). The HostClient is sufficiently customizable that one can pass a custom roundtripper to allow personalized timeouts and dialers to adjust it to your services settings.

Convenience

API communication package also has every possible (as of the time of writing) type returned by API V3 so you can deserialize replies into Go types and create requests in Go before serializing them, reducing the risk for coding mistakes.

Conclusion

We enjoyed writing this plugin. We got to know more about JIRA solid architecture and give back to the developer community much like we did before with gaum, our SQL query builder and executor and Joern, our interactive shell for code analysis. We hope this will encourage more integration of products with Atlassian Cloud by the means of plugins especially for services strongly rooted in Go.

Feel free to drop us emails, tweets or github issues if you want to know more about this framework or have suggestions about where it could go from now and, as usual, Pull Requests and Bug reports are always welcome.


ShiftLeft Engineering — Integrating your Go services with JIRA was originally published in ShiftLeft Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

*** This is a Security Bloggers Network syndicated blog from ShiftLeft Blog – Medium authored by Horacio Duran. Read the original post at: https://blog.shiftleft.io/shiftleft-engineering-integrating-your-go-services-with-jira-e31e4aca3d67?source=rss—-86a4f941c7da—4