Terraform Genesys Provider: Hiding OAuth client_secret from state file

Trying to manage OAuth clients via the Genesys Cloud Terraform provider without leaking the client_secret into the state file. The docs for genesys_cloud_oauth_client state: “The client secret. This value is sensitive and should be treated as such.”

We’re using sensitive = true on the attribute, but running terraform show still spits it out in plain text. Is there a way to force it out of the state entirely? We’re building a CI/CD pipeline and don’t want the secret cached in S3.

Here’s the block:

resource "genesys_cloud_oauth_client" "app_client" {
 name = "Test Integration"
 client_type = "CONFIDENTIAL"
 
 sensitive_attributes = [
 "client_secret"
 ]

 scopes = [
 "admin:oauth_client:read",
 "admin:oauth_client:write"
 ]
}

Output of terraform show:

# genesys_cloud_oauth_client.app_client will be updated in-place
~ resource "genesys_cloud_oauth_client" "app_client" {
 id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
 name = "Test Integration"
 client_type = "CONFIDENTIAL"
 + client_secret = (sensitive value)
 ~ client_secret = "super_secret_value_123"
 }

It’s still there. Just masked slightly. Need it gone. Using Terraform 1.7.4 and provider version 1.15.0.

We’ve tried using a local value to generate the secret and pass it, but the API requires the secret to be set on creation. Can’t update it after. Stuck.

Any workaround? Or is the provider just dumping everything?

The sensitive = true flag doesn’t scrub data from the state file. It just hides it from the CLI output. The secret is still sitting in terraform.tfstate as plain text. You can’t force the provider to omit it entirely if the API requires it for updates.

The only real fix is to encrypt the state file itself or use remote state with encryption at rest. If you’re on AWS, enable encryption on the S3 bucket and the DynamoDB lock table. For Azure, use managed keys on the storage account.

If you’re dead set on keeping secrets out of the local file, switch to a remote backend like Terraform Cloud. It handles encryption. Here’s how to configure the backend in your main.tf:

terraform {
 backend "s3" {
 bucket = "my-terraform-state"
 key = "genesys/oauth/terraform.tfstate"
 region = "us-east-1"
 encrypt = true
 dynamodb_table = "terraform-locks"
 }
}

resource "genesys_cloud_oauth_client" "app_client" {
 name = "My App"
 grant_types = ["client_credentials"]
 # No client_secret defined here. It's generated by Genesys.
 # You have to capture it on creation.
}

The tricky part with OAuth clients is that Genesys generates the secret. You can’t set it in Terraform. You have to retrieve it after creation. Use a null resource with a local-exec to call the API and store the secret in AWS Secrets Manager or Azure Key Vault.

resource "null_resource" "store_secret" {
 triggers = {
 client_id = genesys_cloud_oauth_client.app_client.id
 }

 provisioner "local-exec" {
 command = <<EOT
 curl -X GET \
 "https://api.mypurecloud.com/api/v2/oauth/clients/${genesys_cloud_oauth_client.app_client.id}" \
 -H "Authorization: Bearer ${var.access_token}" \
 | jq -r '.client_secret' > /tmp/secret.txt
 
 aws secretsmanager create-secret \
 --name "genesys/oauth/my-app" \
 --secret-string file:///tmp/secret.txt
 EOT
 }
}

This keeps the secret out of the state file. It lives in your vault instead. Just make sure your CI/CD pipeline has permissions to read that vault. Don’t hardcode the access token either. Use OIDC or assume role.

Cause: The sensitive flag is purely cosmetic for the CLI. It stops terraform plan from screaming your secret at you, but it writes the plaintext value straight into terraform.tfstate. That’s by design. Terraform needs the current value to calculate diffs. You can’t omit it if the resource requires it for API calls.

Solution: You have to encrypt the state container, not the attribute. If you’re dumping state on S3, enable server-side encryption (SSE-S3 or SSE-KMS). For Azure, use managed keys on the storage account.

Here’s the minimal backend config for S3 with KMS. This is the only real fix.

terraform {
 backend "s3" {
 bucket = "my-secure-state-bucket"
 key = "prod/genesys/terraform.tfstate"
 region = "us-east-1"
 encrypt = true
 kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/your-key-id"
 dynamodb_table = "terraform-lock-table"
 }
}

If you’re using local state (don’t), you’re on your own. Encrypt the file manually or move it.

Also, check your CI/CD pipeline. If you’re storing state in a repo or logging it, you’re leaking it anyway. Make sure your pipeline doesn’t echo state contents.

The provider docs saying “treat as such” is a warning, not a feature. It means “encrypt your state.”