From 4f132f0a94fd3d97059f2366b3fa84629fbb084b Mon Sep 17 00:00:00 2001 From: Nimish Date: Fri, 11 Apr 2025 13:37:55 +0530 Subject: [PATCH] docs: terraform secret crud - wip --- .../platforms/hashicorp-terraform.mdx | 215 +++++++++++++++++- 1 file changed, 206 insertions(+), 9 deletions(-) diff --git a/src/pages/integrations/platforms/hashicorp-terraform.mdx b/src/pages/integrations/platforms/hashicorp-terraform.mdx index 07e2e513..5da7935f 100644 --- a/src/pages/integrations/platforms/hashicorp-terraform.mdx +++ b/src/pages/integrations/platforms/hashicorp-terraform.mdx @@ -7,7 +7,7 @@ export const description = 'Use Phase with Terraform to manage your secrets' # Terraform Provider -The Phase Terraform Provider allows you to securely retrieve secrets directly from your Terraform configurations. This integration enables you to incorporate secret management into your infrastructure-as-code workflows. +The Phase Terraform Provider allows you to securely manage and retrieve secrets directly from your Terraform configurations. This integration enables you to incorporate secure secret management into your infrastructure-as-code workflows. ## Prerequisites @@ -21,7 +21,7 @@ The Phase Terraform Provider allows you to securely retrieve secrets directly fr 2. Fetch your Phase **Application ID** (AppID) by going to your application settings in the Phase Console, hovering over UUID under the App section and clicking the `Copy` button: -![hello world](/assets/images/console/settings/application-id.png) +![Application ID](/assets/images/console/settings/application-id.png) ## Step 1: Install the Provider @@ -32,7 +32,7 @@ terraform { required_providers { phase = { source = "phasehq/phase" - version = "0.1.1" // replace with latest version + version = "0.2.0" // replace with latest version } } } @@ -47,6 +47,7 @@ To configure the provider, you need to provide your Phase API credentials. We re ```hcl provider "phase" { phase_token = "pss_service:v1:..." # or "pss_user:v1:..." // A Phase Service Token or a Phase User Token (PAT) + // Alternatively supply a PHASE_TOKEN environment variable } ``` @@ -54,8 +55,9 @@ If you are using a self-hosted instance of Phase, you can specify the API host u ```hcl provider "phase" { - host = "https://phase.example.io" - phase_token = "pss_service:v1:..." # or "pss_user:v1:..." // A Phase Service Token or a Phase User Token (PAT) + host = "https://phase.example.io" + skip_tls_verification = true # Optional, if your Phase instance is using a self-signed certificate, you can set this to true to skip TLS verification. + phase_token = "pss_service:v1:..." # or "pss_user:v1:..." // A Phase Service Token or a Phase User Token (PAT) } ``` @@ -71,9 +73,9 @@ To fetch secrets from Phase, use the `phase_secrets` data source: ```hcl data "phase_secrets" "all" { - env = "development" - app_id = "your-app-id" - path = "" + env = "development" // The environment to fetch secrets from. + app_id = "your-app-id" // The ID of the Phase application to fetch secrets from. + path = "" // Use an empty string to fetch all secrets in the application. } output "all_secret_keys" { @@ -84,6 +86,35 @@ output "all_secret_keys" { ☝️ This will fetch all secrets stored inside your Phase application in the development environment. +Example: + +```hcl +terraform { + required_providers { + phase = { + source = "phasehq/phase" + version = "0.2.0" + } + } +} + +provider "phase" { + skip_tls_verification = true + host = "https://phase.internal.acme.com" +} + +data "phase_secrets" "all" { + env = "production" + app_id = "907549ca-1430-4aa0-9998-290525741005" + path = "" +} + +output "all_secret_keys" { + value = data.phase_secrets.all.secrets + sensitive = true +} +``` + ### Fetching Secrets from a Specific Path To fetch all secrets under a specific path: @@ -101,6 +132,34 @@ output "backend_secret_keys" { } ``` +Example: + +```hcl +terraform { + required_providers { + phase = { + source = "phasehq/phase" + version = "0.2.0" + } + } +} + +provider "phase" { + skip_tls_verification = true + host = "https://phase.internal.acme.com" +} + +data "phase_secrets" "all" { + env = "production" + app_id = "907549ca-1430-4aa0-9998-290525741005" + path = "/folder/path" +} + +output "all_secret_keys" { + value = data.phase_secrets.all.secrets + sensitive = true +} +``` ☝️ This will fetch the `JWT_SECRET` secret from the `/backend` folder inside your Phase application in the production environment. ### Fetching a Single Secret @@ -118,8 +177,103 @@ output "database_url" { sensitive = true } ``` -☝️ This will fetch the `DATABASE_URL` secret from your Phase application in the development environment. +☝️ This will fetch the value of the `DATABASE_URL` secret from your Phase application in the development environment. + +Example: + +```hcl +terraform { + required_providers { + phase = { + source = "phasehq/phase" + version = "0.2.0" + } + } +} + +provider "phase" { + host = "https://phase.internal.acme.com" +} + +data "phase_secrets" "single" { + env = "production" + app_id = "907549ca-1430-4aa0-9998-290525741005" + +} + +output "database_url" { + value = data.phase_secrets.single.secrets["DATABASE_URL"] + sensitive = true +} + +``` + +### Creating Secrets + +```hcl +resource "phase_secret" "example" { + app_id = "8b94fe5c-ea7d-4091-9087-e0e03089bd47" + env = "production" + key = "DATABASE_URL" + path = "/database/pgsql" + comment = "AWS RDS PostgreSQL database creds" + tags = ["database", "RDS"] // Tags must be pre-created in the Phase Console + value = "postgres://${USER}:${PASSWORD}@${HOST}:{PORT}/${DATABASE}" +} +``` + + +To be able to assign tags to secrets, the tags must already be created in the Phase Console beforehand. + + +Example: + +```hcl +terraform { + required_providers { + phase = { + source = "phasehq/phase" + version = "0.2.0" + } + random = { + source = "hashicorp/random" + version = "3.6.0" + } + } +} +provider "phase" { + host = "https://internal.phase.acme.com" +} + +# Generate random values for secrets +resource "random_bytes" "secret_1" { + length = 32 +} + +resource "random_bytes" "secret_2" { + length = 64 +} + +resource "phase_secret" "terraform_secret_1" { + app_id = "8b94fe5c-ea7d-4091-9087-e0e03089bd47" + env = "development" + key = "TF_SECRET_1" + value = random_bytes.secret_1.hex + path = "/" + comment = "Created by Terraform" + tags = ["database"] # Tag must already exist in Phase Console +} + +resource "phase_secret" "terraform_secret_2" { + app_id = "8b94fe5c-ea7d-4091-9087-e0e03089bd47" + env = "production" + key = "TF_SECRET_2" + value = random_bytes.secret_2.hex + path = "/foo-bar" + comment = "Created by Terraform" +} +``` ### Using Secrets in Resources @@ -150,6 +304,48 @@ Execute your Terraform workflow: terraform apply ``` +## Step 5: Destroy the resources + +To destroy the resources created by the Terraform configuration, run the following command: +```fish +terraform destroy +``` + +### Importing Existing Secrets + +You can import existing secrets from Phase into your Terraform state using: + +```fish +terraform import phase_secret. ":::" +``` + +For example: +```fish +terraform import phase_secret.imported_secret "907549ca-1430-4aa0-9998-290525741005:production:/database/:DB_HOST" +``` + +### Secret Versions and Metadata + +The provider automatically tracks secret versions and metadata: + +```hcl +resource "phase_secret" "database_url" { + env = "production" + app_id = "your-app-id" + key = "DATABASE_URL" + value = "postgres://user:password@localhost:5432/db" + tags = ["database", "credentials"] # Tags must already exist in Phase Console +} + +output "secret_version" { + value = phase_secret.database_url.version +} + +output "secret_created_at" { + value = phase_secret.database_url.created_at +} +``` + ## Personal Secret Overrides Personal Secret Overrides allow individual users to temporarily override a secret's value for their own use, without affecting the value for other users or systems. Important points to note: @@ -167,3 +363,4 @@ Personal Secret Overrides allow individual users to temporarily override a secre 1. Use variables or environment variables for the Phase token to keep it out of your Terraform configurations. 2. Utilize Terraform's `sensitive` argument when outputting or using secret values to prevent accidental exposure. 3. Be cautious when using `terraform output` commands, as these may display sensitive information. +4. Create all necessary tags in the Phase Console before referencing them in Terraform configurations. In the near future, we will add an API to automatically create tags in Terraform.