Secrets are managed by Drone by injecting them as environment variables into your build container.
Here’s how Drone handles secrets, and how you can leverage it for secure CI/CD.
The Problem: Hardcoding Secrets
The most basic way to use a secret in a CI pipeline is to hardcode it directly into your .drone.yml file.
kind: pipeline
type: docker
name: default
steps:
- name: deploy
image: plugins/drone-cli
settings:
token:
from_secret: github_token
This example uses a secret named github_token. When Drone runs this pipeline, it will look for a secret named github_token in your repository’s settings and inject its value into the github_token environment variable within the deploy step’s container.
Where Secrets Live
Drone stores secrets in a few places:
- Repository-level secrets: These are specific to a single repository. You can manage these through the Drone UI under your repository’s settings.
- User-level secrets: These are available to all repositories owned by a specific user. You manage these in your user settings in the Drone UI.
- Organization-level secrets: These are available to all repositories within a specific organization. You manage these in the organization’s settings in the Drone UI.
The order of precedence for secrets is: Repository > User > Organization. If a secret with the same name exists at multiple levels, the repository-level secret will take precedence.
Injecting Secrets: The from_secret Keyword
The from_secret keyword is the primary mechanism for injecting secrets.
steps:
- name: build
image: golang:1.20
commands:
- go build
- echo $CI_GITHUB_TOKEN # This will be empty by default
- name: push
image: plugins/docker
settings:
username:
from_env: DOCKER_USERNAME # Example of using an environment variable
password:
from_secret: docker_password
In this example:
- The
buildstep has access to environment variables that Drone automatically injects, likeCI_GITHUB_TOKEN(if configured). - The
pushstep needs adocker_password. It retrieves this from a secret nameddocker_password. - It also shows
usernamebeing sourced from an environment variableDOCKER_USERNAME. This is useful if you have aDOCKER_USERNAMEsecret and want to use its value in a different environment variable name for your plugin.
Sensitive Data and Environment Variables
Drone automatically injects a set of predefined environment variables prefixed with CI_. Some of these are sensitive.
CI_COMMIT_SHA: The commit SHA.CI_COMMIT_REF: The branch or tag name.CI_COMMIT_AUTHOR: The author of the commit.CI_PIPELINE_STATUS: The status of the pipeline (successorfailure).CI_BUILD_NUMBER: The build number.CI_BUILD_URL: The URL to the build.
Important: While Drone attempts to mask secrets in logs, it’s not foolproof. Never rely solely on log masking for truly sensitive data.
Using Secrets with Plugins
Many Drone plugins are designed to consume secrets directly.
kind: pipeline
type: docker
name: publish-docker-image
steps:
- name: build
image: plugins/docker
settings:
repo: octocat/hello-world
username:
from_secret: docker_username
password:
from_secret: docker_password
Here, the plugins/docker image expects username and password settings. We provide these by referencing secrets named docker_username and docker_password. Drone will automatically make these secrets available as environment variables within the build step’s container, and the plugin will read them.
Managing Secrets in the UI
- Repository Secrets: Navigate to your repository in the Drone UI, click "Settings," and then "Secrets." You can add, edit, and delete secrets here.
- User Secrets: Navigate to your user settings in the Drone UI (usually by clicking your avatar), then "Secrets."
- Organization Secrets: Navigate to your organization settings in the Drone UI, then "Secrets."
How from_secret Works Under the Hood
When Drone encounters from_secret: my_secret_name, it does the following:
- Lookup: It searches for a secret named
my_secret_namein the following order: repository secrets, user secrets, organization secrets. - Injection: Once found, Drone injects the secret’s value into the build container as an environment variable. The name of this environment variable is derived from the secret name, typically by converting it to uppercase and prefixing it with
CI_if it’s a repository or organization secret, or just uppercase if it’s a user secret. For example, a repository secret nameddocker_passwordmight become theCI_DOCKER_PASSWORDenvironment variable. - Plugin Consumption: If you’re using a plugin that expects a specific setting (like
password), and that setting is configured withfrom_secret: docker_password, the plugin will access the injected environment variable (e.g.,CI_DOCKER_PASSWORD).
Best Practices
- Least Privilege: Grant secrets only to the repositories or organizations that absolutely need them.
- Avoid Overriding: Be mindful of secret naming collisions between repository, user, and organization levels. Use distinct names to prevent unexpected behavior.
- Use Environment Variables for Non-Sensitive Data: For configuration values that aren’t strictly sensitive (like build arguments or image tags), use
from_envor directly set them in your.drone.yml. - Regularly Rotate Secrets: Treat CI/CD secrets like any other sensitive credential and rotate them periodically.
- Consider Vault Integration: For more advanced secret management, Drone integrates with HashiCorp Vault and other external secret stores. This allows you to manage secrets centrally outside of Drone itself.
The next step in mastering Drone secrets is understanding how to integrate with external secret management systems like HashiCorp Vault.