独自認証局で発行したデバイス証明書を使って複数のクラウドに接続する

Vaultを使用し認証局を構築し、独自認証局で生成したデバイス証明書を使ってクラウドへ接続します。

💡
独自認証局の構築も意外と簡単にできます。

認証局の構築

Vaultを使用します。OSSです。

独自認証局の構築方法はこちらのドキュメントを参考にしました。

💡
最近のプロジェクトではなく、かなり前からあるプロジェクトのようです。

Vaultの起動

Dockerイメージが用意されているので起動は簡単です。

・設定ファイルを作成
・Dockerで起動
  • config.hcl
storage "raft" {
  path    = "/vault/file"
  node_id = "node1"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = "true"
}

disable_mlock = true

api_addr = "http://127.0.0.1:8200"
cluster_addr = "https://127.0.0.1:8201"
ui = true
docker run --rm -p 8200:8200 \
  -v `pwd`/vault/file:/vault/file  \
  -v `pwd`/vault/logs:/vault/logs  \
  -v `pwd`/config.hcl:/config.hcl  \
  vault server -config=/config.hcl

Vaultへのログイン

設定ファイルでUIを有効化しているので、全てブラウザ上で操作が可能です。

ブラウザでhttp://localhost:8200にアクセスします。

Create a new Raft clusterを選択します。

Key sharesを5、Key thresholdを3に指定。Shamir's Secret Sharingという暗号化に使用します。(詳細は公式ドキュメントを参照ください。)

画面遷移後、少し待つとキーが発行されます。Download keysでキーを一括ダウンロードし、Continue to Unsealをクリックします。

ダウンロードしたファイルのkeysから、3回別々のkey入力します。

右上のStatusが緑色に変わりました。これでUnsealが完了です。サーバーシャットダウン後も、再度このUnseal作業が必要になります。

ダウンロードしたファイルのroot_tokenを使ってログインします。

これでログインまでが完了です。root権限なので、適切なユーザーを作成する必要がありますが、今回はこのままroot権限で進めます。

💡
Web UIが用意されているので、操作は簡単な印象です。CLIでも同等の操作はできます。

Vaultに認証局を作成

Enable new Engineをクリックします。

PKI Certificatesを選択し、Nextをクリックします。

Method Optionsを開き、Max Lease TTL3650daysに設定します。Enable Engineをクリックします。

ConfigurationタブのConfigureをクリック、Configure CAをクリックします。

以下の項目を入力し、Saveをクリックします。

項目
Common name My Private Certificate Authority
Options -> TTL 3650days

Certificateが生成されるのでファイルに保存します。名前はprivate_root_CA.pemとしておきます。

URLsタブを選択し、以下の項目を入力し、Saveをクリックします。

項目
Issuing certificates http:// 127.0.0.1:8200/v1/pki/ca
CRL Distribution Points http:// 127.0.0.1:8200/v1/pki/crl

パンくずリストのpkiから画面を戻り、RolesタブのCreate roleをクリックします。

以下の項目を入力し、Create roleをクリックします。

項目
Role name MyPrivateCertificateAuthority
Options -> Allow any name チェックを付ける
Options -> Enforce hostnames チェックを外す

ここまでで認証局の作成は完了です。

💡
少し手順は多いですが、認証局の構築ができました。デバイス証明書を発行する際に大事なのは、最後のAllow any nameとEnforce hostnamesの設定です。

デバイス証明書の作成

デバイス証明書を作成します。

Vaultの画面でMyPrivateCertificateAuthorityロールのメニューからGenerate certificateをクリックします。(ロール名のクリックでもOKです)

Common nameを入力し、Generateをクリックします。

Certificate、Private keyを保存しておきます。(それぞれcertificate.pem、private.keyなど)

画面下部のCopy credentialsからJSON形式で一括取得が可能です。

これでデバイス証明書の作成は完了です。

💡
デバイス証明書は簡単に発行できました。

各クラウドへの接続

作成したデバイス証明書を使って、各クラウドに接続を試してみましょう。


接続手順(A)

検証証明書の作成

コンソールでCA証明書まで遷移し、CA証明書を登録ボタンをクリックします。

ページ中程に説明のある検証証明書を作成する必要があります。登録コードはこの後必要なのでコピーしておきます。

OpenSSLで以下のコマンドを実行します。

openssl genrsa -out verification_cert_key_filename.key 2048

鍵ファイルが作成されます。続いてこちらのコマンドでCSR(証明書署名要求)を作成します。

openssl req -new -key verification_cert_key_filename.key -out verification_cert_csr_filename.csr

入力が求められるので、Common Name以外は未入力でエンター、Common Nameは先程の登録コードを入力します。

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:     <===== ここに検証コード
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

‌CSRへの署名はVaultで構築した認証局で行います。

Rolesに作成したMyPrivateCertificateAuthorityの右側メニューから、Sign certificateを選択します。

以下の項目を入力し、Generateをクリックします。

項目
Certificate Signing Request (CSR) OpenSSLで生成したCSRファイルの内容
Common name 検証コード
Options -> Exclude Common Name from Subject Alternative Names (SANs) チェックを付ける

証明書が作成されるので、ファイルに保存します。(verification_cert_filename.pemとします)

CA証明書の登録

管理画面に戻ります。

CA 証明書にprivate_root_CA.pem、検証証明書にverification_cert_filename.pemを指定し、登録をクリックします。

CA証明書が登録されました。

デバイス証明書の登録

証明書画面の証明書を登録をクリックします。

CA が登録されていますを選択した状態で先程登録したCA証明書を選択。作成済みのデバイス証明書(certificate.pem)をアップロードします。有効化もこのタイミングで実施しておくと良いでしょう。登録をクリックします。

これでデバイス証明書の登録は完了です。

ポリシーの作成とアタッチ

このままでは権限がないため接続ができませんのでIoTポリシーを作成します。

ポリシーの画面でポリシーを作成ボタンをクリックします。

お試しなので、フル権限で作成します。ポリシーアクションとポリシーリソースはいずれも*です。作成をクリックします。

証明書の画面に戻り、先程登録したデバイス証明書にポリシーをアタッチします。

これで接続の準備は完了です。

💡
CAを登録することで、認証局が発行した証明書だけがデバイス証明書として有効化されます。

接続(A)

接続してみましょう。

MQTTクライアントに以下の内容を入力し、接続します。

項目
プロトコル mqtts
ホスト名 設定画面で表示されるエンドポイント
ポート番号 8883
クライアントID 任意の文字
ユーザー名 未指定
パスワード 未指定
CAファイル Amazon Root CA 1を保存したファイル
クライアント証明書 デバイス証明書(certificate.pem)
プライベートキー プライベートキー(private.key)

Publish

任意のトピック名に対してPublishが可能です。(一部予約トピックあり)

Subscribe

任意のトピック名に対してSubscribeが可能です。(一部予約トピックあり)

💡
他のクラウドのサービスに比べ、純粋なMQTTブローカーに一番近い印象です。

接続手順(B)

IoT Hubの作成

管理画面を開き、IoTハブの作成をクリックします。

IoT Hub名を入力し、確認及び作成をクリック、作成をクリックします。

ルート証明書の登録

ルート証明書を登録します。左の証明書メニューを選択し、追加をクリックします。

証明署名を入力、private_root_CA.pemを選択、アップロード時に証明書の状態を確認済みに設定するにチェックを入れ、保存をクリックします。


デバイスの登録

次にデバイスを登録します。左のデバイスメニューを選択し、デバイスの追加をクリックします。

デバイスIDを入力しますが、ここで指定するデバイス名はデバイス証明書作成時に指定したCommon nameと同一である必要があります。認証の種類をX.509 CA 署名済みとし、保存をクリックします。

💡
デバイスとデバイス証明書の事前登録が不要という特徴があります。

接続(B)

接続してみましょう。

MQTTクライアントに以下の内容を入力し、接続します。

項目
プロトコル mqtts
ホスト名 接続先URL
ポート番号 8883
クライアントID {デバイスID}
ユーザー名 ユーザー名
パスワード 未指定
CAファイル Baltimore CyberTrust Rootを保存したファイル
クライアント証明書 デバイス証明書(certificate.pem)
プライベートキー プライベートキー(private.key)

Publish

以下のトピック名に対してPublishが可能です。

/devices/{デバイスID}/messages/events/

Subscribe

以下のトピック名に対してSubscribeが可能です。

/devices/{デバイス名}/commands/#
/devices/{デバイスID}/messages/devicebound/#

管理画面からデバイスへのメッセージでテスト送信が可能です。

💡
接続ができました。pub/subできるトピックが限られてます。また、IoT Hubのプランによってもできることとできないことがありそうです。

接続手順(C)

レジストリの作成

管理画面を開き、レジストリを登録をクリックします。

レジストリID、リージョン、Cloud Pub/Subトピックを入力、CA証明書欄private_root_CA.pemの値を貼り付け、作成をクリックします。

デバイスの登録

続いてデバイスを登録します。

デバイスID(device1)を入力し、認証欄にcertificate.pemの内容を貼り付けます。公開鍵の種類はRS256_X509を選択します。作成をクリックします。

以上で接続の準備は整いました。

💡
CA証明書の登録とデバイス証明書の事前登録を行います。

接続(C)

接続してみましょう。

MQTTクライアントに以下の内容を入力し、接続します。

パスワードの生成が少し手間ですが、サンプルコードがあるのでそちらを参考にしてください。

項目
プロトコル mqtts
ホスト名 mqtt.xxxxxapis.com
ポート番号 8883
クライアントID projects/{プロジェクトID}/locations/{リージョン}/registries/{レジストリ名}/devices/{デバイス名}
ユーザー名 unused
パスワード こちらの方法で生成したJWT
CAファイル ルート CA 認証パッケージを保存したファイル
クライアント証明書 デバイス証明書(certificate.pem)
プライベートキー プライベートキー(private.key)

Publish

以下のトピック名に対してPublishが可能です。

/devices/{デバイス名}/events

Subscribe

以下のトピック名に対してSubscribeが可能です。

/devices/{デバイス名}/commands/#
/devices/{デバイス名}/config

管理画面から構成を編集コマンドを送信でテスト送信が可能です。

💡
パスワードの作成の特徴があります。

以上、独自認証局で発行したデバイス証明書を使って接続する方法でした。