LoginSignup
13
14

More than 5 years have passed since last update.

[AWS]フォーム付き静的コンテンツを独自SSL/独自ドメインで公開するまで②-lambda/Cognito編

Last updated at Posted at 2015-12-23

お問い合わせフォーム付きWeサイトを

  • S3で
  • Slack通知ありで
  • 独自ドメインで(お名前.comよりCNAMEを利用)
  • 独自SSLで(https/SNIベース)

公開するまでの備忘録
どこにでもやり方やリンクは転がってますが個人的にまとめます。

前回でS3での静的コンテンツ配信は可能となりましたので、
次はlambda/Cognitoを使って問い合わせフォームより送信があった場合はslack通知をしましょう。

流れは、
Cognitoで一時的なIAM Userを作成して、
そのアカウントを使ってフォームの入力内容をS3でテキストでアップロード、
S3のアップロードをLambdaでフックして内容をSlack通知です。

各リンクは以下

技術要件

  • AWS
    • S3
    • aws-cli
    • Cognito <-今回
    • Lambda <-今回
    • aws-sdk <-今回
    • CloudFront
  • dnsまわり

参考リンク

S3 + Lambda + Cognitoを使って、簡単お問い合わせシステム構築

Slack

Incoming Webhook取得

1.Slackログイン状態で、https://api.slack.com/incoming-webhooks にアクセス

以下をクリック
2015-12-22_21h46_59.png

2.通知をしたいチャンネルまたは個人を選択

2015-12-22_21h49_31.png

3.Incoming Webhook用のURLを取得

以下のURLをちゃんとメモしておいてください
2015-12-22_21h52_01.png

必要があればアイコンや名前など上記ページの下「Integration Settings」でいじれます。

Cognito

S3にアップロードするための一時的なIAM Userを作成するためにCognitoを使用します。

1.Identity Poolの作成

Amazon Management Consoleより「Cognito」を選択。
「Create New Identity Pool」
「Name」は適用に分かりやすいやつを
「Unauthenticated identities」にチェックを入れましょう
特定の認証(ID/PASSだったり、Facebook認証だったり)をしないでもIAM Userを作成できるようにするため
2015-12-22_22h09_18.png

2.新しいIAM Roleの確認

上が「authenticated role」
認証をした場合のIAM Role
下が「unauthenticated role」
認証をしなかった場合のIAM Role

それぞれ新しく作成されます。
2015-12-22_22h10_51.png

3.Identity Pool Id の取得

ここにあるIDを後ほど使います。
2015-12-22_22h11_21.png

4.作成したunauthenticated Roleに権限を付与

Amazon Management Consoleより「Identity and Access Management」を選択。
左メニュー「Role」より先ほど作成した「UnAuth」のロールをクリック
2015-12-22_22h12_53.png

インラインポリシー 「ロールポリシーの作成」
2015-12-22_22h13_29.png

今回は以下のようなポリシーを追加 : 特定のBucketへのアップロード権限

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::example.co.jp/*" <- アクセス許可するBucket
        }
    ]
}

aws-sdk-js

フォームのための処理

アップロードする箱と権限は設定したの実際にアップロードしてみましょう。
aws-sdkを使うのでHTMLのヘッダで読み込んでおきましょう。
今回はCDNで読み込みます。

<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js"></script>

以下のようなHTMLとJSをS3に置きます。
こんな感じのフォームがあったとします(あくまで例です)

<div>
    <input type="text" id="ContactCompanyName"/>
    <input type="text" id="ContactName"/>
    <input type="text" id="ContactEmail"/>
    <input type="text" id="ContactTel"/>
    <textarea cols="40" rows="4" id="ContactDetailBody"></textarea>
    <a href="#" id="put_contact"><img src="/send_btn.gif" alt="送信"/></a>
</div>

aws-sdkを使って送信ボタンがクリックしたときにフォームの内容をuploadします

$('#put_contact').on('click', function() {
    AWS.config.region = "ap-northeast-1";
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({IdentityPoolId: "取得した Identity Pool Id"});
    AWS.config.credentials.get();

    //作成したBucketを指定しましょう
    var bucket = 'example.co.jp';
    var s3 = new AWS.S3({
        params: {
            Bucket: bucket
        }
    });

    var now = new Date();
    var obj = {
        "問い合わせ時間" : now.toLocaleString(),
        "御社名" : $("#ConfirmContactCompanyName").text(),
        "お名前" : $("#ConfirmContactName").text(),
        "メールアドレス" : $("#ConfirmContactEmail").text(),
        "電話番号" : $("#ConfirmContactTel").text(),
        "お問い合わせ内容" : $("#ConfirmContactDetailBody").text(),
    };

    var blob = new Blob([JSON.stringify(obj, null, 2)], {type:'text/plain'});

    //Bucketの「contacts」フォルダの下にアップロード
    s3.putObject({Key: "contacts/" + now.getTime()+".txt", ContentType: "text/plain", Body: blob},
    function(err, data){
        if(data !== null){
             window.location.href = '/contact_end.html';
        }
        else{
            alert("お問い合わせ送信に失敗しました。お手数ですが再度ご入力をお願いします。");
            window.location.href = '/contact.html';
        }
    });
});

S3にCORSの設定

アップロードまでもう少し。
JavaScriptでS3にアクセスするにはCORSの設定が必要となります。
CORS…http://dev.classmethod.jp/etc/about-cors/
Amazon Management ConsoleからS3で作成したBucketに行きましょう
2015-12-22_23h06_37.png
ここにこんな感じに記述

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>アクセス元(今回はBucketの静的コンテンツ配信のためのエンドポイントのURL)</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

さて、疲れましたね。
もうアップロードは出来るはず。

lambda

アップロードは出来たので最後にSlack通知のためのlambda functionを設置します。

1.lambda function作成のための準備

npmをインストール(CentOS6の場合)

yum install epel-release
yum install nodejs npm --enablerepo=epel

npmより「reqest」「aws-sdk」をインストール

  • request…HTTPリクエストを簡単にするため
  • aws-sdk…S3からアップロードされたファイルの内容取得のため
npm install aws-sdk
npm install request

2.コードサンプル

index.jsを「node_modules」と同じ階層に作成

var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var request = require('request');

exports.handler = function(event, context) {
    var bucket = event.Records[0].s3.bucket.name;
    var key = event.Records[0].s3.object.key;
    s3.getObject({Bucket:bucket, Key:key}, function(err, data) {

        //アップロードされたファイルの内容を取得
        var contentType = data.ContentType;
        var body = data.Body.toString("utf-8");

        var options = {
            uri: '取得したSlackのIncoming Webhook URL',
            json: true
        };

        if (key.match(/^contacts/)) {
            options['form'] = {
                payload: JSON.stringify({
                    'username': 'webhookのusername',
                    'channel': '通知するchannel',
                    'text': 'お問い合わせがありました。'
                })
            };
        }

        request.post(options, function(err, responce, body) {
            if(!err && responce.statusCode == 200) {
                console.log('success');
            } else {
                console.log('error: ' + responce.statusCode);
            }
            context.done(null, '');
        });
    });
};

3.zip化

「index.html」と「node_modules」をzip化しましょう

zip -r contact.zip index.js node_modules

4.lambda用のIAM Roleを作成

デプロイ前にひと手間
今回、lambda function内でS3の中身を取得しているので、lambda用のRoleを作成しましょう。

Amazon Management Consoleより「Identity and Access Management」を選択。
左メニュー「Role」より新しいRoleを作成しましょう
Role名は適当に分かりやす名前で

2015-12-22_23h37_26.png

Role type でLambdaを選択

2015-12-22_23h40_07.png

S3のReadOnlyのポリシーを付与

2015-12-22_23h47_46.png

これで、lambda用のRoleが完成

5.lambdaにデプロイ

さて、いよいよデプロイです。

Amazon Management Consoleより「lambda」を選択
「Create a Lambda Function」
色々雛形が出てきますが、今回はスルー

2015-12-22_23h49_34.png

名前は適当に分かりやすいものを
Upload a ZIP fileで先ほど作成したlambda functionをまとめたzipをアップロード
Roleに先ほど作成したlambda用のRoleを選択します。

説明2015-12-22_23h50_42.png

最終確認画面でEnableを選択すればlambda functionが有効となります。
ただ最後に最後にあと一仕事
lambdaが何のEventにhookされるのか設定しましょう。

作成されたlambda functionの「Event source」を選択
「Add event source」でhookするポイントを追加します

2015-12-23_00h10_35.png

BucketはアップロードするBucket
Event typeはS3へオブジェクトがクリエイトされた時
prefixは今回は「contacts/」にアップロードされるので記入しているだけです

2015-12-23_00h11_25.png

ここまででサイトとしては機能している

さて、長くなりましたが今回はここで終了です。
きっと静的コンテンツ越しにアップロードされたファイルがslackで通知されている(ハズ

次はamazonから与えられるエンドポイント用の長いURLではなく
独自のドメインでサイトにアクセスするのと、通信のSSL化です。

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14