AWS IoT Coreで自分のCAで署名した証明書を使う話
はじめに
AWS IoT Coreにて、クライアント証明書(デバイス証明書)をIoT Coreが発行した証明書を使うのではなく、自前のCAを使って署名した証明書を使う場合の話[1]。
自前のCA証明書をIoT Coreに登録する手順がでてくるので混乱しがちだが、今回はクライアント認証の話であり、IoT Coreのエンドポイント(およびサーバー証明書のCN)は通常通り*.iot.ap-northeast-1.amazonaws.com
である。つまり、クライアントがIoT Coreに接続する際にはサーバー証明書のルート証明書はAmazonの AmazonRootCA1.pem
を使うことになる。
いろいろとオプションがありそのPro/Conは以下公式の引用の通り。基本的にはモードはSNI_ONLYにしておけばよくて、JITRを使うのであればCAの証明書を登録、そうでなければデバイスの証明書のみを登録という考え方で良いと思う。
JITRは別途やってみたい。
クライアントと AWS IoT 間の通信を有効にするには、クライアント証明書を AWS IoT に登録する必要があります。各クライアント証明書を手動で登録するか、クライアントが AWS IoT に初めて接続したときにクライアント証明書が自動的に登録されるように設定できます。
クライアントやデバイスの初回接続時にクライアント証明書を登録させたい場合は、クライアント証明書の署名に使用したCA証明書を使用するリージョンでAWS IoTに登録する必要があります。Amazon Root CA は自動的に AWS IoT に登録されます。
クライアント証明書は、AWS アカウントおよびリージョンで共有できます。クライアント証明書を使用するアカウントおよびリージョンごとに、以下の手順を実行する必要があります。あるアカウントやリージョンでクライアント証明書を登録しても、別のアカウントやリージョンでは自動的に認識されません。
デバイスやクライアントが最初に AWS IoT に接続したときにそのクライアント証明書を登録する (ジャストインタイムのプロビジョニングとも呼ばれます) 場合、AWS IoT に署名用 CA を登録して自動登録を有効にする必要があります。
署名 CA を登録できない場合は、CA なしでクライアント証明書を登録することを選択できます。CA なしで登録されたデバイスの場合、AWS IoT への接続時に Server Name Indication (SNI) を提示する必要があります。
注記 CA を使用してクライアント証明書を登録するには、階層内の他の CA ではなく、AWS IoT に対して署名 CA を登録する必要があります。
注記 CA 証明書は、リージョン内の 1 つのアカウントでのみ DEFAULT モードで登録できます。CA 証明書は、リージョン内の複数のアカウントで SNI_ONLY モードで登録できます。
実際にやってみる
OpenSSLはこんな感じ。
openssl version
OpenSSL 3.1.1 30 May 2023 (Library: OpenSSL 3.1.1 30 May 2023)
CA証明書
何はともあれ、デバイスの証明書に署名するCA証明書が必要。
CAの秘密鍵を作成
openssl genrsa -out ca.key 2048
CA証明書の作成
openssl req -x509 -new -nodes \
-key ca.key \
-sha256 -days 1024 \
-out ca.crt \
-subj "/CN=MyCA"
CA証明書をIoT Coreに登録する
CERTIFICATE_ID=$(aws iot register-ca-certificate \
--ca-certificate file://ca.crt \
--certificate-mode SNI_ONLY \
--set-as-active \
--query 'certificateId' \
--output text)
aws iot describe-ca-certificate --certificate-id $CERTIFICATE_ID
登録したCA証明書を確認する
aws iot describe-ca-certificate --certificate-id $CERTIFICATE_ID
デバイス証明書
デバイスの秘密鍵を作る
openssl genrsa -out device.key 2048
デバイスの秘密鍵からCSRを作る
openssl req -new \
-key device.key \
-out device.csr \
-subj "/CN=MyDevice"
CSRにCA証明書で署名してデバイスの証明書を作る
openssl x509 -req \
-in device.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out device.crt \
-days 500 -sha256
デバイス証明書をIoT Coreに事前登録
Option1. デバイス証明書に署名したCAがIoT Coreに登録されている場合
CERTIFICATE_ARN=$(aws iot register-certificate \
--set-as-active \
--certificate-pem file://device.crt \
--ca-certificate-pem file://ca.crt \
--query 'certificateArn' \
--output text)
echo $CERTIFICATE_ARN
確認する
aws iot list-certificates --query "certificates[?certificateArn=='$CERTIFICATE_ARN']"
Option2. デバイス証明書に署名したCAをIoT Coreに登録しない場合
CERTIFICATE_ARN=$(aws iot register-certificate-without-ca --status ACTIVE --certificate-pem file://device.crt)
echo $CERTIFICATE_ARN
Thingを作る
THING_NAME=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z0-9' | head -c 8; echo)
echo $THING_NAME
aws iot create-thing --thing-name $THING_NAME
Thingにデバイス証明書をアタッチする
aws iot attach-thing-principal --principal $CERTIFICATE_ARN --thing-name $THING_NAME
デバイス証明書にポリシーをアタッチする。
p1は事前に作成してある。
aws iot attach-policy \
--target $CERTIFICATE_ARN \
--policy-name p1
クライアントから接続する
END_POINT=$(aws iot describe-endpoint --endpoint-type iot:Data-ATS --query endpointAddress --output text)
mosquitto_pub --cafile AmazonRootCA1.pem \
--cert device.crt \
--key device.key \
-h $END_POINT \
-p 8883 \
-t t1 \
-d \
-m '{"id":1}' \
-i $THING_NAME
mosquitto は -h
で指定したホストをSNIとして送信しているはず
その他
証明書の中身を見るコマンド
openssl x509 -in ca.crt -text -noout
ここだけサーバ側の証明書の話になる。実際にTLSでやり取りされているサーバ側の証明書をWiresharkで引っこ抜いて上のコマンドで覗いてみるとIssuer
とSubject
はこんな感じ。なるほどこういうトラストチェーンになってるのか。
Issuer: C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
Subject: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
Subject: C = US, O = Amazon, CN = Amazon Root CA 1
Issuer: C = US, O = Amazon, CN = Amazon Root CA 1
Subject: C = US, O = Amazon, CN = Amazon RSA 2048 M01
Issuer: C = US, O = Amazon, CN = Amazon RSA 2048 M01
Subject: CN = *.iot.ap-northeast-1.amazonaws.com
参考にしたサイト
- 独自のクライアント証明書を作成する
- AWS IoT Core 使用時のマルチアカウントデバイスプロビジョニングと認証局登録の簡略化
- 独自 CA で発行した証明書を使って AWS IoT Core に接続するまでの手順を全てコマンドラインでやってみた
- [AWS IoT Core] CA証明書をSNI_ONLYモードで登録してみました
- [IoT Core] プライベートCAで署名されたサーバ証明書を使用してカスタムドメインを設定してみました
- AWS IoTで独自CAで発行した証明書を自動登録するようにしてみた
- AWS IoTに1つの証明書で複数のAWSアカウントへの接続に対応してみた
-
IoT Coreが署名するデバイス証明書での接続方法については以前に「AWS IoTにRubyのMQTTクライアントから接続」に書いた。 ↩︎
Discussion