VPC S3エンドポイントを使ってプライベートサブネットからS3へ接続する

今度、S3エンドポイントを試そうと思っているので使ってみました。確認のためにプライベートサブネットに配置したEC2からS3へアクセスできるか確認します。

# 前提

+ AWS CLI環境構築済み

# 参考

+ [Amazon S3のVPCエンドポイント](http://aws.typepad.com/aws_japan/2015/05/vpcendpointfors3.html)
+ [【新機能】S3がVPCのプライベートサブネットからアクセス可能になりました！](http://dev.classmethod.jp/cloud/vpc-endpoint-for-s3/)

# VPCの作成

VPCとサブネット(パブリック、プライベート）を作ります。
面倒なので、CloudFormationを使ってやります。

```lang:MyStack.json
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "A simple stack that launches an instance.",
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.1.0.0/16",
        "EnableDnsHostnames" : "true"
      }
    },

    "PublicSubnetAZa" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "AvailabilityZone" : "ap-northeast-1a",
        "CidrBlock" : "10.1.11.0/24",
        "VpcId" : { "Ref" : "VPC" }
      }
    },

    "PrivateSubnetAZa" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "AvailabilityZone" : "ap-northeast-1a",
        "CidrBlock" : "10.1.15.0/24",
        "VpcId" : { "Ref" : "VPC" }
      }
    },

    "InternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway"
    },

    "InternetGatewayAttach" : {
      "Type" : "AWS::EC2::VPCGatewayAttachment",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "InternetGatewayId" : { "Ref" : "InternetGateway" }
      }
    },

    "DHCPOptions" : {
      "Type" : "AWS::EC2::DHCPOptions",
      "Properties" : {
        "DomainName" : "ap-northeast-1.compute.internal",
        "DomainNameServers" : [ "AmazonProvidedDNS" ]
      }
    },

    "VPCDHCPOptionsAssociation" : {
      "Type" : "AWS::EC2::VPCDHCPOptionsAssociation",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "DhcpOptionsId" : { "Ref" : "DHCPOptions" }
      }
    },

    "RouteTable" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" }
      }
    },

    "Route1" : {
      "Type" : "AWS::EC2::Route",
      "Properties" : {
        "DestinationCidrBlock" : "0.0.0.0/0",
        "RouteTableId" : { "Ref" : "RouteTable" },
        "GatewayId" : { "Ref" : "InternetGateway" }
      },
      "DependsOn" : "InternetGatewayAttach"
    },

    "SubnetRoute1" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "RouteTableId" : { "Ref" : "RouteTable" },
        "SubnetId" : { "Ref" : "PublicSubnetAZa" }
      }
    }
  }
}
```

上記ファイルをローカルに作成後、以下のコマンドを実行します。

```
$aws cloudformation create-stack --template-body file://Mystack.json --stack-name MyFirstStack
```

# S3エンドポイントの作成

現状、CloudFormationからS3エンドポイントの作成はできなさそうだったので、別途マネージメントコンソールから実施します。

+ VPC->Endpoints
+ Create Endpoint

最初の画面ではCIDRが**"10.1.0.0/16"**となっている、先ほど作成したVPCを設定します。

![Screen Shot 2015-06-30 at 10.12.12 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/c7d521de-7a94-6d1c-b7f3-9b16b2bb388f.png "Screen Shot 2015-06-30 at 10.12.12 AM.png")

次の画面ではプライベートサブネットを選択します。プライベートサブネットのCIDRは**10.1.15.0/24**となっている方を選択します。

![Screen Shot 2015-06-30 at 10.13.00 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/e20627bb-ddb8-7df2-5033-79120c909da0.png "Screen Shot 2015-06-30 at 10.13.00 AM.png")

これでプライベートサブネットにS3エンドポイントが作成できました。

# EC2の作成

確認のためにプライベートサブネットにEC2を立てて、インターネットへの接続ができない状態でS3へアクセスできるか確認します。

マネージメントコンソールなどからパブリックサブネット(プライベートサブネットへのSSH接続用)とプライベートサブネットにEC2をそれぞれ1台ずつ立てます。今回の例ではAmazonLinuxを利用しました。なお、起動するEC2にはS3へアクセス可能なIAMロールを付与しておいてください。

起動後、パブリックサブネットのパブリックIPとプライベートサブネットにのプライベートIPを確認します。

自身のマシンからプライベートサブネットのEC2にアクセスするためにsshconfigの設定を変更します。なお、**52.69.163.180**はパブリックサブネットのEC2のパブリックIP、**10.1.15.140**はプライベートサブネットのEC2のプライベートIP、**~/.ssh/hogefuga.pem**は設定したSSH認証の鍵を自身の環境に合わせて変更してください。


```lang:~/.ssh/conf
Host FumidaiServer
  HostName 52.69.163.180
  User ec2-user
  Port 22
  IdentityFile ~/.ssh/hogefuga.pem

Host TargetServer
  HostName 10.1.15.140
  User ec2-user
  port 22
  IdentityFile ~/.ssh/hogefuga.pem
  ProxyCommand ssh -W %h:%p FumidaiServer
```

上記設定により、自身のマシンから以下のコマンドでプライベートサブネットのEC2へログインができます。

```
$ssh TargetServer
```

試しにインターネットへ繋がるかやってみます。

```
$wget -T 10 http://google.co.jp
--2015-06-30 01:35:23--  http://google.co.jp/
google.co.jp (google.co.jp) をDNSに問いあわせています... 173.194.117.159, 173.194.117.143, 173.194.117.151, ...
google.co.jp (google.co.jp)|173.194.117.159|:80 に接続しています... 失敗しました: 接続がタイムアウトしました.
```

プライベートサブネットでNATの設定などもしていないのでインターネットへのアクセスは出来ません。

# プライベートサブネットからS3へアクセスする

事前にIAMロールでS3へのアクセス権を付与しているのでアカウントの設定は行わず、S3へのアクセスを実施してみます。

```
$aws s3 --region ap-northeast-1 ls
2015-05-29 07:58:18 toshihiro-elb-test
2015-05-31 13:09:57 toshihirock-cloudtrail
2015-06-04 23:39:22 toshihirock-cognito
```

上記の通り、プライベートサブネットでもS3へのアクセスができました！