暗号化ファイルシステム "EncFS" のパスフレーズにSORACOM Air メタデータサービスを使う

冒頭から謝罪
==========

[SORACOM Advent Calendar](http://qiita.com/advent-calendar/2015/soracom) 12/10 担当の[ma2shita](https://twitter.com/ma2shita)です

![Screenshot from 2015-12-06 15-54-54.png](https://qiita-image-store.s3.amazonaws.com/0/22754/5728e2f6-7001-692f-c48e-6cddd590d9c2.png)

とか書いておきながら、EncFSとかマイナーなネタを書きました

![usodesu_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/22754/a16b41be-1d5d-0b4c-3d18-b5e3439987cf.jpeg)

ごめんなさい、BLEネタは近日中に必ず書きます！

TL;DR
=====

SORACOM Airのメタデータサービス内ユーザデータ(パスフレーズとして `AccessSecretFileKey` を使用)を設定

```bash
$ soracom group create --tags=name:demo_encrypted
$ soracom group update_configuration \
  --group-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX \
  --namespace SoracomAir \
  --params '[{"key": "userdata", "value":"AccessSecretFileKey"}]'
$ soracom sim set_group --imsi YYYYYYYYYYYYYYY \
  --group-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
```

それを読み出し、EncFSのパスフレーズに使用

```bash
$ encfs --extpass='curl -s http://metadata.soracom.io/v1/userdata' ~/.crypted ~/mnt
```

概要
====

暗号化ファイルシステム実装の一つである EncFS は、ディレクトリの暗号化を行うことができます
EncFSは `--extpass=program` というオプションを持っており、パスフレーズの入力に **program** の標準出力を使うことができます

もうおわかりですね

[すでにメソられているAWSのIAMネタ](http://dev.classmethod.jp/soracom/use-air-tag-metadata/)を、EncFSのパスフレーズに焼き直しただけのパクりネタです

利点
====

マウントに使用するパスフレーズをローカル保存しなくても良くなります

たとえばプログラムファイルの難読化を目的として使用することができます
デバイスの中身を見られなくない時、例えば契約切れでプログラムを使わせたくない、デバイスが盗難された、といった時に効果を発揮するでしょう

ただし、盗難自体を防げるわけじゃありませんのでご注意
メタデータ内の **location** とか、使えるようになりませんか？ <唐突な要望>

また、暗号化されているからと行って過信は禁物です
プログラムによっては `/tmp` や `/var` に一時ファイル/キャッシュを保存＆削除し忘れという可能性もあるのでご注意ください

この辺りの注意事項や他の暗号化ファイルシステムとの比較については[ディスク暗号化 - ArchLinux](https://wiki.archlinuxjp.org/index.php/%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E6%9A%97%E5%8F%B7%E5%8C%96)に詳細があります

準備
====

EncFSを準備する
---------------

### 前提 ###

- `~/.crypted` を EncFS による暗号化済データ保存ディレクトリとし、そのディレクトリをのマウント先として `~/mnt` とします
- パスフレーズは `AccessSecretFileKey` とします
- 暗号化パラメータはパラノイア(=偏執狂、ようするにできる限り最強ってことでしょう)とします

初回のマウント操作で、暗号化に関する設定を求められます

```bash
$ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y encfs
$ mkdir ~/.crypted ~/mnt
$ encfs ~/.crypted ~/mnt
新しい暗号化ボリュームを作成します。
Please choose from one of the following options:
 enter "x" for expert configuration mode,
 enter "p" for pre-configured paranoia mode,
 anything else, or an empty line will select standard mode.
?> <== p を入力

Paranoia configuration selected.

設定が完了しました。以下のプロパティのファイルシステムが
作成されます:
ファイルシステム暗号アルゴリズム: "ssl/aes", バージョン 3:0:2
Filename encoding: "nameio/block", version 4:0:2
鍵サイズ: 256 ビット
ブロックサイズ : 1024 バイト (8 バイト MAC ヘッダ含む)
Each file contains 8 byte header with unique IV data.
Filenames encoded using IV chaining mode.
File data IV is chained to filename IV.
File holes passed through to ciphertext.

-------------------------- 警告 --------------------------
The external initialization-vector chaining option has been
enabled.  This option disables the use of hard links on the
filesystem. Without hard links, some programs may not work.
The programs 'mutt' and 'procmail' are known to fail.  For
more information, please see the encfs mailing list.
If you would like to choose another configuration setting,
please press CTRL-C now to abort and start over.

Now you will need to enter a password for your filesystem.
You will need to remember this password, as there is absolutely
no recovery mechanism.  However, the password can be changed
later using encfsctl.

新しい Encfs パスワード: <== AccessSecretFileKey を入力
Encfs パスワードの確認:  <== AccessSecretFileKey を入力
```

これで暗号化＆マウントが完了しました。確認してみましょう

```bash
$ df -h ~/mnt
Filesystem      Size  Used Avail Use% Mounted on
encfs           231G   62G  158G  29% /home/user0/mnt
```

```bash
$ echo "hoge" > /home/user0/mnt/bar
$ mkdir -p /home/user0/mnt/dir0/subdir0
$ tree /home/user0/mnt
/home/user0/mnt
├── bar
└── dir0
    └── subdir0

2 directories, 1 file
$ tree /home/user0/.crypted/
/home/user0/.crypted/
├── Rdub0T6WYTSiuzjGS0eHKtzZ
│   └── 4R02B3,8E94W39e5di,yl4bz
└── c,jxy1NVlX4,f2x8ylazC2DC
$ cat /home/user0/.crypted/c,jxy1NVlX4,f2x8ylazC2DC 
p,���
�U��� ��JU|
```

上記の通り、ファイル名や中身が暗号化されている事がわかります
ディレクトリ構造は残念ながら隠匿化できませんが、[他の暗号化ファイルシステム](https://wiki.archlinuxjp.org/index.php/%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E6%9A%97%E5%8F%B7%E5%8C%96)で解決できる可能性があります

EncFSの操作
-----------

### アンマウント ###

EncFSはfuseを使っているので、アンマウントは `fusermount -u` です

```bash
$ fusermount -u /home/user0/mnt
```

### (再)マウント ###

```bash
$ encfs ~/.crypted ~/mnt
EncFS パスワード: <== AccessSecretFileKey
```

パスフレーズが一致しない場合はマウントできません

```bash
$ encfs ~/.crypted ~/mnt
EncFS パスワード:  <== hoge
Error decoding volume key, password incorrect
```

SORACOM Airのメタデータサービスの準備
-------------------------------------

ユーザデータはグループ毎に設定することができます

今回は `demo_encrypted` というグループを作成し、そのグループのユーザデータにEncFSのパスフレーズ `AccessSecretFileKey` を設定します。せっかくなのでCLIから行います


```bash
$ soracom group create --tags=name:demo_encrypted
{
  "operatorId": "OPXXXXXXXXXX",
  "groupId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "createdAt": 1449383020624,
  "lastModifiedAt": 1449383020624,
  "configuration": {
  },
  "tags": {
    "name": "demo_encrypted"
  },
  "createdTime": 1449383020624,
  "lastModifiedTime": 1449383020624
}
$ soracom group update_configuration --group-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX --namespace SoracomAir --params '[{"key": "userdata", "value":"AccessSecretFileKey"}]'
{
  "operatorId": "OPXXXXXXXXXX",
  "groupId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "createdAt": 1449383020624,
  "lastModifiedAt": 1449383350396,
  "configuration": {
    "SoracomAir": {
      "userdata": "AccessSecretFileKey",
      "metadata": {
        "enabled": false,
        "readonly": true,
        "allowOrigin": null
      },
      "useCustomDns": false,
      "dnsServers": [

      ]
    }
  },
  "tags": {
    "name": "demo_encrypted"
  },
  "createdTime": 1449383020624,
  "lastModifiedTime": 1449383350396
}
```

グループ作成とユーザーデータ設定できたら、SIMを所属させます

```bash
$ soracom sim set_group --imsi YYYYYYYYYYYYYYY --group-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
{
  "imsi": "YYYYYYYYYYYYYYY",
  "msisdn": "ZZZZZZZZZZZZ",
  "ipAddress": "XXX.XXX.XXX.XXX",
  "apn": "soracom.io",
  "type": "s1.standard",
  "groupId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "createdAt": 1444992915451,
  "lastModifiedAt": 1449383959562,
  "expiredAt": null,
  "terminationEnabled": false,
  "status": "active",
  "tags": {
    "name": "IMSI NAME 0"
  },
  "sessionStatus": {
    "lastUpdatedAt": 1449234567601,
    "imei": null,
    "location": null,
    "ueIpAddress": null,
    "dnsServers": null,
    "online": false
  },
  "speedClass": "s1.standard",
  "moduleType": "nano",
  "plan": 1,
  "expiryTime": null,
  "operatorId": "OPXXXXXXXXXX",
  "createdTime": 1444992915451,
  "lastModifiedTime": 1449383959562
}
```

SORACOM Air側の準備も完了です

動作確認
========

先ほど `demo_encryted` に所属させたSIMの回線から curl コマンドで ユーザデータが取得できるか確認します

```bash
$ curl -s http://metadata.soracom.io/v1/userdata
AccessSecretFileKey
```

確認できたら EncFS の `--extpass` オプションに指定してマウントできるか確認です

```bash
$ encfs --extpass='curl -s http://metadata.soracom.io/v1/userdata' ~/.crypted ~/mnt
```

お疲れ様でした

References
==========

- <a href="http://reasonset.net/journal/archives/livewithlinux/370" >暗号化ファイルシステム EncFS と eCryptFS について</a>
- <a href="https://wiki.archlinuxjp.org/index.php/EncFS" >EncFS - ArchWiki</a>
- <a href="https://wiki.archlinuxjp.org/index.php/%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E6%9A%97%E5%8F%B7%E5%8C%96" >ディスク暗号化 - ArchWiki</a>
- <a href="https://blog.soracom.jp/blog/2015/11/27/air-metadata/" >SORACOM Air メタデータサービスのご紹介 - SORACOM Blog</a> 
- <a href="https://dev.soracom.io/jp/docs/api/#!/Group/bulk_update_group_configuration_parameters" >API リファレンス | SORACOM Developers</a>