├── .github └── FUNDING.yml ├── 01-s3-read ├── README.md └── policy.json ├── 02-s3-prefix ├── README.md └── policy.json ├── 03-parameterstore-path ├── README.md └── policy.json ├── 04-kms-cmk ├── README.md └── policy.json ├── 05-ec2-terminate-tag ├── README.md └── policy.json ├── 06-ec2-launch-tag ├── README.md └── policy.json ├── LICENSE ├── README.md └── lab-environment.yml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: widdix 4 | -------------------------------------------------------------------------------- /01-s3-read/README.md: -------------------------------------------------------------------------------- 1 | # Lab 01: S3 read access 2 | 3 | ## Introduction 4 | 5 | During bootstrapping your EC2 instance needs to download several artifacts from S3. Therefore, you are using the AWS CLI to synchronize all objects from an S3 bucket with a local folder on your instance. Replace with the output `S3Bucket` of your CloudFormation stack. 6 | 7 | Write an IAM policy that allows you to synchronize all objects from a specific S3 bucket. 8 | 9 | `aws s3 sync s3:// ~/` 10 | 11 | Make sure, you don't allow access to any other S3 buckets. 12 | 13 | ## Instructions 14 | 15 | 1. Open [S3](https://s3.console.aws.amazon.com/s3/home). Search for a bucket with a name equal to the `S3Bucket` output of your CloudFormation stack and upload a few files. 16 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 17 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 18 | 1. Add an inline policy to your IAM role. 19 | 1. Make sure you are logged into the SSH bastion host. 20 | 21 | Now it is time to test weather the EC2 instance is allowed to list and download all objects from your S3 bucket. 22 | 23 | `aws s3 sync s3:// ~/` 24 | 25 | ## Help 26 | 27 | * [Actions, Resources, and Condition Keys for Amazon S3](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazons3.html) 28 | * `policy.json` includes a sample solution for the necessary IAM policy. 29 | 30 | ## Clean up 31 | 32 | 1. Remove the inline policy from your IAM role. 33 | -------------------------------------------------------------------------------- /01-s3-read/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "s3:ListBucket", 7 | "Resource": "arn:aws:s3:::" 8 | }, 9 | { 10 | "Effect": "Allow", 11 | "Action": "s3:GetObject", 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /02-s3-prefix/README.md: -------------------------------------------------------------------------------- 1 | # Lab 02: S3 read and write with prefix 2 | 3 | ## Introduction 4 | 5 | Several EC2 instances are uploading backups to an S3 bucket. You want to make sure that each EC2 instance is only allowed to upload and download files to with a specific prefix (also known as folder). 6 | 7 | Write an IAM policy that allows you to upload and download objects with prefix `/test/` to your S3 bucket. Make sure, you don't allow access to any other S3 buckets or with another prefix than `/test`. 8 | 9 | Actions that should be allowed: 10 | 11 | ``` 12 | aws s3 cp test.txt s3:///test/test.txt 13 | aws s3 cp s3:///test/test.txt test.txt 14 | ``` 15 | 16 | Actions that should be rejected: 17 | ``` 18 | aws s3 cp test.txt s3:///badprefix/test.txt 19 | aws s3 cp test.txt s3:///test/test.txt 20 | ``` 21 | 22 | ## Instructions 23 | 24 | 1. Open [S3](https://s3.console.aws.amazon.com/s3/home). Search for a bucket with a name equal to the `S3Bucket` output of your CloudFormation stack and upload a few files. 25 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 26 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 27 | 1. Add an inline policy to your IAM role. 28 | 1. Make sure you are logged into the SSH bastion host. 29 | 30 | Now it is time to test weather the EC2 instance is allowed to list and download all objects from your S3 bucket. 31 | 32 | ``` 33 | aws s3 cp test.txt s3:///test/test.txt 34 | aws s3 cp s3:///test/test.txt test.txt 35 | ``` 36 | 37 | The following upload should be rejected. 38 | 39 | ``` 40 | aws s3 cp test.txt s3:///badprefix/test.txt 41 | ``` 42 | 43 | ## Help 44 | 45 | * [Actions, Resources, and Condition Keys for Amazon S3](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazons3.html) 46 | * `policy.json` includes a sample solution for the necessary IAM policy. 47 | 48 | ## Clean up 49 | 50 | 1. Remove the inline policy from your IAM role. 51 | -------------------------------------------------------------------------------- /02-s3-prefix/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "s3:GetObject", 8 | "s3:PutObject" 9 | ], 10 | "Resource": "arn:aws:s3:::/test/*" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /03-parameterstore-path/README.md: -------------------------------------------------------------------------------- 1 | # Lab 03: Parameter Store read access 2 | 3 | ## Introduction 4 | 5 | Your application running on EC2 instances is loading it's configuration parameters from the AWS Systems Manager Parameter Store. 6 | 7 | Write an IAM policy that allows to read all parameters by a specific path. 8 | 9 | ``` 10 | aws ssm get-parameters-by-path --region --path //a/ 11 | ``` 12 | 13 | ## Instructions 14 | 15 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 16 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 17 | 1. Add an inline policy to your IAM role. 18 | 1. Make sure you are logged into the SSH bastion host. 19 | 20 | Getting all parameters from path `/.../a/` should work. 21 | 22 | ``` 23 | aws ssm get-parameters-by-path --region --path //a/ 24 | ``` 25 | 26 | Getting parameters from path `/.../b/` should be denied. 27 | 28 | ``` 29 | aws ssm get-parameters-by-path --region --path //b/ 30 | ``` 31 | 32 | ## Help 33 | 34 | **Warning: It might take several minutes until changes to an IAM policy becomes effective.** 35 | 36 | * [Actions, Resources, and Condition Keys for Amazon Simple Systems Manager](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonsimplesystemsmanager.html#amazonsimplesystemsmanager-parameter) 37 | * `policy.json` includes a sample solution for the necessary IAM policy. 38 | 39 | ## Clean up 40 | 41 | 1. Remove the inline policy from your IAM role. 42 | -------------------------------------------------------------------------------- /03-parameterstore-path/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "ssm:GetParametersByPath", 7 | "Resource": "arn:aws:ssm:::parameter//a/*" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /04-kms-cmk/README.md: -------------------------------------------------------------------------------- 1 | # Lab 04: Grant access to KMS customer managed CMK 2 | 3 | ## Introduction 4 | 5 | You want to use KMS to encrypt sensitive data. A customer managed CMK allows you to control who is able to encrypt and decrypt the data. 6 | 7 | 8 | Write and IAM policy that allows to encrypt and decrypt sensitive data with a specific customer managed CMK. 9 | 10 | ``` 11 | aws kms encrypt --key-id --region --plaintext "Sensitive Data" --output text --query CiphertextBlob 12 | aws kms decrypt --ciphertext-blob fileb://encrypted.txt --region --output text --query Plaintext | base64 -d 13 | ``` 14 | 15 | ## Instructions 16 | 17 | 1. Open [KMS](https://eu-central-1.console.aws.amazon.com/kms/home) and go to *Customer-managed keys*. 18 | 1. Ensure that the correct region is selected 19 | 1. Create a customer managed CMK: 20 | 1. Key type `Symmetric` and key usage `Encrypt and decrypt`. 21 | 1. Choose a unique alias. 22 | 1. Choose your IAM role/user as the key administrator. 23 | 1. Keep the defaults for all the following steps. 24 | 1. Create the key. 25 | 26 | The key policy attached to your customer managed CMK enables IAM to grant access to administer and use the key. To be able to use the key from the SSH bastion host, you need to create an IAM policy which grants access to the encrypt and decrypt actions. 27 | 28 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 29 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 30 | 1. Add an inline policy to your IAM role. 31 | 1. Make sure you are logged into the SSH bastion host. 32 | 33 | Try to encrypt sensitive data. 34 | 35 | ``` 36 | aws kms encrypt --key-id --region --plaintext "Sensitive Data" --output text --query CiphertextBlob | base64 --decode > encrypted.txt 37 | ``` 38 | 39 | Try to decrypt the data. 40 | 41 | ``` 42 | aws kms decrypt --ciphertext-blob fileb://encrypted.txt --region --output text --query Plaintext | base64 -d 43 | ``` 44 | 45 | ## Help 46 | 47 | * [Actions, Resources, and Condition Keys for AWS Key Management Service](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_awskeymanagementservice.html) 48 | * [Using Key Policies in AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html) 49 | * [Allows Access to the AWS Account and Enables IAM Policies](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam) 50 | * `policy.json` includes a sample solution for the necessary IAM policy. 51 | 52 | ## Clean up 53 | 54 | Open the AWS Management Console to: 55 | 56 | 1. Remove the inline policy from your IAM role. 57 | 1. Delete your customer managed CMK. 58 | -------------------------------------------------------------------------------- /04-kms-cmk/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "kms:Encrypt", 8 | "kms:Decrypt" 9 | ], 10 | "Resource": "" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /05-ec2-terminate-tag/README.md: -------------------------------------------------------------------------------- 1 | # Lab 05: Terminate EC2 instance with tag 2 | 3 | ## Introduction 4 | 5 | You want to make sure that engineers are not allowed to terminate EC2 instances running production workloads. Therefore, an engineer should only be allowed to terminate instances that are tagged with `environment = test`. 6 | 7 | Write an IAM policy that only allows to terminate instances with a specific tag key and tag value. 8 | 9 | ``` 10 | aws ec2 terminate-instances --region --instance-ids 11 | ``` 12 | 13 | ## Instructions 14 | 15 | 16 | 1. Launch an instance and add a unique tag (Key = Name, Value = ...). Note down the instance id, please. 17 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 18 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 19 | 1. Add an inline policy to your IAM role. 20 | 1. Make sure you are logged into the SSH bastion host. 21 | 22 | Try to terminate your newly launched instance. 23 | 24 | ``` 25 | aws ec2 terminate-instances --region --instance-ids 26 | ``` 27 | 28 | Should fail, as the instance is not tagged with `environment = test` yet. Go to the Management Console and add a tag `environment = test` to your instance. 29 | 30 | Try to terminate the instance again! 31 | 32 | ``` 33 | aws ec2 terminate-instances --region --instance-ids 34 | ``` 35 | 36 | 37 | ## Help 38 | 39 | * [Actions, Resources, and Condition Keys for Amazon EC2](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonec2.html) 40 | * [Restricting Access to EC2 Instances Based on Tags](https://cloudonaut.io/restricting-access-to-ec2-instances-based-on-tags/) 41 | * `policy.json` includes a sample solution for the necessary IAM policy. 42 | 43 | ## Clean up 44 | 45 | 1. Remove the inline policy from your IAM role. 46 | -------------------------------------------------------------------------------- /05-ec2-terminate-tag/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "ec2:TerminateInstances", 7 | "Resource": "*", 8 | "Condition": { 9 | "StringEquals": { 10 | "ec2:ResourceTag/environment": "test" 11 | } 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /06-ec2-launch-tag/README.md: -------------------------------------------------------------------------------- 1 | # Lab 06: Launch EC2 instance with tag 2 | 3 | ## Introduction 4 | 5 | You are using tags to allocate your AWS costs to different cost centers. Therefore, you want to make sure that EC2 instance are not launched without a tag `costcenter`. 6 | 7 | Write an IAM policy that allows to launch EC2 instances only when a tag with key ` costcenter` is set. 8 | 9 | ``` 10 | aws ec2 run-instances --tag-specifications "ResourceType=instance,Tags=[{Key=costcenter,Value=test}]" "ResourceType=volume,Tags=[{Key=costcenter,Value=test}]" --instance-type t3.micro --region --image-id --subnet-id 11 | ``` 12 | 13 | ## Instructions 14 | 15 | 1. Open [IAM](https://console.aws.amazon.com/iam/home). 16 | 1. Search an IAM role with a name equal to the `IamRole` output of your CloudFormation stack. 17 | 1. Add an inline policy to your IAM role. 18 | 1. Make sure you are logged into the SSH bastion host. 19 | 20 | Launching an EC2 instance without any tags should be denied. 21 | 22 | ``` 23 | aws ec2 run-instances --instance-type t3.micro --region --image-id --subnet-id 24 | ``` 25 | 26 | But launching an EC2 instance with a tag `costcenter` should work. 27 | 28 | ``` 29 | aws ec2 run-instances --tag-specifications "ResourceType=instance,Tags=[{Key=costcenter,Value=test}]" "ResourceType=volume,Tags=[{Key=costcenter,Value=test}]" --instance-type t3.micro --region --image-id --subnet-id 30 | ``` 31 | 32 | Note down the instance id of the launched instance, please. 33 | 34 | ## Help 35 | 36 | * [Actions, Resources, and Condition Keys for Amazon EC2](https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonec2.html) 37 | * [Restricting Access to EC2 Instances Based on Tags](https://cloudonaut.io/restricting-access-to-ec2-instances-based-on-tags/) 38 | * `policy.json` includes a sample solution for the necessary IAM policy. 39 | 40 | ## Clean up 41 | 42 | Open the AWS Management Console to: 43 | 44 | 1. Remove the inline policy from your IAM role. 45 | 1. Terminate the EC2 instance you have launched. 46 | -------------------------------------------------------------------------------- /06-ec2-launch-tag/policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "ec2:RunInstances", 7 | "Resource": [ 8 | "arn:aws:ec2:*:*:volume/*", 9 | "arn:aws:ec2:*:*:instance/*" 10 | ], 11 | "Condition": { 12 | "Null": { 13 | "aws:RequestTag/costcenter": "false" 14 | } 15 | } 16 | }, 17 | { 18 | "Effect": "Allow", 19 | "Action": "ec2:RunInstances", 20 | "NotResource": [ 21 | "arn:aws:ec2:*:*:volume/*", 22 | "arn:aws:ec2:*:*:instance/*" 23 | ] 24 | }, 25 | { 26 | "Effect": "Allow", 27 | "Action": "ec2:CreateTags", 28 | "Resource": "*", 29 | "Condition": { 30 | "StringEquals": { 31 | "ec2:CreateAction": [ 32 | "RunInstances" 33 | ] 34 | } 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2019 widdix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learn-iam-policy 2 | 3 | Labs helping you to learn how write IAM policies following the least privilege principle. 4 | 5 | Are you looking for an instructor-led workshop based on these labs? Say [hello@widdix.net](mailto:hello@widdix.net). 6 | 7 | ## Introduction 8 | 9 | We are using `` to indicate that you should replace parts of the instructions with a variable. 10 | 11 | ## Preparing the lab environment 12 | 13 | The CloudFormation template `lab-environment.yml` creates a lab environment consisting of: 14 | 15 | * EC2 Instance with an IAM role attached (*access to SSM is granted for Session Manager access*) 16 | * S3 bucket 17 | * SSM parameters 18 | 19 | 1. Create a CloudFormation stack based on the template `lab-environment.yml`. 20 | 1. Set stack name to your name but only use characters `a-z` (lowercase!). 21 | 1. Make a note with the outputs of the stack: `IamRole`, `S3Bucket`. 22 | 1. Connect to the EC2 instance using SSM Session Manager 23 | 1. Visit https://console.aws.amazon.com/systems-manager/session-manager/start-session 24 | 1. Select your instance 25 | 1. Push the **Start Session** button 26 | 1. Jump to your home directory: `cd ~` 27 | 1. Done. You can now start with the labs. 28 | 29 | ## Labs 30 | 31 | * [Lab 01: S3 read access](https://github.com/widdix/learn-iam-policy/tree/master/01-s3-read) 32 | * [Lab 02: S3 read and write with prefix](https://github.com/widdix/learn-iam-policy/tree/master/02-s3-prefix) 33 | * [Lab 03: Parameter Store read access](https://github.com/widdix/learn-iam-policy/tree/master/03-parameterstore-path) 34 | * [Lab 04: Grant access to KMS customer managed CMK](https://github.com/widdix/learn-iam-policy/tree/master/04-kms-cmk) 35 | * [Lab 05: Terminate EC2 instance with tag](https://github.com/widdix/learn-iam-policy/tree/master/05-ec2-terminate-tag) 36 | * [Lab 06: Launch EC2 instance with tag](https://github.com/widdix/learn-iam-policy/tree/master/06-ec2-launch-tag) 37 | 38 | ## Clean up 39 | 40 | 1. Empty your S3 bucket ``. 41 | 1. Delete your CloudFormation stack. 42 | 43 | ## More Labs 44 | 45 | We offer AWS workshops tailored to your needs. See [widdix/learn-*](https://github.com/widdix?q=learn-) for more labs. 46 | -------------------------------------------------------------------------------- /lab-environment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: '2010-09-09' 3 | Description: 'learn-iam-policy: lab environment' 4 | Parameters: 5 | Vpc: 6 | Description: 'Choose a VPC for the lab environment.' 7 | Type: 'AWS::EC2::VPC::Id' 8 | Subnet: 9 | Description: 'Choose a Subnet for the lab environment.' 10 | Type: 'AWS::EC2::Subnet::Id' 11 | Mappings: 12 | RegionMap: 13 | 'ap-south-2': 14 | AMI: 'ami-0fd07010d91ec94ed' 15 | 'ap-south-1': 16 | AMI: 'ami-0501e3547293b2db3' 17 | 'eu-south-1': 18 | AMI: 'ami-064e641df9c88db1a' 19 | 'eu-south-2': 20 | AMI: 'ami-03e38c7ccbe876512' 21 | 'me-central-1': 22 | AMI: 'ami-098c0ce6c458f300e' 23 | 'il-central-1': 24 | AMI: 'ami-06c7a65b4ba37244d' 25 | 'ca-central-1': 26 | AMI: 'ami-024076c81e3291472' 27 | 'eu-central-1': 28 | AMI: 'ami-08b47394fb4c462b9' 29 | 'eu-central-2': 30 | AMI: 'ami-046f9d0ba1e596fe8' 31 | 'us-west-1': 32 | AMI: 'ami-04918638df2143901' 33 | 'us-west-2': 34 | AMI: 'ami-05c89af705fc8fb3c' 35 | 'af-south-1': 36 | AMI: 'ami-060b324aa32c23562' 37 | 'eu-north-1': 38 | AMI: 'ami-04c9ea0e72cda507a' 39 | 'eu-west-3': 40 | AMI: 'ami-090f3b471c0bb9c7f' 41 | 'eu-west-2': 42 | AMI: 'ami-018302178b8f5d0a6' 43 | 'eu-west-1': 44 | AMI: 'ami-05e9a7830635fe160' 45 | 'ap-northeast-3': 46 | AMI: 'ami-0c3613ae50638f6c0' 47 | 'ap-northeast-2': 48 | AMI: 'ami-0819c049403b5aa6b' 49 | 'me-south-1': 50 | AMI: 'ami-0c710a975841e684b' 51 | 'ap-northeast-1': 52 | AMI: 'ami-022c3cb73fbed1cc7' 53 | 'sa-east-1': 54 | AMI: 'ami-037cb310a4cd89c1c' 55 | 'ap-east-1': 56 | AMI: 'ami-09f4076013f7a5cad' 57 | 'ca-west-1': 58 | AMI: 'ami-07ebbc212c45de49d' 59 | 'ap-southeast-1': 60 | AMI: 'ami-03d7c57e0f49d78d2' 61 | 'ap-southeast-2': 62 | AMI: 'ami-02d628788b362146a' 63 | 'ap-southeast-3': 64 | AMI: 'ami-05754d6f8b26b908c' 65 | 'ap-southeast-4': 66 | AMI: 'ami-049fc5d0791fd7ead' 67 | 'us-east-1': 68 | AMI: 'ami-04c0f9ef2f505b609' 69 | 'us-east-2': 70 | AMI: 'ami-0118c442c801c0d26' 71 | Resources: 72 | SecurityGroup: 73 | Type: 'AWS::EC2::SecurityGroup' 74 | Properties: 75 | GroupDescription: 'learn-iam-policy' 76 | VpcId: !Ref Vpc 77 | Ec2Instance: 78 | Type: 'AWS::EC2::Instance' 79 | Properties: 80 | ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI] 81 | InstanceType: 't2.micro' 82 | IamInstanceProfile: !Ref IamInstanceProfile 83 | NetworkInterfaces: 84 | - AssociatePublicIpAddress: "true" 85 | DeviceIndex: '0' 86 | GroupSet: [!Ref SecurityGroup] 87 | SubnetId: !Ref Subnet 88 | Tags: 89 | - Key: Name 90 | Value: !Ref 'AWS::StackName' 91 | IamInstanceProfile: 92 | Type: 'AWS::IAM::InstanceProfile' 93 | Properties: 94 | Roles: 95 | - !Ref IamRole 96 | IamRole: 97 | Type: 'AWS::IAM::Role' 98 | Properties: 99 | AssumeRolePolicyDocument: 100 | Version: '2012-10-17' 101 | Statement: 102 | - Effect: Allow 103 | Principal: 104 | Service: 'ec2.amazonaws.com' 105 | Action: 'sts:AssumeRole' 106 | Policies: 107 | - PolicyName: 'DO-NOT-CHANGE-LAB-SSM-CONNECTION' 108 | PolicyDocument: 109 | Version: '2012-10-17' 110 | Statement: 111 | - Effect: Allow 112 | Action: 113 | - 'ssm:DescribeAssociation' 114 | - 'ssm:GetDeployablePatchSnapshotForInstance' 115 | - 'ssm:GetDocument' 116 | - 'ssm:GetManifest' 117 | - 'ssm:GetParameters' 118 | - 'ssm:ListAssociations' 119 | - 'ssm:ListInstanceAssociations' 120 | - 'ssm:PutInventory' 121 | - 'ssm:PutComplianceItems' 122 | - 'ssm:PutConfigurePackageResult' 123 | - 'ssm:UpdateAssociationStatus' 124 | - 'ssm:UpdateInstanceAssociationStatus' 125 | - 'ssm:UpdateInstanceInformation' 126 | Resource: '*' 127 | - Effect: Allow 128 | Action: 129 | - 'ssmmessages:CreateControlChannel' 130 | - 'ssmmessages:CreateDataChannel' 131 | - 'ssmmessages:OpenControlChannel' 132 | - 'ssmmessages:OpenDataChannel' 133 | Resource: '*' 134 | - Effect: Allow 135 | Action: 136 | - 'ec2messages:AcknowledgeMessage' 137 | - 'ec2messages:DeleteMessage' 138 | - 'ec2messages:FailMessage' 139 | - 'ec2messages:GetEndpoint' 140 | - 'ec2messages:GetMessages' 141 | - 'ec2messages:SendReply' 142 | Resource: '*' 143 | S3Bucket: 144 | Type: 'AWS::S3::Bucket' 145 | Properties: 146 | BucketName: !Sub 'learn-iam-policy-${AWS::StackName}' 147 | SsmParameterPathAValue1: 148 | Type: 'AWS::SSM::Parameter' 149 | Properties: 150 | Name: !Sub '/${AWS::StackName}/a/1' 151 | Value: 'a1' 152 | Type: 'String' 153 | SsmParameterPathAValue2: 154 | Type: 'AWS::SSM::Parameter' 155 | Properties: 156 | Name: !Sub '/${AWS::StackName}/a/2' 157 | Value: 'a2' 158 | Type: 'String' 159 | SsmParameterPathBValue1: 160 | Type: 'AWS::SSM::Parameter' 161 | Properties: 162 | Name: !Sub '/${AWS::StackName}/b/1' 163 | Value: 'b1' 164 | Type: 'String' 165 | Outputs: 166 | InstanceId: 167 | Description: 'The EC2 instance ID.' 168 | Value: !Ref Ec2Instance 169 | IamRole: 170 | Description: 'The name of the IAM role attached to the EC2 instance.' 171 | Value: !Ref IamRole 172 | S3Bucket: 173 | Description: 'The name of the S3 bucket.' 174 | Value: !Ref S3Bucket 175 | --------------------------------------------------------------------------------