Amazon Linux + Apache でLet’s encrypt

Let’s encryptの設定

参考サイト

http://webfood.info/letsencrypt-renewal-failure/

Let’s encrypt とは?

「安全な接続を世界中に広めよう」という素晴らしい考えを持ったプロジェクト。
非営利団体の ISRG (Internet Security Research Group) によって運営されており、いろいろな大手企業がこの活動をサポートしている。利用料はもちろん無料。

なにがすごいんじゃ

Let’s encrypt では、「certbot」というクライアントソフトを使うことで、
自動的にSSL証明書の更新を行うことが出来るようになっている。
独自ドメインさえあればコマンド操作のみでSSL証明書がゲット出来るのである。

Amazon Linux に入れてみよう

Amazon Linuxはcertbotにまだ対応できていないため、単純にyumインストールができない(2017/11/16現在)
その為wgetでソースを落として直接インストールする必要がある。

$ wget https://dl.eff.org/certbot-auto
--2017-11-16 12:49:31--  https://dl.eff.org/certbot-auto
dl.eff.org (dl.eff.org) をDNSに問いあわせています... 151.101.32.201, 2a04:4e42:8::201
dl.eff.org (dl.eff.org)|151.101.32.201|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 57312 (56K) [application/octet-stream]
`certbot-auto' に保存中

certbot-auto            100%[==============================>]  55.97K  --.-KB/s    in 0.02s   

2017-11-16 12:49:31 (2.39 MB/s) - `certbot-auto' へ保存完了 [57312/57312]

$ chmod a+x certbot-auto

ここまでは公式サイトに乗っている手順通り。
後1コマンド!・・・というところでこんな表示が出てしまう。

$ ./certbot-auto
Requesting to rerun ./certbot-auto with root privileges...
FATAL: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!
Alternatively, you can install OS dependencies yourself and run this script
again with --no-bootstrap.

要約すると、
「Amazon Linuxでのcertbotはまだ実験段階だよ。もし君がその実験のお手伝いをしたいならバックアップを必ず取ってさっきのコマンドに–debugオプションを付けて実行してね!」
と書いてある。優しい。

というわけでバックアップをとって自己責任で実行してみる。

$ ./certbot-auto --debug
Requesting to rerun ./certbot-auto with root privileges...
Bootstrapping dependencies for Amazon... (you can skip this with --no-bootstrap)
yum は /usr/bin/yum です
読み込んだプラグイン:priorities, update-motd, upgrade-helper
パッケージ 1:openssl-1.0.2k-8.105.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ ca-certificates-2015.2.6-65.0.1.16.amzn1.noarch はインストール済みか最新バージョンです
パッケージ python27-2.7.12-2.121.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ python27-devel-2.7.12-2.121.amzn1.x86_64 はインストール済みか最新バージョンです
パッケージ python27-virtualenv-15.1.0-1.14.amzn1.noarch はインストール済みか最新バージョンです
パッケージ python27-pip-9.0.1-1.24.amzn1.noarch はインストール済みか最新バージョンです
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ augeas-libs.x86_64 0:1.0.0-5.7.amzn1 を インストール

~省略~

依存性を解決しました

===============================================================================================
 Package                   アーキテクチャー
                                        バージョン                    リポジトリー        容量
===============================================================================================
インストール中:
 augeas-libs               x86_64       1.0.0-5.7.amzn1               amzn-main          345 k
 gcc                       noarch       4.8.5-1.22.amzn1              amzn-main          4.1 k

~省略~

トランザクションの要約
===============================================================================================
インストール  6 パッケージ (+17 個の依存関係のパッケージ)

総ダウンロード容量: 32 M
インストール容量: 61 M
Is this ok [y/d/N]: 

お、なんとかなりそう。
というわけで実行しましょう。ちゃんと完了しました!と表示されるはずです。

これでインストールが完了です。ここからが本番です。

証明書を取得する

以下のコマンドを入力し、証明書を入手します。

./certbot-auto certonly --webroot -w [ドキュメントルート] -d [ドメイン]

–webrootオプションをつけることで、Webサーバを停止することなく実行できます。

以下のメッセージが表示されていれば成功です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/[ドメイン名]/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/[ドメイン名]/privkey.pem
   Your cert will expire on 2018-02-14. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

皆さん寄付をご検討ください。

このメッセージが表示されていれば、以下のパスに証明書ファイルが生成されています。
見に行きましょう。

$ cd /etc/letsencrypt/live/[ドメイン名]/
$ ls
cert.pem  chain.pem  fullchain.pem  privkey.pem  README

こいつらが生成されていればOK
Apacheにmod_SSLをインストールするのをお忘れなく

$ yum install -y mod24_ssl

ssl.confを修正

$ vi /etc/httpd/conf.d/ssl.conf 
以下を記述
SSLCertificateFile /etc/letsencrypt/live/[ドメイン名]/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/[ドメイン名]/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/[ドメイン名]/chain.pem

んでApaheを再起動すれば完了!

service httpd restart

問題なければここでおわり!
本当はhttpのアクセスをhttpsに流したりとかあるんだろうけど、それはまた別のお話。
お疲れ様でした。

…Apacheが起動しない人へ

最後に何故かApacheが起動しなくなりました・・エラーメッセージは以下

Starting httpd: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:443

443ポートがすでに使われているとのこと。しかしポートが使われている形跡はない・・・
悩みに調べて30分後

「もしやhttpd自身が443ポートを2回バインドしようとしているのでは・・・?」
とおもいhttpd.confを見てみると、ありました

Listen 443

こいつ。ssl.confの中にも書いてあるんですね。
httpd.confの方をコメントアウトしてhttpd再起動!

上手く行った!!!
よかったよかった。

誰かの助けになればいいなと思います。

続きを読む

Classic Load BalancerからALBにOne-stepでMigrationできるようになったのでやってみた

Classic Load BalancerからALBにOne-stepで移動できるようになったのでやってみた

目的

Classic Load BalancerからApplication Load Balancer(以下、ALB)にポチで作成できるようになったので
リリース分を早速試してみた:sunglasses:

リリース内容
New One-step Migration Wizard to Migrate a Classic Load Balancer

Classic Load Balancerの元設定

ほぼデフォルトのまま
nginxを2台ぶら下げているだけ

  • elb名確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].LoadBalancerName' --output table

-----------------------
|DescribeLoadBalancers|
+---------------------+
|  test-elb01         |
+---------------------+
  • instance id確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].Instances' --output table
-------------------------
| DescribeLoadBalancers |
+-----------------------+
|      InstanceId       |
+-----------------------+
|  i-aaaaaaaaaaaaaaaaa  |
|  i-bbbbbbbbbbbbbbbbb  |
+-----------------------+

  • Listeners確認
# aws --profile PROFILE名 elb describe-load-balancers --load-balancer-name=test-elb01 --query 'LoadBalancerDescriptions[].ListenerDescriptions' --output table
------------------------------------------------------------------------
|                         DescribeLoadBalancers                        |
||                              Listener                              ||
|+--------------+--------------------+--------------------+-----------+|
|| InstancePort | InstanceProtocol   | LoadBalancerPort   | Protocol  ||
|+--------------+--------------------+--------------------+-----------+|
||  80          |  HTTP              |  80                |  HTTP     ||
|+--------------+--------------------+--------------------+-----------+|
  • マネジメントコンソール上

01.PNG

ALBにMigrationしてみる

  • 手順

※マネジメントツコンソール上から操作

  1. 対象のClassic Load Balancerを選択
  2. 下のタブの「移行」を選択
  3. 「ALB移行ウィザードを起動」をクリック
  4. 確認画面が表示
  5. 変更するものは変更して
  6. 作成をクリック
  7. チェック・起動が走って
  8. 作成完了画面が出る
  • 手順1~3

02.PNG

  • 手順4~6

03.PNG

  • 手順7,8

04.PNG

うーん簡単!:smiley:

作成されたALBを確認

  • alb名
# aws --profile PROFILE名 elbv2 describe-load-balancers  --names=test-elb01 --query 'LoadBalancers[].LoadBalancerName' --output table

-----------------------
|DescribeLoadBalancers|
+---------------------+
|  test-elb01         |
+---------------------+
  • targetgroup名
# aws --profile PROFILE名 elbv2 describe-target-groups --names=test-elb01 --query 'TargetGroups[].TargetGroupName' --output table
----------------------
|DescribeTargetGroups|
+--------------------+
|  test-elb01        |
+--------------------+
  • Instane ID・healthcheck
# aws --profile PROFILE名 elbv2  describe-target-health --target-group-arn=TARGETGROUPのARN --query 'TargetHealthDescriptions[].[Target.Id,TargetHealth.State,Target.Port]' --output table
------------------------------------------
|          DescribeTargetHealth          |
+----------------------+-----------+-----+
|  i-aaaaaaaaaaaaaaaaa |  healthy  |  80 |
|  i-bbbbbbbbbbbbbbbbb |  healthy  |  80 |
+----------------------+-----------+-----+
  • マネージドコンソール上

05.PNG

ALBが同じ名前で作成されてますね!!:wink:

結果

ELBを元にALBをワンクリックで作成することが出来ました!!:beers:

Classic Load BalancerからALBに入れ替えるには

まだサービスにはアサインされていないので
以下の手順が必要

  1. ALBへのアクセスの動作確認
  2. Route53などのDNSで、サービスのDNSレコードをClassic ELBからALBへ変更する

※注意点
ELB配下のサーバたちがそのままALBに入れ替わるってことではないので
気をつけてください :tiger:

続きを読む

EC2(Amazon Linux)とRDS(MySQL)でLAMP環境を構築するまで

備忘録程度に簡単にメモ

EC2でLAMP環境を構築するまでにやったこと

AWSでやったこと

  • AWSのアカウントを作った
  • 無料枠の範囲内でとりあえずEC2とRDSを立てる
    理由はなくなんとなくAmazon LinuxとMySQLの構成で作成。
    RDSを作成する時は無料枠のオプションを表示することが出来るので、そのチェックを入れておくと料金が発生する設定にしてしまうことを防ぐことができる。
  • 請求アラームの作成
    0ドルを超えるとメールで発報するよう設定(通常料金でも1,000円に収まる範囲だと思うが無料枠でいろいろしたいので)
  • Elastic IPの取得
    IPアドレスを取得し、EC2に関連付ける(無料枠内で起動しているEC2に関連付けされている間は無料らしい)
  • EC2のセキュリティグループにアクセスする際のIPからのSSH接続を許可
    ここで一緒に任意のIPからのHTTP/HTTPSも許可しとくといい

たぶんざっくりこんなもん
リージョンはオレゴン(リージョン次第で無料かどうか変わるのかはわからない)

SSH接続の設定

EC2を作成したときにpemをDLしているはずなので、それを使ってSSH接続してみる

pemの権限設定を変更する

$ chmod 400 [pemのパス]

SSH接続してみる

$ ssh -i [pemのパス] ec2-user@[パブリックドメイン]

パブリックドメインはec2から始まるインスタンスごとに勝手に設定されているもの
こんなの(ec2-11-111-111-1.us-east-2.compute.amazonaws.com)

これでつながるはず。繋がらなかったらインバウンドで許可したIPアドレスに間違いがないか、
ユーザ名(デフォはec2-user)を別に設定していないかなどを確認

ここまでできればあとはサーバ側の設定とDNSさえどうにかすればWebサーバとして利用できる

SSHConfigをいじって接続しやすくする(おまけ)

$ vi ~/.ssh/config 

以下のような感じで追記

#AWSサーバ
Host [sshコマンドで使う名前]
        HostName [パブリックドメイン]
        User ec2-user
        IdentityFile [pemのパス]

これで以下みたいに簡単に接続できる

$ ssh [sshコマンドで使う名前]

サーバ側の設定(とりあえずPHPとMySQLが使える状態に持っていく)

とりあえずソフトウェアパッケージを更新

$ sudo yum update -y

Apahe、PHP、MySQLをインストール

$ sudo yum install -y httpd24 php70 mysql56-server php70-mysqlnd

Apache起動とサーバ起動時に自動的に立ち上がるよう設定

$ sudo service httpd start
$ sudo chkconfig httpd on
chkconfig --list httpd
httpd           0:off   1:off   2:on    3:on    4:on    5:on    6:off

EC2のインバウンド設定でHTTPを任意のIPに対して許可していれば、ブラウザにIPアドレスを入力すると
Apacheのテストページが見れるはず

Apacheのドキュメントルートを編集できるようにする

デフォルトではApacheは/var/www/htmlをドキュメントルートにしている。
/var/wwwディレクトリはrootが所有者なので、apacheユーザに変更する
SSH時のユーザはec2-userなので、apacheユーザグループにec2-userを追加する。

$ sudo usermod -a -G apache ec2-user

再接続する

$ exit
$ groups
ec2-user wheel apache
$ sudo chown -R ec2-user:apache /var/www

グループ編集許可を与える

$ sudo chmod 2775 /var/www
$ find /var/www -type d -exec sudo chmod 2775 {} ;
$ find /var/www -type f -exec sudo chmod 0664 {} ;

PHPファイルの動作を確認する

さっきの設定がうまく行っていれば、ec2-userはルートディレクトリにファイルを作成する事ができるはず

$ echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

[IPアドレス]/phpinfo.php にアクセスしてPHPの情報が表示されるはず
公開すべき情報ではないので、忘れずに削除しとく

$ rm /var/www/html/phpinfo.php

EC2とRDSを疎通させる

とりあえずMySQLポートを開放

EC2のインバウンドにMYSQLの接続を任意の場所から許可するよう設定

mysqlコマンドでRDSのMySQLへ接続してみる

RDSのインスタンスのセキュリティグループで、EC2インスタンスのセキュリティグループからのMYSQL接続を許可するよう設定

mysql –h [RDSインスタンスのエンドポイント] -P 3306 –u [ユーザ名] –p
Enter password: [パスワード]

基本的にユーザ名とパスワードはAWSのユーザ名パスワードになっているはず(何も設定していなければ)

ここまでできればApache、PHP、MySQLのセットアップはざっくりと完了。
セキュリティ的な話をすると弱い部分はたくさんあるので、実際の公開時には補強の必要があるが、
最低限は上記で完了。
後は静的HTML置くなり、Codeigniterでも入れて本格的なWebアプリ公開するなりする。

続きを読む

AWS PrivateLinkが登場 EC2やELBでどのように使うか

AWS Private link について

先日 AWS Private linkという機能が発表されました。
https://aws.amazon.com/jp/blogs/aws/new-aws-privatelink-endpoints-kinesis-ec2-systems-manager-and-elb-apis-in-your-vpc/

これまでの方式(DynamoDB,S3)はエンドポイントのゲートウェイ経由で各サービスのAPIに接続する形でしたが
新しい方式ではエンドポイントがENIに紐付き、VPCのプライベートIPを持つかたちになります。
この方式のメリットとしては
・セキュリティグループでエンドポイントへのアクセスを管理できるようになる
・エンドポイントにDirect Connectを介してアクセスすることができる
というのが大きいかなと思います。

Private linkに対応するサービス

今回のタイミングで、 以下のサービスが新たにVPCの中から使えるようになりました。
その他のサービスもComing Soonでサポート予定とのこと。

  • Kinesis
  • Service Catalog
  • Amazon EC2
  • EC2 Systems Manager
  • Elastic Load Balancing

EC2やELBでの使いどころ

Kinesisの対応はわかりやすいです。
プライベートなEC2からKinesisにデータプッシュできるとか最高やないか。
でもEC2やELBのエンドポイントって?と私は思ってしまったのでした。
例えば、EC2なら別VPCのパブリックなEC2にプライベートに接続?とかよく分からないことを考え初めてしまった。

基本に立ち返ってドキュメントを確認しました。
新しい方式(インターフェースVPCエンドポイント)についてはまだ日本語のドキュメントはありませんが
原文のドキュメントは以下のURLから参照できます。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpce-interface.html

ページ下部のAccessing an AWS Service Through an Interface EndpointにELBの
エンドポイントにAWS CLIからアクセスする例がありました。

aws elbv2 describe-load-balancers --endpoint-url https://vpce-0f89a33420c193abc-bluzidnv.elasticloadbalancing.us-east-1.vpce.amazonaws.com/

単純にAWS CLIやSDKからAPI操作する際に使えば良いイメージでしょうか。
言われてみれば冒頭のBlogのタイトルも ~Amazon EC2 APIs, and ELB APIs in your VPC でした。

EC2でやってみる

まずは単純にプライベートなEC2でAWS CLIを操作してみます。
当然ですが、接続エラーになりました。

$aws ec2 describe-availability-zones

HTTPSConnectionPool(host='ec2.ap-northeast-1.amazonaws.com', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<botocore.awsrequest.AWSHTTPSConnection object at 0x7f002bf53e10>, 'Connection to ec2.ap-northeast-1.amazonaws.com timed out. (connect timeout=60)'))

PrivateLinkの作成

コンソールのVPCのメニューからエンドポイント → Create Endpoint と進みます。
S3とDynamodbのエンドポイントしか選択できない場合は、一度コンソールの言語設定を英語にすると
以下のような画面が表示されました。

image.png

Service Name: com.amazonaws.ap-northeast-1.ec2 を選択

VPC, subnet, SecurityGroup:それぞれ任意のものを指定します。
SecurityGroupでは443のインバウンドを許可する必要があります。

Enable for this endpoint:
PrivateLinkのエンドポイントはVPCのIPアドレスを使用するため、VPCのプライベートDNSを使用して
AWSサービスのDNS名を上書きすることができます。
チェックを入れると「ec2.ap-northeast-1.amazonaws.com」のVPC内のルックアップが、
作成するエンドポイントのIPアドレスに解決されます。

上記を指定したら、画面下部のCreate endpointを押下します。

動作確認

先ほどと同じく、プライベートなEC2からAWS CLIを実行します。

$ aws ec2 describe-availability-zones
{
    "AvailabilityZones": [
        {
            "State": "available",
            "ZoneName": "ap-northeast-1a",
            "Messages": []
            "RegionName": "ap-northeast-1"
        },
        {
            "State": "available",
            "ZoneName": "ap-northeast-1c",
            "Messages": [],
            "RegionName": "ap-northeast-1"
        }
    ]
}

Enable for this endpointにチェックを入れているので全く同じコマンドで実行することができました。
プライベートDNS名を有効にしない(チェックを入れない)場合は –endpoint-url で
エンドポイント固有に割り当てられているDNS名を指定すると接続することができます。

$ aws ec2 describe-availability-zones --endpoint-url https://vpce-xxxxxxxxxx-xxxxxx.ec2.ap-northeast-1.vpce.amazonaws.com
{
    "AvailabilityZones": [
        {
            "State": "available",
            "ZoneName": "ap-northeast-1a",
            "Messages": [],
            "RegionName": "ap-northeast-1"
        },
        {
            "State": "available",
            "ZoneName": "ap-northeast-1c",
            "Messages": [],
            "RegionName": "ap-northeast-1"
        }
    ]
}

基本的な内容かもしれませんが、参考になれば幸いです。
以上です。

続きを読む

Fitbit Logger with AWS Lambda/CloudWatch

I bought a fitbit device more than 2 years ago. Since then, using the wearable device and its app, almost everything in my ordinary life have been being logged such as workouts, steps, heart rate, sleeps, weights and calories. One of my habit is measur… 続きを読む

ゼロから始めるLINEBot(AWS×node.js) ②オウム返しする

前回の記事の続きです。
ゼロから始めるLINEBot(AWS×node.js) ①とりあえず動かす https://qiita.com/tenn25/items/498f768a58ba6a6de156

この記事で分かること

  • 投稿したメッセージをそのままオウム返しする
  • 自分がハマったポイント

この記事の対象者

  • いろいろと初心者(自分がそうなので)
  • MessagingAPIのような外部APIを使ったことがない
  • AWSもあんま詳しくない(アカウントは持ってるくらい)

流れ

第1回 とりあえず動かす
1.LINE Developersの登録/設定
2.実装(Lambda/node.js)
3.定期実行の設定(CloudWatch)

第2回 オウム返しの実装 (この記事)
4.ドメイン取得,DNS設定,SSL証明書の設定(Route53/ACM/SNS/S3)
5.イベントの受け取り(APIGateWay)
6.ユーザへの返信(Lambda/node.js)

第3回 Botの自動化 (予定)
7.AccessTokenの自動更新

第4回 ユーザ情報の保存 (予定)
8.DBの連携

4. ドメイン取得,DNS設定(※不要です)

LINE上でのメッセージ投稿や、botの友達追加などのイベントは、
WebHookに指定したURLにHTTPSのPOSTリクエストが送られます。

独自ドメインとSSL証明書を取って・・・などと考えましたが、不要でしたね。。
ユーザーが直接アクセスするAPIの場合は独自ドメインを割り当てた方がユーザーに優しいかもですが、
LINE側から叩かれるだけなので、APIのURLはAPIGateWay作成時のままで良いでしょう。

SSL証明書はAWSのACMで無料で取得できるのですが、
ドメインの認証の為にメールを受け取る必要があり、SESを使う必要があり少々面倒です。

流れは以下の通り
①ドメインを取得
②Route53にDNSレコードの設定
③SESでドメインの認証を行い、Route53にMX,TXTレコードを設定
④ACMのドメイン認証メールを受け取るための受信設定
⑤ACMの証明書リクエスト
⑥届いたメール内の認証用リンクにアクセスして認証

クラスメソッドさんの以下の記事を参考になります。
「[ACM] SSL証明書発行時のドメイン認証メールをSESで受け取ってみた」
https://dev.classmethod.jp/cloud/aws/acm-verifydomain-ses/

5. イベントの受け取り

LINEbotがイベントを受け取ると、
WebHookに指定したAPIにHTTPSのPOSTリクエストを送ります。
APIGateWayは指定のLambdaにリクエストを渡し、
LambdaからReplyAPIに対してHTTPSリクエストを投げることでbotの返信を実現しています。

(APIを使ったり作るのが初めてだったので、この流れを理解しておらず、
てっきりリクエストに対してそのままレスポンスを返すのかと思ってしまいました。。)

ではまず、APIGatewayの設定をする前に、
空でも良いのでLambdaの関数を作っておきましょう。
ここでは[LineBotReplyTest]を作りました。

その後に、APIGateWay上にAPIを作成して、
リソースからPOSTメソッドを以下のように定義しましょう。
(私はなぜかここをPUTで作ってしまい、WebHookが動かず謎に時間を無駄にしました。。)

APIGateWayでは、リクエストの中身をある程度加工してからバックエンドのサービス(今回はLambda)に渡すことができます。

スクリーンショット 2017-11-01 22.31.24.png

APIGateWayを初めて使うとおそらく必ずつまづくポイントですが、
リソースに作成しただけでは使えません。
必ず[APIのデプロイ]するのを忘れないようにしてください。
スクリーンショット 2017-11-01 21.13.02.png

作成したAPIのURLを確認して、LINE側の WebhookURLに設定します。
接続確認が成功すればOKです。

スクリーンショット 2017-11-01 23.07.43.png

6. ユーザへの返信

それでは先ほど作成したLambdaにコードを書きましょう。
node.jsのバージョンは6.10で動作確認済みです。

index.js

var https = require('https');

exports.handler = (event, context, callback) => {
    data = event.events[0];
    var replyToken = data.replyToken;
    var message = data.message;
    var txt = message.text;
    var data = JSON.stringify({
       replyToken: replyToken,
       messages: [
           {
               type: "text", 
               text: txt
           }
        ]
    });
    opts = {
        hostname: 'api.line.me',
        path: '/v2/bot/message/reply',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "Content-Length": Buffer.byteLength(data),
            "Authorization": "Bearer " + process.env.CHANNEL_ACCESS_TOKEN
        },
        method: 'POST',
    };

    var req = https.request(opts, function(res) {
        res.on('data', function(res) {
            console.log(res.toString());
        }).on('error', function(e) {
            console.log('ERROR: ' + e.stack);
        });
    });
    callback(null, data);
    req.write(data);
    req.end();

};

APIGateWayから受け取ったリクエストの中身をそのままReplyAPIへ渡すことでオウム返しさせます。

①の記事でも書いてますが、
リクエストヘッダにContent-Lengthを忘れないようにしましょう。

また、process.env.CHANNEL_ACCESS_TOKEN を環境変数から取得しています。

スクリーンショット 2017-11-01 23.26.02.png

これで完成なので、LINEからメッセージを送ってみましょう

スクリーンショット 2017-11-02 00.23.51.png

成功です!

このままでは24時間でTokenが切れてしまうので、
次回は自動更新する仕組みを考えましょう。

所感

結構細かいところにつまずいてしまったのですが、
まとめてみれば、なんてことは無い内容でした。

続きを読む

はじめてのAmazon SES/Lambda。メール送信ができるようになるまでの覚書

はじめに

今回はAmazon SES と Lambdaでメール送信の仕組みを作った時の覚書です。よくネット通販で買い物の後に、確認のための”no-reply”みたいな表題のメールが送られてきますよね。そういう仕組みを作りました。滅多にやらない作業なのでQiitaに残しておくのがよいと思いました。

00.png

なぜSES/Lambda?

実は最初同様の仕組みをイチからスクラッチしかけていましたが、AWSの方も調査してるうちにそっちが楽そうに思えたからです。メールサーバの構築等々、仕組みもさることながら可用性うんぬん議論しはじめたらそれだけで何カ月もかかってビジネス速度に耐えられません。しかも私自身開発業務は初の体験。何が正解かわからない中での模索でしたが、結果的に工数削減の点でこの選択が正解だったと思います。

事前準備

SES

SESの画面でDKIM等の設定を済ませておきます。で、ここで気づくのですが、ドメインの設定を先に済ませておかなければなりません。今回はRoute 53上に専用のサブドメインを用意。必要に応じて元のDNSサーバに対しても委譲設定等を行います。DNS関連は慣れないと難しいですね~。

Route 53

no-replyのメアドで使うサブドメインを作りました。

Lambda実行のためのCLI環境

必須ではありませんが、CLIで実行するのが便利です。もちろんGUIから実行しても問題ありませんが、個人的にAWSのGUIが苦手なのでCLIから叩いています。

Lambda関数

コード

環境変数は基本的にevent.jsonに書いていきます。ハードコーディングしている箇所もありますが使いやすいように書き換えてください。key1、key2…といった具合で必要に応じて増やしていけばよいかと。

mail.python
#!/usr/bin/env python
# coding:utf-8
import boto3
import json
from dateutil.parser import parse

REGION = "us-west-2"

def send_email(source, to, subject, body):
    client = boto3.client('ses', region_name=REGION)

    response = client.send_email(
        Source=source,
        Destination={
            'ToAddresses': [
                to,
            ]
        },
        Message={
            'Subject': {
                'Data': subject,
            },
            'Body': {
                'Text': {
                    'Data': body,
                },
            }
        }
    )

    return response

def lambda_handler(event, context):

    SRC_MAIL = "{送信元メールアドレス}"
    DST_MAIL = event['key1']
    HMAIL = "{返信先メールアドレス}"
    TITLE = "ご購入ありがとうございます"
    BODY = "営業担当です。n"
               + "お買い上げありがとうございます。n"
               + "本メールへの返信は以下にお願い致します。n"
               + HMAIL +"n"

    r = send_email(SRC_MAIL, DST_MAIL, TITLE, BODY)
    return r
$ cat event.json
{
  "key1": "{宛先メールアドレス}"
}

実行

$ python-lambda-local -f lambda_handler mail.py event.json

結果

01.png

もし”no-replyメール”に返信されたら?

“no-replyメール”への返信はあってほしくないもの。「常識を疑います!」などと突き放したいところですが、現実問題ありうる例外処理として作っておく必要があります。今回はS3に飛ばし、そこから特定のメーリングリストに飛ばす処理をLambdaで行っています。

まとめ

SESとLambdaをはじめて触る私にも簡単に作れました。AWSを使えば相当シンプルなプロセスで構築できることがわかりました。普段使わないようなAWSのサービスについても面倒がらずに知っておく・使ってみることは大事ですね。

参考

参考にさせて頂きました。ありがとうございます。

サブドメインの運用と委任

Route53でサブドメインだけ管理する方法

親ドメインの移行を行わずに Amazon Route 53 を DNS サービスとして使用するサブドメインを作成する

Amazon SESによるメール送信環境の構築と実践

AWS Lambda Pythonをローカル環境で実行

Amazon SES での DKIM を使用した E メールの認証

勤怠連絡メールをAPIGatewayとlambdaで作ってみた

その他

当社ではソフトウェア関連取組みの一環として、クラウド型パフォーマンスモニタサービス「New Relic」を提供しています。詳しくはこちらから。

続きを読む