If you’re building open source software, you owe it to your community and the ecosystem to create software that is security-first. We might not have the word “security” in our job titles, but as developers we care a lot about security: We use SSH keys to connect to servers, we make sure that we don’t commit secrets to GitHub repositories, and we use Let’s Encrypt to secure our web apps. But good will alone isn’t enough to robustly secure each step of a software development life cycle that relies on dependencies and packages, and ships products to end users. Many opt to leave security as a last step rather than structuring security as part of initial requirements and builds.
Those of us who contribute to Project Sigstore are working to make security a part of the invisible infrastructure that developers everywhere can use in a frictionless way, so that we can work together to secure the supply chain more effectively.
You can think of Sigstore as a project that helps you determine where software artifacts are coming from so you can decide whether or not to trust and implement them. Free to use and fully open source, all of our Sigstore projects can be found under our GitHub organization. You can also join our large and growing community if open source security—maintained and developed by the open source community—interests you.
Today, there are three main projects that sit under Sigstore:
Cosign enables developers to identify themselves and validate that they’ve created a given software artifact through signing and verification
Fulcio is a free code signing Certificate Authority, letting anyone access short-lived certificates, essentially providing a notary to validate key pairs
Rekor is an immutable, tamper-resistant transparency log so that people can verify the provenance of software artifacts; you can think of it as a bulletin board where posts cannot be removed and others can inspect those posts for veracity
In order for Sigstore to help developers keep their code secure, we have to ensure that our own codebases are secure as well. We leverage tooling from the broader community in order to take a more holistic approach to security overall. One core part of our strategy is code scanning with tfsec and CodeQL, which we automate with GitHub Actions to make sure that every step of our own software development process is as secure as it can be.
CodeQL
Using GitHub Advanced Security’s CodeQL for code scanning has helped us discover issues in our code that we can then triage and prioritize. CodeQL provides us with alerts when security vulnerabilities are found, or the peace of mind that comes from green checkmarks, giving us the data we need to ensure that everything is fully optimized.
Using these tools, you can schedule scans for specific days and times, or trigger scans when a specific event occurs in the repository, such as a pushed commit or on testing a pull request, which helps prevent developers from introducing new problems.
In particular, we have used CodeQL in our Fulcio project in our codeql-analysis.yml under GitHub Actions. We’ve configured CodeQL to work on the main branch on both push and pull requests, and also have scheduled it with a cron job that runs every monday at 10:45 UTC. This enables us to run checks before merging pull requests on our main default branch, plus whenever code is merged into production, while the scheduled check scans any new updates at regular intervals. You can review how we set up scheduling our GitHub Action YAML file for CodeQL analysis below.
name: CodeQL
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '45 10 * * 1'
Because we’re working in the Go programming language, we have limited the scope of CodeQL to the language matrix variable for Go. With this parameter in place, we run CodeQL GitHub Actions to check out the repository, to initialize CodeQL, to autobuild, and to perform the CodeQL analysis.
We’ve pinned these Actions to use specific hashes instead of allowing a mutable version or range of versions in order to reduce a few security risks, including ensuring that both checking and deployment are done with the same software to simplify debugging, enable reproducibility, and help mitigate compromised dependencies from undermining the security of the project. You can view our use of Go for language matrix, and the way we’ve pinned our Actions below, or review the full most up-to-date file in the Fulcio repository.
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
steps:
- name: Checkout repository
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748 # v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@1ed1437484560351c5be56cf73a48a279d116b78 # v2.1.8
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@1ed1437484560351c5be56cf73a48a279d116b78 # v2.1.8
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@1ed1437484560351c5be56cf73a48a279d116b78 # v2.1.8
Towards a more secure DevOps pipeline with tfsec
“In a DevOps workflow, there are a lot of settings that can be modified—like little knobs to twist that can offer varying results,” explains my colleague Nathan Smith, a software engineer at Chainguard and one of our Sigstore contributors. This makes it hard for any individual to fully vet the combination of different settings to ensure the maximum level of security possible.
Enter tfsec, a static analysis security scanner to use with Terraform and other templating languages. Designed to run in a continuous integration pipeline, tfsec is developer-friendly with clear output and fully documented checks so that you can ensure any security issues it uncovers are detected before changes to your infrastructure are put in place.
Because we’re going towards a general availability Sigstore release, tfsec has proven to be an invaluable tool, allowing us to trust that our infrastructure and DevOps practices are being afforded the same security scrutiny as everything else we ship. tfsec empowers the developers who are writing infrastructure as code, providing real time feedback every time we make changes to config files. These frequent updates ensure that we’re aware of vulnerabilities and potential outcomes before we ship. We’ve also been able to make sure that all of our repositories are consistent and that there are no incongruities that we may have overlooked without tfsec to help us audit.
“As part of Sigstore, we have used tfsec together with GitHub Actions and GitHub code scanning in our open source repositories and are able to check warnings in our ‘Security’ tab in GitHub so that we can remediate them immediately,” Smith explains.
We created the sigstore/scaffolding repository to make standing up a full Sigstore stack less onerous on developers, while also making it easier to automate with a focus on running on Kubernetes. A high-level overview of the components include the Rekor transparency log, the Fulcio certificate authority, the Certificate Transparency Log (or CTLog) to audit TLS certificates, and the cryptographically verifiable data store Trillian with MySQL database.
We have tfsec as part of our GitHub Actions workflow in our terraform.yaml file on the .github/workflows path. Our implementation within the YAML file is as follows.
terraform-tfsec:
name: 'Terraform tfsec'
runs-on: ubuntu-latest
permissions:
# required for all workflows
security-events: write
# only required for workflows in private repositories
actions: read
contents: read
steps:
- name: 'Checkout'
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
- name: tfsec
uses: tfsec/tfsec-sarif-action@56bc584a8377626a31e511056772298ccfa69501 # v0.1.0
with:
sarif_file: tfsec.sarif
working_directory: '.'
tfsec_args: --force-all-dirs --verbose
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
# Path to SARIF file relative to the root of the repository
sarif_file: tfsec.sarif
This enables us to run code scans using tfsec within the repo, which can be triggered manually for testing purposes, but that also run continuously like other GitHub Actions. These scans are then logged by creating a file using the standard for sharing static analysis tooling results, SARIF (Static Analysis Results Interchange Format) file.
Securing the future for open source
Together, we can protect our software, engineering teams, and end users against nefarious attacks by considering security alongside our planning, development process, builds, and deployments. We must take care to verify the software we depend on and incorporate as packages or libraries into our own software projects, and to automate continuous checks as versions change, become deprecated, or when a known vulnerability arises.
With Sigstore, our overall goal is to support a more robustly secure software supply chain, which serves the open source and developer communities through increasing trust and making it harder for vulnerabilities to persist. If you’re interested in making your software more secure, you can leverage our Cosign project to sign your software, consult the SLSA framework to audit your software’s security, and use CodeQL and tfsec like we did to check for vulnerabilities and improve your code.
If you’d like to learn more about code scanning and how to implement CodeQL, you can review GitHub’s code scanning documentation, which will take you through the details on how to get up and running with CodeQL and how you may use it with existing continuous integration systems. To learn more about tfsec, you can review the project website, which gives further guidance on how to incorporate CodeQL with GitHub Actions.
Just like with open source more generally, in software security you are never alone, and can take stock of existing and emerging recommendations and tools to support your endeavors toward a more secure software supply chain. You owe it to yourself, to the community, and to the future.