{"id":1347,"date":"2020-04-30T18:04:16","date_gmt":"2020-04-30T16:04:16","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=1347"},"modified":"2021-03-24T12:22:02","modified_gmt":"2021-03-24T11:22:02","slug":"aws-cloudformation-aws-iam-how-to-delegate-deployment-safely","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/aws-cloudformation-aws-iam-how-to-delegate-deployment-safely\/","title":{"rendered":"AWS CloudFormation – AWS IAM: how to delegate deployment safely"},"content":{"rendered":"

Day by day the number of companies that look with interest at the cloud computing world increases and many of them wonder how the cloud can help their business and which security flaws it can introduce. One of the most complicated tasks\u00a0 of the security team in fact is to understand how to exploit novel cloud technologies, with their unprecedented flexibility, without introducing security vulnerabilities.\u00a0<\/span><\/p>\n

One of the most useful tools to enforce compliance with security best practices is certainly Infrastructure as Code (IaC), which allows us to handle our resources inside the cloud environment through templating systems. This makes it possible to deploy the infrastructure in a repeatable and reproducible way.<\/span><\/p>\n

What is AWS CloudFormation?<\/span><\/h2>\n

In this article we will focus on the AWS service called AWS CloudFormation.<\/span><\/p>\n

CloudFormation lets you create, update and handle resources in your AWS Cloud Environment through the use of JSON or YAML templates in which you can describe resource by resource your own infrastructure.<\/span><\/p>\n

 <\/p>\n

This leads to a huge set of questions: how can I have control on who deploy what? If I can handle each resource, can I also handle resources permissions? If I can handle permissions, how can I delegate the use of CloudFormation to other parties or team members without the risk of privileges escalation attacks?<\/span><\/p>\n

To answer these questions we need to introduce another service: AWS Identity Access Management (AWS IAM).<\/span><\/p>\n

What is AWS IAM?<\/span><\/h2>\n

AWS Identity and Access Management (IAM) is the AWS service that allows one to handle all permissions inside your AWS Cloud Environment. If you want to execute any action (using the Console, the CLI or the SDK) the permission to do so has to be written inside a policy attached to your \u201cuser\u201d.\u00a0<\/span><\/p>\n

Use Case<\/span><\/h2>\n

Now that we know which are the instruments we can use, let\u2019s describe a very common situation: we created a CloudFormation template that provisions an infrastructure composed by a pre-configured EC2 instance (through Amazon Machine Image) which needs to access an S3 bucket. Being a simple infrastructure, we would like to allow the developers to deploy this template without asking the Security team.<\/span><\/p>\n

\"\"<\/p>\n

More farsighted people know that to deploy this infrastructure the CloudFormation template needs to create an IAM Role for the EC2. Thus we need to make sure that the developer who will run the template will not be able to modify the policies of this role in order to give the EC2 (and thus himself) wider permission (e.g. admin access).<\/span><\/p>\n

Without Permission Boundaries<\/span><\/h2>\n

The template that we will deploy is the following one:<\/span><\/p>\n

 <\/p>\n

---\r\nAWSTemplateFormatVersion: '2010-09-09'\r\nDescription: |\r\n CloudFormation and IAM Permission Boundaries Demo\r\n \r\n \r\n################################################################################\r\n#                                  Metadata                                    #\r\n################################################################################\r\nMetadata:\r\n \r\n AWS::CloudFormation::Interface:\r\n   ParameterGroups:\r\n     - Label: {default: 'Required parameters'}\r\n       Parameters:\r\n         - VpcId\r\n         - AmiId\r\n         - KeyName\r\n         - SubnetId\r\n     - Label: {default: 'Optional parameters'}\r\n       Parameters:\r\n         - NameSpace\r\n         - ProjectName\r\n         - Environment\r\n \r\n \r\n################################################################################\r\n#                                Parameters                                    #\r\n################################################################################\r\nParameters:\r\n \r\n NameSpace:\r\n   Type: String\r\n   Default: 'besharp'\r\n \r\n ProjectName:\r\n   Type: String\r\n   Default: 'permission-boundaries-demo'\r\n \r\n Environment:\r\n   Type: String\r\n   Default: 'dev'\r\n  VpcId:\r\n   Type: AWS::EC2::VPC::Id\r\n \r\n SubnetId:\r\n   Type: AWS::EC2::Subnet::Id\r\n \r\n AmiId:\r\n   Type: AWS::EC2::Image::Id\r\n \r\n KeyName:\r\n   Type: AWS::EC2::KeyPair::KeyName\r\n \r\n \r\n################################################################################\r\n#                                 Conditions                                   #\r\n################################################################################\r\nConditions: {}\r\n \r\n \r\n################################################################################\r\n#                                  Mappings                                    #\r\n################################################################################\r\nMappings: {}\r\n \r\n \r\n################################################################################\r\n#                                  Resources                                   #\r\n################################################################################\r\nResources:\r\n \r\n #################################### S3 ####################################\r\n S3Bucket:\r\n   Type: AWS::S3::Bucket\r\n   Properties:\r\n     BucketName: !Sub 'com.${NameSpace}.${ProjectName}'\r\n     Tags:\r\n       - Key: Name\r\n         Value: !Sub '${NameSpace}-${ProjectName}'\r\n       - Key: Owner\r\n         Value: 'name.surname@besharp.it'\r\n \r\n ################################### EC2 ####################################\r\n EC2Instance:\r\n   Type: AWS::EC2::Instance\r\n   Properties:\r\n     IamInstanceProfile: !Ref IAMInstanceProfile\r\n     ImageId: !Ref AmiId\r\n     InstanceType: t3a.micro\r\n     KeyName: !Ref KeyName\r\n     NetworkInterfaces:\r\n       - AssociatePublicIpAddress: 'true'\r\n         DeviceIndex: '0'\r\n         GroupSet:\r\n           - !Ref EC2SecurityGroup\r\n         SubnetId: !Ref SubnetId\r\n     Tags:\r\n       - Key: Name\r\n         Value: !Sub '${NameSpace}-${ProjectName}'\r\n       - Key: Owner\r\n         Value: 'name.surname@besharp.it'\r\n \r\n EC2SecurityGroup:\r\n   Type: AWS::EC2::SecurityGroup\r\n   Properties:\r\n     GroupName: !Sub '${NameSpace}-${ProjectName}-ec2'\r\n     GroupDescription: !Sub 'Security Group for ${NameSpace}-${ProjectName}-ec2'\r\n     VpcId: !Ref VpcId\r\n     Tags:\r\n       - Key: Name\r\n         Value: !Sub '${NameSpace}-${ProjectName}-ec2'\r\n       - Key: Owner\r\n         Value: 'name.surname@besharp.it'\r\n \r\n ################################### IAM ####################################\r\n IAMInstanceProfile:\r\n   Type: AWS::IAM::InstanceProfile\r\n   Properties:\r\n     Roles:\r\n       - !Ref IAMRole\r\n     InstanceProfileName: !Sub '${NameSpace}-${ProjectName}'\r\n \r\n IAMRole:\r\n   Type: AWS::IAM::Role\r\n   Properties:\r\n     RoleName: !Sub '${NameSpace}-${ProjectName}'\r\n     AssumeRolePolicyDocument:\r\n       Version: '2012-10-17'\r\n       Statement:\r\n         - Effect: Allow\r\n           Principal:\r\n             Service: ec2.amazonaws.com\r\n           Action: sts:AssumeRole\r\n     Path: '\/'\r\n     Policies:\r\n       - PolicyName: 'EC2Access'\r\n         PolicyDocument:\r\n           Version: '2012-10-17'\r\n           Statement:\r\n             - Effect: 'Allow'\r\n               Action:\r\n                 - 's3:GetObject'\r\n               Resource: !Sub '${S3Bucket.Arn}\/*'\r\n     Tags:\r\n       - Key: Name\r\n         Value: !Sub '${NameSpace}-${ProjectName}'\r\n       - Key: Owner\r\n         Value: 'name.surname@besharp.it'\r\n \r\n \r\n################################################################################\r\n#                                   Outputs                                    #\r\n################################################################################\r\nOutputs:\r\n \r\n StackName:\r\n   Description: 'Stack name.'\r\n   Value: !Sub '${AWS::StackName}'\r\n<\/pre>\n

Here we can find the information to create:<\/span><\/p>\n