[AWS IoT] CSRによる証明書の作成

CSRによる証明書作成では、クライアント側で所有する秘密鍵を使用しますので、秘密鍵の送達が必要ない仕組みを作ることが可能となります。
2020.08.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

CX事業本部の平内(SIN)です。

AWS IoTへの接続で使用されるクライアント証明書は、1-Click証明書作成(推奨) で簡単に作成できます。証明書を作成 のボタンをクリックするだけで、Amazonルート認証局 (CA) によって署名されたクライアント証明書と秘密鍵がダウンロード可能となり、これをデバイス側に配置することで利用可能です。

通常、この要領で全く問題ありませんが、今回は、2つ目の選択にある CSRによる作成 による証明書の作成を試してみました。

CSRによる証明書作成では、クライアント側で所有する秘密鍵を使用しますので、秘密鍵の送達が必要ない仕組みを作ることが可能となります。

2 秘密鍵

CSR作成には、秘密鍵が必要です。下記は、Mac上で鍵長2048bitのRSA鍵を作成している様子です。

% openssl genrsa -out privatekey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...................................+++++
...................................+++++
e is 65537 (0x010001)
% ls -la privatekey.pem
-rw-------  1 sin  staff  1679  8 19 05:13 privatekey.pem

3 CSR

上記の秘密鍵を使用して、CSR(Certificate Signing Request)を作成している様子です。

% openssl req -new -subj "/C=JP/ST=Hokkaido/L=Sapporo/O=MyCompany/CN=AWS IoT Certificate" -key privatekey.pem -out cert.csr
% ls -la cert.csr
-rw-r--r--  1 sin  staff  1001  8 19 05:27 cert.csr

ディスティングイッシュネームは、とりあえず、下記のようになってます。

O MyCompany
L Sapporo
ST Hokkaido
C JP
CN AWS IoT Certificate
% openssl req -text -noout -in cert.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = JP, ST = Hokkaido, L = Sapporo, O = MyCompany, CN = AWS IoT Certificate
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:aa:ac:84:30:fb:10:f8:c8:ab:fc:fe:86:97:7d:
                    9c:ca:71:af:e5:f4:b0:5b:42:86:b8:e5:36:06:ca:
                    b2:04:20:49:c5:93:b5:4c:c5:67:80:ff:e8:e5:c4:
                    f0:f7:ec:6b:6b:65:06:4c:ce:60:2b:db:a9:2c:6d:
                    d9:4f:aa:a8:67:96:56:46:d4:8b:fe:f7:e5:09:77:
                    20:e7:a8:ea:4e:d0:4c:76:63:7d:89:ab:8c:71:6d:
                    87:9d:03:76:eb:53:ad:34:f7:08:ae:b8:98:21:ea:
                    74:a1:ad:a6:19:82:53:bc:6c:9d:09:a9:d6:af:bb:
                    67:51:b8:8c:08:c4:76:xx:xx:xx:1b:ee:f2:f8:30:
                    5a:2f:14:a4:d1:c4:9d:xx:xx:xx:04:02:98:82:4f:
                    8e:e1:36:16:6b:ef:8e:xx:xx:xx:38:70:6a:df:d8:
                    b0:ac:f6:c0:a8:d9:f6:xx:xx:xx:87:0b:b4:43:b9:
                    45:6c:2b:f2:2c:0c:14:xx:xx:xx:92:66:e1:c9:12:
                    61:3a:5a:1e:6f:ea:00:31:29:ee:d9:14:73:4c:c7:
                    b2:3f:bb:ce:86:45:f1:41:bc:0b:d6:b5:d7:c7:fa:
                    b9:d9:3a:9c:12:b8:a4:0c:1e:d2:4d:ed:18:a9:00:
                    60:77:f9:96:0b:7b:ff:6b:99:9b:ec:3e:3a:23:04:
                    af:a3
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         4d:2b:ab:c7:6f:67:52:7a:05:9b:f4:46:a6:64:2f:60:ef:52:
         dc:ab:23:21:bd:e1:40:61:28:22:b8:e4:ac:2c:f8:8b:35:d1:
         d2:b2:bd:57:ac:0c:c8:1b:40:fc:e2:aa:50:bb:ac:1e:47:0d:
         dd:b0:12:b6:b7:11:1e:27:9a:dc:50:69:03:8a:90:64:87:71:
         68:71:53:2d:2b:8e:bc:10:23:e9:4a:cf:de:78:88:2b:05:f5:
         09:1d:0c:e4:a9:a2:f2:4a:1b:54:5b:b5:53:1c:cd:5c:8e:7a:
         62:20:6e:9d:f1:61:6f:50:56:48:00:dd:eb:49:74:21:8d:ef:
         c3:f5:b1:f3:95:69:54:3e:xx:xx:xx:c9:2c:9b:93:35:f5:d9:
         84:48:9c:ba:71:3d:b1:3a:xx:xx:xx:38:8b:ba:97:22:53:95:
         2b:8d:27:57:b1:cd:a9:1f:xx:xx:xx:40:cb:ed:2e:01:68:f3:
         4f:d9:cd:3c:d2:bc:9d:5c:xx:xx:xx:8a:28:8c:7d:24:fc:9a:
         37:f1:24:3c:4f:f8:5c:07:xx:xx:xx:15:d5:b7:e6:ee:01:9b:
         02:ec:ad:ea:35:2c:e2:00:2a:60:cc:b6:5c:78:f6:42:ec:32:
         1c:06:89:5b:12:cd:2c:04:ad:c1:43:e1:a6:ac:a2:d0:fa:6d:
         d9:06:76:0d

4 レジストリへの登録

CSRによる作成を選択すると、ファイル選択となるので、作成したcert.csrを選択します。

ファイルアップロードをクリックすると証明書の作成が完了します。

証明書は、有効化して適当なポリシーを設定し、ダウンロードしてクライアントに配置しました。

% openssl x509 -text -noout -in 47f1008c07-certificate.pem.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4b:9f:1f:0e:07:6c:e9:aa:25:f7:18:89:9a:76:12:d0:39:98:e0:fc
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: OU = Amazon Web Services O=Amazon.com Inc. L=Seattle ST=Washington C=US
        Validity
            Not Before: Aug 18 20:29:23 2020 GMT
            Not After : Dec 31 23:59:59 2049 GMT
        Subject: C = JP, ST = Hokkaido, L = Sapporo, O = MyCompany, CN = AWS IoT Certificate
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:aa:ac:84:30:fb:10:f8:c8:ab:fc:fe:86:97:7d:
                    9c:ca:71:af:e5:f4:b0:5b:42:86:b8:e5:36:06:ca:
                    b2:04:20:49:c5:93:b5:4c:c5:67:80:ff:e8:e5:c4:
                    f0:f7:ec:6b:6b:65:06:4c:ce:60:2b:db:a9:2c:6d:
                    d9:4f:aa:a8:67:96:56:46:d4:8b:fe:f7:e5:09:77:
                    20:e7:a8:ea:4e:d0:4c:76:63:7d:89:ab:8c:71:6d:
                    87:9d:03:76:eb:53:ad:34:f7:08:ae:b8:98:21:ea:
                    74:a1:ad:a6:19:82:xx:xx:xx:9d:09:a9:d6:af:bb:
                    67:51:b8:8c:08:c4:xx:xx:xx:cd:1b:ee:f2:f8:30:
                    5a:2f:14:a4:d1:c4:xx:xx:xx:1b:04:02:98:82:4f:
                    8e:e1:36:16:6b:ef:xx:xx:xx:97:38:70:6a:df:d8:
                    b0:ac:f6:c0:a8:d9:xx:xx:xx:5d:87:0b:b4:43:b9:
                    45:6c:2b:f2:2c:0c:14:a5:fb:62:92:66:e1:c9:12:
                    61:3a:5a:1e:6f:ea:00:31:29:ee:d9:14:73:4c:c7:
                    b2:3f:bb:ce:86:45:f1:41:bc:0b:d6:b5:d7:c7:fa:
                    b9:d9:3a:9c:12:b8:a4:0c:1e:d2:4d:ed:18:a9:00:
                    60:77:f9:96:0b:7b:ff:6b:99:9b:ec:3e:3a:23:04:
                    af:a3
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                keyid:4F:3F:CE:F8:54:34:D3:2A:C8:FA:67:F3:A1:C3:9F:1F:76:73:62:6B

            X509v3 Subject Key Identifier:
                A7:13:9D:B7:49:F7:6E:6D:55:04:AE:D9:5E:06:E7:33:13:89:8C:BF
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature
    Signature Algorithm: sha256WithRSAEncryption
         ac:4d:be:61:21:7d:c2:be:8d:80:02:8d:2c:3f:d8:03:57:d1:
         d6:d5:c2:69:9d:b2:a7:20:2c:83:f6:72:48:21:d1:dd:9e:4a:
         98:96:28:8a:2f:60:ec:d0:b7:20:9a:3c:e9:e7:e5:fc:03:5c:
         11:09:42:29:0b:2b:bf:70:31:5c:25:ac:a6:3a:5a:2f:40:2f:
         b7:f4:58:5f:aa:1f:94:f2:57:f3:f3:8b:cb:71:8b:7d:6c:8d:
         d6:96:fe:36:af:08:9d:4d:66:f0:48:aa:3f:1c:4f:45:23:79:
         48:e3:8b:b6:c0:b5:ad:42:xx:xx:xx:01:ee:b1:78:b3:c5:21:
         7f:3d:cf:6a:20:89:4a:09:xx:xx:xx:29:05:43:0b:5a:82:3f:
         af:5c:74:b3:d8:64:d7:85:xx:xx:xx:67:73:56:2f:f2:e7:11:
         36:b8:a4:6b:52:d8:b0:0d:xx:xx:xx:53:1e:0d:18:77:58:40:
         b2:51:21:17:92:bd:91:43:3e:cd:dc:d3:82:b6:ed:50:4d:d5:
         52:ff:11:f3:11:76:fe:4c:d7:d3:b0:bb:c7:aa:fe:b9:a3:f8:
         b7:68:7e:32:c6:03:a4:61:18:03:e7:d8:2a:75:c9:40:3c:b1:
         46:b6:ba:77:8e:b0:c9:fc:c0:10:2a:a5:aa:f8:ef:f6:4d:d5:
         ee:e1:cb:30

5 動作確認

動作確認に使用したコードは、以下の通りです。5秒に1回、カウント値をpublishしています。

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import time
import json

class Mqtt():
    def __init__(self, endPoint, port, rootCA, certificate, privateKey, clientId):
        self.__client = AWSIoTMQTTClient(clientId)
        self.__client.configureEndpoint(endPoint, port)
        self.__client.configureCredentials(rootCA, privateKey, certificate)
        self.__client.configureAutoReconnectBackoffTime(1, 32, 20)
        self.__client.configureOfflinePublishQueueing(-1)
        self.__client.configureDrainingFrequency(2)
        self.__client.configureConnectDisconnectTimeout(10)
        self.__client.configureMQTTOperationTimeout(5)
        try:
            self.__client.connect()
        except Exception as e:
            print("ERROR {}".format(e))

    def subscribe(self, topic, callback):
        self.__client.subscribe(topic, 1, callback)

    def publish(self, topic, payload):
        self.__client.publish(topic, payload, 1)

def callback(client, userdata, data):
    print(data.payload.decode("utf-8"))

def main():
    endPoint = "xxxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com"
    port = 8883
    rootCA = "./root-CA.crt"
    privateKey = "./privatekey.pem"
    certificate = "./47f1008c07-certificate.pem.crt"
    clientId = "client-001"
    topic = "topic_001"
    mqtt = Mqtt(endPoint, port, rootCA, certificate, privateKey, clientId)
    mqtt.subscribe(topic, callback)

    counter = 0
    while True:
        mqtt.publish(topic, json.dumps({
            "counter": counter
        }))
        counter += 1
        time.sleep(5)

main()

6 最後に

手順は、非常に簡単でした。

最初に書いたとおり、この要領では、秘密鍵の送達が必要ありません。また、既存の秘密鍵を使いまわしたい場合も利用可能かも知れません。