mockmockでSORACOM Beamから連携するシステムの開発を効率化する

# 動機
IoTデバイスと連携するクラウドサービスを作ろうとして、デバイス側とクラウド側を別の会社が別個に開発するというのはとても良くあることかと思います。

デバイスからはSORACOM Beamを使ってhttpsに変換してこんな感じのデータ送るからよろしくねー・・と決めてスタートしたあと、クラウド側は自分たちの作った物の動作検証、どうやったら良いでしょうか？デバイスはまだ手元にないし、Beamからデータを流すにはSORACOM Air経由じゃないと流れないし。はて困った。

「きっとこういうデータが来る」と信じて開発時点ではcurl辺りでデータを送って頑張る・・というのもいいのですが、ここにBeamのヘッダ認証が絡むと話がややこしかったりします。
これまでですと、恐らく皆さん

- Beamの署名検証部分は単体試験だけしておいて、データ処理部分だけcurl辺りでテストしておく
- ラズパイやWioLTE辺りで実際にBeam経由でデータを送ってみて頑張る

辺りだったのではないかと思います。これはこれでいいんですが、やはりデバイスがない状態でも結合試験や負荷試験はしたいので実際にBeamからどんなデータで飛んでくるかは受け取りたいし、ラズパイ準備してとなるとせっかくソフト屋さんとハード屋さんで分業してるのにソフト屋さんの辛みが増えてしまいます。

そんな中、2019年7月2日にこんなニュースが飛び込んできました。

[mockmockの仮想デバイスからSORACOMプラットフォームへ疑似データが送信できる「SORACOM連携機能」が提供開始されました](https://fusic.co.jp/news/455)

おお、これで万事解決できそう！ということで早速試しました。

# mockmockとは

[mockmock](https://mock-mock.com/ja/)は、[(株)Fusic](https://fusic.co.jp/)さんが提供されているサービスで、クラウド上の仮想デバイスを用いる事で、開発中のサーバ(IoTデバイスからのデータを受け付けて何かをするもの)の動作検証や負荷試験を簡単に行えるサービスです。
サーバ側の開発時にはなかなか数万単位のデバイスから負荷がかかる状態などの試験をするのは難しいですが、mockmockを使えばいとも簡単にそれを実現できる素晴らしいサービスです。

今回はmockmockアカウントの作成については省略します。

# 仮想デバイス(mock)の準備

Acroquest Technologyさんのテクニカルブログにまさにそのままの記事がありましたので参考に進めてください(手抜き)。

[mockmockのSORACOM連携機能を試してみた](http://acro-engineer.hatenablog.com/entry/2019/07/03/120000)

注意点としては、soracom cliのプロファイルのセットアップの時に「カバレッジ(coverageType)」を聞かれるのを「japan」にしてください。うっかりglobalにするとうまく動きません(こんなんハマるの僕だけかもしれませんが・・)

# 署名検証をしてみよう

では、本記事の肝である「Beamの署名検証」をやってみましょう。

cliから流し込むjsonを以下のような感じで変更します。

```json
[
  {
    "key": "inventory://beam.soracom.io",
    "value": {
      "enabled": true,
      "name": "test",
      "addEquipmentHeader": false,
      "addSignature": true,
      "addSubscriberHeader": false,
      "customHeaders": {},
      "skipStatusCode": false,
      "useClientCert": false,
      "useClientCredentials": false,
      "addDeviceIdHeader": true,
      "destination": "<エンドポイント>",
      "psk": "平文の共有鍵",

    }
  }
]
```

変更するのは

- addDeviceIdHeaderをtrueに
- addSignatureをtrueに
- pskで事前共有鍵を渡す

の3点です。自分自身のアカウントを使ってSORACOMのコンソールから事前共有鍵を設定すると、鍵の情報を別の所に保存した上でbeamの設定にはその名称だけが渡されるので、流し込むjsonが

```json
"psk":{"$credentialsId": "鍵の名前"} 
```

という形になってより安全なのですが、今回はmockmockさんのSORACOMアカウントを操作する関係上、事前共有鍵を預けるということが出来ないので平文で直接指定するしかありません。念の為、必ず試験用の文字列を使うようにしましょう。

次に、署名の検証をするコードを修正します。[こちら](https://dev.soracom.io/jp/beam/send-data-using-beam/#signature)にあるように、実際のBeamの署名は

```
SHA256(${事前共有鍵文字列}+x-soracom-imei=${IMEI}x-soracom-imsi=${IMSI}x-soracom-timestamp=${TIMESTAMP}
```

という形になりますが、今回はimeiやimsiは付与されません。代わりにx-soracom-device-idというのが付与される(設定でaddDeviceIdHeader=trueにしましたので)ので、これを使って

```
SHA256(${事前共有鍵文字列}+x-soracom-device-id=${DEVICEID}x-soracom-timestamp=${TIMESTAMP}
```

としてやります。

私は今回サービスをAWS Lambdaで書いて、署名検証はLambdaオーソライザーでやろうと考え、[こちらの記事](https://qiita.com/ma2shita/items/64328324bee3c922b4a3)を参考に実装しました(Maxいつもありがとう！)。
この場合、書き換えるのは

```python
for header in ['x-soracom-imei', 'x-soracom-imsi', 'x-soracom-timestamp']:
```

ここを

```python
for header in ['x-soracom-imei', 'x-soracom-imsi', 'x-soracom-device-id', 'x-soracom-timestamp']:
```

とするだけです。これで本番のBeamに切り替えたときもそのまま動きます(本番だとx-soracom-device-idがなくなるから影響ない)。

# まとめ

SORACOM Beamを使ってIoTデバイスと連携する、クラウドサービス(クラウドじゃなくてもいいけど)を開発するときはぜひmockmockを使いましょう！デバイスがない状態でもしっかり動作検証や試験を行うことが出来てとても便利です。