How to get an AWS role's friendly name from its ARN?

Viewed 878

I am trying to attach a policy to an IAM role in Terraform. I only know the ARN number of the role, not its "friendly name". But the policy attachment function requires me to use a friendly name, instead of the ARN number.

How can I get the friendly name of an IAM role if I already have the ARN number?

Here's what I have so far -- it's giving me "ValidationError: The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_-". I believe this is because I am using the ARN number of the role name instead of the friendly role name.

resource "aws_iam_role_policy_attachment" "my-policy-attachment" {
  role       = "arn:aws:iam::my_user_account_id:role/my_role_name"
  policy_arn = aws_iam_policy.my_policy.arn
}

Thanks!

3 Answers

The "friendly name" is just the last part of the ARN.

So for arn:aws:iam::my_user_account_id:role/my_role_name the friendly name will be my_role_name. You can use Terraform to naively get at this by using split like this:

resource "aws_iam_role_policy_attachment" "my-policy-attachment" {
  role       = split("/", "arn:aws:iam::my_user_account_id:role/my_role_name")[1]
  policy_arn = aws_iam_policy.my_policy.arn
}

Or, maybe more nicely, like this:

variable "role_arn" {}

locals {
  role_friendly_name = split("/", var.role_arn)[1]
}

resource "aws_iam_role_policy_attachment" "my-policy-attachment" {
  role       = local.role_friendly_name
  policy_arn = aws_iam_policy.my_policy.arn
}

That works for this case but you might also need to consider roles that have a path prefix in them as well. This would then give you an ARN that looks more like arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole so the above would return service-role instead.

In some languages you can use negative indexing to access things from the end of the list but Terraform/HCL2 doesn't currently allow that (see this feature request). So instead we need to use the length function as well:

variable "role_arn" {}

locals {
  role_split = split("/", var.role_arn)[1]
  role_friendly_name = local.role_split[length(local.role_split) - 1]
}

resource "aws_iam_role_policy_attachment" "my-policy-attachment" {
  role       = local.role_friendly_name
  policy_arn = aws_iam_policy.my_policy.arn
}
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn#resource

data "aws_arn" "ecs_role" {
  arn = aws_iam_role.ecs_task_role.arn
}

Example arn from above is = arn:aws:iam:abc:role/app/task/ecs_task_role

# https://www.terraform.io/language/functions/trimprefix

locals {
  ecs_task_role_name = trimprefix(data.aws_arn.ecs_role.resource, "role/")
}

data.aws_arn_ecs_role.resource would resolve to: role/app/task/ecs_task_role. Now trimprefix can be used to split role out of the data output.

Can also use functions like trimprefix. Helps in this case to get a load balancer name from an arn.

load_balancer_arn = "arn:aws:elasticloadbalancing:us-east-1:xxxxx:loadbalancer/app/awseb-AWSEB-xxxx/xxxxxx"

locals {
  arn_split          = split("/", var.load_balancer_arn)
  load_balancer_name = trimprefix(trimprefix(var.load_balancer_arn, local.arn_split[0]), "/")
}

returns "app/awseb-AWSEB-xxxx/xxxxxx"
Related