hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.86k stars 9.21k forks source link

[Enhancement]: `aws_secretsmanager_secret` data source to return a versionless arn using 6 question marks suffix `-??????` and partial arn #39953

Open nitrocode opened 3 weeks ago

nitrocode commented 3 weeks ago

Description

When using the data source aws_secretsmanager_secret, we get the exact versioned ARN which makes it cumbersome to allow versionless access to these secrets in IAM policies.

https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_iam-policies.html

Because you can predict all of the parts of the ARN of a secret except the 6 random characters, using the wildcard character '??????' syntax enables you to securely grant permissions to a secret that doesn't yet exist. Be aware, however, if you delete the secret and recreate it with the same name, the user automatically receives permission to the new secret, even though the 6 characters changed.

Here is an example of three workarounds used to replace the last 6 characters with questionmarks so the policy is allowed to retrieve all versions of the secret in secrets manager.

data "aws_iam_policy_document" "default" {
  statement {
    sid    = "ReadSecret"
    effect = "Allow"

    resources = [
      # examples of manually crafting a versionless arn
      ## Workaround 1: example of building the arn manually
      "arn:aws:secretsmanager:us-east-1:${local.aws_account_id}:secret:service/secret-??????",
      ## Workaround 2: datasource + substr
      "${substr(data.aws_secretsmanager_secret.default.arn, 0, length(data.aws_secretsmanager_secret.default.arn) - 6)}??????",
      ## Workaround 3: datasource + replace
      replace(data.aws_secretsmanager_secret.default.arn, "/-[a-zA-Z0-9]{6}/", "-??????"),
      ## Workaround 4: using arn_parse + replace/substr
      ## Workaround 5: using arn_parse + arn_build/replace/substr
    ]

    actions = [
      "secretsmanager:GetSecretValue",
      "secretsmanager:DescribeSecret",
    ]
  }
}

There must be an easier way by adding a new versionless_arn output

Affected Resource(s) and/or Data Source(s)

Potential Terraform Configuration

Option 1: data source change

data "aws_secretsmanager_secret" "default" {
  name = "service/secret"
}

output "arn" {
  value = data.aws_secretsmanager_secret.default.arn
}

output "partial_arn" {
  value = data.aws_secretsmanager_secret.default.partial_arn
}

output "versionless_arn" {
  value = data.aws_secretsmanager_secret.default.versionless_arn
}

Which should return

  + arn             = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret-gqLY34"
  + versionless_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret-??????"
  + partial_arn     = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret"

Option 2: new function

I spoke with @apparentlymart in slack and he mentioned the following

Another interesting thing I notice is that there's already a trim_iam_role_path function which seems like it's intended to solve the somewhat-related problem of turning a pathful IAM role ARN into a pathless one. So... similar idea of taking a more specific ARN and returning a less specific ARN related to it.

So perhaps a secretsmanager_versionless_arn or similar function?

output "versionless_arn" {
  value = provider::aws::secretsmanager_versionless_arn(data.aws_secretsmanager_secret.default.arn)
}

References

Would you like to implement a fix?

No

github-actions[bot] commented 3 weeks ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

dimaman2001 commented 3 weeks ago

@nitrocode - Are you talking about the 6 random characters after your secret's name? See Docs. This is the actual ARN of your secret and and versions of the secret's value will not change the ARN. The 6 characters would change only if you delete the secret entirely and recreate it (as you mentioned in your description).

For my knowledge, what is your usecase? Why are secrets being deleted and recreated rather than updating their values?

nitrocode commented 3 weeks ago

@dimaman2001 the secrets aren't getting recreated. I update the secrets using auto rotation. When the secrets update, the version changes. When the version changes, the policy requires the 6 question marks or the IAM role is unable to retrieve the new secret version.

We have a number of workarounds now to swap out the versioned string to the 6 question marks which works. However it could be easier to set up if it was natively supported instead of needing the above workarounds.

evilensky commented 2 weeks ago

Love this idea!

Suggestion: name the exported property "partial_arn" or similar.

Reasoning: In the GetSecretValue documentation, the secret_id parameter is documented as:

The ARN or name of the secret to retrieve. To retrieve a secret from another account, you must use an ARN. For an ARN, we recommend that you specify a complete ARN rather than a partial ARN.

Where partial arn refers to the "versionless" arn described in this request.

This is as close as I can find for AWS terminology of this form of "arn."

nitrocode commented 2 weeks ago

Thanks for the comment

The partial arn sounds like it only has the arn without the specific version but also without the 6 question marks which is needed for iam principals to access all versions of a secret. Unless I'm mistaken?

  + arn             = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret-gqLY34"
  + versionless_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret-??????"
  + partial_arn     = "arn:aws:secretsmanager:us-east-1:123456789012:secret:service/secret"

I updated the above description to clarify the differences between arn, partial arn, and versionless arn.