Securing the Code to Cloud Pipeline with GitHub and Azure
DevOps is a modern application development and delivery approach that helps organisations to release quality software more quickly into production with less defects! Though DevOps itself is not a product, implementing its practices requires services and tools. Microsoft offers two widely used platforms for implementing DevOps practices – the Azure DevOps platform and the GitHub platform.
Adopting a DevOps approach does not yield benefits in isolation, but rather in conjunction with other concepts such as Agile planning and Cloud computing. By utilising platforms such as GitHub for implementing DevOps practices and Azure for cloud services, organisations can achieve a continuous “Code to Cloud” process. This process emphasizes the use of modern CICD platforms to streamline software development for applications running on cloud-based infrastructure and services, including cloud-managed container orchestration platforms and serverless computing services, instead of relying on traditional on-premises servers and infrastructure.
Supply chain attacks
As organisations embrace this approach, security teams are faced with new challenges due to the increased velocity, automation, and decentralisation of the development process. Attackers are increasingly targeting organisations through their software development processes. This is where software supply chain security becomes crucial! The software supply chain encompasses everything necessary to create and deliver software, including IDEs, source control systems, build systems, deployment systems, CICD platforms, runtime environments, and various artifacts such as application code, open-source dependencies, infrastructure code, and deployment artifacts.
Securing the software supply chain is not an easy task and requires a comprehensive and thorough approach. Figure 1 divides the GitHub to Azure code-to-cloud pipeline into five stages.
NOTE: GitHub offers multiple product options, but this article will centre on GitHub Enterprise which offers some capabilities that are not available in the other options. Specifically, I will emphasize security areas that I consider crucial but may be overlooked.
Securing the DEVELOPMENT stage
The development stage is where the code is created, and the first step towards securing this stage is to ensure that developers are using a secure environment for development. A significant concern is the possibility of a compromised development environment resulting from the use of unpatched IDEs or the installation of vulnerable or malicious extensions. IDEs, like any other application, can contain vulnerabilities and require regular updates to ensure their security. A recent example is CVE-2022-41034, a critical vulnerability disclosed for Visual Studio Code that allows for remote code execution on any system with the IDE installed.
Using a managed development environment like GitHub Codespaces provides the advantage of quickly applying necessary patches to ensure the environment’s security. In addition to this, each Codespaces environment runs on its own freshly built isolated virtual machine and network with a firewall used to block incoming connections from the internet and internal networks.
Codespaces also
Securing the SOURCE CONTROL stage
The source control stage is where the code is stored, discussed, and managed, and it is essential to ensure that the source code repository is secure. This starts with access controls and permissions. Only authorised individuals should have access to our repositories.
To access GitHub enterprise services and resources, users need to be authenticated. There are three methods for adding users to our GitHub Enterprise organisation for access (Figure 2).
The first option is to invite users with their personal GitHub account which enables them to authenticate through GitHub.com and access our organisation resources. With this option, the user maintains control of their identity (since it is their personal account), and can continue to contribute to other enterprises, organisations, and repositories outside of our organisation.
The second option is to use an external identity provider that supports SAML single sign-on. With this option, users authenticate with an identity in the external SAML provider that is linked to a personal GitHub identity. This means that while users are still utilising a GitHub identity to access our organisation’s resources, the actual authentication takes place through the external identity provider. The identity can be used for contributions to other enterprises, organisations, and repositories outside of our organisation.
The third option is to use “Enterprise Managed Users“ – EMU which is similar to other single sign-on solutions. With EMU, users will access GitHub organisation resources using a single identity created and managed in the external identity provider. They do not need to have a personal GitHub identity. This gives the most control for enterprise users.
The recommendation, if you are an enterprise, is to use either the second option or the third option.
To perform any actions on GitHub, such as creating a pull request in a repository, a person must have sufficient access to the relevant resource. This access is controlled by permissions. A permission is the ability to perform a specific action. For example, the ability to delete an issue is a permission. A role is a set of permissions you can assign to individuals or teams.
GitHub supports roles at different levels depending on what we are looking to achieve:
- Organisation-level roles which are sets of permissions that can be assigned to individuals or teams to manage the organisation settings, repositories, teams.
- Repository-level roles which gives organisation members, outside collaborators and teams of people varying levels of access to repositories.
- Team-level roles that give permissions to manage a team.
The recommendation here is to carefully guard and audit assignment of roles like Organisation owners. It is also prudent to be mindful of the base permission set, which affects all members of an organisation who access any of its repositories (except outside collaborators).
Securing the BUILD stage
The build stage is where the code is compiled into an executable or deployable artifact, and it is essential to ensure that the build process is secure. Implementing security in this phase involves adding automated security tools like Static application security testing (SAST) tools, software composition analysis (SCA) and unit testing. It is important to test the build output artifacts.
A key area of concern here is the heavy dependence on open-source libraries, indicating that development teams have transitioned from creating software to assembling it. Veracode’s “state of software security research” analysed the proportion of code included in software and found that 97% of Java applications consist of open-source libraries. The percentage of third-party code in .NET applications was around 60% whereas JavaScript and Python applications were found to contain about 50% of open-source libraries. This approach makes practical sense as it enables teams to provide value to customers more efficiently without duplicating efforts.
However, using someone else’s code can come with potential risks. By incorporating their code into your application, you’re essentially giving them access to your code repository. It’s important to consider whether you trust the author and contributors of the code you’re using, as well as whether the code could contain flaws or vulnerabilities that may impact your customers or users. This is especially true for transitive dependencies, which make up a significant portion of JavaScript dependencies (over 98% according to GitHub State of the Octoverse report 2021). Even if the code you’re using appears to be secure, the transitive dependencies it relies on could contain vulnerabilities that you’re not aware of.
GitHub Advanced Security includes features for supply chain security that enable you to scan software dependencies for potential vulnerabilities. Additionally, the GitHub Marketplace provides numerous actions that allow you to seamlessly integrate third-party security platforms, such as Prisma Cloud, into your GitHub workflows. This can help ensure that your code is protected and secure from potential threats.
Securing the DEPLOY stage
The deploy stage is where software that has been tested and approved (artifact) is sent to the production environment. This may happen without the need for manual intervention (automatically), and it makes it faster and more efficient to roll-out product changes. Implementing security in this phase involves making sure that the artifacts we are releasing and the environment we are releasing them to are verified, secure and compliant. This includes making sure that the artifacts are stored in a secure and trusted location and having processes in place to validate the integrity of the artifacts against tampering.
GitHub Packages provides a hosting service for storing and managing software packages. Packages are stored in a secure registry, and access is controlled by the user’s authentication and authorisation credentials.
Many companies also use infrastructure as code (IaC) to set up their environments prior to deploying new or updated artifacts. However, it’s crucial to ensure that these IaC templates adhere to security guidelines and compliance requirements, particularly with regards to encryption, logging, and secure access.
According to a study by the Unit42 team, several open-source deployment artifacts were analysed, and the results were concerning. Specifically, the study found that 64% of Terraform modules had at least one high or critical insecure configuration, 99% of Kubernetes Helm charts had misconfigurations, and 91% of container images had at least one critical or high severity vulnerability. These findings highlight the importance of thoroughly assessing and validating IaC templates to ensure that they are secure and compliant before deploying them. The extensibility of GitHub with marketplace extensions makes it easy to integrate open-source tools like Chekov for this use case.
Securing the RUNTIME stage
In the runtime stage, the focus is on running and maintaining deployed software in the production environment. Implementing security in this phase involves regularly applying security patches and updates to keep the software and runtime environment up to date; Monitoring for security vulnerabilities or breaches; Implementing security controls such as firewalls and intrusion detection systems; Implementing processes for regularly reviewing and analysing security logs to identify potential threats; Establishing processes for responding to and mitigating security incidents. Azure has an excellent security baseline documentation that I recommend looking into.