Leverage Turing Intelligence capabilities to integrate AI into your operations, enhance automation, and optimize cloud migration for scalable impact.
Advance foundation model research and improve LLM reasoning, coding, and multimodal capabilities with Turing AGI Advancement.
Access a global network of elite AI professionals through Turing Jobs—vetted experts ready to accelerate your AI initiatives.
The NIST glossary defines security as “a condition that results from the establishment and maintenance of protective measures that enable an organization to perform its mission or critical functions despite risks posed by threats to its use of systems. Protective measures may involve a combination of deterrence, avoidance, prevention, recovery, and correction that should form part of the organization’s risk management approach.”
In this post, we’ll learn about the importance of security in the CI/CD pipeline as well as CI/CD security best practices and how to implement them.
Imagine there are multiple developers who make code changes every day. These changes need to be integrated yet not introduce errors. They need to be tested before being deployed. What can be done? The test is automated and then deployed to the development/staging environment before it goes to production. This automation is triggered with every revision. The process is called continuous integration (CI).
After the integration and testing are complete, the application needs to be deployed automatically and continuously to production. This is called continuous deployment. Alongside this is continuous delivery, wherein the application is delivered continuously to production but requires approval before deployment. Once approved, the process continues to trigger scripts or methods to deploy the application.
Example of CI/CD pipeline
The CI/CD pipeline or workflow may be different for each organization. It depends on the programming language used, the organization’s policy, CI/CD security tools, the deployment target, the application type, etc.
Here’s an example of a workflow.
You can see that there are some activities in the CI, such as Plan, Code, Build, and Test. Let’s explore them in brief.
If the test is passed, the code is released and deployed. You can add the approval process before the deployment process as mentioned before, i.e., continuous delivery.
The next stage is monitoring. Some of the tools used are Grafana, Prometheus, Jaeger, AWS CloudWatch, and Datadog. The feedback from the monitoring process is valuable for the next planning process. Think of it as a loop.
Security can be incorporated in the build or test step. You can add security checking in the pull request actions to avoid security problems before merging the changes from the request.
You can add static code analysis, which is a process that will analyze code and check for vulnerabilities. There are many other security practices that you can add to your workflow, such as dynamic program analysis, penetration testing, etc.
Below are a few general CI/CD security best practices. They aren’t specific to a platform.
A mistake that some people make is to use hard-coded or plain text credentials in the CI/CD pipeline. Use encrypted credentials instead. You can use a secret manager to handle multiple secrets which are reused at many CI/CD pipelines. Credentials can include, but are not limited to, passwords, secrets tokens, and API keys.
If you create new keys or update new passwords, you will need to update multiple CI/CD pipelines. A secret manager can be used to rotate credentials. You’ll only need to update the secrets in the same.
You should validate each input in the CI/CD pipeline. For example, you have a pipeline that allows a user to trigger it with an input to define the version you want to deploy. You have a script to publish by that version, but do not validate it and use the value as it is.
When you don’t validate the input, attackers or hackers can use it to inject scripts (script injection). They may do this to find out credentials, download malware, and so on. Hence, it’s crucial to validate inputs to make sure they are expected.
Consider using OpenID as an authentication option in your CI/CD pipeline as it reduces the need to store credentials or secrets. You should also use it when connecting to cloud services like AWS, Azure, and GCP.
Having a sound understanding of basic cyber security is a plus so that you can implement the best practices in your CI/CD pipeline. If possible, learn more about DevOps (development and operations) and DevSecOps (development, security, and operations).
To sum up some of the important CI/CD security best practices, ensure you don’t expose your credentials, use a secret manager whenever possible, and use OpenID as an authentication method when connecting to cloud services. Implementing the principle of least privilege is an additional step you can take.
The Continuous Delivery Foundation (CDF) provides best practices for CI/CD. For CI, these are:
This reference contains CDF's best practices.
It’s important to conduct unit testing in CI to reduce the chance of delivering defective software. Unit testing validates each unit of the code to ensure it performs as expected.
You can check here for the published config pull request, and here for the sample running job. You can also check here for the published package.
Sample:
Let’s implement a security practice to have source code analysis in our previous workflow.
name: "CodeQL"on: push: branches: [ "main" ] pull_request:
The branches below must be a subset of the branches above
branches: [ "main" ] schedule:
jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'csharp' ]
steps:
name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }}
name: Autobuild uses: github/codeql-action/autobuild@v2
name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: category: "/language:${{matrix.language}}"
Here are some best practices for CD provided by CDF:
Security practices can be implemented after delivering the packages. For example, if you use Docker and push docker image, you can scan it to check the binaries that are delivered to it. There are various tools for scanning the docker image, such as Snyk and Trivy. Docker registry also provides scan options that help to check the image and find vulnerabilities.
It’s important to avoid unnecessary content in software packages or docker images. Choose the appropriate image when delivering the docker image. Secure the docker registry with a private docker registry as well.
Risk-based security is an important aspect of a CI/CD pipeline as it reduces the chance of data breaches and security vulnerabilities. Avoiding plain text credentials, implementing credential rotation, validating inputs, having source code analysis, and omitting unnecessary files in packages are some of the measures to take.
Bervianto Leo Pratama is a software engineer and technical writer who loves to learn every day. He actively writes technical blogs. His blog is about Microservices, DevOps, and Developer Tools.