1.0 Introduction
This article explains how to integrate Fortanix-Data-Security-Manager (DSM) with GitHub Actions to securely retrieve secrets during a build pipeline.
It also explains how to:
Authenticate GitHub Actions workflows with Fortanix DSM.
Retrieve secrets securely during pipeline execution.
Use those secrets in build steps (for example, code signing).
2.0 Prerequisites
Ensure the following:
Access to a Fortanix DSM account with appropriate administrative privileges.
Knowledge of how to create and manage security objects (secrets) in Fortanix DSM, including generating or importing secrets.
A GitHub repository with permission to manage:
Repository Secrets
Repository Variables
GitHub Actions workflows
Basic understanding of GitHub Actions workflows and YAML configuration
3.0 Configure Fortanix DSM
This section describes the steps to configure Fortanix DSM to generate and import a security object.
3.1 Signing Up
To get started with the Fortanix DSM cloud service, you must register an account at <Your_DSM_Service_URL>. For example, https://eu.smartkey.io.
On-premises customers use the KMS URL, and the SaaS customers can use the URLs as listed here based on the application region.
For detailed steps on how to set up the Fortanix DSM, refer to the User's Guide: Sign Up for Fortanix Data Security Manager SaaS.
3.2 Logging In
Access <Your_DSM_Service_URL> in a web browser and enter your credentials to log in to Fortanix DSM.

Figure 1: Logging In
For more information on how to set up an account in Fortanix DSM, refer to the User's Guide: Getting Started with Fortanix Data Security Manager - UI.
3.3 Creating a Group
Perform the following steps to create a group in the Fortanix DSM:
In the DSM left navigation panel, click the Groups menu item, and then click ADD GROUP to create a new group.

Figure 2: Add Groups
On the Adding new group page, do the following:
Title: Enter a name for your group.
Description (optional): Enter a short description of the group.
Click SAVE to create the new group.
The new group is added to Fortanix DSM successfully.
3.4 Creating an Application
Perform the following steps to create an application (app) in the Fortanix DSM:
In the DSM left navigation panel, click the Apps menu item, and then click ADD APP to create a new app.

Figure 3: Add Application
On the Adding new app page, do the following:
App name: Enter the name for your application.
ADD DESCRIPTION (optional): Enter a short description of the application.
Authentication method: Select API Key or Certificate as the authentication method, depending on your security and automation requirements, from the dropdown menu. For more information on these authentication methods, refer to the User's Guide: Authentication.
Assigning the new app to groups: Select the group created in Section 3.3: Creating a Group from the list.
Click SAVE to add the new application.
The new application is added to Fortanix DSM successfully.
3.5 Copying the API Key
Perform the following steps to copy the API key from the Fortanix DSM:
In the DSM left navigation panel, click the Apps menu item, and then click the app created in Section 3.4: Creating an Application to go to the detailed view of the app
On the INFO tab, click VIEW API KEY DETAILS.
From the API Key Details dialog box, copy the API Key of the app to use it later.
3.6 Creating a Security Object
Perform the following steps to generate a Secret security object in Fortanix DSM:
In the DSM left navigation panel, click the Security Objects menu item, and then click ADD SECURITY OBJECT to create a new security object.

Figure 4: Add Security Object
On the Add new Security Object page, do the following:
Security Object name: Enter the name of your security object. For example, Github_secret.
Group: Select the group as created in Section 3.3: Creating a Group.
Select the IMPORT radio button.
In the Choose a type section, select the Secret key type.
In the Place value here or import from file section, select the value format type as Hex, Base64, or Raw, and click UPLOAD A FILE to upload the key file.
In the Key operations permitted section, select the required operations to define the actions that can be performed with the cryptographic keys, such as encryption, decryption, signing, and verifying.
NOTE
Ensure that the Export permission is selected.
Click IMPORT to generate the security object.
Open the newly created Security Object and copy the Security Object ID. This ID is the
KIDand will be used in the GitHub Actions workflow to retrieve the secret value.
4.0 Integration Steps
Perform the following steps:
Navigate to GitHub and select the repository where you want to set up the integration.
Navigate to Settings → Secrets and variables → Actions → Secrets.
Click New repository secret and add the required secrets based on your authentication method:
API Key-based Authentication:
API_KEY: The Fortanix DSM Application API Key obtained in Section 3.5: Copying the API Key, used for API Key-based authentication.
Certificate-based Authentication:
DSM_CERT: The Base64-encoded client certificate (public certificate) used for Certificate-based authentication with Fortanix DSM. This certificate must correspond to the DSM Application configured for certificate authentication.DSM_KEY: The Base64-encoded private key associated with the client certificate (DSM_CERT). This private key is used during mutual TLS (mTLS) authentication when GitHub Actions connects to Fortanix DSM.

Figure 5: Add repository secrets
Navigate to Settings → Secrets and variables → Actions → Variables.
Click New repository variable to add the following variables:
DSM_FQDN: The Fortanix DSM endpoint. For example, eu.smartkey.io.KID: Fortanix DSM Secret Key ID obtained in Section 3.6: Creating a Security object when the secret is imported into Fortanix DSM.

Figure 6: Add variables
Create a new workflow file (for example,
fetch-secret.yml) in your repository at the following path:.github/workflows/fetch-secret.yml.Edit the
fetch-secret.ymlfile as follows to configure the integration as a manually triggered workflow usingworkflow_dispatch.API Key-based Authentication
name: Fetch Secret from DSM on: workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Fetch Secret from DSM id: kms run: | RESPONSE=$(curl -s -X POST https://${{ vars.DSM_FQDN }}/crypto/v1/keys/export \ -H "Authorization: Basic ${{ secrets.API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"kid":"${{ vars.KID }}"}') SECRET=$(echo "$RESPONSE" | jq -r '.value') if [ -z "$SECRET" ] || [ "$SECRET" = "null" ]; then echo "KMS did not return a secret value" exit 1 fi DECODED=$(echo "$SECRET" | base64 -d) echo "::add-mask::$SECRET" echo "MY_SECRET=$DECODED" >> $GITHUB_ENV - name: Use Secret run: echo "Secret retrieved successfully"Certificate-based Authentication
name: Fetch Secret from DSM on: workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Get certificates run: | set -euo pipefail echo "${{ secrets.DSM_CERT }}" | base64 -d > client.crt echo "${{ secrets.DSM_KEY }}" | base64 -d > client.key chmod 600 client.key - name: Fetch Secret from DSM id: kms run: | RESPONSE=$(curl -s -X POST https://${{ vars.DSM_FQDN }}/crypto/v1/keys/export \ --cert client.crt \ --key client.key \ -H "Content-Type: application/json" \ -d '{"kid":"${{ vars.KID }}"}') SECRET=$(echo "$RESPONSE" | jq -r '.value') if [ -z "$SECRET" ] || [ "$SECRET" = "null" ]; then echo "KMS did not return a secret value" exit 1 fi DECODED=$(echo "$SECRET" | base64 -d) echo "::add-mask::$SECRET" echo "MY_SECRET=$DECODED" >> $GITHUB_ENV - name: Use Secret run: echo "Secret retrieved successfully"
NOTE
If you want to run the workflow automatically, you must replace the
workflow_dispatchunder theon:section with the appropriate trigger (for example,push,pull_request, orschedule).For detailed steps on how to configure the trigger, refer to Triggering a workflow.
After editing the file, run the workflow.

Figure 7: Run the workflow
Verify that the workflow completes successfully by navigating to the Actions tab in your GitHub repository and confirming that the job (For example, Fetch Secret from External KMS) runs without errors and retrieves the secret successfully.

Figure 8: Verify the integration
5.0 Appendix
5.1 Optional: Generate and Import a Secret Using the DSM Plugin
This section describes how to use a Fortanix DSM plugin to generate a random secret and optionally import it as a SECRET security object.
NOTE
The GitHub Actions workflow does not invoke this plugin. This plugin is only used to generate and optionally store a secret in Fortanix DSM before integration.
Perform the following steps to generate a plugin in Fortanix DSM to generate and store a secret in Fortanix DSM:
Add the following plugin code while generating a new plugin in Fortanix DSM:
For more information, refer to the User’s Guide: Plugin Library.
numericAlphabet = "0123456789" alphanumericAlphabet = numericAlphabet .. "abcdefghijklmnopqrstuvwxyz" alphanumericCapsAlphabet = alphanumericAlphabet .. "ABCDEFGHIJKLMNOPQRSTUVWXYZ" alphanumericCapsSymbolsAlphabets = alphanumericCapsAlphabet .. "!@#$&*_%=" function genPass(alphabet, len, name, import) local alphabetSize = #alphabet local password = '' for i = 1, len, 1 do local random_char = math.random(alphabetSize) password = password .. string.sub(alphabet, random_char, random_char) end local pass = Blob.from_bytes(password) if import == "yes" then local sobject = assert(Sobject.import { name = name, obj_type = "SECRET", value = pass, key_ops = {'APPMANAGEABLE', 'EXPORT'} }) -- Return both password and KID return { password = password, kid = sobject.id } end -- If not importing, return only generated password return { password = password } end function run(input) if input.type == "numeric" then return genPass(numericAlphabet, input.length, input.name, input.import) end if input.type == "alphanumeric" then return genPass(alphanumericAlphabet, input.length, input.name, input.import) end if input.type == "alphanumeric_caps" then return genPass(alphanumericCapsAlphabet, input.length, input.name, input.import) end if input.type == "alphanumeric_caps_symbols" then return genPass(alphanumericCapsSymbolsAlphabets, input.length, input.name, input.import) end end
Set the import option to yes if you want to store the secret in Fortanix DSM.
{ "type": "numeric", "length": 64, "name": "GitHub-Secret", "import": "yes" }Output:
{ "password": " 839274938274...", "kid": "b3f1c2a4-xxxx-xxxx-xxxx-xxxxxxxx" }
Set the import option to no if you only want a new value generated for rotation.
{ "type": "numeric", "length": 64, "name": "GitHub-Secret", "import": "no" }Output:
{ "password": " 839274938274..." }