Amazon web services 为什么在terraform中创建的S3 bucket需要bucket策略来授予对lambda的访问权限

Amazon web services 为什么在terraform中创建的S3 bucket需要bucket策略来授予对lambda的访问权限,amazon-web-services,amazon-s3,aws-lambda,terraform,aws-api-gateway,Amazon Web Services,Amazon S3,Aws Lambda,Terraform,Aws Api Gateway,我们使用云形成和terraform的组合,其中一些常见资源(如DynamoDB、S3)使用terraform创建,其他资源(如APIGateway)使用无服务器和云形成创建。所有资源都在同一AWS帐户中 我有一个地形的S3水桶 resource "aws_s3_bucket" "payment_bucket" { bucket = "payment-bucket-${var.env_name}" acl = "private" tags = merge( module

我们使用云形成和terraform的组合,其中一些常见资源(如DynamoDB、S3)使用terraform创建,其他资源(如APIGateway)使用无服务器和云形成创建。所有资源都在同一AWS帐户中

我有一个地形的S3水桶

resource "aws_s3_bucket" "payment_bucket" {
  bucket = "payment-bucket-${var.env_name}"
  acl    = "private"

  tags = merge(
    module.tags.base_tags,
    {
      "Name" = "payment-bucket-${var.env_name}"
    }
  )

  lifecycle {
    ignore_changes = [tags]
  }
}
当我运行tf apply时,这将在我的AWS帐户中创建一个私有bucket
支付bucket dev

我们在使用serverless创建的同一AWS帐户中有一个APIGateway,其中一个lambda需要访问该bucket,因此我为lambda函数创建了一个IAM角色,以授予访问该bucket的权限

  makePayment:
    name: makePayment-${self:provider.stage}
    handler: src/handler/makePayment.default
    events:
      - http:
          path: /payment
          method: post
          private: true
          cors: true
    iamRoleStatementsName: ${self:service}-${self:provider.stage}-makePayment-role
    iamRoleStatements:
      - Effect: Allow
        Action:
          - s3:PutObject
        Resource:
          - arn:aws:s3:::#{AWS::Region}:#{AWS::AccountId}:payment-bucket-${self:provider.stage}/capture/batch/*

但是,当我运行这个lambda
makepayment dev
时,它会抛出一个AccessDenied错误,除非我添加授予lambda角色访问权限的bucket策略

resource "aws_s3_bucket_policy" "payment_service_s3_bucket_policy" { 
..
..
}
当S3 bucket和lambda函数和角色在同一个帐户中时,为什么我需要添加S3 bucket策略?我错过什么了吗


另外,如果我使用
AWS::S3::bucket
创建了bucket,作为Apigateway所在的云形成堆栈的一部分(我们使用的是无服务器),我不需要添加bucket策略,而且一切正常。

我认为问题在于S3 bucket ARN不正确


S3 bucket ARN中没有帐户ID或区域。使用
arn:aws:s3:::mybucket/myprefix/*

我认为问题在于s3 bucket arn不正确


S3 bucket ARN中没有帐户ID或区域。使用
arn:aws:s3:::mybucket/myprefix/*

答案取决于应用地形平面图的aws IAM角色,因为aws s3 bucket-canted ACL规则:“private”限制bucket访问,因为:Owner获得完全控制权。其他人没有访问权限(默认)。根据文件:

在这一点上,您必须相对明确谁可以访问bucket。通常,如果我使用私有ACL,但希望AWS帐户中的每个其他角色都能访问bucket,我会将bucket策略附加到terraform AWS_s3_bucket资源,以首先允许访问bucket。然后,我通过另一个内联策略显式地授予lambda角色对所述bucket的访问权

在您的情况下,它看起来像这样:

// Allow access to the bucket
data "aws_iam_policy_document" "bucket_policy" {
  statement {
    sid = "S3 bucket policy for account access"

    actions = [
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject"
    ]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::{your_account_id_here}:root",
      ]
    }

    resources = [
      "arn:aws:s3:::test_bucket_name",
      "arn:aws:s3:::test_bucket_name/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "aws:PrincipalArn"
      values   = ["arn:aws:iam::{your_account_id_here}:role/*"]
    }
  }
}

resource "aws_s3_bucket" "this" {
  bucket = "test_bucket_name"
  acl    = "private"

  policy = data.aws_iam_policy_document.bucket_policy.json
}

// Grant the lambda IAM role permissions to the bucket
data "aws_iam_policy_document" "grant_bucket_access" {
  statement {
    sid = "AccessToTheAppAuxFilesBucket"
    actions = [
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject"
    ]

    resources = [
      "arn:aws:s3:::test_bucket_name/*",
      "arn:aws:s3:::test_bucket_name"
    ]
  }
}

// Data call to pull the arn of the lambda's IAM Role
data "aws_iam_role" "cloudformation_provisioned_role" {
  name = "the_name_of_the_lambdas_iam_role"
}

resource "aws_iam_role_policy" "iam_role_inline_policy" {
    name = "s3_bucket_access"
    role = data.aws_iam_role.cloudformation_provisioned_role.arn

    policy = data.aws_iam_policy_document.grant_bucket_access.json
}

答案取决于AWS IAM角色在应用terraform plan时扮演的角色,因为AWS s3 bucket canned ACL规则:“private”限制bucket访问,因为:Owner获得完全控制权。其他人没有访问权限(默认)。根据文件:

在这一点上,您必须相对明确谁可以访问bucket。通常,如果我使用私有ACL,但希望AWS帐户中的每个其他角色都能访问bucket,我会将bucket策略附加到terraform AWS_s3_bucket资源,以首先允许访问bucket。然后,我通过另一个内联策略显式地授予lambda角色对所述bucket的访问权

在您的情况下,它看起来像这样:

// Allow access to the bucket
data "aws_iam_policy_document" "bucket_policy" {
  statement {
    sid = "S3 bucket policy for account access"

    actions = [
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject"
    ]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::{your_account_id_here}:root",
      ]
    }

    resources = [
      "arn:aws:s3:::test_bucket_name",
      "arn:aws:s3:::test_bucket_name/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "aws:PrincipalArn"
      values   = ["arn:aws:iam::{your_account_id_here}:role/*"]
    }
  }
}

resource "aws_s3_bucket" "this" {
  bucket = "test_bucket_name"
  acl    = "private"

  policy = data.aws_iam_policy_document.bucket_policy.json
}

// Grant the lambda IAM role permissions to the bucket
data "aws_iam_policy_document" "grant_bucket_access" {
  statement {
    sid = "AccessToTheAppAuxFilesBucket"
    actions = [
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject"
    ]

    resources = [
      "arn:aws:s3:::test_bucket_name/*",
      "arn:aws:s3:::test_bucket_name"
    ]
  }
}

// Data call to pull the arn of the lambda's IAM Role
data "aws_iam_role" "cloudformation_provisioned_role" {
  name = "the_name_of_the_lambdas_iam_role"
}

resource "aws_iam_role_policy" "iam_role_inline_policy" {
    name = "s3_bucket_access"
    role = data.aws_iam_role.cloudformation_provisioned_role.arn

    policy = data.aws_iam_policy_document.grant_bucket_access.json
}

这是一个公开的错误。acl和force_destroy在terraform导入时没有很好地导入:

这是一个开放的bug。acl和force_destroy不能很好地与terraform导入一起导入。:

S3 bucket ARN中没有帐户ID或区域。使用
arn:aws:s3:::mybucket/myprefix/*
。谢谢!这解决了问题。S3 bucket ARN中没有帐户ID或区域。使用
arn:aws:s3:::mybucket/myprefix/*
。谢谢!这解决了问题。