Reputation: 1457
I have the following trust policy:
data "aws_iam_policy_document" "lambda_role_policy" {
statement {
sid = "LightsailFullAccess"
effect = "Allow"
resources = ["arn:aws:lightsail:::*"]
not_actions = [
"lightsail:GetInstanceAccessDetails",
"lightsail:GetRelationalDatabaseMasterUserPassword"
]
}
statement {
sid = "LogsFullAccess"
effect = "Allow"
resources = ["arn:aws:logs:::*"]
actions = ["logs:*"]
}
}
and then I am using a module (https://github.com/terraform-aws-modules/terraform-aws-iam/tree/master/modules/iam-assumable-role):
module "iam_assumable_role_custom_trust_policy" {
source = "git::https://github.com/terraform-aws-modules/terraform-aws-iam//modules/iam-assumable-role?ref=e63dff8de9f6aee7e9ebfbe8c676fa980f5233c0"
#version = "5.33.0"
create_role = true
trusted_role_actions = ["sts:AssumeRole"]
role_name = "LambdaModifyLightsailSnapshotsRole"
role_description = "Policy to Create / Delete Lightsail Snapshots"
create_custom_role_trust_policy = true
custom_role_trust_policy = data.aws_iam_policy_document.lambda_role_policy.json
}
When I execute the terraform I get the following error:
Error: creating IAM Role (LambdaModifyLightsailSnapshotsRole): MalformedPolicyDocument: Has prohibited field Resource
Any help resolving would be appreciated. Thanks
As requested please find the plan output below:
# module.create_instance_snapshot_lambda.data.aws_iam_policy_document.logs[0] will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "logs" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
]
+ effect = "Allow"
+ resources = (known after apply)
}
}
# module.prune_instance_snapshot_lambda.data.aws_iam_policy_document.logs[0] will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "logs" {
+ id = (known after apply)
+ json = (known after apply)
+ statement {
+ actions = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
]
+ effect = "Allow"
+ resources = (known after apply)
}
}
# module.sns.data.aws_iam_policy_document.this[0] will be read during apply
# (config refers to values not yet known)
<= data "aws_iam_policy_document" "this" {
+ id = (known after apply)
+ json = (known after apply)
+ override_policy_documents = []
+ source_policy_documents = []
+ statement {
+ actions = [
+ "sns:AddPermission",
+ "sns:DeleteTopic",
+ "sns:GetTopicAttributes",
+ "sns:ListSubscriptionsByTopic",
+ "sns:Publish",
+ "sns:RemovePermission",
+ "sns:SetTopicAttributes",
+ "sns:Subscribe",
]
+ effect = "Allow"
+ resources = [
+ (known after apply),
]
+ sid = "__default_statement_ID"
+ condition {
+ test = "StringEquals"
+ values = [
+ "074217812019",
]
+ variable = "AWS:SourceOwner"
}
+ principals {
+ identifiers = [
+ "*",
]
+ type = "AWS"
}
}
}
Roles
# module.create_instance_snapshot_lambda.aws_iam_role.lambda[0] will be created
+ resource "aws_iam_role" "lambda" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "lambda.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = true
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "createLightSailSnapshots"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# module.create_instance_snapshot_lambda.aws_iam_role_policy_attachment.logs[0] will be created
+ resource "aws_iam_role_policy_attachment" "logs" {
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "createLightSailSnapshots"
}
# module.eventbridge.aws_iam_role.eventbridge[0] will be created
+ resource "aws_iam_role" "eventbridge" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "events.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = true
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "default"
+ name_prefix = (known after apply)
+ path = "/"
+ tags = {
+ "Name" = "default"
}
+ tags_all = {
+ "Name" = "default"
}
+ unique_id = (known after apply)
}
# module.iam_assumable_role_custom_trust_policy.aws_iam_role.this[0] will be created
+ resource "aws_iam_role" "this" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Effect = "Allow"
+ NotAction = [
+ "lightsail:GetRelationalDatabaseMasterUserPassword",
+ "lightsail:GetInstanceAccessDetails",
]
+ Resource = "arn:aws:lightsail:::*"
+ Sid = "LightsailFullAccess"
},
+ {
+ Action = "logs:*"
+ Effect = "Allow"
+ Resource = "arn:aws:logs:::*"
+ Sid = "LogsFullAccess"
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ description = "Policy to Create / Delete Lightsail Snapshots"
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "LambdaModifyLightsailSnapshotsRole"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# module.prune_instance_snapshot_lambda.aws_iam_role.lambda[0] will be created
+ resource "aws_iam_role" "lambda" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "lambda.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = true
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "pruneLightSailSnapshots"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# module.prune_instance_snapshot_lambda.aws_iam_role_policy_attachment.logs[0] will be created
+ resource "aws_iam_role_policy_attachment" "logs" {
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "pruneLightSailSnapshots"
}
Upvotes: 0
Views: 160
Reputation: 74499
Broadly speaking, AWS IAM has two main different kinds of policy: Identity-based policies, and Resource-based policies.
These two kinds of policy differ in what they are attached to and, conversely, in what they may specify:
Syntactically then, the main difference is that identity-based policies have Resource
/NotResource
elements, while resource-based policies have Principal
/NotPrincipal
elements. It isn't valid to include a Resource
element in a resource-based policy, because the resource is implied to be whatever object the policy was attached to.
An assume-role policy is an awkward special case in this taxonomy, because it's a resource-based policy where the resource is actually a principal! Specifically, it's an IAM role. When assuming a role, the principal is the user or role that is trying to assume the role, and the resource is the role they are trying to assume. An assume role policy is attached to the target role, and confers access to the principal trying to assume it, and so it must be written as a resource-based policy where the Principal
elements describe who may assume the role.
The assume role policy you've assigned to module.iam_assumable_role_custom_trust_policy.aws_iam_role.this[0]
is invalid in two ways:
lightsail:GetRelationalDatabaseMasterUserPassword
, lightsail:GetInstanceAccessDetails
, and logs:*
, which are not actions that can be taken against an IAM role. The only actions that make sense in this context are the "assume role" family of actions, such as sts:AssumeRole
, or sts:AssumeRoleWithWebIdentity
.Resource
instead of Principal
, and so it isn't stating which principals are allowed to perform the action. This is what the error message is referring to.There are some missing parts in the information you've shared in your question which mean that I cannot give a full working example, but the shape of the solution here will be:
assume_role_policy
arguments to be valid assume role policies, which means that they must all be resource-based policies with Principal
elements describing who can perform actions like sts:AssumeRole
against the role.aws_iam_role_policy_attachment
(to attach an existing named policy object) or iam_role_policy
(to specify an "inline policy" which lives directly on the role and isn't attachable anywhere else). This is the policy that should include Resource
elements and describe what actions can be taken once the role has already been assumed. The access rules about lightsail:GetRelationalDatabaseMasterUserPassword
etc belong here.The main takeaways to keep in mind are:
sts:AssumeRole
.Some of my previous answers to other questions have more context on this topic:
Upvotes: 0