1
votes

This is the current role I am using which is created through IAM console.
enter image description here Then, I tried to create another role with same permission using cloudformation referring below tutorial.
https://blog.petej.org/2020/01/04/infrastructure-as-code-with-aws-lambda-and-api-gateway/

However, after creating the roles, I find that all of the policy are inline policy.
Does it has any difference with my current role in terms of permission?
I use Role.json as a template for the stack.

Role.json

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
      "LambdaRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
          "RoleName": "hello-world-Admin",
          "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
              "Effect": "Allow",
              "Principal": {
                "Service": ["lambda.amazonaws.com"]
              },
              "Action": ["sts:AssumeRole"]
            }]
          },
          "Path": "/",
          "Policies": [{
              "PolicyName": "AWSLambdaBasicExecutionRole",
              "PolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [{
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "*"
                }]
              }
            },
            {
              "PolicyName": "AmazonS3GetObject",
              "PolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [{
                  "Effect": "Allow",
                  "Action": "s3:GetObject",
                  "Resource": [
                    "arn:aws:s3:::pj-lambda-functions/",
                    "arn:aws:s3:::pj-lambda-functions/*"
                  ]
                }]
              }
            },
            {
                "PolicyName": "AmazonS3FullAccess",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [{
                    "Effect": "Allow",
                    "Action": "s3:*",
                    "Resource": "*"
                    }]
                }
            },
            {
                "PolicyName": "AmazonDynamoDBFullAccess",
                "PolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Action": [
                                "dynamodb:*",
                                "dax:*",
                                "application-autoscaling:DeleteScalingPolicy",
                                "application-autoscaling:DeregisterScalableTarget",
                                "application-autoscaling:DescribeScalableTargets",
                                "application-autoscaling:DescribeScalingActivities",
                                "application-autoscaling:DescribeScalingPolicies",
                                "application-autoscaling:PutScalingPolicy",
                                "application-autoscaling:RegisterScalableTarget",
                                "cloudwatch:DeleteAlarms",
                                "cloudwatch:DescribeAlarmHistory",
                                "cloudwatch:DescribeAlarms",
                                "cloudwatch:DescribeAlarmsForMetric",
                                "cloudwatch:GetMetricStatistics",
                                "cloudwatch:ListMetrics",
                                "cloudwatch:PutMetricAlarm",
                                "datapipeline:ActivatePipeline",
                                "datapipeline:CreatePipeline",
                                "datapipeline:DeletePipeline",
                                "datapipeline:DescribeObjects",
                                "datapipeline:DescribePipelines",
                                "datapipeline:GetPipelineDefinition",
                                "datapipeline:ListPipelines",
                                "datapipeline:PutPipelineDefinition",
                                "datapipeline:QueryObjects",
                                "ec2:DescribeVpcs",
                                "ec2:DescribeSubnets",
                                "ec2:DescribeSecurityGroups",
                                "iam:GetRole",
                                "iam:ListRoles",
                                "kms:DescribeKey",
                                "kms:ListAliases",
                                "sns:CreateTopic",
                                "sns:DeleteTopic",
                                "sns:ListSubscriptions",
                                "sns:ListSubscriptionsByTopic",
                                "sns:ListTopics",
                                "sns:Subscribe",
                                "sns:Unsubscribe",
                                "sns:SetTopicAttributes",
                                "lambda:CreateFunction",
                                "lambda:ListFunctions",
                                "lambda:ListEventSourceMappings",
                                "lambda:CreateEventSourceMapping",
                                "lambda:DeleteEventSourceMapping",
                                "lambda:GetFunctionConfiguration",
                                "lambda:DeleteFunction",
                                "resource-groups:ListGroups",
                                "resource-groups:ListGroupResources",
                                "resource-groups:GetGroup",
                                "resource-groups:GetGroupQuery",
                                "resource-groups:DeleteGroup",
                                "resource-groups:CreateGroup",
                                "tag:GetResources"
                            ],
                            "Effect": "Allow",
                            "Resource": "*"
                        },
                        {
                            "Action": "cloudwatch:GetInsightRuleReport",
                            "Effect": "Allow",
                            "Resource": "arn:aws:cloudwatch:*:*:insight-rule/DynamoDBContributorInsights*"
                        },
                        {
                            "Action": [
                                "iam:PassRole"
                            ],
                            "Effect": "Allow",
                            "Resource": "*",
                            "Condition": {
                                "StringLike": {
                                    "iam:PassedToService": [
                                        "application-autoscaling.amazonaws.com",
                                        "dax.amazonaws.com"
                                    ]
                                }
                            }
                        },
                        {
                            "Effect": "Allow",
                            "Action": [
                                "iam:CreateServiceLinkedRole"
                            ],
                            "Resource": "*",
                            "Condition": {
                                "StringEquals": {
                                    "iam:AWSServiceName": [
                                        "replication.dynamodb.amazonaws.com",
                                        "dax.amazonaws.com",
                                        "dynamodb.application-autoscaling.amazonaws.com",
                                        "contributorinsights.dynamodb.amazonaws.com"
                                    ]
                                }
                            }
                        }
                    ]
                }
            },
            {
                "PolicyName" : "CognitoUserPoolsManagement",
                "PolicyDocument" : {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Sid": "VisualEditor0",
                            "Effect": "Allow",
                            "Action": "cognito-idp:ListUsers",
                            "Resource": "*"
                        }
                    ]
                }
            },
            {
                "PolicyName" : "DynamoDBWriteAccess",
                "PolicyDocument" : {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Sid": "VisualEditor0",
                            "Effect": "Allow",
                            "Action": [
                                "dynamodb:PutItem",
                                "dynamodb:DeleteItem",
                                "dynamodb:GetItem",
                                "dynamodb:Scan",
                                "dynamodb:UpdateItem"
                            ],
                            "Resource": "arn:aws:dynamodb:us-east-1:063575524122:table/test_users"
                        }
                    ]
                }
            },
            {
                "PolicyName" : "hello-world-s3-policy",
                "PolicyDocument" : {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Sid": "VisualEditor0",
                            "Effect": "Allow",
                            "Action": [
                                "s3:PutObject",
                                "s3:GetObject",
                                "s3:PutObjectAcl"
                            ],
                            "Resource": "arn:aws:s3:::kwai-tsing-dev/*"
                        }
                    ]
                }
            }
          ]
        }
      },
      "ApiGatewayRole": {
        "Type": "AWS::IAM::Role",
        "Properties": {
          "RoleName": "kwai-tsing-api-for-lambda",
          "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
              "Effect": "Allow",
              "Principal": {
                "Service": ["apigateway.amazonaws.com"]
              },
              "Action": ["sts:AssumeRole"]
            }]
          },
          "Policies": [{
              "PolicyName": "AWSApiGateWay",
              "PolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [{
                  "Effect": "Allow",
                  "Action": "lambda:InvokeFunction",
                  "Resource": "*"
                }]
              }
            },
            {
              "PolicyName": "ApiGatewayFullAccess",
              "PolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [{
                  "Effect": "Allow",
                  "Action": [
                    "apigateway:*"
                  ],
                  "Resource": "*"
                }]
              }
            }
          ]
        }
      },
      "MyRestApi": {
        "Type": "AWS::ApiGateway::RestApi",
        "Properties": {
            "Body": {
                "OpenAPI specification": null
            },
            "Description": "A test API",
            "Name": "MyRestAPI"
        }
    }
    }
  }

On the other hand, I would like to ask below questions as I am a beginner of aws cloudformation.
1.what is the most popular option to manage the stack, by CLI or creating the stack in cloudformation console directly?
2.How to decide the contents of the template, for example, if I use api gateway,lambda and dynamodb together, should I create 3 seperate template files, or a single files contain all of them?

2

2 Answers

2
votes

If you don't want to use inline policies, then you have to create AWS::IAM::ManagedPolicy first, and then reference it in your role in ManagedPolicyArns.

Does it has any difference with my current role in terms of permission?

No it does not. The benefit of managed policies is that you can create one manage policy and reference it in multiple roles, users or groups. Whereas, inline policies always have to be duplicated, which makes it more difficult to manage.

1.what is the most popular option to manage the stack, by CLI or creating the stack in cloudformation console directly?

Depends on your use-case. There is no one correct answer to suite all possible scenarios. But if you want to go fully in IaC, then console deployments should be avoided, and you should keep everything as code under source control, including deployment procedures/scripts.

How to decide the contents of the template, for example, if I use api gateway,lambda and dynamodb together, should I create 3 separate template files, or a single files contain all of them?

Again, it depends. If they are part of the same application, I would keep them in one template. As with one deployment you create entire application stack, and same when you tear it down. But if they are totally unrelated to each other, I would keep them separate, which gives you more room and freedom on their modifications.

1
votes

The answer is yes there will be differences as the first role you create uses the AWS Managed policy AdminstratorAccess if you have an Inline policy that allowed the same permissions then there would be no difference.

  1. Most popular is Cloudformation/Terraform/CDK/Pulumi I like to use Cloudformation
  2. If you can separate the resources into Nested Cloudformation stacks as much as possible that is the best practice i.e https://github.com/aws-samples/ecs-refarch-cloudformation/blob/master/master.yaml