Terraform ELB S3 权限问题

Posted

技术标签:

【中文标题】Terraform ELB S3 权限问题【英文标题】:Terraform ELB S3 Permissions Issue 【发布时间】:2017-09-08 00:40:02 【问题描述】:

我在使用 Terraform (v0.9.2) 向 ELB 添加服务时遇到问题(我正在使用: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 账户中运行)。

bucket和ELB都在eu-west-2

任何关于问题可能是什么的想法都将不胜感激。

【问题讨论】:

【参考方案1】:

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 data source 自动获取用于写入日志的帐户 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"
  

【讨论】:

在政策中正确使用Resource 对我来说是解决问题的方法。文档要求类似"arn:aws:s3:::my-loadbalancer-logs/my-app/AWSLogs/123456789012/*". Leaving off the account id at the end worked (e.g. "arn:aws:s3:::my-loadbalancer-logs/my-app/AWSLogs/*"`)【参考方案2】:

即使拥有文档中的所有内容,我仍然不断收到“拒绝访问存储桶”错误。从存储桶中删除加密对我有用。

【讨论】:

谢谢,为我解决了这个问题。您是否找到了一种方法来修改政策,从而不再需要这样做? 不,我停止尝试,因为这对我的情况并不重要。很想听听是否有人找到了实现这项工作的方法。【参考方案3】:

在存储桶策略中,帐号必须不是您的。相反,它属于 AWS,对于每个区域,您应该在存储桶策略中使用的帐号列在:https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html#attach-bucket-policy

例如,对于us-east-1 区域,帐号是127311923021

虽然问题是关于 Terraform,但我发布了 CloudFormation sn-p 为 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,因为这是AWS账号,us-east-1中的账号应该使用。

【讨论】:

【参考方案4】:

存储桶权限 当您启用访问日志时,您必须为访问日志指定一个 S3 存储桶。桶必须满足以下要求。 要求 存储桶必须与负载均衡器位于同一区域。 需要 Amazon S3 托管的加密密钥 (SSE-S3)。不支持其他加密选项。 存储桶必须具有授予 Elastic Load Balancing 将访问日志写入您的存储桶的权限的存储桶策略。存储桶策略是使用访问策略语言编写的 JSON 语句的集合,用于定义存储桶的访问权限。每个语句都包含有关单个权限的信息并包含一系列元素。

使用以下选项之一准备 S3 存储桶以进行访问日志记录。

需要 Amazon S3 托管的加密密钥 (SSE-S3)。不支持其他加密选项。

所以 AWS 文档说不支持 KMS...

【讨论】:

【参考方案5】:

在我的例子中,request_payer 选项设置为Requester。需要设置为BucketOwner 才能工作。

【讨论】:

以上是关于Terraform ELB S3 权限问题的主要内容,如果未能解决你的问题,请参考以下文章

Terraform 配置 LB 属性失败

使用 terraform 启动 aws elb 实例

如何赋予目标存储桶日志传递组 WRITE 和 READ_ACP 权限?

如何授予 AKS 通过 terraform 访问 ACR 的权限?

Terraform - 具有编程访问权限的 AWS IAM 用户

如何使用 terraform 创建具有访问权限和密钥的 AWS IAM 服务账户