にわかサーバー屋さんの覚書

サーバー系を担当しているけど、設計などは日々勉強中のプログラマの覚書

【朗報】LINE BOT の Server IP Whitelist がOptionalになってた

久しぶりに、LINE BOTの設定を除いていると、、、

なんと、

LINE BOTのServer IP Whitelistが任意になっていました。

 

つまり、設定しなければ、どのホストからもアクセス出来ちゃう!

 

つまり、諦めていた、

AWSのAPI Gateway+Lambdaのサーバーレスで、BOTのサーバーが作れるわけです。

 

で、適当に作った「なんでも頭にをつけて返すBOT」。

 f:id:xev:20160518202524p:plain

 

流れとしては、

 

  1. API Gatewayのエンドポイントを作る
  2. Lambdaのファンクションを作り
  3. APIGatewayとに、作ったLambdaを紐付ける
  4. LINEのコンソールで、API GatewayのURIをいれる

基本的な流れは、これで出来るはず。

 

書いたLambdaのファンクションは以下の様な感じ

var https = require('https');

exports.handler = function(event, context) {
    
    if (!event.result){
        return context.fail("fail");
    }
    var msg = event.result[0];
    var data = JSON.stringify({
      to: [msg.content.from.toString()],
      toChannel: 1383378250,
      eventType: "138311608800106203",
      content: {
        contentType:1,
        toType:1,
        text: "お"+msg.content.text
      }
    });
    var opts = {
        hostname: 'trialbot-api.line.me',
        path: '/v1/events',
        method: 'POST',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "X-Line-ChannelID": "CHANNEL_ID", //自分のChannel ID
            "X-Line-ChannelSecret": "CHANNEL_SECRET",//自分のChannel Secret
            "X-Line-Trusted-User-With-ACL": "MID" //自分のMID
        }
    };
    console.log(data);
    //リクエスト送信
    var req = https.request(opts, function(res){
        console.log('statusCode: ', res.statusCode);
        console.log('headers: ', res.headers);
        res.on('data', function(d){
            console.log(d.toString());
        }).on('error', function(e){
            console.log(e.stack);
        });
    });
    req.write(data);
    req.end();
};

 

あとは、Dynamoとかにデータいれて、データ見て処理変えられたりしたら、
おぉ、夢は広がりますなぁ。

ココまでのものが、サーバーレスで出来てくるわけですよ。

AWSは無料証明書も東京リージョンで始めましたし、もう、AWSにどっぷりですよ。

 

サーバー屋のつもりが、どんどんとレイヤー上がっていきます。

もう、MySQLを1から立てるなんてめんどくせーという自分がいます。。。

AWS Lambda + DynamoDBで吐く"NetworkingError: write EPROTO"エラーについて

AWS Lambdaで楽しくサーバーレス環境を作っていたところ。。。

 

なにやらログにエラーが書き出されていた。

{
       "errorMsg": "NetworkingError: write EPROTO",
       "param": {
                "id": "XXXXXXXXXXXXXX",
                "store": "SHOP_AAAA",
        }
}

EPROTOていうのはプロトコルエラーって事らしい。

これまでLambdaでDynamoDBにリクエストを投げていてこんなエラーは出ていなかったし、ほとんどコードも変えていない。

 

となると、要因に心当たりがある。

 

AWSLambdaがnode.js 4.3に対応したため、

Promise使えるしサイコーって言ってbluebird外して、

Lambdaファンクションをnode.js 4.3で動かしたのでした。


調べると、やはり、nodeの4、5系で報告されているようでした。

github.com

このエラーがを改善するには、

DynamoDBの設定に、

 

  • keepAliveを設定する
  • secureProtocolに、TLSv1_methodを指定する

と、軽減するというっぽいです。

 

ということで、この設定をした後は、

今のところ、設定以降、私の環境でもエラーは出ていません。

 

以下、こんな感じで書いたって言う覚書。

 

const dynamodb = new AWS.DynamoDB({
       region: 'ap-northeast-1',
       httpOptions: {
              agent: new https.Agent({
                   keepAlive: true,
                   secureProtocol: 'TLSv1_method'
              })
       }
});

var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB(dynamodb); 

 

LINE BOTに設定しているコールバックに飛んでこないのは多分SSLの水準のせい?

ここ数日、LINE BOTをイジイジしていたんですが、

architect.hatenadiary.jp

 

結局、引っかかったLINE BOTからのコールバックは解決してません。
設定してから反映されるまでに時間がかかるって話もありましたが、
AWSのAPI Gatewayと自己ドメインで相互書き換えしてみたのですが、
結局、2,3分で切り替わり、疎通<>不通を繰り返すのでした。

 

しかもログにも残らないので、、、。
まぁ、じゃあ、、、、

 

「何らかの理由で、LINE BOTがリクエストしてこない」しかない。

 

で、現状提示されている条件としてはCAが発行したSSLが必須ということしかない。

で、APIGatewayの証明書違うのは、CAが違うということしか無い。

 

つまり、メール認証でぺろっと生成できるようなSSL証明書を使ってるサーバーなんかには、リクエスト出すかいな!ってことだろうと思います。

 

推測にしか過ぎませんが、

上記のURLで言われているClass1では通してくれないんではないでしょうかね。

StartSSLもClass2の証明になると管理費がかかるようになりますので、この検証の為にということで二の足を踏んじゃうんですね。。。

 

qiita.com

情報をまとめてくれている方もいましたが、軒並み無料SSLが拒否られてる感じがしますね。これらが全てClass1かどうかは判りませんが、そんな感じと言うことで。

 

こちらからはこの辺になります。

LINE BOT API Trial で引っかかったところ

いや、まだ絶賛苦戦中なんですが。。。 ひとまず、落ち着きました。

まぁ、LINEのBOTが話題に上がったので、試そうとしたんですが、 スキル不足でつまずいたところを書いておきます。

linecorp.com

調子こいてAWS API GatewayとLambdaでやろうとした

これができたらサーバー管理いらずにプログラムだけで完結できるんですが、

残念ながら、LINE BOTにWHITE LISTという形で許可するIPアドレスを指定しないといけなく、 LambdaはIPアドレスが不明なので、上手く許可できませんでした。

適当にAWSのリージョンのIPアドレス調べて入れようかと思ったんですが、 残念ながらマスクが24-30のレンジでしか受け付けてくれなかったので断念。。。

(2016/05/19) これに関しては改善されたようで、サーバーレスで構築できるようになりました。

コールバックの書き方が判らなかった

設定でCallback URLが必要なのですが、 https://mydomain.com/sample/callbackとやってもダメで、 ただしくは https://example.com:443/sample/callback と、SSLのポート番号を入れてあげる必要がありました。

コールバックはSSL必須、そしてSSLきちんと張っているドメイン持っていなかった

当初、AWS API Gatawayでって考えてたのでxxxxxxxxx.execute-api.region.amazonaws.com的なドメイン使ったら良いわ、 って思っていたのですが、Lambdaの夢破れてしまい、個人ドメインの無料証明書をStartSSLで作りました。

https://www.startssl.com/

この後、問題が発生?するので、これで解決するかどうかは疑問です。

なぜかJSONパースエラーがでる

{
  "statusCode": "400",
  "statusMessage": "Failed to parse json data. Please check json data is well-formed."
}

投稿のフォーマットの"to"の項目を配列にし忘れていた。。。

{
    "to":["{$from}"],
    "toChannel":1383378250,
    "eventType":"{$event_type}",
    "content":{
        "toType":1,
        {$content}
     }
}

投稿する際の"to"の項目ですが、to自体を配列として渡さないといけないので、

誤)$post["to"] = $content->from

正)$post["to"][] = $content->from

上記の様に配列に入れた後、json変換すればOKでした。

なんだかコンテンツタイプで怒られる

{
  "statusCode": "422",
  "statusMessage": "contentType is not valid : 0"
}

結局、原因は判らなかったのですが、上記のJSONエラーを修正していたら、エラーが消えていた。。。 でも、結局、JSONフォーマットが悪かったのかな。

どうもLINE BOTのコールバック指定したURLにメッセージ飛んでこない

アクセスログを見てもどうも来ない。LINE BOTが来たよっていう足跡が残らない。。。

そこで、API Gatewayをプロキシにして、プログラムを叩くと、ログにも残ったし、返事のメッセージもきちんと送れました。

LINE BOT -> (☓) ->おいらのサーバーのプログラム

LINE BOT -> (○) ->API Gateway ->おいらのサーバーのプログラム

うーん、証明書は入れたつもりなんですけどね。

f:id:xev:20160409031643p:plain

AWS Lambdaで、DynamoDBをgetItemするときのパラメータの覚書

いやー、AWS API Gateway良いですね。


結構、APIサーバーを作成する作業が多かったのですが、
API Gatewatyならサーバーいらねー!ってことで、運用負担がスゲー減って最高。

ミドルウェアのバージョンやらなにやらも気にしないでいいので、
もう、すべてこいつでやっていきたいと思ってるくらい。

まぁ、まださわり始めたばかりなので、これからですが。

で、

AWS LambdaからDynamoDBにgetItemするときに、
パラメータの記述で結構ValidationExceptionを起こしてしまったので覚書。

Lambdaで、DynamoからgetItemするときに使えるものとして、

  • AWS SDK
  • DynamoDB Document SDK

がある。

で、その違いでLambdaからDynamoDBに渡すJSON形式に気をつけないといけない。

AWS SDKの場合

var aws = require('aws-sdk');
var dynamo = new aws.DynamoDB();

//キーに型を付ける
{
	"TableName": "user_info",
	"Key": {
		"Id": { "S": "STR000ABCD"},
		"code": { "N": "1"}
	}
}

DynamoDB Document SDKの場合

var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();

//キーに型を付けない
{
	"TableName": "user_info",
	"Key": {
	        "Id": "STR000ABCD",
	        "code": 1
	}
}

aws-sdkとdynamo-docとでは、ダブルクオーテーションで囲むとか囲まないとか、
型指定するとか、しないとか、そういった部分で違いがある。

いろいろ検索でしてたんですが、なんでサンプルが、キーを"で囲んでるやつ、囲んでないヤツ、
シングルクオーテーションなやつなど、いろいろあるんでしょうね。。。

やってみると、ダブルクオーテーションで囲まないと、なーんにもエラーで通らないんですけどね。不思議。


stackoverflow.com