AWS CloudWatchでEC2のCPU使用率を監視してSNSで通知する

サーバ監視ってややこしそうな印象でしたが、AWSを使うと簡単でした。
タイトルの通り、CloudWatchでEC2のCPU使用率を監視してSNSで通知した時のメモです。
ここでいう SNS は、Social Networking Service ではなく、AWSのサービスの一つである Simple Notification Service のことです。

前提

  • EC2インスタンスが稼働中であること(事前に監視対象のインスタンスIDをメモしておく)

SNS(Simple Notification Service)でトピック・サブスクリプション作成

トピックとは

  • 通知のチャンネルのようなもの
  • トピックの中(下?)に通知先を色々設定できる(HTTP、Email、AWS Lambda…)
  • 作成時に トピック名(半角英数字とハイフン、アンダースコアで256文字まで)と、表示名(10文字以内)を入力

サブスクリプションとは

  • トピックの中(下?)に作成する通知先のこと
  • エンドポイントとして、HTTPならURL、Emailならメールアドレスを指定する
  • Emailを指定すると、設定したアドレス宛に承認用URLが届くので、本文内のURLで承認する

SNSの料金設定

  • メール送信であれば、毎月1,000件までは無料
  • それ以降は、100,000件あたり2ドル

※他のサブスクリプションについてはSNS料金ページを参照してください
https://aws.amazon.com/jp/sns/pricing/

作成手順

  1. トピック作成
  2. 作成したトピックに対してサブスクリプション作成
    • プロトコルを Email
    • エンドポイントに 通知先のメールアドレス
  3. 設定したメールアドレス宛に届いた承認メール内のURLにアクセスして、承認
    • 件名は AWS Notification - Subscription Confirmation

CloudWatchでアラーム作成

アラームとは

  • ◯◯が▲▲以上になったら□□する といった設定のこと
  • 以下の3つの状態がある
    • アラーム:設定した条件に合致している状態
    • 不足:データが不足していて設定した条件が判定できない状態
    • OK:設定した条件に合致していない状態

CloudWatchの料金

  • 無料

    • 最大50個のメトリクス、3つのダッシュボード、モニタリングは5分間隔

※詳細はCloudWatch料金ページを参照してください
https://aws.amazon.com/jp/cloudwatch/pricing/

作成手順

※スクショはありません

  1. メトリクスの選択EC2 を選択し、右横のテキストボックスに対象のインスタンスIDを入力して Enter
  2. 下の一覧から CPUUtilization (CPUUtilization) の行にチェックを入れ、次へ
  3. 名前説明 を入力
  4. しきい値、アラームのプレビュー の下にあるテキストボックス、ラジオボタン、セレクトボックスを適宜設定する
    以下、「5分間の使用率平均が70%を超えた場合にトリガー」という条件の場合の設定例
    が:≧ 70
    期間:1 中 1データポイント
    間隔:5分間
    統計:スタンダード 平均
  5. アクション の項目で、アラームが次の時:状態:警告 に、作成したSNSのトピックを指定する
    アラームの状態が、アラーム に変わった時に通知が来る
  6. アラームが次の時:状態:OK も設定すると、アラームの状態が OK に変わったときにも通知が来る

注意点

  • 間隔を 1分 とかに設定することもできますが、無料で使用する場合はモニタリングの最小間隔が 5分 なので、アラームの状態が頻繁に 不足 になります。

続きを読む

Route53で取得したドメインをCognitoユーザープールの送信元アドレスに使う

サービスの認証にCognitoを使う際、サービスへの初回登録時の確認コード送信や、パスワード変更確認メールの送信などをする必要が出てくるかと思います。
そのようなシステムメールの送信元メールアドレスをカスタマイズする方法です。

方法としては、SESに送信元にしたいアドレスを登録し、それをCognitoから参照する形になります。

SESに登録したアドレスを送信元として使えるようにするためには、SES登録後、そのアドレスに送信される確認URLにアクセスする必要があります。

送信元に使いたいアドレスが既にメールを受信できる状態であればつまづくことはないかと思いますが、Route53でドメインを取得した時点ではメールを受信する手段がないためSESからの確認メールを確認する手段がないことになります。

今回はそんな場合の対処法です。
ちなみにドメインは取得済みの想定です。
SES、SNSはバージニアリージョンです。

設定値

  • ドメイン:ykarakita.com
  • Cognitoに設定する送信元メールアドレス :info@ykarakita.com
  • 確認メールが受信可能なメールアドレス:xxx@gmail.com

手順

  1. SNSのトピックを作成し、受信可能なメールアドレス(gmailとか)をサブスクリプションとして登録する
  2. ドメインをSESに登録する、同時にRoute53にMXレコードとTXTレコードを作成する
  3. SESの受信ルールを作成し、1.で作成したSNSトピックを指定する
  4. Cognitoで送信元にするメールアドレスをSESに登録する
  5. 1.で登録したメールアドレスに確認メールが届くので承認リンクをブラウザで開く

1. SNSのトピックを作成し、受信可能なメールアドレス(gmailとか)をサブスクリプションとして登録する

10.png
コンソールでSESを開き、TopicsからCreate new topicを開く。

11.png
Display nameはメール送信時の送信者名になる。
名前を入力してCreate Topic

12.png
作成したTopicのARNのリンクからTopic詳細画面へ。

13.png
Create subscriptionをクリック

14.png
こんな感じで入力する。Endpointはメール受信可能なメールアドレス。Create subscription する。

スクリーンショット 2018-02-02 0.44.41.png
そうすると、登録されたメールアドレスに確認メールが届くのでConfirm subscriptionのリンクへ行くと下のような画面が表示される。

スクリーンショット 2018-02-02 0.44.46.png

これでこのSNSトピックにパブリッシュしたらgmailにメールが飛ぶようになっているはず。

2. ドメインをSESに登録する、同時にRoute53にMXレコードとTXTレコードを作成する

SESコンソール左側のDomainsを選択。
9.png
Verify a New Domainから、あらかじめRoute53で取得済みのドメイン名を入力。

スクリーンショット 2018-02-01 23.52.52.png
このドメイン所有者の確認としてDNSレコードを登録するように言われる。今回はホストゾーンもRoute53に作成しているためそのままUse Route53へ。

スクリーンショット 2018-02-01 23.52.56.png
すべてチェックを付けてCreate Record Sets

1.png
登録したドメインのステータスはpending verificationになっている。
1分くらいたつとverifiedになる。

3. SESの受信ルールを作成し、1.で作成したSNSトピックを指定する

SESのコンソールからRule SetsView Active Rule SetCreate Ruleを開く。
7.png

8.png

スクリーンショット 2018-02-02 0.55.30.png
ここにはCognitoの送信元にしたいメールアドレスを入力。Add Recipientで追加。

スクリーンショット 2018-02-01 22.34.44.png
Next Stepへ。

5.png
Actionには先ほど作成したSNSトピックを選択する。

スクリーンショット 2018-02-01 23.49.20.png
スクリーンショット 2018-02-01 23.50.33.png
スクリーンショット 2018-02-01 23.50.39.png
こんな感じ。

4. Cognitoで送信元にするメールアドレスをSESに登録する

SESコンソールのEmail Addressesを開く。
2.png

3.png
Verify a New Email Addressから送信元メールアドレスにしたいアドレスを入力。

4.png

5. 1.で登録したメールアドレスに確認メールが届くので承認リンクをブラウザで開く

メールアドレスを登録すると、SNSサブスクリプションに登録したメールアドレスあてに確認メールが届くので、その中から下の方にあるhttps://email-verification.us-east-1.amazonaws.comで始まるURLを探し出してブラウザで開く。

スクリーンショット 2018-02-02 1.10.51.png
こんな画面が表示される!

20.png
ちゃんとverifiedになりました。

これでCognitoの送信元メールアドレスに指定する準備ができました。

スクリーンショット 2018-02-02 10.15.52.png

Cognitoの設定画面で選択できる!

以上です。

続きを読む

AWS EC2作成からTeraterm接続まで

※AWSアカウントを持っていて、ログインできる方が対象です。

VPCの構築

・1つのお城のようなイメージ
・参考URLに沿って作成する

VPCとはAWSアカウント上に複数作成することが出来るプライベートなネットワークの単位です。一軒家を建てる為の土地全体といったところでしょうか。
VPCの配下には、AZがあり、その配下にはサブネットがあります。またAZは1つ以上のサブネットを保持することができます。AWS上で初めてネットワークを構築するときは最低でも1つのVPC、1つのAZ、1つのサブネットを作成する必要がします。
AZは建造物エリア、サブネットは建造物を設置するための基礎といったイメージです。

参考URL:https://engineers.weddingpark.co.jp/?p=523

EC2の作成

・これも下記URLに沿って作成する
参考URL:https://engineers.weddingpark.co.jp/?p=523

・ただし、インスタンスのパブリックIPが勝手に設定されていますが、私の時は設定されていなかった
→Elastic IPを取得して、割り当てる必要あります。下記参照

image.png

image.png

画面を閉じて、取得したElastic IPを選択→アクション→アドレスの関連付け
→インスタンスに先ほど作成したEC2を選択し、関連付け
※Elastic IPはEC2に関連付けしないと課金されるので注意

関連付けるとパブリックDNS、IPが記載されるのでそちらでSSH接続する。

SSH接続(Windows)

Teratermでアクセスしました。
下記参照。ファイルの種類を「すべてのファイル」にしないと秘密鍵を選択できないので注意

参考URL:https://dev.classmethod.jp/cloud/aws/aws-beginner-ec2-ssh/

image.png

ping応答設定

EC2に紐づいているセキュリティグループに「ICMP」を追加する

参考URL:http://a1-style.net/amazon-web-service/ping-icmp-setting/

続きを読む

20180201勉強まとめ

WebDAV

Web-based Distributed Authoring and Versioning

Webサーバ上のファイル管理を目的とした分散ファイルシステムを実現するプロトコル

Webサーバに対して直接ファイルのコピーや削除を行ったり、ファイル所有者や更新日時などのファイル情報を取得・設定するといった機能を持つ分散ファイルシステムで、HTTP 1.1を拡張したプロトコルで実現される
参考URL:https://ja.wikipedia.org/wiki/WebDAV

FTP

FTPクライアントを用いてサーバーへ接続することで、ファイルのアップロード・ダウンロード、またファイルの削除やディレクトリ作成などの操作が行えます

  • FTPクライアント不要で直感的に管理できる

FTPでファイルを送受信するには、FFFTP/FileZilla/WinSCPなどのFTPクライアント(FTPソフト)をまずパソコンにインストールしておかなければなりません。
WebDAVでは、Windowsのエクスプローラー(MacであればFinder)でWebDAVのパスを入力すると、エクスプローラー内にサーバー上のファイルを表示させることができます。

  • FTPのポートが塞がれている環境でも使える
    FTPではこれは20番と21番
    WebDAVでの通信は、ftpではなくhttp/https(ポート番号は80番/443番)、つまり普段ウェブサイトを閲覧するのに使うのと同じ手段

  • サーバー上のファイルを直接編集できる
    FTPの場合、サーバー上のファイルを編集したいと思ったら、まずいったんそのファイルをダウンロードする必要があります。その上で自分のパソコンでファイルの内容を修正して、あらためてアップロード、そして既存ファイルに上書きするという手順
    WebDAVではサーバー上のファイルを直接編集できます。つまりファイルをダウンロード・アップロードという手間が必要ありません。ダブルクリックでファイルを開いて修正して上書き保存、で作業が完結

  • アクセス権限の設定がしにくい
    各FTPアカウントごとにどのディレクトリまでならアクセスできるかを個別に指定できることも一般的

  • FTPと比べると不安定
    WebDAVはFTPに比べると通信がやや不安定になることがある

参考URL:https://serverkurabe.com/about-webdav/

続きを読む

初めてのAWS Lambda(どんな環境で動いているのかみてみた)

月曜日から3日間、AWSアーキテクト研修でした。そこではじめてLambdaに接しまして、ひととおり驚いてきたところです。自分なりのまとめです(ご存知の方には釈迦に説法)。

Lambdaとは?

恥ずかしながら私は「サーバーレス」という言葉を聞いてもいまいちピンと来ていませんでした。ですが、これは文字通りなんですよね。プログラムが動作する環境なんてどうだっていいんです。OSがなんだとか、ミドルウェアがなんだとか、メモリがどれくらいでCPUがいくらで、NWがどうで、トポロジーがなんでとか、そんなことはどうでもいいんです。
とにかく、「トリガー」と呼ばれる”きっかけ”を契機に、コード(プログラム)が動くんです。JavaならJVMがおもむろに立ち上がって、アップロードしておいたjarが実行されるんです。「トリガー」はAWSサービスと高度に統合されていて、例えば

  • ファイルストレージサービスであるところのS3(もはや単なるストレージの域を超越していますが)にファイルがアップロードされた
  • メッセージがキューにputされた
  • API Gatewayにリクエストがきた
  • EC2インスタンスが起動した
  • 3時になった
  • おなかがすいた(とAmazon echoに話した)
  • e.t.c.

MDBならぬTDB(Trigger Driven Bean)でしょうか。Beanである必要もないので、TBC(Trigger Driven Code)とでも言ったほうがいいのかもしれません。

うごかしてみる

研修の間、実習時間に余裕があったので、研修端末に入っていたEclipseで簡単なコードを書いて動かしてみました。テストはAWS Consoleからキックできるので、特に「トリガー」を定義しなくても動かすだけなら簡単に試せます。

お作法

基本的にどんなJavaプログラムでも必要なライブラリを組み込んでおけば動きますが、コールするメソッドにはお約束があるようです。それは引数です。第一引数にObjectをもらい、第二引数にContextをもらいます。メソッド名はなんでもいいです。型もなんでもいいです(ただし第一引数と戻り値の型ともにSeriarizableである必要あり。プリミティブ型もOK)。

第一引数に入るのは、具体的には「トリガー」からの情報です。メッセージがキューにputされたことをトリガーとするのであれば、そのメッセージ自体を渡してあげたり。戻り値は同期呼び出しであればほぼそのまんまでしょう。インタフェース要件に従って、Serializeして返してあげればよいだけです。

第二引数のContextですが、これはjavax.naming.Contextではなく、com.amazonaws.services.lambda.runtime.Contextです。というわけで、AWSが提供するjarファイルをビルドパスに追加する必要があります。1

作る

まだ意味のあるコードを書くほどの技量もアイディアもないので、インフラ屋っぽくどんな環境(システムプロパティ、環境変数、渡されたContextオブジェクト)で動いているのかみてみることにしました。

SystemInfo.class
package net.mognet.aws.lambda;

import java.util.Map;
import java.util.Properties;

import com.amazonaws.services.lambda.runtime.Context;

public class SystemInfo {

    public static String printSystemInfo(int i, Context context) {
            StringBuilder sb = new StringBuilder();
            //ヘッダを追加
            sb.append("name,value\n");

            //システムプロパティ取得
            Properties prop = System.getProperties();
            for(Object key : prop.keySet()) {
                String name = (String) key;
                String value  = prop.getProperty(name);
                sb.append(name + "," + value + "\n");
            }
            //環境変数取得
            Map<String, String> env = System.getenv();
            for(String key : env.keySet()) {
                String value = env.get(key);
                sb.append(key + "," + value + "\n");
            }
            //Contextの情報を取得
            sb.append("context" + "," + context.toString());
            return sb.toString();
    }

    public static void main(String[] args) {
            System.out.println(printSystemInfo(1, null));
    }
}

mainはテスト用です。1個目の引数こそ本来は大事なんでしょうけど今回は何もしません。

乗せる

AWSコンソールを開いてLambdaの関数を作ります(関数という単位で動きます。複数の関数をオーケストレーションするサービスもあるようです(詳細未調査))。
スクリーンショット 2018-01-31 21.39.16.png
適当に名前とランタイム(今回はJava8)を選んで「関数の作成」を押します。
標準出力はCloudWatchLogsへ流れるので、事前にCloudWatchLogsへのWrite権限のあるロールを作って必要に応じてここでアタッチしてください。
スクリーンショット 2018-01-31 21.39.50.png
スクリーンショット 2018-01-31 21.39.57.png
本来ならここでトリガーを選んで云々となりますが、とにかくテストしてみたいだけなので、その辺の条件だけいれます。
スクリーンショット 2018-01-31 21.40.05.png
関数コードのところで、「アップロード」からjarファイルをアップロード、大事なのが「ハンドラ」でここに実行するメソッドを入力します。書き方が決まっていて、”.”表記でクラスのフルパスの後ろに”::“をつけてメソッド名です。
今回は”net.mognet.aws.lambda.SystemInfo::printSystemInfo“となります。ついでに環境変数もつけてみました。一旦「保存」すると実際にファイルがアップロードされます。
スクリーンショット 2018-01-31 21.41.03.png
次にテストの準備です。テストケース(入力設定=第一引数設定)です。画面上部の「テストイベントの設定」を選びます。
スクリーンショット 2018-01-31 21.41.19.png
実行するメソッドpublic static String printSystemInfoの第一引数がintなので、1とだけ書いて終わりです。下の方にある「保存」を押します。これでテスト準備完了です。

いざ実行!

おもむろに「テスト」を押します。
スクリーンショット 2018-01-31 21.42.15.png
動きました。今回はログ出力(標準出力)なしなので、ログは見ませんが開始と終了のメッセージが出ていました。String型のメソッドを実行したので、returnした文字列がそのまま画面上に表示されています(改行コードは改行してほしかったけど実行結果表示コンソールとしてはこれが正しいあり方ですね)。

付録

付録で実行結果を載せておきます。

name value
java.runtime.name OpenJDK Runtime Environment
sun.boot.library.path /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/amd64
java.vm.version 25.141-b16
java.vm.vendor Oracle Corporation
java.vendor.url http://java.oracle.com/
path.separator :
java.vm.name OpenJDK 64-Bit Server VM
file.encoding.pkg sun.io
user.country US
sun.java.launcher SUN_STANDARD
sun.os.patch.level unknown
java.vm.specification.name Java Virtual Machine Specification
user.dir /
java.runtime.version 1.8.0_141-b16
java.awt.graphicsenv sun.awt.X11GraphicsEnvironment
java.endorsed.dirs /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/endorsed
os.arch amd64
java.io.tmpdir /tmp
line.separator
java.vm.specification.vendor Oracle Corporation
os.name Linux
sun.jnu.encoding UTF-8
java.library.path /lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name Java Platform API Specification
java.class.version 52.0
sun.management.compiler HotSpot 64-Bit Tiered Compilers
os.version 4.9.77-31.58.amzn1.x86_64
user.home /home/sbx_user1066
user.timezone UTC
java.awt.printerjob sun.print.PSPrinterJob
file.encoding UTF-8
java.specification.version 1.8
java.class.path /var/runtime/lib/LambdaJavaRTEntry-1.0.jar
user.name sbx_user1066
java.vm.specification.version 1.8
sun.java.command /var/runtime/lib/LambdaJavaRTEntry-1.0.jar
java.home /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre
sun.arch.data.model 64
user.language en
java.specification.vendor Oracle Corporation
awt.toolkit sun.awt.X11.XToolkit
java.vm.info mixed mode, sharing
java.version 1.8.0_141
java.ext.dirs /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/resources.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/rt.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/jce.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/lib/jfr.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.141-1.b16.32.amzn1.x86_64/jre/classes
java.vendor Oracle Corporation
file.separator /
java.vendor.url.bug http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding UnicodeLittle
sun.cpu.endian little
sun.cpu.isalist
PATH /usr/local/bin:/usr/bin/:/bin
AWS_XRAY_DAEMONADDRESS 169.254.79.2
LAMBDA_TASK_ROOT /var/task
AWS_LAMBDA_FUNCTION_MEMORY_SIZE 128
TZ :UTC
AWS_SECRET_ACCESS_KEY secret
AWS_EXECUTION_ENV AWS_Lambda_java8
AWS_DEFAULT_REGION ap-northeast-1
AWS_LAMBDA_LOG_GROUP_NAME /aws/lambda/SystemInfo
XFILESEARCHPATH /usr/dt/app-defaults/%L/Dt
_HANDLER net.mognet.aws.lambda.SystemInfo::printSystemInfo
LANG en_US.UTF-8
LAMBDA_RUNTIME_DIR /var/runtime
AWS_SESSION_TOKEN tokenString
AWS_ACCESS_KEY_ID accessKeyId
LD_LIBRARY_PATH /lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib
X_AMZN_TRACEID Root=1-5a71b98c-393aaa7b51f5612a348586c0;Parent=3ff8164301e3ccd4;Sampled=0
AWS_SECRET_KEY secretKey
hogehoge gehogeho
AWS_REGION ap-northeast-1
AWS_LAMBDA_LOG_STREAM_NAME 2018/01/31/[$LATEST]29640ec0ac8e426ab2b0a041b3a1b1f4
AWS_XRAY_DAEMON_ADDRESS 169.254.79.2:2000
AWS_XRAY_DAEMONPORT 2000
NLSPATH /usr/dt/lib/nls/msg/%L/%N.cat
AWS_XRAY_CONTEXT_MISSING LOG_ERROR
AWS_LAMBDA_FUNCTION_VERSION $LATEST
AWS_ACCESS_KEY accessKey
AWS_LAMBDA_FUNCTION_NAME SystemInfo
context lambdainternal.api.LambdaContext@604ed9f0

アクセスキー等の情報も環境変数に乗っていましたのでそこはマスクしてます。そういう仕様だということは理解しておくべきかもしれません。この辺のキーを使ってAWS API呼び出したりするのかな?あと、ちゃんと設定した環境変数も出て来てます(あたりまえですが)。
OpenJDK on Amazon Linuxで動かしているみたいですね。こればっかりは実際に本稼働したときにどうなるかわかりませんけれども。あくまでこのテスト実行時はこうでした、というだけです。なんといってもサーバーレスですので、繰り返しになりますが実行環境(HW、OS、MW等々)はどうでもいいです。というか、どうでもいい前提でコードを書いてください、というのがLambda的な使い方と認識しました。

参考

Lambda 関数ハンドラー(Java) – AWS Lambda


  1. EclipseにはAWSのツールキットプラグインがあるので、この環境をセットアップしておくだけでも可です。 

続きを読む

2018.1.31勉強まとめ

・デフォルトのリージョン:us-east-1

・AWS Storage Gateway:仮想テープライブラリ。オンプレのデータバックアップなどで使用

Route53:エイリアスレコードを使用してELBにルーティングできる
Zone Apexに割り当てる場合もエイリアスレコード使用

・メタデータ
http://169.254.169.254/latest/meta-data/でメタデータ取得可能
http://169.254.169.254/latest/meta-data/public-ipv4:パブリックIP
http://169.254.169.254/latest/meta-data/local-ipv4:プライベートIP
curl/GETで取得可能。テキストとして返される

・ユーザデータ
http://169.254.169.254/latest/user-data/で取得可能
コンテンツタイプはapplication/octet-stream
カンマで区切られたテキストで取得

プレイスメントグループ
同一のAZ内に複数のEC2を配置可能

プレイスメントグループは、単一のアベイラビリティーゾーン内のインスタンスを論理的にグループ化したものです。サポートされているインスタンスタイプとともにプレイスメントグループを使用すると、アプリケーションが低レイテンシーの 10 Gbps (ギガビット/秒) ネットワークに参加できるようになります。
どちらもインスタンス間における低レイテンシな通信を実現するための機能オプション
クラスタコンピューティングやDBの同期レプリケーションのように、サーバ間の通信レイテンシがサービス品質に影響するような場合に効果を発揮

拡張ネットワーキング
高い帯域幅、1 秒あたりのパケット (PPS) の高いパフォーマンス、常に低いインスタンス間レイテンシーを実現します。

参考URL:https://dev.classmethod.jp/cloud/aws/ec2-placement-group/

侵入テスト
事前にAWSに許可必要
EC2とRDSに限定対象外もある

参考URL:http://kakakakakku.hatenablog.com/entry/2016/08/08/022520

続きを読む

AWSセキュリティとコンプライアンス勉強まとめ

AWS責任共有モデル

  • お客様自身でクラウドをコントロール可能
    ネットワーク、サーバ、セキュリティなどなど
  • AWSがクラウドのセキュリティを担当。AWS基本サービス

AWS の責任はクラウドのセキュリティ(Security "of" the Cloud)
AWS は、AWS クラウドで提供されるすべてのサービスを実行するインフラストラクチャの保護に責任を負います。
このインフラストラクチャはハードウェア、ソフトウェア、ネットワーキング、AWS クラウドのサービスを実行する施設で構成されます。
データセンターの物理セキュリティ
ネットワークセキュリティ(DDoS攻撃対策、ポートスキャニング対策、)
論理的なセキュリティ(ホストOS、ゲストOS)
従業員・アカウントの管理
データセキュリティ
ストレージの廃棄プロセス

お客様の責任はクラウドにおけるセキュリティ(Security "in" the Cloud)
お客様の責任は、選択した AWS クラウドのサービスに応じて異なります。選択によって、セキュリティに関する責任の一環としてお客様が実行する構成作業の量が決定します。例えば、Amazon Elastic Compute Cloud (Amazon EC2)、Amazon Virtual Private Cloud (Amazon VPC)、Amazon S3 などのサービスは Infrastructure as a Service (IaaS) に分類されているため、必要なすべてのセキュリティ構成および管理のタスクをお客様が実行する必要があります。お客様が Amazon EC2 インスタンスをデプロイした場合、お客様は、ゲストオペレーティングシステムの管理 (更新やセキュリティパッチなど)、インスタンスにインストールしたアプリケーションソフトウェアまたはユーティリティの管理、AWS より各インスタンスに提供されるファイアウォール (セキュリティグループと呼ばれる) の構成に責任を負います。
IAM, KMS, CloudTrail, Trusted Advisor, VPC, セキュリティグループなどなど
サーバーOS、セキュリティ
Amazon Inspector(セキュリティ診断サービス)
ネットワークセキュリティ(VPCなど)
論理的アクセスコントロール(IAMなど)
Key Management Service
CloudHSM(ハードウェアセキュリティモジュール)
CloudTrail

参考URL:https://aws.amazon.com/jp/compliance/shared-responsibility-model/

Security by Design(SbD)
AWSアカウントの設計の規格化、セキュリティ制御の自動

CloudFormationで設計をテンプレート化

Trusted Advisor定期的な調査

参考URL:https://www.slideshare.net/AmazonWebServicesJapan/awswebinar-aws-59853341

続きを読む

AWS DDoS対策勉強まとめ

・DDOS攻撃
複数の攻撃元が協調して大量のパケットやリクエストを送ってサービスを停止させる

・ランサムDDoS
攻撃者が公開サーバーをいつでも停止できる

下記三軸で考える
【高さ】
レイヤーごと
– アプリケーション層攻撃
アプリケーションリソースを攻撃。
HTTPGET

DNSクエリフロッド
→ボットネットと呼ばれる複数の感染ホストを利用し、大量のクエリをDNSに配信

  • 状態枯渇攻撃
    ファイヤーウォールなどに攻撃
    TCP SYNフロッド
    →クライアントから意図的にACKを返さないことで、他のユーザがアクセス出来なくする
  • ボリューム攻撃
    処理できる能力を越えたトラフィックを送る
    UDP反射攻撃
    →攻撃者はIPを偽装。要求と応答のパケットのサイズ差を利用

【深さ】
アプリケーションごとに対策は違う。
→エッジとリージョンなど

・ウェブアプリケーションの場合
エッジでAWS WAF, CloudFrontを利用
リージョンでセキュリティグループで対策

・クライアント/サーバーアプリケーションの場合
EC2の垂直スケール、拡張ネットワークでトラフィック吸収

・ゲームアプリケーションの場合
Routing Matching ServiceでIP配布
特定のIPのみからアクセスするよう制御

【幅】
・地理的分散
→CloudFrontで配信分散

・攻撃対象隠蔽
→セキュリティグループ使用
→Amazon API Gatewayを利用。Web API公開サーバーを立てない
→ELBでEC2を見せない

・攻撃吸収、緩和
→AWS Shieldによる自動緩和システム
→CloudFrontによるGEOリストリクション
→Route53。高可用性
→ELBとAutoscalingでインスタンスそp増減
→拡張ネットワーク。NICへのアクセスを複数あるようにする

・計画、監視
→CloudWatchでの監視

・AWS Shield Standard
Layer 3/4 protection
→一般的な攻撃から防御
無料

Layer 7 protection
→WAFを利用
→使った分だけ支払い

・AWS Shield Advanced
Standardに加え、より大規模な攻撃からの防御

参考URL:
https://www.slideshare.net/mobile/AmazonWebServicesJapan/20170905-aws-blackbeltddosmitigation-79478348

続きを読む

[AWS][Terraform] Terraform で Amazon Inspector を導入する

TerraformAmazon Inspector を導入して、CloudWatch Events で定期実行させるための手順。
Terraform は v0.11.2 を使っています。

Inspector の導入

Inspector を導入するには、Assessment targets (評価ターゲット) と Assessment templates (評価テンプレート) を設定する必要があります。

Assessment targets の設定

Terraform で Assessment targets を設定するには、aws_inspector_resource_group, aws_inspector_assessment_target リソースを使用します。
こんな感じです。

inspector_target.tf
variable "project" { default = "my-big-project" }
variable "stage"   { default = "production" }

resource "aws_inspector_resource_group" "inspector" {
    tags {
        project   = "${var.project}"
        stage     = "${var.stage}"
        inspector = "true"
    }
}

resource "aws_inspector_assessment_target" "inspector" {
    name               = "my-inspector-target"
    resource_group_arn = "${aws_inspector_resource_group.inspector.arn}"
}

aws_inspector_resource_group では、対象となるインスタンスを特定するための条件を記述します。
上記の例だと、以下のタグが設定されているインスタンスを対象にします。

Name Value
project my-big-project
stage production
inspector true

aws_inspector_assessment_target では、aws_inspector_resource_group で定義した条件を元に Assessment targets を作成します。

Assessment templates の設定

Terraform で Assessment templates を設定するには、aws_inspector_assessment_template リソースを使用します。
こんな感じです。

inspector_template.tf
variable "inspector-rule" = {
    type = "list"
    default = [
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-gHP9oWNT",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-knGBhqEu"
    ]
}

resource "aws_inspector_assessment_template" "inspector" {
    name       = "my-inspector-template"
    target_arn = "${aws_inspector_assessment_target.inspector.arn}"
    duration   = 3600

    rules_package_arns = [ "${var.inspector-rule}" ]
}

output "assessment_template_arn" {
    value = "${aws_inspector_assessment_template.inspector.arn}"
}

rules_package_arns では、利用可能な Inspector rule package の ARN を設定します。
variable にしておくと、後で rule package を変更したい時に楽ですね。
こんな感じで、使用する rule package を変更できます。

terraform.tfvars
"inspector-rule" = [
    "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
    "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq"
]

使用できる rule package は、aws-cli で取得してください。

# パッケージ一覧の表示
$ aws --region ap-northeast-1 inspector list-rules-packages
{
    "rulesPackageArns": [
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-bBUQnxMq",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-gHP9oWNT",
        "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-knGBhqEu"
    ]
}
# 詳細を確認
$ aws --region ap-northeast-1 inspector describe-rules-packages 
  --rules-package-arns "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu"
{
    "rulesPackages": [
        {
            "description": "The CIS Security Benchmarks program provides well-defined, un-biased and consensus-based industry best practicesto help organizations assess and improve their security.nnThe rules in this package help establish a secure configuration posture for the following operating systems:nn  -   Amazon Linux version 2015.03 (CIS benchmark v1.1.0)n  n    ",
            "version": "1.0",
            "name": "CIS Operating System Security Configuration Benchmarks",
            "arn": "arn:aws:inspector:ap-northeast-1:406045910587:rulespackage/0-7WNjqgGu",
            "provider": "Amazon Web Services, Inc."
        }
    ],
    "failedItems": {}
}

参考URL: Terraform v0.8.5でAWS Inspectorに対応します

これで terraform apply すれば Assessment targets, templates が作成されます。

動作確認

実際に Inspector が実施されるか確認して見ましょう。

$ aws inspector start-assessment-run 
  --assessment-template-arn arn:aws:inspector:ap-northeast-1:************:target/0-xxxxxxxx/template/0-xxxxxxxx
{
    "assessmentRunArn": "arn:aws:inspector:ap-northeast-1:************:target/0-xxxxxxxx/template/0-xxxxxxxx/run/0-7WNjqgGu"
}

実行状況の確認は aws inspector describe-assessment-runs

$ aws inspector describe-assessment-runs 
  --assessment-run-arns arn:aws:inspector:ap-northeast-1:************:target/0-QOvPswHA/template/0-uCIUy636/run/0-n9nnWOem

CloudWatch Events Schedule による定期実行

当初は CloudWatch Events で定期実行するには Lambda から呼び出すようにしなければいけませんでした。
しかし、CloudWatch Event から直接 Inspector を実行できるようになったため、Lambda を使用しなくても aws_cloudwatch_event_targetaws_cloudwatch_event_rule だけで定期実行設定が可能です。

CloudWatch Events で使用する IAM ロールの作成

まずは、CloudWatch Events で使用する IAM ロールを作ります。

cloudwatch-events-iam-role.tf
esource "aws_iam_role" "run_inspector_role" {
    name               = "cloudwatch-events-run-inspector-role"
    assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_policy" "run_inspector_policy" {
    name        = "cloudwatch-events-run-inspector-policy"
    description = ""
    policy      = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "inspector:StartAssessmentRun"
            ],
            "Resource": "*"
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "run_inspector_role" {
    role       = "${aws_iam_role.run_inspector_role.name}"
    policy_arn = "${aws_iam_policy.run_inspector_policy.arn}"
}

CloudWatch Events への登録

CloudWatch Events に登録するために aws_cloudwatch_event_target リソースと aws_cloudwatch_event_rule を作りましょう。

cloudwatch-events.tf
variable "schedule"    { default = "cron(00 19 ? * Sun *)" }

resource "aws_cloudwatch_event_target" "inspector" {
  target_id = "inspector"
  rule      = "${aws_cloudwatch_event_rule.inspector.name}"
  arn       = "${aws_inspector_assessment_template.inspector.arn}"
  role_arn  = "${aws_iam_role.run_inspector_role.arn}"
}

resource "aws_cloudwatch_event_rule" "inspector" {
  name        = "run-inspector-event-rule"
  description = "Run Inspector"
  schedule_expression = "${var.schedule}"
}

schedule_expression の cron() は UTC で設定する必要があるので注意してください。
記述方法は、以下を参考に
参考URL: Rate または Cron を使用したスケジュール式

EC2 への IAM Role の設定と、ユーザーデータによる Inspector エージェントのインストール

評価ターゲットとなる EC2 には、Inspector エージェントがインストールされていて、適切なインスタンスロールが設定されている必要があります。
導入するには、こんな感じ

インスタンスロール

inspectora エージェントを使用するために必要なポリシーをアタッチしたインスタンスロールの作成はこんな感じです。

ec2-instance-role.tf
resource "aws_iam_role" "instance_role" {
    name               = "my-ec2-role"
    path               = "/"
    assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_instance_profile" "instance_role" {
    name = "my-ec2-role"
    role = "${aws_iam_role.instance_role.name}"
}

resource "aws_iam_policy" "inspector" {
    name        = "my-ec2-iam-policy-inspector"
    description = ""
    policy      = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeCustomerGateways",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "ec2:DescribeInternetGateways",
                "ec2:DescribeNatGateways",
                "ec2:DescribeNetworkAcls",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribePrefixLists",
                "ec2:DescribeRegions",
                "ec2:DescribeRouteTables",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeSubnets",
                "ec2:DescribeVpcEndpoints",
                "ec2:DescribeVpcPeeringConnections",
                "ec2:DescribeVpcs",
                "ec2:DescribeVpn",
                "ec2:DescribeVpnGateways",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeLoadBalancerAttributes",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeTags",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetHealth"
            ],
            "Resource": "*"
        }
    ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "inspector" {
    role       = "${aws_iam_role.instance_role.name}"
    policy_arn = "${aws_iam_policy.inspector.arn}"
}

ユーザーデータによる inspector エージェントのインストール

OS は Amazon Linux を想定してます。
ユーザーデータに書いておけば、インスタンス起動直後に inspector エージェントインストールできますね。
参考URL: Amazon Inspector エージェントをインストールする

ssh-key.pemssh-key.pem.pubssh-keygen で適当に作っておきましょう。

ec2.tf
## AMI
##
data "aws_ami" "amazonlinux" {
    most_recent = true
    owners      = ["amazon"]

    filter {
        name   = "architecture"
        values = ["x86_64"]
    }

    filter {
        name   = "root-device-type"
        values = ["ebs"]
    }

    filter {
        name   = "name"
        values = ["amzn-ami-hvm-*"]
    }

    filter {
        name   = "virtualization-type"
        values = ["hvm"]
    }

    filter {
        name   = "block-device-mapping.volume-type"
        values = ["gp2"]
    }
}

## SSH Key Pair
##
resource "aws_key_pair" "deployer" {
    key_name   = "ssh-key-name"
    public_key = "${file(ssh-key.pem.pub)}"
}

## EC2
##
resource "aws_instance" "ec2" {
    ami                         = "${data.aws_ami.amazonlinux.id}"
    instance_type               = "t2.micro"
    key_name                    = "${aws_key_pair.deployer.key_name}"
    iam_instance_profile        = "${aws_iam_instance_profile.instance_role.name}"

    user_data                   = <<USERDATA
#!/bin/bash
# install inspector agent
cd /tmp
/usr/bin/curl -O https://d1wk0tztpsntt1.cloudfront.net/linux/latest/install
/bin/bash install -u false
/bin/rm -f install
USERDATA

    tags {
        project   = "${var.project}"
        stage     = "${var.stage}"
        inspector = "true"
    }
}

現場からは以上です。

続きを読む