Securely Signing Software

Travis CI enables software developers to securely sign software artifacts as a part of a build job using a cosign tool and a key.

Cosign is a part of the Sigstore project, which helps to ensure the tooling required for the Secure Software Supply Chain.

You will be able to sign container images or any other artifacts (blobs) which are part of your software releases. Securely signing your software confirms its origin and is a recommended practice in a Secure Software Supply Chain.

Prerequisites #

Before getting started, make sure you have:

  • A key available within a Travis CI build job.
  • Cosign pre-installed in the Linux build environments (this is maintained by Travis CI).

Option 1: Upload Key directly to Travis CI #

A passwordless private PEM key can be generated by the account holder or organization admin and uploaded to Travis CI. Upload the Key to a personal account or an Organizational account(e.g.: https://app.travis-ci.com/organizations/[org_name]/preferences). The key name can contain only alphanumeric characters and the underscore character (_). Make sure to note down the name of the key. The key name must be unique within the scope of personal account or organization.

The key provided will be available for all builds run under this account (either personal or organizational). Please pay attention to individual Repository Settings, particularly the Security Settings -> Share SSH key with forks setting. If enabled, the signing key may be also made available when a forked repository files a Pull Request against the original (base repository).

Option 2: Key from a Key Management System #

You can also obtain a signing key by configuring the Hashicorp Vault access in Travis CI and getting a signing key from it.

Usage #

You will be using open source tool called cosign to securely sign the software. Cosign is a part of Sigstore project and the tool has a good documentation site. Please familiarize yourself with how the tool works before using it.

Please note: To protect private repositories from accidental revealing via, e.g., Rekor registry or any other public registry, we are not allowing keyless (using ephemeral keys) signing using cosign in build jobs run for private repositories. Should you attempt to do so, an error message states that experimental features are not allowed for private repositories.

Using a key stored in Travis CI #

Once the key is configured, you may modify your .travis.yml to include a securely signing code step in one of the build jobs. The below example illustrates a signing sample container image, which can be your release image.

keys:
  - SSH_KEY_FOR_SIGNING # must match the key identifier set in the UI

env:
  secret: “...” # encrypted COSIGN_PASSWORD=...  string; see cosign doc

before_script: 
  - travis_key SSH_KEY_FOR_SIGNING cosign.key  # cosign requires the key to be in a file

script: 
  - cosign sign --key cosign.key [whatever_the_image_identifier_is]

Please mind, that new keys tag and at least one uploaded key identifier are required, if you want to use the key within a build job (or whole build, depending on how you structure the build definition in .travis.yml). If the key identifier is not provided or doesn’t match any of the uploaded keys, no key will become available during the build job or build runtime.

Using a key stored in Hashicorp Vault and obtained to Travis CI build job #

Cosign relies on the following standard Hashicorp Vault environment variables being set within the build job environment:

  • VAULT_ADDR
  • VAULT_TOKEN
  • TRANSIT_SECRET_ENGINE_PATH (Optional)

The default assumption is that your Hashicorp Vault has the transit engine enabled. This is a configuration of Vault, for which the user is responsible.

To perform a secure signing using keys stored in the external Hashicorp Vault Key Management Service (KMS), start with the below example, filling in the required connection details:

vault:
  api_url: [single value endpoint address:port] #mandatory
  token:
    secure: “...” #mandatory
    # This will make the default VAULT_ADDR and VAULT_TOKEN available for cosign.

script:
  - cosign sign --key hashivault://some-key-identifier [whatever_the_image_identifier_is]

Whenever in doubt, please consult the Cosign KMS Support documentation page

Security considerations #

As much as the feature is meant to help you prove the source of the file or image via signature, please at all times consider following aspects of ensuring security of the key used for signing the files or images during the CI/CD process.

The key used for signing uploaded to Travis CI under a personal account or organization account can be used under every repository owned by this entity (assuming proper tag and key identifier are present in the respective repository .travis.yml). The key downloaded from Hashicorp Vault to a specific build job or build can be used, respectively, within a specific build job or every build job of a build.

Therefore please carefully review repository settings in Travis CI for repositories belonging to the account and assess the risk of the key used for signing being exposed, e.g. via malicious pull request from a fork or accidental debug message. We’d recommend paying attention whether the repository is public (which makes the job logs public by default), if the pull requests from forks are allowed, are the repository SSH keys shared and who may access the job logs. Please mind that job logs, especially public, can be used to expose the secret via a malicious or accidental debug message in the pull request or commit that triggers a build in Travis CI.

We recommend considering following security measures:

  • using separate key just for purpose of file/image signing
  • using private repository to trigger builds, during which the files are signed, if possible
  • reviewing who has push/write access to such repository
  • reviewing Repository Settings, particularly the Security Settings -> Share SSH key with forks setting
  • excluding a build, which signs the release to a separate account/organization (if possible and viable) with limited list of collaborators
  • limiting access to repository job logs in individual repository settings
  • if using Hashicorp Vault KMS as a source of the key used for signing: always encrypt secrets needed to connect to Vault in the respective Repository Settings or the .travis.yml file

Travis CI will attempt to obfuscate secrets in the job logs, yet since there are many ways to print them in the output there’s no guarantee all vulnerable data will be spotted and masked. Since Travis is a cloud CI/CD system, please be wary of associated risks and ways to minimize these. Please read also Best Practices in Securing Your Data.