Octoterra interacts with Octopus via the Octopus API. One of the security features built into the Octopus API is that it does not return sensitive values. This means Octoterra can not export the values of any secrets, such as the value assigned secret variables.
There are two ways to import projects that contain secret variables:
- Define all the values as Terraform variables when calling
terraform apply
- Apply the Terraform module with Octopus and use variable substitution to inject secret values during deployment
Supplying space level resource secret values
Space level resources such as accounts, certificates, feeds, Git credentials, and targets may include secret values. These values must be passed to the terraform apply
command or set to dummy values to allow the resources to be created without knowing the secret values beforehand. Unlike project sensitive variables, it is not possible to have Octopus automatically inject these values during deployment.
Teams can choose to enable the Default Secrets to Dummy Values
option in the Octopus - Serialize Space to Terraform
step to export a Terraform module with all secret values set to a placeholder string. For example, this is an account exported with the Default Secrets to Dummy Values
option enabled:
resource "octopusdeploy_aws_account" "account_aws_account" {
name = "AWS Account"
description = ""
environments = []
tenant_tags = ["TenantType/InternalCustomer"]
tenants = []
tenanted_deployment_participation = "TenantedOrUntenanted"
access_key = "ABCDEFGHIJKLMNOPQRS"
secret_key = "${var.account_aws_account}"
depends_on = [octopusdeploy_tag_set.tagset_tenanttype,octopusdeploy_tag.tag_internalcustomer]
lifecycle {
ignore_changes = [secret_key]
}
}
variable "account_aws_account" {
type = string
nullable = false
sensitive = true
description = "The AWS secret key associated with the account AWS Account"
default = "Change Me!"
}
Note the default value of the Terraform variable account_aws_account
is Change Me!
. All other secret values have similar placeholders. Also note that the lifecycle
meta-argument on the account resource is set to ignore_changes = [secret_key]
. This indicates that Terraform will not reapply the placeholder secret value if the target resource was manually updated after it was created.
This means that the space level resources exported by the Octopus - Serialize Space to Terraform
step with the Default Secrets to Dummy Values
option enabled can be applied without having to supply all the secret values. It is then expected that the newly created Octopus resources are updated manually with the correct values.
If the Default Secrets to Dummy Values
option is disabled, no default value will be defined for the terraform variables, and you must pass values for these variables to terraform apply
. For example:
-var=account_aws_account=TheAwsAccountSecretKey
You may wish to define all space level secrets in a variable set in the upstream space, exclude the variable set from being exported, and pass the variable set values to the terraform apply
argument when deploying space level resources.
Supplying project secret variable values
Octoterra exposes every secret value it exports as a Terraform variable. These variables can then be defined when running terraform apply
.
All project secret variables are defined in files with the prefix project_variable_sensitive_
. These files then define a pair of Terraform blocks.
The first is a Terraform variable:
variable "eks_octopub_frontend_secret_value_1" {
type = string
nullable = false
sensitive = true
description = "The secret variable value associated with the variable Secret.Value"
default = "#{Secret.Value}"
}
The second is the Octopus variable:
resource "octopusdeploy_variable" "eks_octopub_frontend_secret_value_1" {
owner_id = "${octopusdeploy_project.project_eks_octopub_frontend.id}"
name = "Secret.Value"
type = "Sensitive"
sensitive_value = "${var.eks_octopub_frontend_secret_value_1}"
is_sensitive = true
lifecycle {
ignore_changes = all
}
}
The value of the secret variable is then defined by passing an argument like -var=eks_octopub_frontend_secret_value_1=SecretValueGoesHere
to terraform apply
.
Injecting secret values during deployment
Octoterra formats the Terraform sensitive variable default values to allow them to be replaced by Octopus. If you look at the example sensitive variable resource listed in the previous section, you’ll see the default value is set to #{Secret.Value}
.
This Octostache template can be replaced by Octopus when the Terraform module is deployed with the Apply a Terraform template
step. Note that the Octopus - Populate Octoterra Space
step templates are based on the Apply a Terraform template
step, and are configured to replace Octostache template syntax in files matching the pattern **/project_variable_sensitive*.tf
.
There are, however, some special considerations that must be taken into account to ensure a project can inject all secret variables when deployed downstream:
- A dedicated environment must be used for deploying downstream projects (this documentation and step templates assume an environment called
Sync
) - All sensitive variables must have a single value
- All sensitive variables must be available to the
Sync
environment
Following these rules ensures the Octostache templates defining the default value of a sensitive variables have a single, unambiguous value injected into them when they are deployed.
The Sync environment
Dedicating an environment to the process of serializing and deploying downstream projects allows the upstream environment to scope sensitive variables such that:
- They are made available when deploying downstream projects
- They dot no leak into any regular deployment environments
This documentation and the step templates assumes this environment is called Sync
. The Sync
environment must not appear in the lifecycle of regular deployments, which ensures any variables scoped to the Sync
environment do not leak into regular deployments.
Octoterra excludes the Sync
environment from the variable scopes in exported projects. This ensures the downstream projects do not rely on the Sync
environment.
Sensitive variables with single values
Any sensitive values in the upstream project must have one value assigned to them. For example, if you had a sensitive variable for a database password, and the value was unique per environment, it must be captured as three variables e.g.:
Dev.Database.Password
scoped to theDev
andSync
environmentsTest.Database.Password
scoped to theTest
andSync
environmentsProduction.Database.Password
scoped to theProduction
andSync
environments
These three variables can then be referenced by a non-sensitive variable scoped to all three environments:
Database.Password
set to#{Dev.Database.Password}
and scoped to theDev
environmentDatabase.Password
set to#{Test.Database.Password}
and scoped to theTest
environmentDatabase.Password
set to#{Production.Database.Password}
and scoped to theProduction
environment
The deployment process can then reference #{Database.Password}
to receive the environment scoped sensitive variable during deployment.
Sensitive variables made available to the Sync environment
All sensitive variables must be available to the Sync
environment. This means:
- Sensitive variables have no scope
- Sensitive variables scoped to any environments must also be scoped to the
Sync
environment
This ensures the steps deploying downstream projects have access to all sensitive variables, and replace the Octostache template syntax in files matching the pattern project_variable_sensitive*.tf
with the correct value.
Help us continuously improve
Please let us know if you have any feedback about this page.
Page updated on Thursday, November 23, 2023