I am creating two S3 buckets to keep logs, I want SRR Same Region Replication. Whilst I am not so much familiar with S3 service my code has worked except for the last stage of adding logging to make tfsec and checkov, compliant
s3.tf
resource "aws_iam_role" "iam_role_replication" {
name = "tf-iam-role-replication-12345"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
POLICY
}
resource "aws_iam_policy" "iam_policy_replication" {
name = "tf-iam-role-policy-replication-12345"
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"${aws_s3_bucket.s3_bucket_master.arn}"
]
},
{
"Action": [
"s3:GetObjectVersionForReplication",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
],
"Effect": "Allow",
"Resource": [
"${aws_s3_bucket.s3_bucket_master.arn}/*"
]
},
{
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags"
],
"Effect": "Allow",
"Resource": "${aws_s3_bucket.s3_bucket_slave.arn}/*"
}
]
}
POLICY
}
resource "aws_iam_role_policy_attachment" "replication" {
role = aws_iam_role.iam_role_replication.name
policy_arn = aws_iam_policy.iam_policy_replication.arn
}
resource "aws_s3_bucket" "s3_bucket_slave" {
bucket_prefix = "s3-bucket-slave-"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_bucket_slave_sse_config" {
bucket = aws_s3_bucket.s3_bucket_slave.bucket
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.kms_key.arn
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_versioning" "s3_bucket_slave_versioning" {
bucket = aws_s3_bucket.s3_bucket_slave.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket" "s3_bucket_master" {
provider = aws.apac
bucket_prefix = "s3-bucket-master-"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_bucket_master_sse_config" {
bucket = aws_s3_bucket.s3_bucket_master.bucket
provider = aws.apac
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.kms_key.arn
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_versioning" "s3_bucket_master_versioning" {
provider = aws.apac
bucket = aws_s3_bucket.s3_bucket_master.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_replication_configuration" "s3_bucket_master_replication" {
provider = aws.apac
# Must have bucket versioning enabled first
depends_on = [aws_s3_bucket_versioning.s3_bucket_master_versioning]
role = aws_iam_role.iam_role_replication.arn
bucket = aws_s3_bucket.s3_bucket_master.id
rule {
id = "foobar"
delete_marker_replication {
status = "Disabled"
}
filter {
prefix = "foo"
}
status = "Enabled"
destination {
bucket = aws_s3_bucket.s3_bucket_slave.arn
storage_class = "STANDARD"
}
}
}
resource "aws_s3_bucket_acl" "s3_bucket_master_acl" {
bucket = aws_s3_bucket.s3_bucket_master.id
acl = "private"
provider = aws.apac
}
resource "aws_s3_bucket_acl" "s3_bucket_slave_acl" {
bucket = aws_s3_bucket.s3_bucket_slave.id
acl = "log-delivery-write"
}
resource "aws_s3_bucket_public_access_block" "s3_bucket_master_public_access" {
provider = alias.apac
bucket = aws_s3_bucket.s3_bucket_master.id
restrict_public_buckets = true
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
}
resource "aws_s3_bucket_public_access_block" "s3_bucket_slave_public_access" {
bucket = aws_s3_bucket.s3_bucket_slave.id
restrict_public_buckets = true
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
}
resource "aws_s3_bucket_logging" "example" {
provider = alias.apac
bucket = aws_s3_bucket.s3_bucket_master.id
target_bucket = aws_s3_bucket.s3_bucket_slave.id
target_prefix = "log/"
}
provider.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.22.0"
}
null = {
source = "hashicorp/null"
version = "3.1.1"
}
alias = {
source = "hashicorp/aws"
version = "4.22.0"
}
}
}
provider "null" {
# Configuration options
}
# Configure AWS provider:
provider "aws" {
region = "ap-southeast-2"
}
provider "aws" {
alias = "apac"
region = "ap-southeast-1"
}
kms.tf
resource "aws_kms_key" "kms_key" {
description = "This key is used to encrypt bucket objects"
deletion_window_in_days = 10
enable_key_rotation = true
}
Unfortunately, I am getting errors like the below:
╷
│ Warning: Duplicate required provider
│
│ on provider.tf line 4, in terraform:
│ 4: aws = {
│ 5: source = "hashicorp/aws"
│ 6: version = "4.22.0"
│ 7: }
│
│ Provider hashicorp/aws with the local name "aws" was previously required as "alias". A provider can only be required once within required_providers.
│
│ (and one more similar warning elsewhere)
╵
╷
│ Error: error putting S3 bucket (s3-bucket-master-20220712130829925900000001) logging: CrossLocationLoggingProhibitted: Cross S3 location logging not allowed.
│ status code: 403, request id: 85528RE6KMQJDMJM, host id: 3cpcDdHT3Wl442f7L/x3VLCp26wCghaIPTwKKhnWLOmsTW4cSI9f5pFROHr7q4fDLQJMyfNBZIA=
│
│ with aws_s3_bucket_logging.example,
│ on s3.tf line 166, in resource "aws_s3_bucket_logging" "example":
│ 166: resource "aws_s3_bucket_logging" "example" {
│
╵
What help I am seeking from more experienced people is
What part code do I need to delete to make SRR? thereby resolve the error.
Any idea how to suppress the warning for alias?
Do note if I remote the section
alias = {
source = "hashicorp/aws"
version = "4.22.0"
}
I get errors like the below for ** terraform init **
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/alias: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/alias
│
│ All modules should specify their required_providers so that external consumers will get the correct providers when using a module. To see which
│ modules are currently depending on hashicorp/alias, run the following command:
│ terraform providers
╵
terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/aws] 4.22.0
├── provider[registry.terraform.io/hashicorp/null] 3.1.1
└── provider[registry.terraform.io/hashicorp/alias]
Providers required by state:
provider[registry.terraform.io/hashicorp/aws]
CodePudding user response:
You don't need to define the aws
twice in the required_providers
block, it's enough to be defined only once:
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.22.0"
}
null = {
source = "hashicorp/null"
version = "3.1.1"
}
}
}
Then, you need to remove the .terraform
directory prior to re-running terraform init
to make sure you have a clean slate. Lastly, make sure if you want SRR and not CRR to use either the aliased or non-aliased provider, but not both.
So you are currently defining one of the buckets as:
resource "aws_s3_bucket" "s3_bucket_slave" {
bucket_prefix = "s3-bucket-slave-"
}
And the second one as:
resource "aws_s3_bucket" "s3_bucket_master" {
provider = aws.apac # <---- note the aliased provider, hence a different region
bucket_prefix = "s3-bucket-master-"
}
In order to fix that, either remove the aliased provider from the second bucket or add it to the first one. As you current configuration is using aws.apac
in more places than it is not, I would suggest adding the aliased provider to the first bucket if the region is not important:
resource "aws_s3_bucket" "s3_bucket_slave" {
provider = aws.apac
bucket_prefix = "s3-bucket-slave-"
}