5
votes

In my AWS account, I am building a new Cloudformation template that creates new policies, and I want to attach those to a few existing roles in the account. Here is how I have been trying to reference them:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Names of existing roles to which the restrictive policies need added",
    "Parameters": {
        "AdditionalExecutionRoleParameter": {
            "Type": "AWS::IAM::Role",
            "Default": "CloudOps"
        }
    },
    "Resources": { (and so on)

Then down in the section below the new policies, I have been trying to reference these existing roles ("AdditionalExecutionRoleParameter" in this case) and attach the policies to them using the Roles parameter. However, I keep getting a "failed to retrieve external values" error when trying to deploy the CloudFormation template... I've tried inputting "CloudOps", which is the role name, as the parameter "Default", and I've also tried inputting the role ARN there... nothing is working.

2
Could you provide the relevant section of the template shownig how and where you are referencing AdditionalExecutionRoleParameter? - Marcin
Sure... I'm referencing it down with the other roles: }, "Roles": [ { "Ref": "NewRoleNoProblem" }, { "Ref": "AdditionalExecutionRoleParameter" } ] } }, There's no issue with attaching the policies to the new roles that I'm creating within the template; the issue is how to attach to existing roles in the account that my template isn't creating - lorena
Ah i see. @jarmod already pointed out the issue. Can use String data type instead of AWS::IAM::Role to pass the role. - Marcin
Sorry, I should have mentioned I already tried that... and I got this error when I tried to deploy: The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_- (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: f2958ace-4cf8-4079-a447-eb3fe3bbe8e0) What I'd inputted was the role ARN, using * as the account ID so I can deploy to multiple accounts. Any other ideas? - lorena
That may be... thank you for the advice! I am pretty familiar with CFTs but not so much with macros, etc., or how I would implement that in a useful way with my templates. I'll have to look into it. - lorena

2 Answers

6
votes

Not all AWS resource types are supported in the parameter type field.

The full list is at AWS-Specific Parameter Types. It includes, for example:

  • AWS::EC2::VPC::Id
  • List<AWS::EC2::VPC::Id>
  • AWS::SSM::Parameter::Name

This list does not include AWS::IAM::Role (or any IAM resources).

If you're simply trying to associate a new IAM policy with an existing named IAM role, then note that the AWS::IAM::Policy construct has a Roles property and you should supply a list of role names to apply the policy to. It requires role names, not role ARNs, so you don't need the account ID.

If you do ever need the account ID then it's available as a pseudo-parameter and you can get it from "Ref" : "AWS::AccountId", but I don't think you need it here.

Here's a JSON example of how to create a new IAM policy (allowing s3:Get* on mybucket/*) and associate it with an existing IAM role, whose name you supply as a parameter to the stack:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Add policy to role test",
  "Parameters": {
    "TheRoleName": {
      "Type": "String",
      "Default": "CloudOps",
      "Description": "Name of role to associate policy with"
    }
  },
  "Resources": {
    "ThePolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "s3-read",
        "PolicyDocument": {
          "Statement": {
            "Effect": "Allow",
            "Action": [
              "s3:Get*"
            ],
            "Resource": ["arn:aws:s3:::mybucket/*"]
          }
        },
        "Roles": [
          {
            "Ref": "TheRoleName"
          }
        ]
      }
    }
  }
}
2
votes

Well... what I ended up doing is something as simple as this, which works fine...

"Parameters": {
    "RoleNameRoleParameter": {
        "Type": "String",
        "Default": "RoleNameRole"