我正在学习 Terraform。我正在尝试创建一个新的 Lambda 函数。我意识到我还需要创建一个 IAM 角色。所以我尝试使用 Terraform 来完成这两件事。但它不允许我创建这个角色。
这是我的 Terraform 文件
provider "aws" {
profile = "default"
region = "eu-west-1"
}
data "aws_iam_policy" "AWSLambdaBasicExecutionRole" {
arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_iam_role" "terraform_function_role" {
name = "terraform_function_role"
assume_role_policy = "${data.aws_iam_policy.AWSLambdaBasicExecutionRole.policy}"
}
resource "aws_lambda_function" "terraform_function" {
filename = "terraform_function.zip"
function_name = "terraform_function"
handler = "index.handler"
role = "${aws_iam_role.terraform_function_role.id}"
runtime = "nodejs8.10"
source_code_hash = "${filebase64sha256("terraform_function.zip")}"
}
这是我遇到的错误
Error creating IAM Role terraform_function_role: MalformedPolicyDocument: Has prohibited field Resource
status code: 400
我该如何解决这个问题?
IAM角色的信任关系(或承担角色策略)定义了哪些资源/服务可以承担该角色。在此,我们没有定义 Resource 字段。因此,我们无法附加 IAM 策略或按原样使用该策略。信任关系的正确格式是:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
在此场景中,您账户中的所有 Lambda 函数都可以承担此角色。
您可以参考这个 AWS 链接了解更多示例。
编辑:基于@ydaetskcoR评论,这是一个工作示例:
provider "aws" {
profile = "default"
region = "eu-west-1"
}
data "aws_iam_policy_document" "AWSLambdaTrustPolicy" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "terraform_function_role" {
name = "terraform_function_role"
assume_role_policy = data.aws_iam_policy_document.AWSLambdaTrustPolicy.json
}
resource "aws_iam_role_policy_attachment" "terraform_lambda_policy" {
role = aws_iam_role.terraform_function_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "terraform_function" {
filename = "terraform_function.zip"
function_name = "terraform_function"
handler = "index.handler"
role = aws_iam_role.terraform_function_role.arn
runtime = "nodejs8.10"
source_code_hash = filebase64sha256("terraform_function.zip")
}
您的代码的更改包括以下内容:
由于您仍处于学习阶段,我建议您改为使用
terraform 0.12
,这样您就可以使用templatefile
之类的东西。因此你不需要创建 data
对象。
另一件事是在创建策略时始终使用最小权限原则,这意味着您的资源(在本例中为 Lambda)只能访问其需要的内容。目前,只有 CloudWatch,但在现实世界中情况很可能并非如此。
回到您的问题,以下是如何创建 IAM 角色、IAM 策略、最后的 IAM 策略附件(这是策略和角色之间的桥梁)以及 AssumeRolePolicy(这是服务之间的信任关系)它将使用它和角色本身)。我已经将它们全部提取到模板中,以便以后更容易维护。要点(为了更容易用眼睛阅读)可以在here找到。
# iam_role
resource "aws_iam_role" "iam_role" {
name = "iam-role"
assume_role_policy = templatefile("${path.module}/templates/lambda-base-policy.tpl", {})
}
#content of lambda-base-policy.tpl
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
#iam_policy
resource "aws_iam_policy" "policy" {
name = "policy"
policy = templatefile("${path.module}/templates/cloudwatch-policy.tpl", {})
}
#content of cloudwatch-policy.tpl
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
#iam_policy_attachment
resource "aws_iam_policy_attachment" "policy_attachment" {
name = "attachment"
roles = ["${aws_iam_role.iam_role.name}"]
policy_arn = "${aws_iam_policy.policy.arn}"
}
正如评论中提到的,您必须创建假设角色,然后将假设规则附加到新创建的策略中,这是完整的工作示例。
#assume role
resource "aws_iam_role" "role" {
name = "test-alb-logs-to-elk"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
# Created Policy for IAM Role (s3 and log access)
resource "aws_iam_policy" "policy" {
name = "my-test-policy"
description = "A test policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
EOF
}
# Attached IAM Role and the new created Policy
resource "aws_iam_role_policy_attachment" "test-attach" {
role = "${aws_iam_role.role.name}"
policy_arn = "${aws_iam_policy.policy.arn}"
}
# Created AWS Lamdba Function: Memory Size, NodeJS version, handler, endpoint, doctype and environment settings
resource "aws_lambda_function" "elb_logs_to_elasticsearch" {
function_name = "mytest-alb-logs-to-elk"
description = "elb-logs-to-elasticsearch"
memory_size = 1024
filename = "terraform_function.zip"
runtime = "nodejs8.10"
role = "${aws_iam_role.role.arn}"
handler = "index.handler"
}