Skip to content

IParameter.grantRead() omits ssm:GetParametersByPath (silent failure for confd-style readers) #133

Description

@so0k

IParameter.grantRead() grants four actions (src/aws/storage/parameter.ts:256):

ssm:DescribeParameters
ssm:GetParameters
ssm:GetParameter
ssm:GetParameterHistory

This matches aws-cdk exactly, so this is a parity issue rather than a regression — but it cost me a full e2e cycle to find, and the failure mode is bad enough that it seems worth raising.

What happened

An L3 writes config to Parameter Store for a confd daemon baked into an AMI. confd reads with GetParametersByPath. Granting with parameter.grantRead(instance) produced:

AccessDeniedException: User: arn:aws:sts::…:assumed-role/…/i-0da8ca22b804061ad is not
authorized to perform: ssm:GetParametersByPath on resource:
arn:aws:ssm:us-east-1:…:parameter/e2e-cobvrl/atlantis-yaml/contents
because no identity-based policy allows the ssm:GetParametersByPath action

The instance booted, passed health checks, and registered with SSM Session Manager. But no config file was ever rendered, so the app exited on a missing config, the reverse proxy never started, and git-sync never cloned. Nothing surfaced as an error at the infrastructure layer — terraform apply reported success and every resource existed. The only symptom was a service that would not start, and the cause was four levels away in an IAM policy.

Notably the parameters I granted by hand-written PolicyStatement (with GetParameters + GetParametersByPath, mirroring the Terraform module being ported) worked fine in the same boot. Only the ones using grantRead() failed, which made it look like a Parameter Store problem rather than an IAM one.

Why this is not simply "add it to grantRead"

GetParametersByPath authorizes against the ARN of the path being queried, not the individual parameters returned. So a per-parameter grant is only meaningful when the caller queries that exact path — which is my case (confd queries each key's full path), but would not be for a caller doing a genuine recursive walk of /prefix. Silently widening grantRead() would grant something whose semantics don't quite match the resource it's attached to.

So this may be better as an explicit, separately-named capability than as a change to grantRead.

Options

  1. Add GetParametersByPath to grantRead() — simplest, diverges from aws-cdk, and slightly overloads the ARN semantics above.
  2. Add a dedicated method, e.g. grantGetByPath(grantee) on IParameter, and/or a hierarchy-level helper that grants on a path prefix ARN (…:parameter/prefix + /prefix/*). This models the action correctly and keeps grantRead at CDK parity.
  3. Leave the behaviour and document it on grantRead() — cheap, and would have saved me the debugging round.

I'd lean toward (2) plus (3), but happy to be told otherwise.

Current workaround

role.addToPrincipalPolicy(new aws.iam.PolicyStatement({
  actions: ["ssm:GetParametersByPath"],
  resources: parameters.map((p) => p.parameterArn),
}));

Observed on terraconstructs@0.2.12.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions