ELBにサービスを追加するTerraform(v0.9.2)を使用して問題が発生しています(使用しているものは https://github.com/segmentio/stack/blob/master/s3-logs/main.tf )。
terraform apply
を実行すると、次のエラーが発生します。
* module.solr.module.elb.aws_elb.main: 1 error(s) occurred:
* aws_elb.main: Failure configuring ELB attributes:
InvalidConfigurationRequest: Access Denied for bucket: my-service-
logs. Please check S3bucket permission
status code: 409, request id: xxxxxxxxxx-xxxx-xxxx-xxxxxxxxx
私のサービスは次のようになります:
module "solr" {
source = "github.com/segmentio/stack/service"
name = "${var.prefix}-${terraform.env}-solr"
environment = "${terraform.env}"
image = "123456789876.dkr.ecr.eu-west-2.amazonaws.com/my-docker-image"
subnet_ids = "${element(split(",", module.vpc_subnets.private_subnets_id), 3)}"
security_groups = "${module.security.Apache_solr_group}"
port = "8983"
cluster = "${module.ecs-cluster.name}"
log_bucket = "${module.s3_logs.id}"
iam_role = "${aws_iam_instance_profile.ecs.id}"
dns_name = ""
zone_id = "${var.route53_zone_id}"
}
私のs3-logsバケットは次のようになります。
module "s3_logs" {
source = "github.com/segmentio/stack/s3-logs"
name = "${var.prefix}"
environment = "${terraform.env}"
account_id = "123456789876"
}
S3をチェックインしたところ、バケットポリシーは次のようになります。
{
"Version": "2012-10-17",
"Id": "log-bucket-policy",
"Statement": [
{
"Sid": "log-bucket-policy",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789876:root"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-service-logs/*"
}
]
}
私が見る限り、ELBはログを保存するためにS3バケットにアクセスできるはずです(同じAWSアカウントで実行されています)。
バケットとELBはすべてeu-west-2
にあります。
問題が何であるかについてのアイデアは大歓迎です。
ELBアクセスログの docs は、特定のAmazonアカウントに、自分のアカウントではなくS3への書き込みを許可したいことを示しています。
そのため、次のようなものが必要です。
{
"Id": "Policy1429136655940",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1429136633762",
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-loadbalancer-logs/my-app/AWSLogs/123456789012/*",
"Principal": {
"AWS": [
"652711504416"
]
}
}
]
}
Terraformでは、 aws_elb_service_accountデータソース を使用して、ドキュメントの例にあるように、ログの書き込みに使用されるアカウントIDを自動的にフェッチできます。
data "aws_elb_service_account" "main" {}
resource "aws_s3_bucket" "elb_logs" {
bucket = "my-elb-tf-test-bucket"
acl = "private"
policy = <<POLICY
{
"Id": "Policy",
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-elb-tf-test-bucket/AWSLogs/*",
"Principal": {
"AWS": [
"${data.aws_elb_service_account.main.arn}"
]
}
}
]
}
POLICY
}
resource "aws_elb" "bar" {
name = "my-foobar-terraform-elb"
availability_zones = ["us-west-2a"]
access_logs {
bucket = "${aws_s3_bucket.elb_logs.bucket}"
interval = 5
}
listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
}
ドキュメントですべてを持っている場合でも、「バケットのアクセスが拒否されました」エラーが発生し続けました。バケットから暗号化を削除するのがうまくいきました。
バケットポリシーでは、アカウント番号は自分のものではない必要があります。代わりにAWSに属しており、リージョンごとに、バケットポリシーで使用する必要があるアカウント番号は次のリストに記載されています https://docs.aws.Amazon.com/elasticloadbalancing/latest/classic/enable-access -logs.html#attach-bucket-policy
たとえば、us-east-1
リージョンの場合、アカウント番号は127311923021
です。
問題はTerraformについてですが、CloudFormationスニペットを投稿し、ELBのアクセスログのバケットを作成しました。
MyAccessLogsBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
MyAllowELBAccessBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref MyAccessLogsBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
AWS: "arn:aws:iam::127311923021:root"
Action:
- "s3:PutObject"
Resource: !Sub "arn:aws:s3:::${MyAccessLogsBucket}/AWSLogs/*"
原則として、127311923021
は、us-east-1
のアカウント番号に使用されるAWSアカウント番号であるため、使用されます。