独自 CA で発行した証明書を使って AWS IoT Core に接続するまでの手順を全てコマンドラインでやってみた

はじめに

テントの中から失礼します、CX 事業本部のてんとタカハシです!

AWS IoT Core では、証明書の発行やデバイス登録の方式が複数用意されています。今回は、独自 CA で発行した証明書を使用して、AWS IoT Core に接続する手順を全てコマンドラインでやってみました。

詳細の説明は AWS さんが公開している下記の動画をご参照ください。下記動画で説明されている「4. 独自CAによる証明書発行&AWS IoTへの事前登録」に該当します。

環境

環境は下記の通りです。MQTT クライアントとしてmosquittoを使用します。

% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H2

% openssl version
LibreSSL 2.8.3

% aws --version
aws-cli/2.0.28 Python/3.7.4 Darwin/19.6.0 botocore/2.0.0dev32

% mosquitto_pub --help
mosquitto_pub is a simple mqtt client that will publish a message on a single topic and exit.
mosquitto_pub version 2.0.9 running on libmosquitto 2.0.9.
...

手順

CA 証明書を発行する

CA 証明書を発行する前にopenssl.cnfv3_caセクションを確認します。 basicConstraintsCA:trueになっていれば OK です。

% openssl version -d
OPENSSLDIR: "/private/etc/ssl"

% cat /private/etc/ssl/openssl.cnf

...

[ v3_ca ]
basicConstraints = CA:true

...

CA 証明書を発行します。

% openssl req -newkey rsa:2048 -x509 -sha256 -nodes -days 3650 -extensions v3_ca -subj "/CN=example.classmethod.jp" -keyout root-ca.key -out root-ca.crt

% ls
root-ca.crt	root-ca.key

プライベートキー検証証明書を発行する

AWS IoT Core に CA 証明書を登録する際、併せてプライベートキー検証証明書も登録する必要があります。 プライベートキー検証証明書のCommon Nameには、AWS アカウント別リージョン別に存在する登録コードを設定する必要があることにご注意ください。

登録コードを AWS IoT Core から取得して変数に格納します。

% REGISTRATION_CODE=$(aws iot get-registration-code \
--query registrationCode \
--output text)

取得した登録コードを使用して、プライベートキー検証証明書を発行します。

% openssl genrsa -out verification-cert.key 2048
% openssl req -new -key verification-cert.key -out verification-cert.csr -subj "/CN=${REGISTRATION_CODE}"
% openssl x509 -req -in verification-cert.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out verification-cert.crt -days 365 -sha256

% ls   
root-ca.crt		root-ca.srl		verification-cert.csr
root-ca.key		verification-cert.crt	verification-cert.key

CA 証明書を登録する

AWS IoT Core に CA 証明書を登録する際は、併せてプライベートキー検証証明書も登録します。また、登録と同時に CA 証明書を有効化します。

% aws iot register-ca-certificate \
--ca-certificate file://$(pwd)/root-ca.crt \
--verification-cert file://$(pwd)/verification-cert.crt \
--set-as-active

{
    "certificateArn": "arn:aws:iot:<REGION>:<ACCOUNT_ID>:cacert/<CERTIFICATE_ID>",
    "certificateId": "<CERTIFICATE_ID>"
}

クライアント証明書を発行する

続いて、独自 CA にてクライアント証明書を発行します。

% openssl genrsa -out my-client.key 2048
% openssl req -new -key my-client.key -out my-client.csr -subj "/CN=my-client"
% openssl x509 -req -in my-client.csr -CA root-ca.crt -CAkey root-ca.key -CAcreateserial -out my-client.crt -days 365 -sha256

% ls
my-client.crt		root-ca.crt		verification-cert.crt
my-client.csr		root-ca.key		verification-cert.csr
my-client.key		root-ca.srl		verification-cert.key

クライアント証明書を登録する

AWS IoT Core にクライアント証明書を登録 & 有効化します。後のコマンドにて、登録したクライアント証明書の ARN を使用するため、変数に格納しておきます。

% CERTIFICATE_ARN=$(aws iot register-certificate \
--certificate-pem file://$(pwd)/my-client.crt \
--ca-certificate-pem file://$(pwd)/root-ca.crt \
--set-as-active \
--query certificateArn \
--output text)

AWS IoT Core ポリシーを作成する

MQTT クライアントが AWS IoT Core に接続 & Publish できるようにポリシーを作成します。

下記の JSON ファイルを用意します。REGIONACCOUNT_IDは各々の環境に合わせて変更してください。

% cat sample-aws-iot-core-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:<REGION>:<ACCOUNT_ID>:client/*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:<REGION>:<ACCOUNT_ID>:topic/*"
    }
  ]
}

上記の JSON ファイルを使用して AWS IoT Core ポリシーを作成します。

% aws iot create-policy \
--policy-name sample-aws-iot-core-policy \
--policy-document "file://$(pwd)/sample-aws-iot-core-policy.json"

{
    "policyName": "sample-aws-iot-core-policy",
    "policyArn": "arn:aws:iot:<REGION>:<ACCOUNT_ID>:policy/sample-aws-iot-core-policy",
    "policyDocument": "...",
    "policyVersionId": "1"
}

AWS IoT Core ポリシーをアタッチする

クライアント証明書に、AWS IoT Core ポリシーをアタッチします。

% aws iot attach-policy \
--policy-name sample-aws-iot-core-policy \
--target ${CERTIFICATE_ARN}

これで接続するまでの設定は完了です。

Publish して接続を確認する

mosquitto を使用して、AWS IoT Core のエンドポイントに向けて Publish します。トピックはiot/topicとしています。

% curl -O https://www.amazontrust.com/repository/AmazonRootCA1.pem

% AWS_IOT_CORE_ENDPOINT=$(aws iot describe-endpoint --endpoint-type iot:Data-ATS \
  --query endpointAddress \
  --output text
)

% mosquitto_pub --cert my-client.crt \
--key my-client.key \
--cafile AmazonRootCA1.pem \
-h ${AWS_IOT_CORE_ENDPOINT} \
-p 8883 \
-t iot/topic \
-m '{"hello": "world"}'

AWS IoT Core の MQTT テストクライアントにて、iot/topicをサブスクライブした状態で Publish すると、上手く接続できていることが確認できます。

おわりに

今回紹介した登録方式の他にも、Fleet Provisioning 登録や、JITR、JITP、マルチアカウント登録など様々存在します。それぞれの特徴をキチンと把握して、設計、構築できたらめちゃ格好良いですね!私も色々と試してみようと思います。

今回は以上になります。最後まで読んで頂きありがとうございました!