Genesyscloud_oauth_client secret in Terraform state despite sensitive flag

Running into a classic secret management headache with the Genesys Cloud Terraform provider. I’ve got a CI/CD pipeline spinning up OAuth clients for our internal tools, and I need to keep the client secrets out of the remote state file.

I’ve set sensitive = true on the resource definition, which stops the value from showing up in the terraform plan output. That’s good. But the secret still ends up in the .tfstate file in plain text. I know Terraform stores the current state of infrastructure, so it needs the ID to manage the resource, but storing the actual secret key seems like a security risk if the state file gets compromised.

Here’s the config:

resource "genesyscloud_oauth_client" "internal_api_client" {
 name = "Internal Service Account"
 description = "Used for backend integrations"
 sensitive = true # This hides it from plan/output
 
 grant_types = ["client_credentials"]
 redirect_uris = []
}

I’ve tried using the external data source to fetch the secret from AWS Secrets Manager and pass it in, but the provider seems to write the secret to the state anyway once the resource is created.

Is there a way to force Terraform to ignore the secret attribute during state serialization? Or am I stuck having to encrypt the state file and hope for the best? I’ve looked at the terraform-provider-genesyscloud source but can’t find a flag to exclude specific attributes from the state payload.

Any workarounds people are using for this? I don’t want to manually manage these clients via the API if I can help it.

That’s the default behavior, and it’s actually by design. The sensitive flag only masks the value in the console output and log files. It doesn’t encrypt the state file itself. If you’re storing that .tfstate somewhere accessible, you’ve got a leak waiting to happen.

The real fix is to use a remote backend with server-side encryption. If you’re on AWS, switch to an S3 backend with encrypt = true. Azure uses Blob Storage with managed keys. Google Cloud Storage handles it automatically. This keeps the plaintext secret out of local files and adds a layer of protection at rest.

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

If you can’t change the backend, you’ll need to rotate the secret immediately. Treat that state file as compromised. You can’t just delete the value from the JSON file manually either. Terraform will detect a drift and try to recreate the resource, which might break your OAuth client if the ID changes.

Instead, use the terraform state rm command to remove the resource from state, then re-import it or let it recreate with a new secret. Make sure your CI/CD pipeline uses environment variables for the actual secret values, not hardcoded strings in the .tf files.

terraform state rm genesyscloud_oauth_client.my_client

Also, consider using Vault or AWS Secrets Manager to inject the secret at runtime rather than storing it in Terraform at all. The provider supports data sources for these tools. It’s more setup work, but it keeps secrets out of your state entirely. You’ll need to update your provider config to authenticate with Vault first. It’s a bit of a pain initially, but it’s the only way to be truly safe with long-lived secrets.