https://dev.classmethod.jp/articles/myfirstnvpcsetup/


初心者向け】初めて VPC 環境作成してみた

はじめて Amzon VPC を作成してみました。まずは手を動かしてみたい方向けに、手順ごとにスクリーンショットを添付しています。Amazon VPC や各用語については AWS ドキュメントのリンクを貼っていますので、そちらを参考にしてください。
2019.08.31

こんにちは chicca です。

初めてEC2インスタンスを起動してみます。

今回はその準備として VPC 環境を作成した時のおさらいメモブログです。

とりあえず、手を動かしてみました。

知っておきたい用語

  • VPC…仮想ネットワークのこと。この中に EC2 を起動する。
  • CIDR(Classless Inter-Domain Routing)…VPC を作成するときに IPv4 アドレスの範囲を指定する形式。サイダーと読む。
  • インターネットゲートウェイ…ネットワークの出入り口。 VPC にひとつ付ける。
  • ルートテーブル…ネットワークの交通整理をする。通信の経路(ルート)を決める。パブリックサブネットに付ける。

手順

0-1.AWS アカウントにログイン

0-2.マネジメントコンソール「サービスを検索する」から「VPC」を検索

1.VPCを作成:Amazon VPC とは?

VPC > 「VPCの作成」 
次の2箇所を入力し「作成」をクリックします

名前タグ: 任意の名称。今回は「vpc-no1」

IPv4 CIRD ブロック: 任意の IP アドレス。今回は「10.0.0.0/16」

 

 
VPC が作成されたら「閉じる」 
VPC ができました 

2.パブリックサブネットとプライベートサブネットを作成:VPC とサブネット

パブリックサブネットとプライベートサブネットの作成手順は同じです。

サブネット > 「サブネットの作成」 
次の3箇所を入力し「作成」をクリックします

【パブリックサブネット】

名前タグ: 任意の名称。今回は「vpc-no1-public」

VPC: リストから先ほど作成した VPC を選択

IPv4 CIRD ブロック: 任意の IP アドレス。今回は「10.0.0.0/24」

【プライベートサブネット】

名前タグ: 任意の名称。今回は「vpc-no1-private」

VPC: リストから先ほど作成した VPC を選択

IPv4 CIRD ブロック: 任意の IP アドレス。今回は「10.0.1.0/24」

 
サブネット が作成されたら「閉じる」
サブネット ができました 

3 .インターネットゲートウェイを作成:インターネットゲートウェイ

インターネットゲートウェイ > 「インターネットゲートウェイの作成」 
次の1箇所を入力し「作成」をクリックします

名前タグ: 任意の名称。今回は「igw-no1」

 

 
ゲートウェイ が作成されたら「閉じる」 
ゲートウェイ ができました 

4.VPC にインターネットゲートウェイをアタッチ

手順 3.で作成したゲートウェイを選択し、「アクション」をクリック

選択肢から「VPC にアタッチ」を選ぶ

 
VPC: 手順 1.で作成した VPCを選択し「アタッチ」 
アタッチされました

5.ルートテーブルの作成:ルートテーブル

サブネットを作成するとデフォルトのルートテーブルが作成されますが、今回は自分で作成します

ルートテーブル > 「ルートテーブルの作成」 
次の2箇所を入力し「作成」をクリックします

名前タグ: 任意の名称。今回は「rtb-no1-public」

VPC: 手順 1.で作成した VPC を選択

 
ルートテーブル が作成されたら「閉じる」 
ルートテーブル ができました 

6.ルートテーブルをパブリックサブネットにアタッチ

手順 5.で作成したルートテーブルを選択し、「サブネットの関連付け」タブ > 「サブネット関連付けの編集」 
手順 2.で作成したパブリックサブネットを選択し「保存」 
パブリックサブネットにルートテーブルがアタッチされました 

 

本日はここまでです。


https://dev.classmethod.jp/cloud/apigateway-supports-vpc-endpoint/


ども、大瀧です。
昨日、API Gatewayの新機能としてプライベートAPIがリリースされ、同時にAPI GatewayがVPCエンドポイントに対応しました。

API Gatewayは、AWS Lambdaとの組み合わせでAWSにおけるサーバーレスアプリケーションを実現する鉄板構成です。今回追加された2つの機能で、VPCやDirect Connectなどのプライベートなネットワークからのみアクセスできるプライベートなサーバーレスアプリを構築できるようになりました。その様子をご紹介します。

プライベートなサーバーレスアプリの構成

VPCエンドポイントは、AWSでプライベートなネットワークを提供するVPCからインターネットを経由せずにAWSサービスにアクセスできる機能です。最近対応サービスが増えてきており、今回VPCエンドポイント経由でAPI Gatewayにもアクセスできるようになりました。

一方でAPI Gatewayはこれまでインターネットからのアクセスのみを想定し、リージョンごとにエンドポイントを持つ地域タイプとエッジロケーションを利用するエッジ最適化タイプから選択していました。今回、リージョンごとにVPCエンドポイントを経由するアクセスのみ可能となるプライベートタイプが追加されたわけです。

プライベートタイプは一部 *1を除くAPI Gatewayのほとんどの機能が利用できるため、バックエンドにLambdaを構成することでVPCエンドポイント経由でプライベートネットワークにサーバーレスアプリケーションを提供できます。

1. VPCエンドポイントの作成

今回はAPI GatewayのサンプルAPI PetStoreをVPCからアクセスできるように、東京リージョンで構成してみます。

VPCやDirect ConnectからアクセスするためのVPCエンドポイントの作成をVPC管理画面のメニュー[エンドポイント] - [エンドポイントの作成]から行います。[サービスカテゴリ]は「AWSサービス」のままにし、サービス一覧からAPI Gateway(com.amazonaws.<リージョン名>.execute-api)を選択します。

加えてVPCサブネット(基本的には全部選択)およびセキュリティグループ(API GatewayはHTTPS:443なのでそれを許可するルール)を選択、エンドポイントを作成します。

エンドポイント一覧には、プライベートネットワークから接続するためDNS名がいくつか表示されます。それぞれ解説します。

  1. execute-api.<リージョン名>.amazonaws.com : ドキュメントにあるプライベートDNS名のひとつ。任意のAPI Gatewayにアクセスできるが証明書のCNが合わないため実用的ではなく、後述のCNAMEの振り先と推測される。Direct Connect経由のオンプレミスからは直接引けない点に注意。
  2. *.execute-api.<リージョン名>.amazonaws.com : ドキュメントにあるプライベートDNS名のひとつ。後の手順で作成するAPI Gatewayのリソース名をサブドメインに指定してアクセスする。Direct Connect経由のオンプレミスからは直接引けない点に注意。
  3. vpce-XXXX-XXXX.execute-api.<リージョン名>.vpce.amazonaws.com : ドキュメントにあるパブリックDNS名のひとつ。Hostヘッダに2のドメインを指定しないと動作しないため、あまり実用的では無い。
  4. vpce-XXXX-XXXX-<AZ名>.execute-api.<リージョン名>.vpce.amazonaws.com : ドキュメントにあるパブリックDNS名のひとつ。3と同様あまり実用的では無い。

というわけで、特別な事情がない限り2を常用することになると思います。

2. APIの作成

続いてAPI GatewayでAPIを管理画面の[APIの作成]から行います。今回は[APIの例]でサンプルのPetStoreをインポートしつつ、[名前と説明]の[エンドポイントタイプ]で「プライベート」を選択します。

APIを作成したら、画面上部のパンくずリストからAPIのリソースID(PetStore(XXXXXX)XXXXXX)を確認します。これがアクセスするリソースURLのサブドメインになります。

続いて画面左のメニューから[API] - [PetStore] - [リソースポリシー]を選択し、画面右下にある[ソースVPCホワイトリスト]ボタンをクリックしてリソースポリシーのテンプレートを呼び出します。

以下のJSONドキュメントがテキストエリアに貼り付けられるので、13行目の値を作成したVPCエンドポイントのIDに書き換えて[保存]をクリックします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringEquals": {
                    "aws:sourceVpce": "vpce-XXXXXXXXXXXX"
                }
            }
        }
    ]
}

画面左のメニューから[API] - [PetStore] - [リソース]を選択し、[アクション]ボタンをクリックし[APIのデプロイ]を選択します。[デプロイされるステージ]は[新しいステージ]で任意のステージ名(今回はv1)としてデプロイすればOKです。

動作確認

早速VPCに配置したEC2からアクセスしてみると...

$ curl https://XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/v1/pets/
[
  {
    "id": 1,
    "type": "dog",
    "price": 249.99
  },
  {
    "id": 2,
    "type": "cat",
    "price": 124.99
  },
  {
    "id": 3,
    "type": "fish",
    "price": 0.99
  }
]$

正常にレスポンスが返ってきました。ホスト名のIPアドレスを調べてみると...

$ host XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com
XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com is an alias for execute-api.ap-northeast-1.amazonaws.com.
execute-api.ap-northeast-1.amazonaws.com has address 172.31.17.157
execute-api.ap-northeast-1.amazonaws.com has address 172.31.45.78
execute-api.ap-northeast-1.amazonaws.com has address 172.31.12.159

CNAMEになっていて、IPアドレスはVPCエンドポイントで設定したVPCサブネットのプライベートIPが返ってきています。VPC内で通信が完結していることがわかりますね。ちなみにサブドメインに何を指定してもexecute-api.ap-northeast-1.amazonaws.comが返ってくるので、Amazon DNS側ではCNAMEレコードがワイルドカードとして設定されているっぽいです。

$ host mesoko.execute-api.ap-northeast-1.amazonaws.com
mesoko.execute-api.ap-northeast-1.amazonaws.com is an alias for execute-api.ap-northeast-1.amazonaws.com.
execute-api.ap-northeast-1.amazonaws.com has address 172.31.12.159
execute-api.ap-northeast-1.amazonaws.com has address 172.31.17.157
execute-api.ap-northeast-1.amazonaws.com has address 172.31.45.78
$ host satoshi.execute-api.ap-northeast-1.amazonaws.com
satoshi.execute-api.ap-northeast-1.amazonaws.com is an alias for execute-api.ap-northeast-1.amazonaws.com.
execute-api.ap-northeast-1.amazonaws.com has address 172.31.45.78
execute-api.ap-northeast-1.amazonaws.com has address 172.31.12.159
execute-api.ap-northeast-1.amazonaws.com has address 172.31.17.157
$

言い換えると、VPCエンドポイントを一回作成しておけばそこから複数のプライベートAPIにアクセスできます。

まとめ

API GatewayプライベートAPIとVPCエンドポイントを利用して、サーバーレスアプリをプライベートサービスとして構築する様子をご紹介しました。Internal ELBのようにサーバーレスで開発するマイクロサービスを内部同士で呼び出すケースなどに利用できそうですね。

考察

興味深いのは、VPCエンドポイント側にはAPI GatewayのAPIを特定する設定を特に持たないところです。それゆえ任意のAWSアカウントのAPIにVPCエンドポイント経由でアクセスできるので、API Gatewayのリソースポリシーできちんと制限しないといけないわけですが、この特徴を逆手に取るとクロスアカウントでAPIを提供する手段としてオープンなプライベートAPIを作成することも可能だったりします。以下のリソースポリシーを試してみたところ、別のAWSアカウントのVPCエンドポイントでプライベートAPIにアクセスすることができました。動作確認用途のポリシーなので、十分リスクを理解したうえで利用してください

1
2
3
4
5
6
7
8
9
10
11
12
13
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        }
    ]
}

同様の機能で承認プロセスを踏むエンドポイントサービスもありますが、あちらよりも簡単に提供する手段として利用できるかもしれません。API Gatewayのカスタム認証APIキーを用いてアクセス元を識別する感じにすると良さそうですよね。

また、インターネットに出ない経路なので各種閉域サービスとの組み合わせも模索したいですね。VPCエンドポイントの制約でAWSハードウェアVPNは利用できない一方、Direct Connectを利用する各種閉域接続サービスでの利用を検討する価値がありそうです。IoT向け閉域サービスのSORACOM Canalのピア元(Virtual Private Gatewayのある)VPCでAPI Gateway用のVPCエンドポイントを用意してエンドポイントIDをユーザーに提示してくれると、IoTデバイスにプライベートAPI経由でサーバーレスアプリケーションを提供できて便利そうです。ソラコムさん、ご検討ください!

参考URL

脚注

  1. 2018年6月現在、プライベートタイプはカスタムドメイン名に非対応です。 


https://qiita.com/sho7/items/6b1c58924d26f0398cd6



S3バケットの内容をLambda関数で読み込んでみる(Python)

この記事は最終更新日から1年以上が経過しています。

Lambda関数からS3を操作する練習です。
S3にファイルをアップロードしたタイミングでLambda関数が実行されるように設定します。
アップロードされたタイミングで、バケット名やファイルの一覧を取得する関数を書いてみます。

S3バケットを作成する

「バケットを作成する」をクリックします。
S3 Management Console 2018-01-06 09-29-55.png

バケット名とリージョンを入力します。
S3 Management Console 2018-01-06 09-31-18.png

プロパティの設定は特に何もせずに「次へ」をクリックします。
次の「アクセス許可の設定」はユーザーに対する設定のみです。とりあえずそのまま「次へ」をクリックします。

S3 Management Console 2018-01-06 09-35-11.png

Lambdaにファイルをアップロードする

適当なファイルをアップロードしてみます。
S3 Management Console 2018-01-06 09-38-15.png

ドラッグアンドドロップでファイルのアップロードができます。
S3 Management Console 2018-01-06 09-39-58.png

「アップロード」をクリックします。
S3 Management Console 2018-01-06 09-41-26.png

以下のようにアップロードしたファイルが表示されます。
S3 Management Console 2018-01-06 09-42-26.png

IAMに権限を設定する

Lambdaを操作するIAMにS3へのアクセス権限を与えます。
IAM Management Console 2018-01-06 09-57-31.png

AmazonS3FullAccessポリシーはフルアクセス権を与えてしまうので、どのS3バケットにもアクセスできてしまうことには注意が必要です。今回はサンプルなのでFullAccessを与えますが、実運用に入る際は、インラインポリシーを設定してポリシーを絞るのがいいと思います。
IAM Management Console 2018-01-06 09-58-50.png

Lambda関数を作成する

設計図s3-get-object-pythonから作成します。
Lambda Management Console 2018-01-06 10-04-43.png

Lambda Management Console 2018-01-06 10-07-20.png

Lambda Management Console 2018-01-06 10-07-37.png

boto3で何ができるかは本家のドキュメントをじっくり読むのがいいと思います。
ネットの情報は古くなってしまったものも多く、単純に真似するだけでは動かないものもありました。
「Boto 3 Docs documentation」
http://boto3.readthedocs.io/en/latest/reference/services/s3.html#client

こちらのサンプルはちゃんと動いてわかりやすかったです。
https://github.com/bloomberg/chef-bcs/blob/master/cookbooks/chef-bcs/files/default/s3-example-boto3.py

以下のような関数を作ってみました。

  • S3バケット名を取得する
  • S3バケット内のファイルの一覧を取得する
  • S3バケット内のファイルの詳細情報を表示する

などを行っています。

from __future__ import print_function import json import urllib import boto3 print('Loading function') #http://boto3.readthedocs.io/en/latest/reference/services/s3.html#client s3 = boto3.client('s3') def lambda_handler(event, context): bucket_name = event['Records'][0]['s3']['bucket']['name'] print('==== bucket information =====') print(bucket_name) print('=============================') #https://github.com/bloomberg/chef-bcs/blob/master/cookbooks/chef-bcs/files/default/s3-example-boto3.py print('==== your bucket list ====') buckets = s3.list_buckets() for bucket in buckets['Buckets']: print(bucket.get('Name')) print('==== file list in bucket ====') # https://github.com/boto/boto3/issues/134 AWS_S3_BUCKET_NAME = 'example.read.000' s3_resource = boto3.resource('s3') bucket = s3_resource.Bucket(AWS_S3_BUCKET_NAME) result = bucket.meta.client.list_objects(Bucket=bucket.name, Delimiter='/') for o in result.get('Contents'): print(o.get('Key')) print('==== file details ====') # https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UsingObjects.html GET_OBJECT_KEY_NAME = 'sample.png' object = s3.get_object(Bucket=AWS_S3_BUCKET_NAME, Key=GET_OBJECT_KEY_NAME) print('Content ->' + object['body'].read().decode('utf-8'))

    print('ContentType ->' + str(object.get('ContentType')))
    print('ContentLength ->' + str(object.get('ContentLength')))


    print('==== uploaded file ====')
    for rec in event['Records']:
        print(rec['s3']['object']['key'])
    print('=============================')

    print("Received event: " + json.dumps(event, indent=2))

テストを実行すると以下のようなログが表示されます。

START RequestId: bdbee72e-f28b-11e7-a401-0d0509334621 Version: $LATEST
==== bucket information =====
sourcebucket
=============================
==== your bucket list ====
example.read.000
learnjs.benrady.com
==== file list in bucket ====
sample.png
sample2.png
==== file details ====
ContentType ->image/png
ContentLength ->82361
==== uploaded file ====
HappyFace.jpg
=============================

S3にオブジェクトをプットしても同じように関数が実行されます。


https://dev.classmethod.jp/cloud/aws/elasticache-redis-supports-encryption-in-transit-and-client-auth/




Amazon ElastiCache for Redisの通信暗号化とクライアント認証をやってみた




2017年10月末のアップデートにより、Amazon ElastiCache for Redis が通信の暗号化とクライアント認証に対応しました

通信の暗号化(encryption in-transit)を使うと

  • アプリとRedis間の通信(encrypted connections)
  • プライマリ↔レプリカなどのRedis間の通信(encrypted replication)

が暗号化されます。

redis-in-transit-encryption

また、Redis の AUTH コマンドによるクライアント認証にも対応したため、認証レベルを強化できます。

これらの機能追加により、個人を特定できる情報(PII)など機密度の高い情報を扱うシステムでAmazon ElastiCache for Redisを導入しやすくなりました。

それでは、実際に使ってみましょう。

なお、同時に機能追加された、保管時の暗号化は次のブログをご確認下さい。

通信の暗号化

Redis の公式ドキュメント "Redis Security" では "Redis general security model" について次のように記載されています。

Redis is designed to be accessed by trusted clients inside trusted environments.

この前提の上で、Redis サーバーとは TCP や UNIX ソケットで通信します。

一方で、よりセキュアなシステムが求められるシステムには、 Redis Labs が提供する Redis Enterprise Pack (RP)のような通信の暗号化に対応した Redis が利用されてきました。

今回の機能追加は以下のような通信の暗号化機能を提供するというものです。

  • TLS 1.2
  • 追加費用なし
  • サーバ証明書の発行・更新も含めてフルマネージド

クライアントとサーバー間(encrypted connections)だけでなく、プライマリ↔レプリカのようにRedis間の通信(encrypted replication)も含めて暗号化されます。

TLS 通信には AmazonがOSSとして開発する S2N が利用されている点も見逃せません。

設定

Redisクラスター作成時に「Encryption in-transit」をチェックするだけです。

redis-encryption-3.2.6 only

2017/11/15時点では、最新の 3.2.10 では利用出来ませんでした。お気をつけ下さい。

Enables encryption of data on-the-wire. Currently, enabling encryption in-transit can only be done when creating a Redis cluster using Redis version 3.2.6 only.

作成済みのクラスターで有効にすることは出来ません。クラスターの再作成が必要です。

サーバー接続を試す

Redisクラスター作成後、実際に接続を試してみましょう。

telnet コマンドから暗号化通信を試す

Redis への通信が暗号化されていない場合の接続方法は、過去に次のブログにまとめました。

telnet で暗号化されたRedisに接続してみましょう。

1
2
3
4
5
6
$ telnet $REDIS-ENDPOINT 6379
Trying 172.31.31.65...
Connected to dummy.euc1.cache.amazonaws.com.
Escape character is '^]'.
PING
Connection closed by foreign host.

telnet は TLS をしゃべれないので接続をきられました。

openssl コマンドから暗号化通信を試す

TLS 通信のクライアントとして、Linux 系 OS であれば必ず入っている openssl を利用します。

Redis クラスターのエンドポイントに接続し、PING コマンドを実行します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ HOST=REDIS-ENDPOINT
$ openssl s_client -connect $HOST:6379 -quiet
depth=4 C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
verify return:1
depth=3 C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
verify return:1
depth=2 C = US, O = Amazon, CN = Amazon Root CA 1
verify return:1
depth=1 C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
verify return:1
depth=0 CN = *.security.dummy.euc1.cache.amazonaws.com
verify return:1
+OK
PING
+PONG

無事 PONG がかってきました。

サーバーの証明書も確認してみましょう

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ openssl s_client -connect $HOST:6379 < /dev/null
CONNECTED(00000003)
depth=4 C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
verify return:1
depth=3 C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
verify return:1
depth=2 C = US, O = Amazon, CN = Amazon Root CA 1
verify return:1
depth=1 C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
verify return:1
depth=0 CN = *.xxx.dummy.euc1.cache.amazonaws.com
verify return:1
---
Certificate chain
 0 s:/CN=*.xxx.dummy.euc1.cache.amazonaws.com
   i:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon
 1 s:/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon
   i:/C=US/O=Amazon/CN=Amazon Root CA 1
 2 s:/C=US/O=Amazon/CN=Amazon Root CA 1
   i:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2
 3 s:/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2
   i:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/CN=*.xxx.dummy.euc1.cache.amazonaws.com
issuer=/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon
---
No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 5071 bytes and written 375 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID:
    Session-ID-ctx:
    Master-Key: 42B1B59938BA4CE3B6667D4CDB65F1E80BDF31105D75EE1993C98333F1AA1FB9664DE0271A68E1AD1BC230F81204C4A6
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1510421807
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
DONE

Redis-Py から試す

Python の Redis クライアント Redis-Py から通信が暗号化された Redis に接続してみます。

pip 経由で Redis-Py をインストールします。

1
$ pip install redis

まずは暗号化せずに接続してみます

1
2
3
4
5
6
7
>>> import redis
>>> redis.Redis(
  host="REDIS-ENDPOINT",
  port=6379).ping()
Traceback (most recent call last):
...
redis.exceptions.ConnectionError: Error while reading from socket: (104, 'Connection reset by peer')

ConnectionError エラーが発生しました。

TLSで接続するには、接続時の引数で ssl=True を追加するだけです。

1
2
3
4
5
6
>>> import redis
>>> redis.Redis(
  host="REDIS-ENDPOINT",
  port=6379,
  ssl=True).ping()
True

クライアント認証

Redis には認証トークンでサーバーと認証する AUTH コマンドが存在します。 素の Redis では redis.conf の requirepass ディレクティブで設定可能です。

redis.conf
1
requirepass foobared

今回の機能追加は、Amazon ElastiCache for Redis でもこの機能を提供するというものです。

設定

encryption in-transit を有効にする場合のみ、クライアント認証もオプションで有効にできます。

redis-auth-token

また、トークンには16文字〜128文字まで長さで、' '(半角スペース)、"(ダブルクオート)、/(スラッシュ)、@(アットマーク)を除いた printableアスキー文字を利用出来ます。

At least 16 characters, and maximum 128 characters, restricted to any printable ASCII character except ' ', '"', '/' and '@' signs.

サーバー接続を試す

Redisクラスター作成後、実際に接続を試してみましょう。

openssl コマンドから試す

まずは先程と同じコマンドでサーバーに接続します。

1
2
$ openssl s_client -connect REDIS-HOST:6379 -quiet
...

認証なしに PING コマンドを呼び出します

1
2
3
4
$ openssl s_client -connect REDIS-HOST:6379 -quiet
...
PING
-NOAUTH Authentication required.

NOAUTH エラーが発生しました。

次にクラスター作成時に設定したトークンを利用してAUTH コマンドで認証し、PING コマンドを呼び出します。

1
2
3
4
5
6
$ openssl s_client -connect REDIS-HOST:6379 -quiet
...
AUTH YOUR_PASSWORD_COMES_HERE
+OK
PING
+PONG

無事 PONG がかってきました。

Redis-Py から試す

Redis-Pyからも認証なしにPINGを呼び出してみます

1
2
3
4
5
6
7
8
>>> import redis
>>> redis.Redis(
  host='HOST.cache.amazonaws.com',
  port=6379,
  ssl=True).ping()
Traceback (most recent call last):
...
redis.exceptions.ResponseError: NOAUTH Authentication required.

NOAUTH エラーが発生しました。

接続時のオプションに認証トークンを渡します。

1
2
3
4
5
6
7
>>> import redis
>>> redis.Redis(
  host='HOST.cache.amazonaws.com',
  port=6379,
  ssl=True,
  password='YOUR_PASSWORD_COMES_HERE').ping()
True

無事疎通に成功しました。

通信の暗号/Authを有効にしたクラスターの識別方法

管理コンソール

Redis クラスターで赤枠を確認下さい。

redis-security-in-transit

CLI

aws elasticache describe-cache-clusters のレスポンスの

  • TransitEncryptionEnabled
  • AuthTokenEnabled

を確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ aws elasticache describe-cache-clusters
{
    "CacheClusters": [
        {
            ...
            "TransitEncryptionEnabled": true,
            "Engine": "redis",
            ...
            "AuthTokenEnabled": true,
            "AtRestEncryptionEnabled": true,
            "EngineVersion": "3.2.6",
            ...
        }
    ]
}

注意

パフォーマンスへの影響

通信を暗号化すると、データの暗号・復号のオーバーヘッドが発生します。

パフォーマンスが求められるシステムでは、暗号の有無によるパフォーマンスへの影響をベンチマークするようにお願いします。

対応バージョン

通信の暗号化は 3.2.6 にしか対応しておりません。 2017/11/15時点で最新の 3.2.10 では利用出来ないため、お気をつけ下さい。

新規インスタンスのみ対象

作成済みRedisクラスターに対して、通信の暗号化は行なえません。 クラスターの再構築が必要です。

まとめ

通信の暗号化・クライアント認証と、地味ではありますが、セキュリティが重要視されるお客様・システム向けには、要件を満たす上で非常に大事な機能追加です。

通信の暗号の際にはオーバーヘッドが発生するため、パフォーマンスへのインパクトにお気をつけ下さい。

また、システムを見守る人にとっては、Redisの通信が暗号化されていると、これまで慣れ親しんできたコマンドでは接続できなくなります。障害時に接続できずにパニクらないように、接続方法を再確認していただければと思います。

参考



https://qiita.com/whim0321/items/093fd3bb2dd287a72fba



Windows 10でLinuxを使う

Windows 10でUbuntuをインストール

Windows 10では、Windows Subsystem for Linux (WSL)というやつの上で簡単にLinuxを使える。仮想環境を準備するよりお手軽そうなので、使ってみた。

  1. 管理者モードでPowerShellを起動し、下記のコマンドを実行してWSLを有効化。
PS C:\Windows\System32> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

2.下記の問い合わせに対して、Yを入力してPCを再起動

pshell_wsl.png
3. 再起動後、Microsoft Storeを起動し、Ubuntuを検索
Microsoft Storeには版数まで入ったUbuntuもある。(Ubuntu 18.04等)
特定の版数のUbuntuを入れたい場合は、そっちを入れたほうがよい。版数無しUbuntuはインストールする時期によって、版数が変わる模様。(2018/10追記)

winstore_ubuntu.png
2018/10/08現在、Debian, SUSE, openSUSE等もダウンロード可能。
4. 「入手」ボタンをクリックして、Ubuntuをインストール
5. インストール完了後、「起動」をクリックしてUbuntu起動!

winstore_ubuntu2.png
6. 初回起動時にUbuntu用ユーザIDとパスワードを設定して、インストール完了
root権限が必要な場合は、sudoで実行できる。
ubuntu_1st.png

gccインストール

gitは入っているけど、gccは入っていないのでインストール。

$ git --version
git version 2.7.4

$ gcc
The program 'gcc' is currently not installed. You can install it by typing:
sudo apt install gcc

$ sudo apt-get install gcc

$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

sshサーバ起動

Ubuntu 18.04には、openssh-serverがインストール済み。

$ apt list openssh*
Listing... Done
openssh-client/bionic,now 1:7.6p1-4 amd64 [installed]
openssh-client-ssh1/bionic 1:7.5p1-10 amd64
openssh-known-hosts/bionic 0.6.2-1 all
openssh-server/bionic,now 1:7.6p1-4 amd64 [installed]
openssh-sftp-server/bionic,now 1:7.6p1-4 amd64 [installed]

sshdは起動していないため、起動する必要がある。初回のみssh host keyの作成を実施してから、sshdを起動する。なお、systemctl enable sshはできないため、毎回sshdを起動する必要がある。

$ sudo ssh-keygen -A
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
$
$ sudo service ssh start
 * Starting OpenBSD Secure Shell server sshd                                              [ OK ]

後はTera Term等の好きなssh clientで接続可能。接続先のIPアドレスはPCのIPアドレス or localhostでOK。

Windowsとのファイル共有

WindowsのCドライブが/mnt/cにマウントされているので、Windowsとファイルを共有することも簡単にできる。


Rootユーザでログイン、Rootユーザパースワード変更

1. WindowsでCMD実行

2. Ubuntu基本ユーザをRootに変更

ubuntu.exe config --default-user root

3. Ubuntu起動じRootで接続完了

4. 下記のコマンドからパスワード変更

passwd root

5. 再びUbuntuユーザを基本ユーザに変更

ubuntu.exe  config --default-user ubuntu

アンインストール方法

通常のアプリケーションと同様に「プログラムの追加と削除」からアンインストール可能。

その他

コマンドプロンプトからwslconfigコマンドで、インストール済みディストリビューション一覧の参照、アンインストール等ができる。

>wslconfig
Linux 用 Windows サブシステムの管理操作を実行します

使用法:
    /l、/list [/all] - 登録されたディストリビューションを一覧表示します。
        /all - すべてのディストリビューションを一覧表示します (オプション)。
               現在インストールまたはアンインストール中のものも含まれます。
    /s、/setdefault <DistributionName> - 指定のディストリビューションを既定として設定します。
    /u、/unregister <DistributionName> - ディストリビューションの登録を解除します。
>wslconfig /l
Windows Subsystem for Linux ディストリビューション:
Ubuntu-18.04 (既定)


https://qiita.com/sirotosiko/items/2371290e19ab21296ce9



Transit Gatewayを試してみた

Transit Gatewayを試してみました。

どんなもの?

VPCやオンプレ間を単一のゲートウェイで相互に接続できるようにするサービスです。

構成図

aws-transit-gateway.png

VPCpublic/privateSubnet CIDREC2EC2 IP
VPC1public10.10.0.0/24EC2①10.10.0.210
VPC1public10.10.1.0/24
VPC1private10.10.10.0/24
VPC1private10.10.11.0/24EC2②10.10.11.200
VPC2public10.20.0.0/24
VPC2public10.20.1.0/24EC2③10.20.1.4
VPC3public10.30.0.0/24EC2④10.30.0.152
VPC3public10.30.1.0/24

1. VPC・Subnet・EC2を作成する

構成図にあるVPC・Subnet・EC2を作成します。
全て同じリージョンに作成する必要があります。

2. Transit Gatewayを作成する

VPCのコンソールからTransit Gatewayを作成します。

1_create_tg.png

3. Transit GatewayをVPCにアタッチする

続けて作成したTransit GatewayをVPC1とVPC2にアタッチします。
VPCにアタッチする際にSubnetを指定する必要がありますが
指定していないSubnetに作成したEC2からも疎通が通ることを確認するために
ここでは全てPublic Subnetを指定しておきます。

2_attach.png

VPC3は別AWSアカウントなので、Resource Access ManagerでTransit Gatewayを共有してからVPC3にアタッチします。

3_share.png

4. ルートを追加する

Transit Gateway Route Tableには、アタッチしたVPCへのルートが既に設定されています。

4_tg_rt.png

個別のVPCに対しては、自分でルートを設定する必要があります。

VPC1

4_vpc1.png

VPC2

4_vpc2.png

VPC3

4_vpc3.png

5. 疎通をテストする

各EC2のセキュリティーグループを編集し各VPCのCIDRからのsshを許可した後、EC2間でsshの疎通を確認します。
EC2②は、Transit GatewayをVPC1にアタッチする際に指定したサブネット(Public Subnet)でないサブネット(Private Subnet)にありますが、ちゃんと疎通が通ることが確認できます。

EC2① → EC2③
[ec2-user@ip-10-10-0-210 ~]$ ssh -i *****.pem ec2-user@10.20.1.4

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-20-1-4 ~]$
EC2① → EC2④
[ec2-user@ip-10-10-0-210 ~]$ ssh -i *****.pem ec2-user@10.30.0.152
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-30-0-152 ~]$
EC2② → EC2③
[ec2-user@ip-10-10-11-200 ~]$ ssh -i *****.pem ec2-user@10.20.1.4

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-20-1-4 ~]$
EC2② → EC2④
[ec2-user@ip-10-10-11-200 ~]$ ssh -i *****.pem ec2-user@10.30.0.152

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-30-0-152 ~]$

雑感

VPC peeringはリージョン間の接続に対応していますが、Transit Gatewayは未対応です。そのうち対応するかなー。


lambda layers란

[lambda들이 공통적으로 사용하는 라이브러리 + 람다에 실기에는 너무 무거운 라이브러리]를 lambda 보다 한 단 위에 있는 레이어에 실어 lambda들이 공통적으로 사용할 수 있게 하는 기능입니다.

(더 자세한 건 [https://medium.com/@rabter/aws-lambda-layer%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-how-to-use-aws-lambda-layers-c206ba40d4cc] 참고)

무한정으로 라이브러리를 실을 수 있는 것은 아니고, 5개의 layers, 전체 layers 용량 250m 까지라는 제한이 존재 합니다.

lambda layers를 디렉토리 구조로 관리할 수 있을까?

최근 프로젝트에서 lambda를 통해 api를 디플로이하는 요건이 있었습니다. 약 10여개의 api를 디플로이 해야 했는데, 다른 라이브러리에 의존성이 존재했습니다.

위에서 언급했다시피, layers에는 무한정의 라이브러리를 넣을 수 있는 것이 아닙니다. layers직하라면 5개의 라이브러리밖에 들어가지 못하죠.

그래서 다음과 같이 라이브러리의 종류를 나누고 각 디렉토리에 해당하는 디펜던시를 관리하기로 했습니다.

layers
    ├─calculation
    ├─network
    ├─data
    └─custom

이때 !

layers를 인풋하기 위해서 특정한 디렉토리 구조를 지키지 않으면 lambda에서 임포트하지 못합니다.
이를 설명하기 위해 custom 이라는 이름의 layer를 추가하는 시나리오를 가정해봅니다.

└─python
    ├─anasdk
    │  └─src
    │      └─logic
    │          ├─common
    │          └─definition
    └─bizsdk
           └─src
               └─logic
                   ├─common
                   └─definition
  1. 먼저 python 이라는 디렉토리를 만들고, 그 안에 개발자가 원하는 라이브러리를 넣어줍니다. 저같은 경우는 자작된 anasdk, bizsdk라는 라이브러리를 python 디렉토리의 직하에 넣어두었습니다.
  2. python 디렉토리를 zip합니다.
  3. layers만들기에 들어간 후, zip파일을 업로드하고 custom이라는 이름의 layer명으로 저장합니다.
  4. 각 lambda에서 custom 레이어를 디플로이합니다.
  5. lambda에서 잘 import 되는지 확인합니다. lambda에서는 아래와 같은 방식으로 import가 가능합니다.
import json
import anasdk
import bizsdk

라이브러리를 넣는게 아니라 좀 더 화끈하게 가상환경 디펜더시를 통째로 넣어볼까

제가 만든 lambda함수에서는 requests 라이브러리를 사용하고 있습니다. 그런데 lambda에선 requests모듈을 지원하지 않아, layer에 추가하여 관리해야하죠. 그래서 request 라이브러리를 layer에 넣고 사용하려니 이번에는 request에서 필요한 디펜던시를 또 넣어야 하는 문제가 발생했습니다. 이후의 라이브러리를 넣어도, 또 그에 필요한 라이브러리를 넣어달라는 에러가 언제까지나 지속되겠죠.

그래서 로컬 가상환경에 가지고 있는 라이브러리 전체를 layer에 넣기로 했습니다. 방법은 다음과 같습니다.

  1. 로컬에서 pip 가상환경을 인스톨하고, 필요한 라이브러리를 모두 인스톨합니다.
  2. [가상환경 루트] / Lib / site-packages 에 인스톨한 라이브러리가 모두 들어있습니다. 이를 모두 복사합니다.
  3. 위에서 처럼 python 디렉토리를 만든 후, 그 안에 복사한 라이브러리를 모두 넣습니다. 용량이 꽤큽니다.
  4. python 디렉토리를 zip합니다.
  5. layers만들기에 들어간 후, zip파일을 업로드합니다.
  6. 잘 작동하는군요.

주의할 점

주의할 점이 있습니다. pip으로 인스톨한 라이브러리가 lambda에서 전부 사용가능한 것이 아니라는 점. lambda가 제공하는 기본 파이썬 모듈이 기존의 리눅스와는 다르기 때문입니다. 예를 들어 pip으로 인스톨한 pandas 라이브러리나, postgresql을 사용할 수 있는 가장 유명한 프레임워크인 psycopg2 조차도 보통의 소스코드를 인스톨해서는 lambda에서 사용이 불가합니다. 이러한 라이브러리는 검색해서 따로 다운 받은후 넣어주어야 합니다.



AWS リソースのタグ規約を考える

AWS での悩みどころのひとつに EC2 インスタンスなど各種リソースの名前などタグをどう設定すべきかという点があります。調べてみても、命名規約的なものが整備されているわけではなく、個々にベスト・プラクティスがまとめられているだけ、というのが現状のようです。

皆様のご意見を参考にしたいという意味もあり、命名規約案を公開してみることにしました。こうした方がよいなど、ご意見があれば、コメント頂けると幸いです。

[2019/04/02 追記] user: プレフィクスはコスト配分レポートに表示されるときに付与されるものであり、タグ規約に含めるのは不適切であることに気付きましたので、該当の記述は削除しました。

参考となる資料

AWS が正式に公開している資料としては次のものがあります。

ブログ記事では、次のものを参考にさせていただきました。

キーの命名規約

キー名は、次のルールに従います。

  • Upper Camel Case 記法1とします。(例: BuildId)
  • 標準化されていないタグキーには namespace: を付与します。namespace は Lower Camel Case 記法2とします。(例: projA:CostCenter)

なお、namespace として aws は予約されており、user も用途が決まっているため自由に使うことはできません(後述)。

残念なことに AWS が利用/生成しているキーの名前はすでに一貫性がないため、上記のルールが適用できません。AWS が利用/生成するキーには次のようなものがあります。

キー名用途
Nameリソースの表示名として使われます。
aws:createdByAWS Billing and Cost Management にて AWS 生成コスト配分タグとして付与されます。
aws:cloudformation:logical-idCloudFormation で作成されたリソースに自動付与されます。
aws:cloudformation:stack-idCloudFormation で作成されたリソースに自動付与されます。
aws:cloudformation:stack-nameCloudFormation で作成されたリソースに自動付与されます。

値の命名規約

タグの値は次のルールに従って設定します。

  • ブール型である値は true あるいは false を設定します。
  • 数値型である値は、符号、数値、小数点(および必要に応じて単位)のみからなる値として設定します。表示用にしばしば利用されるカンマ編集や指数表示は使用しません。
  • 日付、時刻は ISO 8601 拡張形式で設定します。(例:2001-01-01、01:20:30、2001-01-01T01:20:30、2001-01-01T01:20:30Z)
  • その他の値は特に制約を設けず、空白、記号を含む任意の文字列を設定します。

ただし、ひとつのキーに複数の値が紐づくなど構造化する必要がある場合は次のルールに従います。

  • 値にサブキーを付ける場合には、イコール記号で区切ります。(例: Title=FooBar)
  • 値が複合値(タプル)の場合は、パイプで区切ります。(例: 昭和|S|1926-12-25)
  • 複数の値がある場合は、セミコロンで区切ります。(例: value1;value2;value3)

標準タグ・キー名

次のものを標準タグとします。これ以外のタグを付与する場合は、namespace を付与するものとします。

Name(必須)

リソースの表示名です。値の命名は次のルールに従います。

  • 値は、Lower Kebab Case3とします。これは、ドメイン名やホスト名としても転用できるようするためです。
  • 値は、Stack-Environment-ResourceType-Indentifier の形式とします。
  • Stack には、プロジェクト名など管理単位を設定します。(詳細は Stack タグの項で説明します)
  • Environment には、本番や開発など環境名を設定します。(詳細は Environment タグの項で説明します)
  • ResourceType には、次のようなリソースの種類を表す略称を設定します。
    • vpc: VPC
    • subnet: サブネット
    • igw: インターネットゲートウェイ
    • nat: NAT ゲートウェイ
    • dopt: DHCP オプション
    • rtb: ルートテーブル
    • sg: セキュリティグループ
    • acl: ネットワーク ACL
    • ec2: EC2 インスタンス
  • Identifier には、同じようなリソースが複数ある場合に区別できる名前を設定します。複数の単語から成る場合はハイフンで区切ります。例としては次のようなものがあります。
    • default: デフォルトのリソース
    • public-x: AZ x にあるパブリック・サブネット
    • bastion: 踏み台サーバ
    • ap-1: AP サーバ 1号機
    • db: DB サーバ

Stack(必須)

リソースの管理単位です。リソースグループのクエリ条件としても利用します。多くの場合、プロジェクト名やシステム名となるでしょう。値の命名は次のルールに従います。

  • 英数小文字のみからなる文字列とします。複数単語から成る場合、頭文字をつなげたものや全社共通のシステム ID を使うとよいでしょう。
  • VPC などプロジェクトを跨いで共有するものには global を設定します。

Stack は、リソースグループのクエリ条件として使用可能です。

Environment(必須)

環境名です。リソースグループのクエリ条件としても利用します。原則、次のいずれかを設定します。同じ用途の環境が複数ある場合には末尾に数字を付けて区別します。

  • prod: 本番環境
  • stage: ステージング環境
  • test: テスト環境
  • dev: 開発環境
  • common: 共有環境

Service(任意)

デプロイされているサービス名を設定します。例えば、apache、nginx、mysql などです。必要があればハイフンで区切りバージョンを記載しても構いません。(例: apache-2.2.3)

Version(任意)

デプロイされているアプリケーションのバージョン番号を設定します。

BuildId(任意)

デプロイされているアプリケーションのビルド時に付与された ID を設定します。

ManagedBy(任意)

インフラ構築ツールの管理下にあることを示します。値には ansible、terraform などインフラ構築ツールの名前を設定します。

Owner(任意)

リソースの所有者(所有部署)のコードあるいは名前を設定します。コードと名前を両方記載する場合はパイプ記号で繋いで設定します。

Project(任意)

リソースの構築元となったプロジェクトのコードあるいは名前を設定します。コードと名前を両方記載する場合はパイプ記号で繋いで設定します。

Customer(任意)

リソースにより機能が提供される顧客のコードあるいは名前を設定します。コードと名前を両方記載する場合はパイプ記号で繋いで設定します。

CostCenter(任意)

リソースのコスト負担者(負担部署)コードあるいは名前を設定します。コードと名前を両方記載する場合はパイプ記号で繋いで設定します。

Role(任意)

リソースの役割を設定します。(例:Web Server、DB Server)

Contact(任意)

このインフラに関する問い合わせ先メールアドレスを設定します。


  1. 英数小文字を英大文字で区切る手法(例: XxxXxxXxx) 

  2. 先頭が英小文字となる Camel Case 記法(例: xxxXxxXxx) 

  3. 英数小文字からなる単語をハイフンで区切った記法(例:xxx-xxx-xxx) 


+ Recent posts