Clean template CF z vpc ec2 and s3

AWSTemplateFormatVersion: 2010-09-09
Description: Security Engineering on AWS - Lab 1; Using Identity and resource-based policies
Parameters:
  VPCCIDR:
    Description: CIDR Block for VPC
    Type: String
    Default: 10.0.0.0/16
    AllowedValues:
      - 10.0.0.0/16

  PublicSubnetParam:
    Description: Public Subnet 1
    Type: String
    Default: 10.0.10.0/24
    AllowedValues:
      - 10.0.10.0/24

  AWSAmiId:
    Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

Resources:
  VPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: VPC
          Value: CLI-Server
        - Key: Name
          Value: Lab VPC

  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    DependsOn: VPC

  AttachGateway:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: "AWS::EC2::Subnet"
    DependsOn: AttachGateway
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref PublicSubnetParam
      AvailabilityZone: !Select
        - "0"
        - !GetAZs ""
      Tags:
        - Key: Name
          Value: Public Subnet

  PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    DependsOn: PublicSubnet
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: Public

  PublicRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    DependsOn: PublicRoute
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  HostSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    DependsOn:
      - AttachGateway
    Properties:
      GroupDescription: Enable http access to the web server
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: HostSecurityGroup
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIp: 0.0.0.0/0
        - IpProtocol: udp
          FromPort: 0
          ToPort: 65535
          CidrIp: 0.0.0.0/0

#-----Start - Lambda function to generate random number to use with bucket names-----#
  LambdaRunRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                 - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: allowLambdaLogging
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"

  GenerateNumberLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: >
          const response = require("cfn-response");

          const generateNumber = (length, chars) => {
            var result = '';
            for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
            return result;
          }

          exports.handler = (event, context) =>{
            const str = generateNumber(event['ResourceProperties']['Length'], '0123456789');
            const responseData = {RandomNumber: str};
            response.send(event, context, response.SUCCESS, responseData);
          };
      Handler: index.handler
      Runtime: nodejs12.x
      Role: !GetAtt LambdaRunRole.Arn
      MemorySize: 128
      Timeout: 20

  GenerateNumber:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      Length: 9
      ServiceToken: !GetAtt GenerateNumberLambdaFunction.Arn
#-----End - Lambda function to generate random number to use with bucket names-----#

### S3 bucket
  Bucket1:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: LogDeliveryWrite
      BucketName: !Sub bucket1-${GenerateNumber.RandomNumber}
      PublicAccessBlockConfiguration: #Sets "Block all public access" to "On" for the bucket
          BlockPublicAcls: True
          BlockPublicPolicy: True
          IgnorePublicAcls: True
          RestrictPublicBuckets: True
          
  Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: LogDeliveryWrite
      BucketName: !Sub bucket2-${GenerateNumber.RandomNumber}
      PublicAccessBlockConfiguration: #Sets "Block all public access" to "On" for the bucket
          BlockPublicAcls: True
          BlockPublicPolicy: True
          IgnorePublicAcls: True
          RestrictPublicBuckets: True

### end S3 bucket

### Server used to verify cross account access.
  
  S3InstProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref S3AccessRole
      InstanceProfileName: S3InstanceProfile

  S3AccessRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub S3AccessRole-${AWS::AccountId}
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service: ["ec2.amazonaws.com"]
            Action: ["sts:AssumeRole"]
      Path: "/"

  S3AccessPolicy:
    Type: 'AWS::IAM::Policy'
    Properties:
      PolicyName: S3AccessPolicy
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - 's3:ListAllMyBuckets'
              - 's3:ListBucket'
            Resource: '*'
          - Effect: Allow
            Action:
              - 's3:PutObject'
            Resource:
            - !Sub arn:aws:s3:::${Bucket1}/file1.txt
            - !Sub arn:aws:s3:::${Bucket1}/file2.txt
            - !Sub arn:aws:s3:::${Bucket1}/file3.txt
            - !Sub arn:aws:s3:::${Bucket2}/file1.txt
            - !Sub arn:aws:s3:::${Bucket2}/file2.txt
            - !Sub arn:aws:s3:::${Bucket2}/file3.txt
      Roles:
        - !Ref S3AccessRole

  MyEC2Host:
    Type: "AWS::EC2::Instance"
    CreationPolicy:
      ResourceSignal:
        Timeout: PT8M
    DependsOn: PublicSubnetRouteTableAssociation
    Properties:
      IamInstanceProfile: !Ref S3InstProfile
      ImageId: !Ref AWSAmiId
      InstanceType: t3.micro
      NetworkInterfaces:
        - DeviceIndex: "0"
          AssociatePublicIpAddress: true
          SubnetId: !Ref PublicSubnet
          GroupSet:
            - !Ref HostSecurityGroup
      SourceDestCheck: false
      Tags:
        - Key: Name
          Value: MyEC2Host
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex
          yum install -y git aws-cfn-bootstrap aws-apitools-common aws-apitools-ec2
          yum -y update
          # Create text file to put in S3 bucket
          mkdir /usr/bin/Lab1 &&
          echo "simple text file number 1" > /usr/bin/Lab1/file1.txt &&
          echo "simple text file number 2" > /usr/bin/Lab1/file2.txt &&
          echo "simple text file number 3" > /usr/bin/Lab1/file3.txt
          # Configure the EC2 and ssm users to work properly.
          mkdir /home/ec2-user/.aws &&
          echo "[default]" > /home/ec2-user/.aws/config &&
          echo "region = ${AWS::Region}" >> /home/ec2-user/.aws/config &&
          mkdir -p /home/ssm-user/.aws &&
          echo "[default]" > /home/ssm-user/.aws/config &&
          echo "region = ${AWS::Region}" >> /home/ssm-user/.aws/config &&

          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyEC2Host --region ${AWS::Region}

          until (( $(id -u ssm-user) )); do sleep 10; done
          chown -R ssm-user:ssm-user /home/ssm-user/

  ReadOnlyGroup:
    Type: AWS::IAM::Group
    Properties:
      GroupName: QLReadOnly
      ManagedPolicyArns: [ "arn:aws:iam::aws:policy/ReadOnlyAccess" ]
  GroupAssignment:
    Type: AWS::IAM::UserToGroupAddition
    DependsOn: ReadOnlyGroup
    Properties: 
      GroupName: QLReadOnly
      Users:
        - awsstudent

Outputs:
  AwsRegion:
    Value: !Ref "AWS::Region"
  AccountID:
    Value: !Ref AWS::AccountId
  Bucket1:
    Value: !Ref Bucket1
    Description: Name of s3 Bucket 1
  Bucket2:
    Value: !Ref Bucket2
    Description: Name of s3 Bucket 2
  EC2Role:
    Value: !GetAtt S3AccessRole.Arn