【備忘録】IoTデバイスと時刻同期について

#はじめに
IoTデバイスの時刻設定について、AWS IoTの場合、何がベストプラクティスとなるのか調べた際の備忘録です。
#1　時刻同期のベストプラクティス
AWSにおいて、デバイスの時刻を正確に保つことの必要性は、証明書の有効期限チェックとの兼ね合いでドキュメントで指摘されています。
>デバイスの時刻を正確に保つことが重要です。X.509 証明書には有効期限の日時があります。デバイスのクロックは、サーバー証明書が現在も有効であることを確認するために使用されます。
参考：[AWS IoT Core におけるセキュリティのベストプラクティス - デバイスのクロックを同期させる](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/security-best-practices.html#device-clock)

そして、時刻設定においてはリアルタイムクロック（以下、RTC）ではなくNTP（Network Time Protocol）の利用をベストプラクティスとします。

これは、RTCの場合、クロックドリフトやバッテリの消耗により間違った時刻に設定されることがあるためです。

また、前述の通り証明書のチェックに時刻が使用されるため、IoT Coreの接続前にNTPサーバとの時刻同期をすることがベストプラクティスです。

>ほとんどのシステムでは、デバイスのソフトウェアに Network Time Protocol (NTP) クライアントを含める必要があります。デバイスは、AWS IoT Core への接続を試行する前に、NTP サーバーと同期するまで待機する必要があります。これが不可能な場合は、後続の接続が成功するように、ユーザーがデバイスの時刻を設定する方法を提供する必要があります。
参考：[AWS IoT Core におけるセキュリティのベストプラクティス - デバイスのクロックを同期させる](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/security-best-practices.html#device-clock)

#2　ディストリビューションにntpdが含まれる場合
Linuxが載っているデバイスなどであれば、適切なNTPサーバと時刻同期するように設定します。

例えば、Jetson nano（OSはubuntu 18.04.5）で時刻設定をする場合は以下の通りNTPの設定を行います。
参考：[Ubuntuで時刻同期の設定 (timesyncd.conf)](https://qiita.com/tukiyo3/items/c847d443a6d977083de9)

1.現在同期しているNTPサーバを確認する
※Cloudflareが公開しているNTPサーバ（162.159.200.123）と同期している
　参考：[NTP Pool project - 162.159.200.123 / time.cloudflare.com](https://www.pool.ntp.org/ja/scores/162.159.200.123)

```
$ sudo systemctl status systemd--timesyncd
● systemd-timesyncd.service - Network Time Synchronization
   Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2021-06-08 19:55:49 JST; 22h ago
     Docs: man:systemd-timesyncd.service(8)
 Main PID: 3592 (systemd-timesyn)
   Status: "Synchronized to time server 162.159.200.123:123 (1.pool.ntp.org)."
    Tasks: 2 (limit: 4181)
   CGroup: /system.slice/systemd-timesyncd.service
           mq3592 /lib/systemd/systemd-timesyncd
（後略）
```
2.```/etc/systemd/timesyncd.conf```ファイルを編集し、NICTの公開NTPサーバと同期するよう設定する

```
$ sudo vim /etc/systemd/timesyncd.conf

##以下の通りにする
[Time]
NTP=ntp.nict.jp
FallbackNTP=ntp1.jst.mfeed.ad.jp ntp2.jst.mfeed.ad.jp ntp3.jst.mfeed.ad.jp
```
3.サービスを再起動する

```
$ sudo systemctl restart systemd-timesyncd
```
4.設定が反映されていることを確認する
※NICTが公開しているNTPサーバ（133.243.238.244）と同期している

```
$ sudo systemctl status systemd-timesyncd
● systemd-timesyncd.service - Network Time Synchronization
   Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-06-09 18:21:01 JST; 9s ago
     Docs: man:systemd-timesyncd.service(8)
 Main PID: 3798 (systemd-timesyn)
   Status: "Synchronized to time server 133.243.238.244:123 (ntp.nict.jp)."
    Tasks: 2 (limit: 4181)
   CGroup: /system.slice/systemd-timesyncd.service
           mq3798 /lib/systemd/systemd-timesyncd
```
#3　小型デバイスの場合
RTCが載っていないような小型デバイスの場合、以下のようにして時刻を取得する事が考えられます。
※参考：[Using Device Time to Validate AWS IoT Server Certificates](https://aws.amazon.com/jp/blogs/iot/using-device-time-to-validate-aws-iot-server-certificates/)

* NTPサーバと通信して時刻を取得する
* ドリフトの少ないRTCを搭載し、時刻を設定するインターフェイスを用意する

上記の分けはNTPクライアントを利用できるか否かによるものです。
#参考文献（文中には登場していないもの）

* [国内の公共・公開NTPサーバー一覧](https://www.gigabile.com/2013/02/08/%E5%9B%BD%E5%86%85%E3%81%AE%E5%85%AC%E5%85%B1-%E5%85%AC%E9%96%8Bntp%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E4%B8%80%E8%A6%A7/)
* [ESP32でネットワーク上から現在時刻を取得する（NTP）](https://wak-tech.com/archives/833)
 * 「3　小型デバイスの場合」で触れた「NTPサーバと通信して時刻を取得する」の実装例