Created
June 7, 2020 03:50
-
-
Save sakamaki-kazuyoshi/ea80f8d1e8ca571006796d4402b919d9 to your computer and use it in GitHub Desktop.
AWS WAF environment for logging to S3.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AWSTemplateFormatVersion: '2010-09-09' | |
# ------------------------------------------------------------# | |
# Metadata | |
# ------------------------------------------------------------# | |
Metadata: | |
AWS::CloudFormation::Interface: | |
ParameterGroups: | |
- Label: | |
default: "Common Configuration(Resource prefix)" | |
Parameters: | |
- ProjectName | |
- EnvironmentName | |
- Label: | |
default: "EC2 Configuration" | |
Parameters: | |
- SecurityGroupInboudRule | |
- EC2KeyPair | |
# ------------------------------------------------------------# | |
# Input Parameters | |
# ------------------------------------------------------------# | |
Parameters: | |
ProjectName: | |
Type: String | |
Default: 'test' | |
EnvironmentName: | |
Type: String | |
AllowedValues: [dev,stg,prd] | |
Default: 'dev' | |
SecurityGroupInboudRule: | |
Type: String | |
Default: '0.0.0.0/0' | |
Description: Enter the SSH reception rule of the web server. | |
EC2KeyPair: | |
Type: AWS::EC2::KeyPair::KeyName | |
# ------------------------------------------------------------# | |
# Resources | |
# ------------------------------------------------------------# | |
Resources: | |
# ------------------------------------------------------------# | |
# IAM | |
# ------------------------------------------------------------# | |
WebRole: | |
Type: "AWS::IAM::Role" | |
Properties: | |
AssumeRolePolicyDocument: | |
Version: "2012-10-17" | |
Statement: | |
- | |
Effect: "Allow" | |
Principal: | |
Service: | |
- "ec2.amazonaws.com" | |
Action: | |
- "sts:AssumeRole" | |
Path: "/" | |
ManagedPolicyArns: | |
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore | |
RoleName: !Sub ${ProjectName}-${EnvironmentName}-web-role | |
WebInstanceProfile: | |
Type: "AWS::IAM::InstanceProfile" | |
Properties: | |
Path: "/" | |
Roles: | |
- !Ref WebRole | |
InstanceProfileName: !Sub ${ProjectName}-${EnvironmentName}-web-role | |
# ------------------------------------------------------------# | |
# VPC | |
# ------------------------------------------------------------# | |
VPC: | |
Type: 'AWS::EC2::VPC' | |
Properties: | |
CidrBlock: 10.0.0.0/16 | |
EnableDnsSupport: 'true' | |
EnableDnsHostnames: 'true' | |
InstanceTenancy: default | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-vpc | |
# ------------------------------------------------------------# | |
# Internet Gateway | |
# ------------------------------------------------------------# | |
InternetGateway: | |
Type: 'AWS::EC2::InternetGateway' | |
Properties: | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-igw | |
AttachInternetGateway: | |
Type: 'AWS::EC2::VPCGatewayAttachment' | |
Properties: | |
InternetGatewayId: !Ref InternetGateway | |
VpcId: !Ref VPC | |
# ------------------------------------------------------------# | |
# Subnet | |
# ------------------------------------------------------------# | |
PublicSubnetA: | |
Type: 'AWS::EC2::Subnet' | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: 'ap-northeast-1a' | |
CidrBlock: 10.0.0.0/24 | |
MapPublicIpOnLaunch: 'true' | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-public-subnet-a | |
PublicSubnetC: | |
Type: 'AWS::EC2::Subnet' | |
Properties: | |
VpcId: !Ref VPC | |
AvailabilityZone: 'ap-northeast-1c' | |
CidrBlock: 10.0.1.0/24 | |
MapPublicIpOnLaunch: 'true' | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-public-subnet-c | |
# ------------------------------------------------------------# | |
# RouteTable | |
# ------------------------------------------------------------# | |
PublicRouteTable: | |
Type: 'AWS::EC2::RouteTable' | |
Properties: | |
VpcId: !Ref VPC | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-public-rtb | |
RouteAddInternetGateway: | |
Type: 'AWS::EC2::Route' | |
Properties: | |
DestinationCidrBlock: 0.0.0.0/0 | |
GatewayId: !Ref InternetGateway | |
RouteTableId: !Ref PublicRouteTable | |
AssociatePublicSubnetAToPublicRouteTable: | |
Type: 'AWS::EC2::SubnetRouteTableAssociation' | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
SubnetId: !Ref PublicSubnetA | |
AssociatePublicSubnetCToPublicRouteTable: | |
Type: 'AWS::EC2::SubnetRouteTableAssociation' | |
Properties: | |
RouteTableId: !Ref PublicRouteTable | |
SubnetId: !Ref PublicSubnetC | |
# ------------------------------------------------------------# | |
# Securitygroup | |
# ------------------------------------------------------------# | |
WebSecuritygroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupName: !Sub ${ProjectName}-${EnvironmentName}-web-sg | |
GroupDescription: !Sub ${ProjectName}-${EnvironmentName}-web-sg | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-web-sg | |
VpcId: !Ref VPC | |
SecurityGroupIngress: | |
- IpProtocol: tcp | |
FromPort: '22' | |
ToPort: '22' | |
CidrIp: !Sub ${SecurityGroupInboudRule} | |
- IpProtocol: tcp | |
FromPort: '80' | |
ToPort: '80' | |
SourceSecurityGroupId: !Ref ALBSecuritygroup | |
Description: 'from ALB' | |
ALBSecuritygroup: | |
Type: AWS::EC2::SecurityGroup | |
Properties: | |
GroupName: !Sub ${ProjectName}-${EnvironmentName}-alb-sg | |
GroupDescription: !Sub ${ProjectName}-${EnvironmentName}-alb-sg | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-alb-sg | |
VpcId: !Ref VPC | |
SecurityGroupIngress: | |
- IpProtocol: tcp | |
FromPort: '80' | |
ToPort: '80' | |
CidrIp: '0.0.0.0/0' | |
Description: 'from Internet' | |
# ------------------------------------------------------------# | |
# LoadBalancer | |
# ------------------------------------------------------------# | |
LoadBalancer: | |
Type: AWS::ElasticLoadBalancingV2::LoadBalancer | |
Properties: | |
Name: !Sub ${ProjectName}-${EnvironmentName}-alb | |
Scheme: internet-facing | |
Subnets: | |
- !Ref PublicSubnetA | |
- !Ref PublicSubnetC | |
SecurityGroups: | |
- !Ref ALBSecuritygroup | |
LoadBalancerAttributes: | |
- Key: access_logs.s3.enabled | |
Value: true | |
- Key: access_logs.s3.bucket | |
Value: !Ref ALBLogBucket | |
# - Key: deletion_protection.enabled | |
# Value: true | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-alb | |
# ------------------------------------------------------------# | |
# TargetGroup | |
# ------------------------------------------------------------# | |
TargetGroup: | |
Type: AWS::ElasticLoadBalancingV2::TargetGroup | |
Properties: | |
Name: !Sub ${ProjectName}-${EnvironmentName}-alb-tg | |
Port: 80 | |
Protocol: HTTP | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-alb-tg | |
Targets: | |
- Id: !Ref WebInstance1 | |
Port: 80 | |
VpcId: !Ref VPC | |
# ------------------------------------------------------------# | |
# Listener | |
# ------------------------------------------------------------# | |
Listener: | |
Type: "AWS::ElasticLoadBalancingV2::Listener" | |
Properties: | |
DefaultActions: | |
- TargetGroupArn: !Ref TargetGroup | |
Type: forward | |
LoadBalancerArn: !Ref LoadBalancer | |
Port: 80 | |
Protocol: HTTP | |
# ------------------------------------------------------------# | |
# S3 Bucket | |
# ------------------------------------------------------------# | |
ALBLogBucket: | |
Type: 'AWS::S3::Bucket' | |
Properties: | |
BucketName: !Sub ${ProjectName}-${EnvironmentName}-alb-${AWS::AccountId} | |
AccessControl: Private | |
LifecycleConfiguration: | |
Rules: | |
- Id: LifeCycleRule | |
Status: Enabled | |
ExpirationInDays: '365' | |
ALBLogBucketPolicy: | |
Type: "AWS::S3::BucketPolicy" | |
Properties: | |
Bucket: !Ref ALBLogBucket | |
PolicyDocument: | |
Id: "Allow-Put-ELB-logs" | |
Version: "2012-10-17" | |
Statement: | |
- Action: | |
- "s3:PutObject" | |
Effect: "Allow" | |
Resource: !Join [ "", [ "arn:aws:s3:::" , !Ref ALBLogBucket, "/AWSLogs/", !Ref "AWS::AccountId" ,"/*"] ] | |
Principal: | |
AWS: "582318560864" #Elastic Load Balancing Account ID(ap-northeast-1) | |
# ------------------------------------------------------------# | |
# EC2 | |
# ------------------------------------------------------------# | |
WebInstance1: | |
Type: "AWS::EC2::Instance" | |
Properties: | |
AvailabilityZone: ap-northeast-1a | |
ImageId: ami-0a1c2ec61571737db #AL2 | |
InstanceType: t3.micro | |
KeyName: !Ref EC2KeyPair | |
BlockDeviceMappings: | |
- DeviceName: /dev/xvda | |
Ebs: | |
VolumeType: gp2 | |
VolumeSize: 8 | |
NetworkInterfaces: | |
- AssociatePublicIpAddress: "true" | |
DeviceIndex: "0" | |
GroupSet: | |
- Ref: WebSecuritygroup | |
SubnetId: | |
Ref: PublicSubnetA | |
IamInstanceProfile: !Ref WebInstanceProfile | |
Tags: | |
- Key: Name | |
Value: !Sub ${ProjectName}-${EnvironmentName}-web | |
UserData: | |
Fn::Base64: | | |
#!/bin/bash | |
yum update -y | |
yum install -y httpd | |
echo "<html><body>Hello world</body></html>" > /var/www/html/index.html | |
systemctl enable httpd | |
systemctl start httpd | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AWSTemplateFormatVersion: '2010-09-09' | |
# ------------------------------------------------------------# | |
# Metadata | |
# ------------------------------------------------------------# | |
Metadata: | |
AWS::CloudFormation::Interface: | |
ParameterGroups: | |
- Label: | |
default: "Common Configuration(Resource prefix)" | |
Parameters: | |
- ProjectName | |
- EnvironmentName | |
- Label: | |
default: "WAF v2 Configuration" | |
Parameters: | |
- AlbArn | |
- Label: | |
default: "Kinesis Data Firehose Configuration" | |
Parameters: | |
- BufferSize | |
- BufferInterval | |
- CompressionFormat | |
# ------------------------------------------------------------# | |
# Input Parameters | |
# ------------------------------------------------------------# | |
Parameters: | |
ProjectName: | |
Type: String | |
Default: 'test' | |
EnvironmentName: | |
Type: String | |
AllowedValues: [dev,stg,prd] | |
Default: 'dev' | |
AlbArn: | |
Type: String | |
Default: 'arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:loadbalancer/app/XXXXXXXXXXXX' | |
Description: Enter ALB ARN to associate with WEBACL. | |
BufferSize: | |
Type: String | |
Default: '5' | |
BufferInterval: | |
Type: String | |
Default: '60' | |
CompressionFormat: | |
Type: String | |
AllowedValues: [GZIP,HADOOP_SNAPPY,Snappy,UNCOMPRESSED,ZIP] | |
Default: 'GZIP' | |
# ------------------------------------------------------------# | |
# Resources | |
# ------------------------------------------------------------# | |
Resources: | |
# ------------------------------------------------------------# | |
# WAF v2 | |
# ------------------------------------------------------------# | |
WebACL: | |
Type: AWS::WAFv2::WebACL | |
Properties: | |
DefaultAction: | |
Allow: {} | |
Description: "Used by ALB of web server" | |
Name: !Sub ${ProjectName}-${EnvironmentName}-web-acl | |
Scope: REGIONAL | |
# Tags: | |
# - Tag | |
VisibilityConfig: | |
SampledRequestsEnabled: true | |
CloudWatchMetricsEnabled: true | |
MetricName: !Sub ${ProjectName}-${EnvironmentName}-web-acl | |
WebACLAssociation: | |
Type: AWS::WAFv2::WebACLAssociation | |
Properties: | |
ResourceArn: !Ref AlbArn | |
WebACLArn: !GetAtt WebACL.Arn | |
# ------------------------------------------------------------# | |
# S3 | |
# ------------------------------------------------------------# | |
WAFLogBucket: | |
Type: AWS::S3::Bucket | |
Properties: | |
BucketName: !Sub ${ProjectName}-${EnvironmentName}-waf-${AWS::AccountId} | |
# BucketEncryption: | |
# ServerSideEncryptionConfiguration: | |
# - ServerSideEncryptionByDefault: | |
# SSEAlgorithm: AES256 | |
AccessControl: Private | |
PublicAccessBlockConfiguration: | |
BlockPublicAcls: true | |
BlockPublicPolicy: true | |
IgnorePublicAcls: true | |
RestrictPublicBuckets: true | |
LifecycleConfiguration: | |
Rules: | |
- Id: LifeCycleRule | |
Status: Enabled | |
ExpirationInDays: '365' | |
# ------------------------------------------------------------# | |
# IAM | |
# ------------------------------------------------------------# | |
KinesisDataFirehoseRole: | |
Type: "AWS::IAM::Role" | |
Properties: | |
AssumeRolePolicyDocument: | |
Statement: | |
- | |
Effect: "Allow" | |
Principal: | |
Service: | |
- "firehose.amazonaws.com" | |
Action: | |
- "sts:AssumeRole" | |
Condition: | |
StringEquals: | |
sts:ExternalId: !Ref AWS::AccountId | |
Path: "/" | |
Policies: | |
- | |
PolicyName: "Permissions-Policy-For-Firehose" | |
PolicyDocument: | |
Statement: | |
- | |
Effect: "Allow" | |
Action: | |
- "s3:AbortMultipartUpload" | |
- "s3:GetBucketLocation" | |
- "s3:GetObject" | |
- "s3:ListBucket" | |
- "s3:ListBucketMultipartUploads" | |
- "s3:PutObject" | |
- "logs:PutLogEvents" | |
Resource: | |
- !Join | |
- '' | |
- - 'arn:aws:s3:::' | |
- !Ref WAFLogBucket | |
- !Join | |
- '' | |
- - 'arn:aws:s3:::' | |
- !Ref WAFLogBucket | |
- '/*' | |
- !Join | |
- '' | |
- - 'arn:aws:logs:' | |
- !Ref AWS::Region | |
- ':' | |
- !Ref AWS::AccountId | |
- ':log-group:' | |
- !Ref CloudWatchLogsLogGroup | |
- ':log-stream:*' | |
RoleName: !Sub ${ProjectName}-${EnvironmentName}-delivery-stream-role | |
# ------------------------------------------------------------# | |
# Kinesis Data Firehose | |
# ------------------------------------------------------------# | |
WAFLogDeliveryStream: | |
Type: AWS::KinesisFirehose::DeliveryStream | |
Properties: | |
DeliveryStreamName: !Sub aws-waf-logs-${ProjectName}-${EnvironmentName}-delivery-stream | |
DeliveryStreamType: DirectPut | |
ExtendedS3DestinationConfiguration: | |
BucketARN: !GetAtt WAFLogBucket.Arn | |
BufferingHints: | |
SizeInMBs: !Ref BufferSize | |
IntervalInSeconds: !Ref BufferInterval | |
CloudWatchLoggingOptions: | |
Enabled: true | |
LogGroupName: !Ref CloudWatchLogsLogGroup | |
LogStreamName: !Ref CloudWatchLogsLogStream | |
CompressionFormat: !Ref CompressionFormat | |
Prefix: 'year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/hour=!{timestamp:HH}/' | |
ErrorOutputPrefix: 'year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/hour=!{timestamp:HH}/!{firehose:error-output-type}' | |
RoleARN: !GetAtt KinesisDataFirehoseRole.Arn | |
# ------------------------------------------------------------# | |
# CloudWatch Logs | |
# ------------------------------------------------------------# | |
CloudWatchLogsLogGroup: | |
Type: AWS::Logs::LogGroup | |
Properties: | |
LogGroupName: !Join [ "", [ "/aws/kinesisfirehose/" , !Sub '${ProjectName}-${EnvironmentName}-delivery-stream'] ] | |
RetentionInDays: 90 | |
CloudWatchLogsLogStream: | |
Type: AWS::Logs::LogStream | |
Properties: | |
LogGroupName: !Ref CloudWatchLogsLogGroup | |
LogStreamName: "S3Delivery" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment