I am trying to create an aws_s3_bucket
resource with the following policy:
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::REDACTED:user/REDACTED"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::${bucket}/REDACTED/*"
}
]
}
To do this, I am using the following Terraform code:
resource "template_file" "logs_policy" {
template = "${file("${path.module}/policy.json")}"
vars {
bucket = "${aws_s3_bucket.logs.bucket}"
}
}
resource "aws_s3_bucket" "logs" {
bucket = "${var.s3_bucket_prefix}-logs"
policy = "${template_file.logs_policy.rendered}"
}
Trying to run Terraform fails, however, due to a dependency loop:
Errors:
* 1 error(s) occurred:
* Cycle: template_file.logs_policy, aws_s3_bucket.logs
Hello @joshuaspence –
The cycle is this:
While we "know" what the bucket name will be by reading the var you've specified, we don't "deliver" it to other resources until the bucket is actually created. We don't want to pass on information that's not valid, in the event that it fails to actually create. So, there you have a cycle.
You should be able to simply specify the policy inline:
resource "aws_s3_bucket" "logs" {
bucket = "${var.s3_bucket_prefix}-logs"
policy = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::REDACTED:user/REDACTED"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::${var.s3_bucket_prefix}-logs/REDACTED/*"
}
]
}
EOF
}
Unless of course you have another use for the template_file
resource that I'm not seeing? If you have any more information on your use case maybe I can propose another solution, if I understand your situation better.
Thanks!
This would be slightly easier if there was a self
variable, I suppose.
There is a self
, however it's only available to provisioners, I'm afraid :/
For anyone in the future that lands here I wanted to note an option for doing this:
resource "aws_s3_bucket" "my_bucket" {
bucket = "mybucket"
}
resource "aws_s3_bucket_policy" "my_bucket_policy" {
bucket = "${aws_s3_bucket.my_bucket.id}"
policy = "${data.aws_iam_policy_document.bucket_policy.json}"
}
data "aws_iam_policy_document" "bucket_policy" {
statement {
actions = [
"s3:*"
]
resources = [
"${aws_s3_bucket.my_bucket.arn}",
"${aws_s3_bucket.my_bucket.arn}/*"
]
}
}
How about bucket_prefix ? Sill have * Cycle: data.template_file.policy, aws_s3_bucket.logs
I'm needed unique bucket name
data "template_file" "policy" {
template = "${file("policy.json")}"
vars = {
bucket = "${aws_s3_bucket.logs.id}"
account_id = "127311923021"
}
}
resource "aws_s3_bucket_policy" "elb_logs" {
depends_on = ["aws_s3_bucket.logs"]
bucket = "${aws_s3_bucket.logs.id}"
policy = "${data.template_file.policy.rendered}"
}
resource "aws_s3_bucket" "logs" {
bucket_prefix = "logs-${var.stage}"
policy = "${data.template_file.policy.rendered}"
}
Another option to try would be to create a module and use the following in the call:
resource "random_string" "id" {
special = false
length = 5
upper = false
lower = true
number = true
}
module "bucket1" {
source = "../s3"
providers = {
"aws.proxy" = "aws.useast1" }
prefix = "test"
envname = "app1"
s3_acl = "private"
s3_bucket_name = "${var.prefix}-bucketpurpose-${random_string.id.result}"
}
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
For anyone in the future that lands here I wanted to note an option for doing this: