This article is written by Himesh Panchal
Secret management in shared environments like Continuous Integration and Delivery services is challenging. It’s essential to keep secrets secure and ensure they don’t end up in the wrong place, like logs or code repositories.
Integrating solutions like 1Password into CI/CD workflows offer the advantage of centralising secret management, and it also allows you to encrypt every secret, providing controlled programmatic access to applications.
In this guide, we’ll explore how to make the most of 1Password Service Accounts within your CI/CD pipelines.
Creating a Service Account in 1Password
Service accounts provide a way to interact with 1Password without using individual user credentials, making it ideal for automated processes.
Log in to 1Password’s web interface.
Navigate to the
Integrationssection. Click on
Create New Service Accountand give it a name, e.g. codemagic.
- Select the vault(s) you want to grant access to for this service account.
After creating the service account, an authentication token will be auto-generated. Save the auth token to 1Password.
Copy the auth token. Here, we will use Codemagic CI/CD for demonstration purposes, but the same process should work with any CI/CD service.
Adding auth token to Codemagic
- Open your Codemagic app > Teams > settings >
codemagic.yamlsettings, and go to the Global variables and secrets tab.
- Enter the Variable name,
- Paste the token as a Variable value.
- Enter the variable group name, e.g. 1password. Click the button to create the group.
- Make sure the Secure option is selected.
- Click the Add button to add the variable.
- Now, we can use this token to retrieve secrets from the 1Password vault.
Configuring 1Password in codemagic.yaml
Installing 1Password CLI using Homebrew
name: Installing 1Password CLI script: brew install 1password-cli
Verifying the Authenticated User/Service Account in 1Password
name: Verifying the Authenticated User script: op user get --me
op user get --me This command fetches and displays details of the currently authenticated user or service account in the 1Password CLI. The –me flag gets the authenticated user’s details.
Reading secret references with op read
Fetch the login & API credentials
The command uses
curl to make a POST request to BrowserStack’s API to upload an iOS app IPA file for automated testing. It securely retrieves the username and auth token for BrowserStack from 1Password using the
op read command and then uses them for authentication in the request.
name: Upload artifact to Browserstack for Testing script: | curl -u "$(op read op://ci/browserstack/username):$(op read op://ci/browserstack/password)" \ -X POST "https://api-cloud.browserstack.com/app-live/upload" \ -F "file=@build/ios/ipa/your_app_release.ipa"
Fetch the document file contents
In this step, we’re fetching the
firebase document from a 1Password vault named
ci and storing it in
name: store firebase credentials script: op read -o ./firebase_creds.json op://ci/serviceAccount/firebase.json
op readRead a secret by secret references.
- o, –out-file string, Write the secret to a file instead of stdout.
<reference>reference of the secret path stored in the
Reading secret references with op run
You can map environment variables to specific secret references. By utilizing
op run, these secrets can be dynamically passed to applications or scripts when they’re executed.
op run command checks the environment variables for any references to secrets, fetches the relevant values from 1Password, and then initiates the specified command in a subprocess.
During this subprocess’s lifecycle, the secrets are accessible as environment variables, ensuring they’re available only when needed and safeguarded afterwards.
Consider the below example:
ci.env file, which has the 1Password
secret reference. You can check into source control and use the same environment everywhere.
keyStorePass="op://ci/keystore/password" keyAlias="op://ci/keystore/alias" keyPass="op://ci/keystore/keypass"
Code signing Android Application using gradle
In the below script op run command, combined with the –env-file="./ci.env" option,
- Loads Environment Variables: It reads the
ci.envfile and loads the environment variables specified within.
- Resolves Secret References: If any of the environment variables have values starting with
op runrecognizes them as references to secrets within 1Password. It fetches the actual secret values corresponding to those references.
- Runs the Command in a Subprocess: It then runs the specified command (in this case,
./gradlew bundleRelease) in a subprocess where the environment variables are set to the resolved secret values.
- Cleans Up: Once the subprocess finishes, the environment variables (with secrets) are cleaned up. They aren’t persisted or exposed beyond the lifecycle of the subprocess.
name: Sign Android App script: op run --env-file="./ci.env" -- ./gradlew bundleRelease
By dynamically providing these critical credentials, developers ensure the app’s integrity while keeping sensitive information away from static build configurations.
Incorporating 1Password into your CI/CD processes adds another layer of security, centralising and streamlining the management of secrets and credentials. By centralising and securely managing secrets, you reduce risks associated with manual secret management.