Secrets referencing stores raw value to integration store

Hi team,

Loving the product, just having some issues setting up secrets alongside parameters management and noticed a potential issue with how the integration syncs work.

I have setup a project with two environments (staging and staging secret). I have setup staging to be integrated to AWS Parameters Store and plan to (but not yet) setup staging secret to be integrated to AWS Secrets Manager. I have to keep these two separate as I want different visibility permissions by the least access principle.

What I noticed was that when I added a secret in staging secret with the value SECRET: key and referenced it in staging with the value SECRET: ${stg-secret.SECRET}, the value is stored in AWS Parameters Store with the raw secret value from staging secret.

This is a bit problematic for my use case as it results in potential secret leaks.

Aside:

  • I am unsure if this is a PEBCAK setup issue.
  • Is there a way I could potentially bypass this pattern altogether by somehow injecting multiple service access token secrets into the doppler run --token token1 --token token2 – doSomething command.

Screenshot 1
Integration issue 1

Screenshot 2

Screenshot 3

I just tried this across two separate projects and arrived at the same outcome.

project: example-project
environment: stg
secret:
- OTHER_PROJECT_SECRET: ${example-project-secrets.stg.OTHER_PROJECT_SECRET}

project: example-project-secrets
environment: stg
secret:
- OTHER_PROJECT_SECRET: KEY

Outcome:

Hi @dropbeardan,

Welcome to the Doppler Community!

What you’re experiencing here is just how Doppler works currently. When fetching secrets for a config, secret references are fully resolved. This happens because usually when this is being done, having a Doppler secret reference string as the value isn’t useful outside of Doppler (e.g., when starting a service, having PORT set to ${test.PORT} would result in a crash since the actual port value is what’s expected). The same goes for a sync since most third party services we sync to don’t support secret referencing (and if they did, it wouldn’t necessarily be clear how to map a Doppler secret reference to their own referencing format). As such, we simply fully resolve the secret.

Unfortunately, in this case the fact that AWS Parameter Store displays all its secrets in plain text in their dashboard is a bit unfortunate. There currently isn’t a way to have the Doppler CLI fetch two separate configs and combine them like you asked. That said, you could potentially create a third config in Doppler that combines all the secrets via secret references. You could then fetch those secrets via the CLI using a single service token. Would something like that work for you?

Regards,
-Joel

Hey Joel,

Many thanks for the thorough response.

Regarding what has been mentioned:

When fetching secrets for a config, secret references are fully resolved… That said, you could potentially create a third config in Doppler that combines all the secrets via secret references. You could then fetch those secrets via the CLI using a single service token. Would something like that work for you?

This could potentially work if the secrets store was not integrated in any way to external providers (that way only Doppler knows and has control over it, similar to a projected view).

Despite this being an unintuitive setup (since we would need to maintain 3 separate environments to generate a view for a single use-case), I think it functionally serves the basic needs at the cost of extra maintenance.

# ENV 1 - Insensitive Paramaters Only
environment: stg
integration: AWS Parameters Store
secrets: Non-sensitive secrets
used by: None

# ENV 2 - Sensitive Paramaters Only
environment: stg-secrets
integration: AWS Secrets Manager
secrets: Sensitive secrets
used by: None

# ENV 3 - Projected View Only
environment: stg-view
integration: None
secrets: Purely references to `stg` and `stg-secrets` and other trivial params
used by: Actual implementation (e.g. containers / apps / CI)

In the future, it would be great if we could select integration options at a per-secret level so that we can fine tune which secrets sync to where (with none as an option). This would remove the need to setup a projected view environment as the insensitive paramaters environment could take up that responsibility as well.

EDIT: Actually nevermind, in order for this to work we would need to change how the permissions works so that the consumer of the insensitive parameters won’t be able to see the raw value of the sensitive secrets when they pull it down (and somehow still be able to use it). Since that’s a bit of a hard problem, I think the solution that was suggested (with a pattern of 1 integration / isolated concern → 1 environment) is the preferred method AFAIK.

Unfortunately, in this case the fact that AWS Parameter Store displays all its secrets in plain text in their dashboard is a bit unfortunate.

They have masked and unmasked access to the values / secrets in both Parameter Store and Secrets Manager depending on your permission level. I screenshotted the unmasked value to simply demonstrate the behaviour.


Thanks again for the neat suggestion, this solves a critical problem in deciding how to handle the pipeline!

Cheers,
Dan