🤫

SORACOM Arc on ESP32でSORACOM Kryptonを使ってブートストラップする

2021/12/20に公開

本記事はSORACOM Advent Calendar 2021の20日目の記事です。

これは

ESP32でSORACOM Arcに接続する際の秘匿情報をできるだけソースコードから排除したい、という内容です。

SORACOM Arc on ESP32

いださん(@ciniml)の作られたWireGuard-ESP32ならびにWireGuard-ESP32-Arduinoのおかげで、M5StackなどESP32を搭載したデバイスからもSORACOM Arcに接続できて大変便利です。いださん、本当にありがとうございます!

WireGuard-ESP32-ArduinoのGitHubのサンプルコードの通りに作れば簡単に接続できるのですが、見ての通りいくつかソースコードに秘匿情報を埋め込む必要があります。

  • WiFiのSSID
  • WiFiのパスワード
  • WireGuardのプライベートキー
  • WireGuardのエンドポイントアドレス
  • WireGuardのパブリックキー

パブリックキーやエンドポイントアドレスは秘匿はしなくてもいいかもですが、arcのセッションをリセットすると変わってしまう情報ですので、できればソースコードに直接埋め込まないで済ませたいところです。

一つの解決方法は、motoさんの書かれたブログ記事「SORACOM Arc への接続情報をスケッチに書かないための方法」にあるように、設定画面から入力してもらってそれをEEPROMに書き込んでおくという方法です。

https://zenn.dev/j3tm0t0/articles/d09537d6f94d76

今回は別解として、SORACOMの他のサービスとM5Stack用の3g拡張ボードを使って実現してみたいと思います。

SORACOM Arcのブートストラップ

SORACOM Arcに接続する場合、コンソール等から取得した情報を使って接続するのとは別に、SORACOM公式ツールであるsoratunsoracom cliを用いてブートストラップを行う方法があります。ESP32ではsoratunやsoracom cliを使うことはできませんので、「soratunがどうやってブートストラップしてるのか」を確認し、同じ事をESP32上に実装することにします。

soratunのブートストラップは公式ドキュメントにもありますが、3つの方法があります。

  • SORACOM API 認証キー
    SORACOM APIに接続する認証キーを使い、SORACOM APIを使ってブートストラップする
  • SORACOM Krypton SIM 認証
    SORACOM Kryptonでブートストラップする。krypton cliが必要で、SORACOM Airでの接続も不要
  • SORACOM Krypton セルラー回線認証
    SORACOM Air for セルラー接続を使って認証し、そのセルラー回線(SIM)のサブスクリプションコンテナに仮想SIMを登録してブートストラップする

API認証キーを使うのは「じゃあそのAPI認証キーをどこに保存するの?」ということになりますのでここでは採用しません。また、Krypton SIM認証はKryptonに対応したドングルが必要になるので、やはり今回は利用できません。
今回は3g拡張ボードとSORACOM Airを使って、最後の「SORACOM Kryptonセルラー回線認証」を使うことにします。

なお、API認証キーを使ったブートストラップをESP32上で行うお話は、mozさんの書かれたブログ記事「SORACOM ArcをESP32のArduinoで動かすsoracom-arc-esp32-arduinoのご紹介」を参照ください。

https://moznion.hatenadiary.com/entry/2021/12/17/095957

SORACOM Krypton セルラー回線認証

soratunのソースコードも参考にしつつ、Krypton プロビジョニング API リファレンスを確認します。

今回はSORACOM Air のセルラー回線を使用した認証を使うので、エンドポイントはhttps://krypton.soracom.io:8036になります。

そして、ArcのブートストラップのAPIはこちらになります。これを読むと、/v1/provisioning/soracom/arc/bootstrapに対してPOSTリクエストを送るとこんな感じのJSONが返ってくるようだということが分かります。

{
  "arcAllowedIPs": [
    "string"
  ],
  "arcClientPeerIpAddress": "string",
  "arcClientPeerPrivateKey": "string",
  "arcServerEndpoint": "string",
  "arcServerPeerPublicKey": "string"
}

ここまで分かれば勝ったも同然。この通りに実装していきます。

そして、ブートストラップでKryptonを使いますので、ブートストラップに使うSIMが所属しているSIMグループの「SORACOM Krypton設定」をONにしておきます。


Kryptonの設定

WiFiの秘匿情報

ブートストラップが成功すれば起動時にArcへの接続情報は取得できますが、最後に残ってるのがWiFiの秘匿情報です。これもせっかくなのでSORACOMから取得してみましょう。そのためには、SORACOM Airメタデータサービスを使います。

先ほどKryptonをONにしたのと同じSIMグループの「SORACOM Air for セルラー設定」で「メタデータサービス」をONにします。そして、ユーザーデータにJSONでssidとパスワードを記載しておきます。


メタデータサービスの設定

あとはhttp://metadata.soracom.io/v1/userdataにGETリクエストを送ればこのJSONを取得できます。

実装

M5Stack + 3g拡張ボードでSORACOMに接続する基本の部分はSORACOM IoT DIYレシピを参考にして、HTTP/HTTPSでの通信を実装していきます。

最終的な実装は以下で公開しています。
SORACOM AirではなくSORACOM Arc(WiFi)で通信していることを確実にするため、ブートストラップが終わったらモデムの電源を切っています。そして、5秒に1回unified endpointにかんたんなJSONデータを送信しています。

https://github.com/kenichiro-kimura/m5stack-metadata-and-provisioning-arc-with-krypton

動かしてみた

実際に動かしてみます。3G(Air)でなくWiFi(Arc)からデータが来ていることをコンソールから確認しやすくするため、12/18 10:50頃に起動し、そのまま11:00を過ぎてもしばらく動かしておきました。

そして、SORACOMコンソールの「SIM管理」から該当のSIMを選んで「詳細」→「通信量履歴」→「1時間ごと」と進みます。


通信量の確認

3Gでの通信は「s1.4xfast」、WiFiでの通信は「planArc01」になります。ご覧の通り、10:00代は両方のプランでデータが使われていますが、11:00代はplanArc01のみとなっています。


2021/12/18 10:00-11:00の通信量


2021/12/18 11:00-12:00の通信量

Harvest Dataを見てみると、データも正しく届いていることが確認できます。


Harvest Data

まとめ

SORACOM AirメタデータサービスならびにSORACOM Kryptonセルラー回線認証を使うことで、秘匿情報をソースコードに埋め込むことなく安全にSORACOM Arcに接続できました。
秘匿情報を埋め込まないのはセキュリティ的に良いのはもちろんですが、

  • 複数のデバイスに同じプログラムを配ることができるので、デプロイ手順が簡素化できる
  • 設置場所(WiFi AP)が変わってもプログラムの修正が不要
  • Arcのセッションをリセットして接続情報が変わってしまってもプログラムの修正が不要

ということで、変更にも強く運用にも優しくなります(その代わりに3g拡張ボードとSORACOM AirのSIMが全てのデバイスに必要になりますがw)。

あとは起動の度にブートストラップをせず、一度取得した秘匿情報をEEPROMに書き込んでおいたりするといいのかなと思いますが、その辺りは今後の課題としておきます。

GitHubで編集を提案

Discussion