An extendable HTTP backend implementation for terraform
- Encrypt state at rest with AES-256-GCM
- Extensible store: currently supports S3, more to come
- HSDP UAA integration: use LDAP / functional account credentials for auth
- Allow list support: restrict use of an instance backend to specific accounts
The primary goal of this project is to offer storage of Terraform state on the HSDP platform with little to no setup required. Currently, we use CF credentials to authenticate access to the backend. These credentials are expected to be in your pipeline already. The best practice is to use a CF functional account for authentication. Future iterations may introduce service key credentials similar to the HSDP Docker Registry.
The core is derived from bhoriuchi/terraform-backend-http
When self-hosting, you should deploy both the S3 bucket and the application deployment in a separate space in order to limit who has access. Terraform state will contain operator level secrets so only operators within your organization should have access.
Create an S3 bucket:
cf cs hsdp-s3 s3_bucket my-tfstate-bucket
Use the following manifest.yml
as an example
---
applications:
- name: tfstate
env:
TFSTATE_KEY: SecretKeyHereThisIsUsedForEncryption
TFSTATE_REGIONS: us-east,eu-west
docker:
image: loafoe/terraform-backend-hsdp:v0.3.0
services:
- my-tfstate-bucket
routes:
- route: my-tfstate.eu1.phsdp.com
processes:
- type: web
instances: 1
memory: 64M
disk_quota: 1024M
health-check-type: port
Save this to a manifest.yml
and make the necessary changes i.e. the appname and routes. Then deploy:
cf push -f manifest.yml
After a few seconds you should have a running backend
Environment | Description | Required | Default |
---|---|---|---|
TFSTATE_KEY | The encryption key for storage at rest | Yes |
|
TFSTATE_ALLOW_LIST | Comma separated list of allows users | No |
"" (every valid LDAP user can access) |
TFSTATE_REGIONS | The HSDP regions to validate LDAP accounts in | No |
"us-east,eu-west" |
terraform {
backend "http" {
address = "https://my-tfstate.eu1.phsdp.com/my-state"
lock_address = "https://my-tfstate.eu1.phsdp.com/my-state"
unlock_address = "https://my-tfstate.eu1.phsdp.com/my-state"
}
}
The path of the URL will serve as the key
to your state, so the value should be exactly the same in address
, lock_address
and unlock_address
terraform init \
-backend-config="username=YOUR-CF-LOGIN" \
-backend-config="password=YOUR-CF-PASSWORD"
In case you want to use a variable key for your storage you should also specify the values of address
, lock_address
and unlock_address
in the terraform init command. In that
case you can remove these values from backend.tf
as shown in step 1:
terraform init \
-backend-config="username=${username}" \
-backend-config="password=${password}" \
-backend-config="address=https://my-tfstate.eu1.phsdp.com/${key}" \
-backend-config="lock_address=https://my-tfstate.eu1.phsdp.com/${key}" \
-backend-config="unlock_address=https://my-tfstate.eu1.phsdp.com/${key}"
terraform plan
...
terraform apply
...
License is MIT