Cloud Code Signing Integration with CircleCI

Related Content

Want to keep learning?

Subscribe to SSL.com’s newsletter, stay informed and secure.

This tutorial shows how eSigner is integrated with CircleCI for automated code signing.

eSigner is SSL.com’s cloud environment for code signing. Signing keys and certificates are securely hosted in the cloud by SSL.com and can be accessed for signing from any internet-connected device, thus making eSigner one of the best platforms for enterprise code signing. The eSigner toolkit includes CodeSignTool which is a command-line utility for EV code signing certificates and is ideal for creating automated signing processes in various Continuous Integration/Continuous Delivery (CI/CD) platforms including CircleCI. 

SSL.com’s EV Code Signing certificates help protect your code from unauthorized tampering and compromise with the highest level of validation, and are available for as little as $249 per year. You can also use your EV Code Signing certificate at scale in the cloud using eSigner.

ORDER NOW

Environment Variables

  • USERNAME: SSL.com account username. (Required)
  • PASSWORD: SSL.com account password (Required)
  • CREDENTIAL_ID: Credential ID for signing certificate. If credential_id is omitted and the user has only one eSigner code signing certificate, CodeSignTool will default to that. If the user has more than one code signing certificate, this parameter is mandatory. (Required)
  • TOTP_SECRET: OAuth TOTP Secret. You can access detailed information on https://www.ssl.com/how-to/automate-esigner-ev-code-signing (Required)
  • ENVIRONMENT_NAME : ‘TEST’ or ‘PROD’ Environment. (Required)

Inputs

  • input_file_path: Path of code object to be signed. (Required)
  • output_dir_path: Directory where signed code object(s) will be written. If output_path is omitted, the file specified in -file_path will be overwritten with the signed file.

Prepare the components of the workflow (.NET Code DLL Signing)

  1. Create a .circleci folder

On your code signing workspace, create a .circleci folder. Under it, create a config.yml file.

  1. Set the CI version
version: 2.1
 
  1.  Invoke jobs via workflows. Workflows orchestrate a set of jobs to be run. The jobs for this pipeline are configured below

See: https://circleci.com/docs/2.0/configuration-reference/#workflows

workflows:
 
  1. Write the name of the workflow.
  dotnet:
 
  1. Inside the workflow, you define the jobs you want to run.
 jobs:

      - build

      - sign:

          requires:

            - build
 

Define the Build Stage

  1. Define a job to be invoked later in a workflow.

 (See: https://circleci.com/docs/2.0/configuration-reference/#jobs)

jobs:

  build:

 

  1. Create an environment variable
  • Environment variables are used to make the samples more readable. In the screenshot above of an example signing workflow, the PROJECT_NAME, PROJECT_VERSION, and DOTNET_VERSION were optionally omitted. Signing can still proceed even with these omissions.  
  environment:

        PROJECT_NAME: HelloWorld

        PROJECT_VERSION: 0.0.1

        DOTNET_VERSION: 3.1

        WORKSPACE: /home/circleci/project

 

  1.  Define a Docker executor: (https://circleci.com/docs/2.0/executor-types/)

    # You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI’s Developer Hub.

 docker:

      - image: mcr.microsoft.com/dotnet/sdk:3.1-bullseye

 

  1. Place the working directory for the job
  working_directory: /home/circleci/project

 

  1. Add steps to the job

    See: https://circleci.com/docs/2.0/configuration-reference/#steps

  steps:

 

  1.  Check out the source code so that the workflow can access it.
    - checkout

 

  1. Create Artifact Directory to store signed and unsigned artifact files
    - run:

          name: Create Artifacts Directory

          command: |

            mkdir -p ${WORKSPACE}/artifacts

            mkdir -p ${WORKSPACE}/packages

 

  1.  Build a dotnet project or solution and all of its dependencies.
      - run:

          name: Build Dotnet Project

          Command: dotnet build dotnet/${PROJECT_NAME}.csproj -c Release

 

  1. Copy artifact to artifacts directory
  • In this written signing example workflow, multiple project types were created. This is why files of different project types were kept by creating subfolders. A subfolder named ‘dotnet’ was created for Dotnet projects. In the demo screenshot above, there was no need to create a subfolder named ‘dotnet’ so this was not included in the script.
  - run:

          name: Copy Artifacts

          command: |

            cp dotnet/bin/Release/netcoreapp${DOTNET_VERSION}/${PROJECT_NAME}-${PROJECT_VERSION}.dll ${WORKSPACE}/packages/HelloWorld.dll

 

  1. Persist the artifact to the artifacts directory for signing
  - persist_to_workspace:

          root: .

          paths:

            - packages/*
 

Define the Signing Stage

  1. Define the signing job
 sign:

 

  1. Create an environment variable
  • In the screenshot above, the sign command was defined directly in the sign script and not under environment variables. Both methods can sign correctly with CircleCI.
  • Environment variables are used to make the samples more readable. In the screenshot above of the example workflow, some variables were optionally not included. Signing can still proceed even with these omissions.  
    environment:

          ENVIRONMENT_NAME: PROD

          COMMAND: sign

          WORKSPACE: /home/circleci/project

 

  1.     Place the working directory for the job on Circle-CI
 working_directory: /home/circleci/project

 

  1. Artifact name for signing
  • The ‘artifact-name’ value is an option for multiple projects The ‘artifact-name’ parameter was added so that the same signing part can be used for all project types. Since the example in the screenshot is based on a single project, it was not necessary to include it.
    parameters:

          artifact-name:

            type: string

            default: ''

 

  1. Define a docker executor:

 For additional reference, see: https://circleci.com/docs/2.0/executor-types/

       You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI’s Developer Hub.

       Be sure to update the Docker image tag below to openjdk version of your application.

       A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/openjdk

   docker:

        - image: cimg/openjdk:17.0.3

 

  1. Add steps to the job

      For additional reference, see: https://circleci.com/docs/2.0/configuration-reference/#steps

    steps:

 

  1. Create Artifact Directory to store signed and unsigned artifact files
  - run:

            name: Create Artifacts Directory

            command: |

              mkdir -p ${WORKSPACE}/artifacts

              mkdir -p ${WORKSPACE}/packages

 

  1. Attach to Workspace in order to access the artifact file
   - attach_workspace:

            at: /home/circleci/project

 

  1. Enable Docker for CodeSigner on Circle-CI
 - setup_remote_docker:

            name: Setup Remote Docker

            version: 19.03.13

            docker_layer_caching: true

 

  1. Pull Codesigner Docker Image From Github Registry
        - run:

            name: Docker Pull Image

            command: |

              docker pull ghcr.io/sslcom/codesigner:latest

              docker pull alpine:3.4

 

  1. Write the step where the artifact will be signed with CodeSignTool.
 - run:

            name: Sign Artifact File

            command: |

              docker create -v /codesign/packages  --name codesign-in  alpine:3.4 /bin/true

              docker create -v /codesign/artifacts --name codesign-out alpine:3.4 /bin/true

              docker cp ${WORKSPACE}/packages/<< parameters.artifact-name >> codesign-in:/codesign/packages

              docker run -i --rm --dns 8.8.8.8 --network host --volumes-from codesign-in --volumes-from codesign-out -e USERNAME=${USERNAME} -e PASSWORD=${PASSWORD} -e CREDENTIAL_ID=${CREDENTIAL_ID} -e TOTP_SECRET=${TOTP_SECRET} -e ENVIRONMENT_NAME=${ENVIRONMENT_NAME} ghcr.io/sslcom/codesigner:latest ${COMMAND} -input_file_path=/codesign/packages/<< parameters.artifact-name >> -output_dir_path=/codesign/artifacts

              docker cp codesign-out:/codesign/artifacts/<< parameters.artifact-name >> ${WORKSPACE}/artifacts/<< parameters.artifact-name >>

 

  1. Write the step for your artifact to be uploaded from your workflow allowing you to share data between jobs and store data once a workflow is complete
    - store_artifacts:

            name: Upload Signed Files

            path: /home/circleci/project/artifacts/<< parameters.artifact-name >>

            destination: << parameters.artifact-name >>
 

Create a new repository on the command line

Copy the push command components from the location of your project on  your GitHub account

Include all push command components on your editor

SSL.com’s EV Code Signing certificates help protect your code from unauthorized tampering and compromise with the highest level of validation, and are available for as little as $249 per year. You can also use your EV Code Signing certificate at scale in the cloud using eSigner.

ORDER NOW

Set up a project on CircleCI using the repository that is integrated to GitHub

Define all the Environment Variables

While the project is running, Click the Project Settings button followed by Environment Variables to define the variables

Place the values for each variable

Click the Add Environment Variable button to add the names and values of all variables required for the project.

Wait for the project to be built

Click Persisting to workspace

Briefly wait for the workspace archive to be uploaded successfully.

Click the sign button

Wait for the Remote Docker to be set up

It might take more than a minute, depending on the size of the file

Wait for the artifacts to be signed

Click Artifacts tab

If you click Artifacts, you will be able to see the file that you have successfully code signed. You will also be notified by CircleCI of the successful code signing.

You can refer to the SSL.com Github repository which contains the source codes of the docker image and describes how to use it: https://github.com/SSLcom/ci-images

Sample CircleCI Pipeline

Check out the sample CircleCI pipeline we have created on github.com/SSLcom/codesigner-circleci-sample

Other CI/CD Remote Signing Integration Guides

Need Custom Solutions? 

With our expert knowledge and five-star support staff, we’re ready and willing to work with you on custom solutions or enterprise-level high-volume signing discounts. Fill out the form below and we’ll be in touch.

Stay Informed and Secure

SSL.com is a global leader in cybersecurity, PKI and digital certificates. Sign up to receive the latest industry news, tips, and product announcements from SSL.com.

We’d love your feedback

Take our survey and let us know your thoughts on your recent purchase.