Signing Software Artifacts with Cosign
In today’s world, where technology has become ubiquitous, we rely heavily on software applications to perform various tasks in our daily lives. These applications are built by a vast number of developers and companies, each contributing their own code and libraries.
However, this collaborative effort can also be a double-edged sword. While it enables us to create powerful software quickly, it also increases the risk of malicious actors inserting vulnerabilities or malware into the codebase. These security threats can lead to software supply chain attacks, which can have disastrous consequences for both individuals and organizations. To prevent such attacks, it is essential to securely sign software artifacts such as release files, container images, binaries, bill of material manifests, and more. In this blog post, I will explore the importance of securely signing software artifacts and how it can help protect against supply chain attacks.
Cosign is an open-source tool developed by the Sigstore project that provides a simple and secure way to sign software artifacts. With Cosign, developers can easily sign and verify their software artifacts, such as release files, container images, binaries, and bill of material manifests. By signing these artifacts, developers can help prevent software supply chain attacks and ensure the integrity and authenticity of their software. Cosign provides an easy-to-use command-line interface and integrates with popular container image registries, making it a powerful tool for any developer looking to secure their software supply chain.
The Importance of Signing Software Artifacts
In recent years, software supply chain attacks have become a growing concern for both consumers and software developers. Malicious actors often target the software development process itself, attempting to inject vulnerabilities or malware into the code before it is distributed to the end user. This can happen at any point in the development and distribution process, from open-source repositories to the final product release. As a result, it’s becoming increasingly important for developers to implement security measures that can prevent these types of attacks.
In the past, there have been several high-profile supply chain attacks that have caused significant damage. One such example is the SolarWinds attack, which was discovered in late 2020. In this case, hackers were able to compromise SolarWinds’ software development process, injecting malicious code into their Orion software updates. This allowed them to gain access to a variety of high-profile targets, including multiple US government agencies. Another recent example is the Codecov attack, which took place in April 2021. In this case, attackers were able to compromise the software development pipeline of Codecov, a popular software auditing tool. This allowed them to gain access to sensitive data from thousands of companies that used the tool, potentially exposing them to further attacks. These attacks highlight the need for secure software development practices.
By using Cosign from Sigstore to sign artifacts, you can prevent similar attacks that rely on compromised or malicious software. Cosign provides a tamper-proof record of your artifact’s authenticity and integrity, making it more difficult for attackers to compromise your software supply chain. Additionally, Cosign helps build trust and confidence in the security of the software being used, which is especially important in industries such as healthcare, finance, and government, where security is of utmost importance.
The Benefits of Using Cosign
Using Cosign to secure your software supply chain offers several benefits, including:
Enhanced security: Cosign provides a tamper-proof record of your software artifact’s authenticity and integrity, making it more difficult for attackers to compromise them.
Improved trust: By using Cosign to sign and verify your artifacts, you can build greater trust with your customers and partners, who will have greater confidence in the security of the software you provide.
Simplified compliance: One of the key benefits of using Cosign is that it can help organizations meet the Secure Software Development Lifecycle (SSDL) requirements for compliance, particularly the Supply Chain Levels for Software Artifacts (SLSA) framework. SLSA is an industry-led framework that provides guidelines for ensuring the security and integrity of software supply chains. By using Cosign to sign software artifacts, organizations can establish a secure and verifiable chain of trust, which is a key component of the SLSA compliance framework. Cosign provides a simple and easy-to-use solution for implementing secure signing workflows that can help organizations meet these compliance requirements.
Keyless Signing with Cosign
One of the critical features of Cosign is its ability to perform keyless signing, which eliminates the need for a key pair in order to sign artifacts. Keyless signing is a significant improvement over traditional signing methods because it provides enhanced security and protection against key theft or compromise.
Traditionally, signing software artifacts requires the use of a private key, which must be securely stored and managed to prevent unauthorized access. However, this can be a challenging task for organizations, particularly when managing large numbers of container images or distributing software across multiple environments.
Keyless signing simplifies the signing process by removing the need to manage and protect private keys. Instead, Cosign uses ephemeral keys and certificates, which are automatically signed by the Fulcio certificate authority. Signatures are stored in the Rekor transparency log, which provides a tamper-resistant ledger of all signed artifacts. This approach provides a secure and transparent way to sign container images without the need for a private key.
Using keyless signing with Cosign simplifies the signing process and enhances security by eliminating the risk of key theft or compromise. Additionally, using a publicly-trusted certificate authority like Fulcio helps build trust and confidence in the authenticity and integrity of signed container images. Overall, keyless signing is a powerful feature that can help organizations improve the security and reliability of their software supply chain.
Using Cosign
You’ll need to install Cosign first, and you will need access to a container registry for Cosign to work with. ttl.sh offers free, short-lived (ie: hours), anonymous container image hosting if you just want to try these commands out.
To install Cosign on macOS using Homebrew first, make sure that Homebrew is installed on your system. If it is not installed, you can follow the installation instructions provided on the Homebrew website. Once you have Homebrew installed, open a terminal window and run the following command to install the Cosign CLI:
$ brew install cosign
This command will download and install the latest version of Cosign. Once the installation is complete, you can verify that Cosign is installed correctly by running the following command:
$ cosign version
______ ______ _______. __ _______ .__ __.
/ | / __ \ / || | / _____|| \ | |
| ,----'| | | | | (----`| | | | __ | \| |
| | | | | | \ \ | | | | |_ | | . ` |
| `----.| `--' | .----) | | | | |__| | | |\ |
\______| \______/ |_______/ |__| \______| |__| \__|
cosign: A tool for Container Signing, Verification and Storage in an OCI registry.
GitVersion: 2.0.1
GitCommit: 8faaee4d2b5f65678eb0831a8a3d5990a0271d3a
GitTreeState: "clean"
BuildDate: 2023-04-06T19:10:33Z
GoVersion: go1.20.3
Compiler: gc
Platform: darwin/arm64
Next, you will need to generate a key pair to sign the container image with Cosign. To do so run the following command:
$ cosign generate-key-pair
Enter password for private key:
Enter password for private key again:
Private key written to cosign.key
Public key written to cosign.pub
Now sign the container and store the signature in the registry along with the container image. To do so run the following command in the CLI replacing the “mlunato47/cosign-demo:signed-local” with the name of your image and Docker repo:
$ docker push mlunato47/cosign-demo:signed-local
The push refers to repository [docker.io/mlunato47/cosign-demo]
26cbea5cba74: Mounted from library/alpine
signed-local: digest: sha256:cafe8aee8c4ca63149ab4dc32af1c76192e0872583a800cce2dbbb3f35990bb0 size: 527
$ cosign sign --key cosign.key mlunato47/cosign-demo:signed-local
Enter password for private key:
Pushing signature to: index.docker.io/mlunato47/cosign-demo
Now that the image has been signed and pushed to the registry, we can verify the signature using the public key from the key pair we generated earlier. To do so run the following command:
$ cosign verify --key cosign.pub mlunato47/cosign-demo:signed-local
Verification for index.docker.io/mlunato47/cosign-demo:signed-local --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The signatures were verified against the specified public key
Running Cosign locally and signing a container image was a straightforward process. After installing Cosign using Brew and running a few simple commands, the image was signed and stored in the registry with ease. With the added security of a verifiable signature, software supply chain attacks can be mitigated and trust can be established between teams, organizations, and end users. Now, armed with Cosign, you can sign your container images and other software artifacts with confidence and rest easy knowing your software supply chain is secure.
This demo for local signing with the generated key pair is shown as an example of how to sign images if you do not have an Amazon Web Services (AWS) account for access to Key Management Service (KMS). This SHOULD NOT be used for any type of production deployment and proper key management protections should be put in place.
Signing Container Images with AWS KMS and Cosign
If you’re using AWS, you can leverage AWS KMS to store and manage your keys, including the ones you use to sign your container images with Cosign. With this method, you don’t have to worry about managing keys or storing them securely yourself.
To sign a container image with an AWS KMS managed key, you first need to create a KMS key and set the necessary permissions. You’ll also need to ensure that you have the AWS command-line interface (CLI) tool installed and properly configured. This can also be done via the AWS UI or using Infrastructure as Code (IAC) tools such as Terraform to generate the KMS key.
$ aws kms create-key --key-usage SIGN_VERIFY --customer-master-key-spec RSA_4096 --description "KMS key for signing images with Cosign"
{
"KeyMetadata": {
"AWSAccountId": "123456789012",
"KeyId": "f5a95d9b-0a2f-4d5a-bc3e-01e16648a8a4",
"Arn": "arn:aws:kms:us-east-1:123456789012:key/f5a95d9b-0a2f-4d5a-bc3e-01e16648a8a4",
"CreationDate": "2023-04-18T18:13:00.684000-04:00",
"Enabled": true,
"Description": "KMS key for signing images with Cosign",
"KeyUsage": "SIGN_VERIFY",
"KeyState": "Enabled",
"Origin": "AWS_KMS",
"KeyManager": "CUSTOMER",
"CustomerMasterKeySpec": "RSA_4096",
"KeySpec": "RSA_4096",
"SigningAlgorithms": [
"RSASSA_PKCS1_V1_5_SHA_256",
"RSASSA_PKCS1_V1_5_SHA_384",
"RSASSA_PKCS1_V1_5_SHA_512",
"RSASSA_PSS_SHA_256",
"RSASSA_PSS_SHA_384",
"RSASSA_PSS_SHA_512"
],
"MultiRegion": false
}
}
$ aws kms create-alias \
--alias-name alias/cosign-key \
--target-key-id f5a95d9b-0a2f-4d5a-bc3e-01e16648a8a4
{
"AliasArn": "arn:aws:kms:us-west-2:123456789012:alias/cosign-key",
"AliasName": "alias/cosign-key",
"TargetKeyId": "f5a95d9b-0a2f-4d5a-bc3e-01e16648a8a4"
}
Once you have your KMS key set up, you can use Cosign to sign your container images. First, we will need to export the public key to be able to verify the signature of the image. The public key can be exported via the AWS CLI with the following command:
$ aws kms get-public-key \
--key-id alias/cosign-key \
--output text \
--query 'PublicKey' | base64 --decode > cosignkms.pub
Signing an image is similar to when using a local key but requires active credentials to AWS.
$ docker push mlunato47/cosign-demo:signed-kms
The push refers to repository [docker.io/mlunato47/cosign-demo]
943d74a92286: Pushed
signed-kms: digest: sha256:32b7371d10947b09944c6ce92634889118c406aec51c307b4a025aadfdecd1b18 size: 527
$ cosign sign --key aws-kms://alias/cosign-key mlunato47/cosign-demo:signed-kms
Pushing signature to: index.docker.io/mlunato47/cosign-demo
Using AWS KMS to generate and store keys for signing container images with Cosign provides a secure way to manage your own keys while still enhancing the security and integrity of your software supply chain.
We can now use the public key that we exported earlier to verify the signature of the container image. To do so, run the following command to verify the signature:
$ cosign verify --key cosignkms.pub mlunato47/cosign-demo:signed-kms
Verification for index.docker.io/mlunato47/cosign-demo:signed-kms --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
Conclusion
In conclusion, software supply chain attacks have become a growing concern in recent years, and it is crucial to secure the process of building and distributing software artifacts. One of the key ways to accomplish this is by digitally signing these artifacts. By doing so, developers can ensure that the integrity of their software has not been compromised and that it has not been tampered with in transit.
In this blog, we used Cosign, an open-source tool from Sigstore, to demonstrate how easy it is to sign container images with local or AWS KMS-generated key pairs. Cosign not only provides a simple way to sign artifacts, but it also offers relief when it comes to a secure way to store and manage keys when using the keyless signing option. Additionally, by using Cosign, developers can achieve compliance with the SLSA levels of security.
Overall, the process of signing software artifacts can be simple yet powerful, as it can prevent potential supply chain attacks and increase the trustworthiness of software. As more companies and organizations begin to recognize the importance of software security and supply chain integrity, we will likely see an increase in the adoption of digital signing tools like Cosign.