Conf42 DevOps 2025 - Online

- premiere 5PM GMT

Secure Integration of Private Testing Infrastructure with Public GitHub Repositories

Video size:

Abstract

Cloud-based CI/CD tools are great. But what happens when the tested product introduces limitations that don’t allow for this approach? Learn how to securely achieve full integration between GitHub and privately hosted CI/CD services such as Jenkins without compromising the internal infrastructure.

Summary

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hi everyone, my name is Bianca Popo and I am a DevOps engineer at Analog Devices. Thank you for joining me today for my presentation on GitHub integration within a private Jenkins server. The problem that we're going to tackle during this presentation is integrating a privately hosted Jenkins server with GitHub. The biggest hurdle in achieving this would be ensuring that the server is not compromised. library tags, while also providing as much information as possible to contributors about the status of their projects. The first question someone may ask is, why not just use cloud? There are so many available CI CD cloud services that offer out of the box solutions that are already integrated with GitHub, for example, GitHub Actions, Azure Pipelines, GitLab, and so on. And these are also highly secure, so why not just use these? The answer is that the software product that is tested may impose some limitations on the CI CD infrastructure. These are only some examples that I've encountered so far. For example, the produced artifacts might be too big, and most cloud services impose a limit on the artifact size that they can store. or the software product may require third party tools for building or testing, which may be too big or they may require a paid license. And last but not least, building the software project may be too resource intensive. There's also a possibility that some developers might just prefer a self hosted open source CICD platform. Based on a 2023 study made by JetBrains, Jenkins is the most widely used CI system among developers and companies. So this presentation is going to mostly focus on Jenkins. Let's visualize our goal. And for that, I've prepared this diagram. In the center there is our Jenkins server that is inside a private network. This server contains all of our build and test pipelines. Now, we could have this server run the pipelines once in a while, just to check that our application doesn't contain any bugs, or we could manually run it every time a commit is added to the main branch. But this approach would not work for large repositories, which have frequent commits and many pull requests. We could drastically improve the bug finding process if we could associate a specific build with a commit. This means that every time a commit is made to an important branch, such as main or release branches, the pipelines on our server should be triggered and verify that very commit. Next, we would like to make these results available to all contributors and non contributors on GitHub. But we can't just provide them access to our local Jenkins instance, because that could expose us to attacks. So now that we've defined our goals, let's take a look at what's stopping us from achieving them. In this next diagram, we can see that our local Jenkins instance within our private network is protected by a firewall. This means that while traffic can go from our server to the GitHub servers, our server can't accept any incoming traffic from GitHub. If our aim is to trigger a Jenkins pipeline each time a commit or PR is made, we would need to enable webhook triggers inside our repository settings. These webhook triggers can be configured to send a notification to a certain URL every time a certain event occurs. For example, push, pull request update, new issue, and so on. If we try and configure a webhook trigger to send notifications to our local Jenkins server, we will notice that our server does not receive any data sent from GitHub, due to this firewall being in place. The second issue would be displaying the results of the pipeline runs on GitHub, without compromising our server security. We'll talk more about that in a second, but first let's try and solve the first issue. We've established that we need to enable communication from GitHub to our local server. Now, we wouldn't necessarily want to disable the firewall, since that's what's keeping our private infrastructure, well, private. There are a number of solutions to this problem, but the most straightforward one would be to set up web tunneling. Web tunneling is used to create a secure path between your local machine and another server to send data safely. It works by encrypting data, routing it through the tunnel, and forwarding it to its destination. The most popular web tunneling service is NgRock, because of its reliability and security. We can see in this diagram that running the data through this web tunnel safely bypasses the private network's firewall. When running the ng rok client on the local server with a chosen port, ng rok creates a secure tunnel between that specific endpoint on your machine and the ng rok servers. Their servers then forward this data to the correct location, in our case, the github servers. This doesn't mean that ng rok can see your data though, because it offers end to end encryption of your data. With enabled access through our web tunnel, we can go ahead and set up our pipelines to be triggered by GitHub events. The webhook triggers sent by GitHub will have to be interpreted and processed by Jenkins. There are several plugins that offer such functionalities, but these are the most popular ones. A GitHub plugin offers a lot of functionalities, but the one we're interested in is the processing of push events sent from GitHub. So, this will only work for new commits. Each one of these plugins has a different endpoint that accepts requests. In the case of the GitHub plugin, the endpoint is github webhook. You can see in the image below that I've configured GitHub to send requests to the interrupt tunnel, followed by this specific endpoint. After the plugin is installed on Jenkins, inside the Job Configuration tab, you will now have the option to trigger the job automatically. The same is valid for the GitHub Pull Request Builder plugin, only this plugin accepts the issue comment or pull request events. The endpoint for this plugin is ghprbhook. The option to select inside the Jenkins Job Config is GitHub Pull Request Builder. Just a heads up, this plugin has some security vulnerabilities, so you should probably make sure you configure it properly. The generic webhook trigger plugin is a plugin that accepts all kinds of HTTP requests, so it's more flexible, but less configured for GitHub itself. Nevertheless, you get more control over what happens to your triggers. After configuring GitHub webhooks, you should see a job get triggered every time a commit or pull request is made. We still have one more issue left though, and that is how we're going to let contributors know the test results. So, our goal here is to update the status on each commit or pull request after the Jenkins job is finished. Inside the Jenkins job, you could use the GitHub plugin once again. It offers highly customizable solutions for updating the status. You can run it with parameters, such as the status message, the context, the result, or the reference URL. The latter is the most important one in my opinion, since it's what populates the hyperlink under the details section of the GitHub check stack. By default, the value of this parameter is set to be the URL of the Jenkins server itself, so not the ngrok web tunnel. This is an issue, because it could expose your private IP to anyone on GitHub. You could set it to the ngrok web tunnel URL, but then anyone who wants to see the results would have to either authenticate on your Jenkins server, Or you would have to provide anonymous users with read all access rights. Neither of these options are secure and could expose malicious actors to your internal infrastructure. So how can we make sure that anyone can see the test results without compromising on infrastructure security? You could process these results and then host them on a public webpage. A quick and easy solution would be to use guests. These are small Git repositories hosted by GitHub, and they are primarily used for easily sharing code segments. Gists support markdown, so you could pre process the Jenkins output so that it's easier to read and understand by all contributors, even those that are unfamiliar with Jenkins. You should also sanitize this output before publishing the gist, so that no credentials or secrets are accidentally posted. Creating GISTs is also quite easy to integrate into your existing pipeline scripts, since GitHub offers a command line interface that has such a functionality. In this way, you could easily add a PostBuild stage into your pipelines, which handles preprocessing and posting the job output to GIST. In this example image, I had to create pipelines for a repository which contains multiple projects that need to be built and tested separately. So, my approach with this was to generate a markdown table containing the status of each project and whatever errors or warnings were thrown up during the build or the test stages. You could post the entire Jenkins console output, or You could get creative on how to automatically prepare the output into a nice final form for your repository's contributors. In the rightmost column in this example, you can see the results from another pipeline actually. So this method can be used to merge results from multiple pipelines as well. This other pipeline tests each available project directly on the hardware on a remote server. If you're interested in that, one of my colleagues has a presentation on that topic called Advanced Test Harness Infrastructure for Validating ARM and FPGA Based Systems, which is also a part of this event. I would recommend setting up a bot account for your repository, which will be responsible for setting the status. This account will need reading and writing rights. Now that we tackled the last issue as well, you should get a fully automated process of building and testing your GitHub projects, and have the Jenkins results posted back to GitHub in a nice format. The screenshot is of a pull request that shows our Jenkins job result posted inside the Checks tab. Before ending this presentation, let's recap what we achieved and highlight some benefits that came from all this. We managed to automate the process of building and testing our GitHub projects on our local Jenkins server. We have also set up a process of automatically posting back the Jenkins job results, and we did all this while maintaining a secure testing infrastructure. This means that it will now be easier to catch bugs, since we can identify the faulty commit at any time. We also have a more detailed history for projects, because each commit now has the full test details attached to it. And in the case of pull requests, the review process is much easier, because each pull request is tested in the same controlled environment. So we won't get any more it works on my computer bugs. Both the reviewers and the contributors will have access to the test results, so everyone is on the same page when reviewing the proposed changes. If you have any questions or if you'd like to send me some feedback, feel free to message me on LinkedIn or hit me up on my email here. Thank you so much for tuning into my presentation and happy coding.
...

Bianca Popu

DevOps Software Engineer @ Analog Devices

Bianca Popu's LinkedIn account



Join the community!

Learn for free, join the best tech learning community for a price of a pumpkin latte.

Annual
Monthly
Newsletter
$ 0 /mo

Event notifications, weekly newsletter

Delayed access to all content

Immediate access to Keynotes & Panels

Community
$ 8.34 /mo

Immediate access to all content

Courses, quizes & certificates

Community chats

Join the community (7 day free trial)