diff --git a/ec2-s3-express-one-zone-sam/README.md b/ec2-s3-express-one-zone-sam/README.md new file mode 100644 index 000000000..9880bfb06 --- /dev/null +++ b/ec2-s3-express-one-zone-sam/README.md @@ -0,0 +1,93 @@ +# Amazon EC2 to Amazon S3 Express One Zone directory bucket + +This sample project creates an Amazon EC2 Instance and Amazon S3 Express One Zone Direct Bucket under the same availability zone. + +Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/ec2-s3-express-one-zone-sam + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +- [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +- [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed + +## Prerequisite +1. Please refer to the [list of availability zones where Amazon S3 Express One Zone is currently supported](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-Endpoints.html) and choose one. +2. Execute the below from command line and make a note of the `ZoneName` and `ZoneId`. It will be required during deployment: + ```bash + aws ec2 describe-availability-zones --region {region-name} + ``` +3. Choose an AMI Id for your region. + +## Deployment Instructions + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ```bash + git clone https://github.com/aws-samples/serverless-patterns + ``` +2. Change directory to the pattern directory: + ```bash + cd ec2-s3-express-one-zone-sam + ``` +3. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: + ```bash + sam deploy --guided + ``` +4. During the prompts: + + - Enter a stack name + - Enter the desired AWS Region. Please refer to the prerequisite 1 and choose a region. + - Enter `AvailabilityZoneName` and `AvailabilityZoneId` as per the prerequisite 2. + - Enter the `ImageId` as per prerequisite 3. + - Allow SAM CLI to create IAM roles with the required permissions. + + Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. + +5. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for next step as well as testing. + + +## How it works + + +Please refer to the architecture diagram below: + +![End to End Architecture](images/architecture.png) + +S3 Express One Zone is the first S3 storage class that gives you the option to co-locate high-performance object storage and AWS compute resources, such as Amazon Elastic Compute Cloud, Amazon Elastic Kubernetes Service, and Amazon Elastic Container Service, within a single Availability Zone. +Here, we provisioned both the Amazon EC2 instance and the S3 Express One Zone Directory bucket within same availability zone. We will perform both read and write opertation from the directory bucket from within the EC2 instance and outside. + +## Testing + + +1. Log into the Amazon EC2 instance using AWS console and execute the following command to upload file into Amazon S3 Express One Zone diretory bucket. Please replace `BucketExpressOneZoneName` from the `sam deploy -g` output. + ```bash + echo "Hello World!" > sample.txt + aws s3api put-object --bucket {BucketExpressOneZoneName} --key sample.txt --body sample.txt + + ``` +2. Now, download the same file from your laptop command line using the following command and validate the content.: + ```bash + aws s3api get-object --bucket {BucketExpressOneZoneName} --key sample.txt ./sample.txt --region {my-region} + cat sample.txt + ``` + + +## Cleanup + +1. Delete the content in the Amazon S3 bucket using the following command. Please *ensure* that the correct bucket name is provided to avoid accidental data loss: + ```bash + aws s3 rm s3://{BucketExpressOneZoneName} --recursive --region {my-region} + ``` + +2. To delete the resources deployed to your AWS account via AWS SAM, run the following command: + ```bash + sam delete + ``` + +--- + +Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 diff --git a/ec2-s3-express-one-zone-sam/ec2-s3-express-one-zone-sam.json b/ec2-s3-express-one-zone-sam/ec2-s3-express-one-zone-sam.json new file mode 100644 index 000000000..ceb2a8801 --- /dev/null +++ b/ec2-s3-express-one-zone-sam/ec2-s3-express-one-zone-sam.json @@ -0,0 +1,78 @@ +{ + "title": "Amazon EC2 to Amazon S3 Express One Zone directory bucket", + "description": "SAM Template that creates an EC2 Instance, an Amazon S3 Express One Zone directory bucket and required IAM Role to access the bucket from the instance", + "language": "YAML", + "level": "200", + "framework": "SAM", + "introBox": { + "headline": "How it works", + "text": [ + "S3 Express One Zone is the first S3 storage class that gives you the option to co-locate high-performance object storage and AWS compute resources, such as Amazon Elastic Compute Cloud, Amazon Elastic Kubernetes Service, and Amazon Elastic Container Service, within a single Availability Zone.", + "Here, we provisioned both the Amazon EC2 instance and the S3 Express One Zone Directory bucket within same availability zone. We will perform both read and write opertation from the directory bucket from within the EC2 instance and outside.", + "Both Amazon EC2 Instance and Amazon S3 Express One Zone directory bucket are provisioned within same availability zone.", + "Access to the directory bucket from the EC2 instance is provided through IAM Role associated with the instance profile." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/ec2-s3-express-one-zone-sam", + "templateURL": "serverless-patterns/ec2-s3-express-one-zone-sam", + "projectFolder": "ec2-s3-express-one-zone-sam", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon S3 Express One Zone User Guide", + "link": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-one-zone.html" + }, + { + "text": "AWS CLI Command Refernece", + "link": "https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html" + } + ] + }, + "deploy": { + "text": [ + "sam deploy --guided" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the Amazon S3 bucket content: aws s3 rm s3://{BucketExpressOneZoneName} --recursive --region {my-region}", + "Delete the stack: sam delete." + ] + }, + "authors": [ + { + "name": "Biswanath Mukherjee", + "image": "https://d1rwvjey2iif32.cloudfront.net", + "bio": "I am a Sr. Solutions Architect working at AWS India.", + "linkedin": "biswanathmukherjee" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "ec2", + "label": "Amazon EC2" + }, + "icon2": { + "x": 80, + "y": 50, + "service": "s3", + "label": "Amazon S3 Express One Zone" + }, + "line1": { + "from": "icon1", + "to": "icon2" + } + } +} diff --git a/ec2-s3-express-one-zone-sam/example-pattern.json b/ec2-s3-express-one-zone-sam/example-pattern.json new file mode 100644 index 000000000..4bed5733a --- /dev/null +++ b/ec2-s3-express-one-zone-sam/example-pattern.json @@ -0,0 +1,58 @@ +{ + "title": "Amazon EC2 to Amazon S3 Express One Zone directory bucket", + "description": "SAM Template that creates an EC2 Instance, an Amazon S3 Express One Zone directory bucket and required IAM Role to access the bucket from the instance", + "language": "YAML", + "level": "200", + "framework": "SAM", + "introBox": { + "headline": "How it works", + "text": [ + "Both Amazon EC2 Instance and Amazon S3 Express One Zone directory bucket are provisioned within same availability zone.", + "Access to the directory bucket from the EC2 instance is provided through IAM Role associated with the instance profile." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/ec2-s3-express-one-zone-sam", + "templateURL": "serverless-patterns/ec2-s3-express-one-zone-sam", + "projectFolder": "ec2-s3-express-one-zone-sam", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon S3 User Guide", + "link": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-express-one-zone.html" + }, + { + "text": "AWS CLI Command Refernece", + "link": "https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html" + } + ] + }, + "deploy": { + "text": [ + "sam deploy --guided" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the Amazon S3 bucket content: aws s3 rm s3://{BucketExpressOneZoneName} --recursive --region {my-region}", + "Delete the stack: sam delete." + ] + }, + "authors": [ + { + "name": "Biswanath Mukherjee", + "image": "https://d1rwvjey2iif32.cloudfront.net", + "bio": "I am a Sr. Solutions Architect working at AWS India.", + "linkedin": "biswanathmukherjee" + } + ] +} diff --git a/ec2-s3-express-one-zone-sam/images/architecture.png b/ec2-s3-express-one-zone-sam/images/architecture.png new file mode 100644 index 000000000..2d40ba1e3 Binary files /dev/null and b/ec2-s3-express-one-zone-sam/images/architecture.png differ diff --git a/ec2-s3-express-one-zone-sam/template.yaml b/ec2-s3-express-one-zone-sam/template.yaml new file mode 100644 index 000000000..199d17994 --- /dev/null +++ b/ec2-s3-express-one-zone-sam/template.yaml @@ -0,0 +1,185 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: SAM Template that creates an EC2 Instance, an Amazon S3 Express One Zone directory bucket and required IAM Role to access the bucket from the instance + +# Get the required input parameters +Parameters: + AvailabilityZoneName: + Type: String + Description: Please provide availability Zone Name (e.g. us-east-1a) + AvailabilityZoneId: + Type: String + Description: Please enter the corresponding availability Zone Id (e.g. use1-az6) for your account + ImageId: + Type: String + Description: Please enter the AMI Id for your account + + +Resources: + # Create VPC and related resources + VPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: 10.0.0.0/16 + EnableDnsHostnames: true + EnableDnsSupport: true + InstanceTenancy: default + + Subnet: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref VPC + CidrBlock: 10.0.0.0/24 + AvailabilityZone: !Sub "${AvailabilityZoneName}" + + InternetGateway: + Type: AWS::EC2::InternetGateway + + VPCGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + InternetGatewayId: !Ref InternetGateway + VpcId: !Ref VPC + + RouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref VPC + + Route: + Type: AWS::EC2::Route + DependsOn: VPCGatewayAttachment + Properties: + RouteTableId: !Ref RouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + + SubnetRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref Subnet + RouteTableId: !Ref RouteTable + + SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow HTTP traffic + VpcId: !Ref VPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - CidrIp: 0.0.0.0/0 + IpProtocol: tcp + FromPort: 22 + ToPort: 22 + SecurityGroupEgress: + - IpProtocol: all + CidrIp: 0.0.0.0/0 + + + + # Create EC2 Instance Profile, Role + EC2InstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Path: / + Roles: + - !Ref EC2InstanceRole + + EC2InstanceRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: logs + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + Resource: + - 'arn:aws:logs:*:*:*' + - PolicyName: AllowAccessRegionalEndpointAPIs + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - "s3express:DeleteBucket" + - "s3express:DeleteBucketPolicy" + - "s3express:CreateBucket" + - "s3express:PutBucketPolicy" + - "s3express:GetBucketPolicy" + - "s3express:ListAllMyDirectoryBuckets" + Resource: + - !GetAtt BucketExpressOneZone.Arn + - PolicyName: AllowCreateSession + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - "s3express:CreateSession" + Resource: + - !GetAtt BucketExpressOneZone.Arn + # - "*" + # - !Ref EC2Instance + +# create key-pair + EC2KeyPair: + Type: AWS::EC2::KeyPair + Properties: + KeyName: ec2-keypair + KeyType: rsa + Tags: + - Key: Name + Value: ec2-keypair + # Create EC2 Instance + EC2Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: !Sub "${ImageId}" + InstanceType: t2.micro + KeyName: !Ref EC2KeyPair + IamInstanceProfile: !Ref EC2InstanceProfile + NetworkInterfaces: + - DeviceIndex: "0" + AssociatePublicIpAddress: true + DeleteOnTermination: true + SubnetId: !Ref Subnet + GroupSet: + - !Ref SecurityGroup + Tags: + - Key: Name + Value: !Sub "EC2-Instance-${AvailabilityZoneName}" + + + # Create an Amazon S3 Express One Zone storage class bucket + BucketExpressOneZone: + Type: AWS::S3Express::DirectoryBucket + Properties: + # BucketName: input-bucket-express-one-zone + DataRedundancy: SingleAvailabilityZone + LocationName: !Sub "${AvailabilityZoneId}" + + +# Output EC2 ARN, Bucket names +Outputs: + EC2InstanceId: + Value: !Ref EC2Instance + BucketExpressOneZoneName: + Value: !Ref BucketExpressOneZone