boltops-tools / boltops-tools/terraspace_plugin_aws
client_assume_role_options doesn't recognize the S3 backend's newer nested assume_role block, only the deprecated flat role_arn
- Dominant language
- Ruby
- Stars
- 1
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
Terraform (since ~1.6) and OpenTofu deprecated the flat `role_arn` argument on the S3 `backend` block in favor of a nested `assume_role` object:
```hcl
# Deprecated, produces a warning:
terraform {
backend "s3" {
role_arn = "arn:aws:iam::123456789012:role/example"
bucket = "my-bucket"
...
}
}
# Current:
terraform {
backend "s3" {
assume_role = {
role_arn = "arn:aws:iam::123456789012:role/example"
}
bucket = "my-bucket"
...
}
}
```
(Reference: https://opentofu.org/docs/language/settings/backends/s3/#credentials-and-shared-configuration)
`client_options` in [`lib/terraspace_plugin_aws/clients/options.rb`](https://github.com/boltops-tools/terraspace_plugin_aws/blob/main/lib/terraspace_plugin_aws/clients/options.rb#L6) only checks the flat key:
```ruby
def client_options
return {} unless @info
if @info['role_arn']
client_assume_role_options
else
client_default_options
end
end
```
When `role_arn` is moved under the nested `assume_role` block (to silence the deprecation warning and stay current with Terraform/OpenTofu), `@info['role_arn']` is `nil`, so this silently falls through to `client_default_options` — meaning the plugin's own S3 bucket/DynamoDB-table existence checks (`Backend::Bucket#exist?`, `Backend::Table`) run with the ambient/default credentials instead of assuming the configured role.
### Impact
If the default credentials don't have direct access to the state bucket (a common setup — the whole point of `assume_role` is that the CI identity has no direct bucket access and must assume a separate role), this fails hard:
```
Aws::S3::Errors::Forbidden: Aws::S3::Errors::Forbidden
ERROR: Bucket is not available:
Bucket might be owned by someone else or is on another one of your AWS accounts.
```
This means there's currently no way to use the new, non-deprecated `assume_role` backend syntax with this plugin without breaking its bucket/table preflight checks — users are stuck choosing between a deprecation warning (flat `role_arn`, still works) or broken CI (nested `assume_role`, silently loses the role assumption).
Confirmed still present in the latest release, `v0.6.1`.
### Reproduction
1. Configure an S3 backend using the nested `assume_role` block (flat `role_arn` removed).
2. Run any Terraspace command that hits `Backend::Bucket#exist?` (e.g. `terraspace plan`) where the target bucket is only accessible via the assumed role, not the caller's default credentials.
3. Observe `Aws::S3::Errors::Forbidden` / "Bucket is not available", even though `terraform`/`tofu` itself would correctly assume the role for its own backend init.
### Suggested fix
`client_options` (and the `whitelist`/`assume_role_config` extraction in `client_assume_role_options`) should also check for and read from a nested `assume_role` key, e.g.:
```ruby
def client_options
return {} unless @info
if @info['role_arn'] || @info['assume_role']
client_assume_role_options
else
client_default_options
end
end
```
with `client_assume_role_options` merging `@info['assume_role']` (if present) on top of/instead of the flat keys, matching Terraform's own precedence.
Happy to submit a PR if a maintainer confirms this approach.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in lib/terraspace_plugin_aws/clients/options.rb at client_options and client_assume_role_options, and trace how @info supplies role settings to the S3 and DynamoDB preflight clients. Support the nested assume_role configuration while preserving flat role_arn behavior and precedence, then verify that bucket and table checks use the assumed role for the nested configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, ruby
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100