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
- Add
GetParametersByPath to grantRead() — simplest, diverges from aws-cdk, and slightly overloads the ARN semantics above.
- 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.
- 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.
IParameter.grantRead()grants four actions (src/aws/storage/parameter.ts:256):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 withparameter.grantRead(instance)produced: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 applyreported 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(withGetParameters+GetParametersByPath, mirroring the Terraform module being ported) worked fine in the same boot. Only the ones usinggrantRead()failed, which made it look like a Parameter Store problem rather than an IAM one.Why this is not simply "add it to grantRead"
GetParametersByPathauthorizes 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 wideninggrantRead()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
GetParametersByPathtograntRead()— simplest, diverges from aws-cdk, and slightly overloads the ARN semantics above.grantGetByPath(grantee)onIParameter, and/or a hierarchy-level helper that grants on a path prefix ARN (…:parameter/prefix+/prefix/*). This models the action correctly and keepsgrantReadat CDK parity.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
Observed on
terraconstructs@0.2.12.