LoginSignup
1
2

IoT Coreの証明書でIAM Roles Anywhere的なことをする(アリかもしれない)

Last updated at Posted at 2023-10-21

前回、IAM Roles Anywhereの検証をしてとても良い機能だなと感じました。

そういえば、証明書を使った認証にIoT Coreがあったな🤔と思い出し、同じことができるかやってみました!試したところちょっとした違いがあり、IoT Coreでやるのもアリかもしれません。

手順

IAMロールを作成

  1. IoT Coreの認証情報プロバイダーが引き受けるIAMロールを作成します。
    信頼されたエンティティタイプをカスタム信頼ポリシーにし、信頼ポリシーに以下のJSONを入力します。

    {
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Principal": {
                "Service": "credentials.iot.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    }
    

    image.png

  2. 許可を追加で必要な権限を付与し次へをクリックします。

  3. ロールに名前をつけて保存します。(iot-roles-anywhere-role)としました。

IoT ロールエイリアスを作成

  1. IoT Coreの管理画面に移動し、管理メニュー -> セキュリティ -> ロールエイリアスを表示します。
    ロールエイリアスを作成をクリックします。

    image.png

  2. ロールエイリアスに名前をつけ、先程作成したロールを選択して、作成をクリックします。

    image.png

作成したロールエイリアスのARNをメモしておきます。

IoT ポリシーを作成

  1. 管理メニュー -> セキュリティ -> ポリシーへ移動します。
    ポリシーを作成をクリックします。

    image.png

  2. ポリシー名を入力します。
    ポリシードキュメントは以下を入力して、作成をクリックします。

    • ポリシー効果: 許可
    • ポリシーアクション:iot:AssumeRoleWithCertificate
    • ポリシーリソース:作成したロールエイリアスのARN

    image.png

IoT モノのグループを作成

  1. 管理メニュー -> すべてのデバイス -> モノのグループへ移動します。
    モノのグループを作成をクリックします。

    image.png

  2. モノの静的グループを作成を選択して、次へをクリックします。

  3. モノのグループ名を入力して、モノのグループを作成をクリックします。

  4. 作成したグループを選択して、ポリシータブを選択。ポリシーを管理をクリックします。

    image.png

  5. 先程作成したIoTポリシーを選択して、ポリシーの更新をクリックします。

image.png

IoT モノを作成

  1. 管理メニュー -> すべてのデバイス -> モノへ移動します。
    モノを作成をクリックします。

    image.png

  2. 1 つのモノを作成を選択し、次へをクリックします。

  3. モノの名前を入力して、先ほど作成したモノのグループを選択。次へをクリックします。

    image.png

  4. 新しい証明書を自動生成 (推奨)を選択して、次へをクリックします。

  5. ポリシーはグループに割り当てているので未選択のまま、モノを作成`をクリックします。

  6. デバイス証明書、パブリックキーファイル、プライベートキーファイル、RSA 2048 ビットキー: Amazon ルート CA 1をダウンロードしてから、続行をクリックします。

    image.png

認証情報プロバイダーエンドポイントを取得する

CloudShellなど
aws iot describe-endpoint --endpoint-type iot:CredentialProvider
{
    "endpointAddress": "abcdefghijklm.credentials.iot.ap-northeast-1.amazonaws.com"
}

一時認証情報を取得する

一時認証情報は認証情報プロバイダーエンドポイントにリクエストを送信して取得します。

export ENDPOINT=abcdefghijklm.credentials.iot.ap-northeast-1.amazonaws.com
export ROLE_ALIAS_NAME=alias-for-roles-anywhere
export CERT_PATH=certificate.pem.crt
export PRIVATE_KEY_PATH=private.pem.key
export THING_NAME=client1
export CA_CERT_PATH=AmazonRootCA1.pem

curl \
 --cert ${CERT_PATH} \
 --key ${PRIVATE_KEY_PATH} \
 -H "x-amzn-iot-thingname: ${THING_NAME}" \
 --cacert ${CA_CERT_PATH} \
 https://${ENDPOINT}/role-aliases/${ROLE_ALIAS_NAME}/credentials
{
  "credentials": {
    "accessKeyId": "...",
    "secretAccessKey": "...",
    "sessionToken": "...",
    "expiration": "2023-10-21T09:45:03Z"
  }
}

credential_process の仕組みに合わせる

もうちょいです。

認証情報プロバイダーエンドポイントの出力をcredential_processのフォーマットに変換します。

credential_processのフォーマット
{
  "Version": 1,
  "AccessKeyId": "an AWS access key",
  "SecretAccessKey": "your AWS secret access key",
  "SessionToken": "the AWS session token for temporary credentials", 
  "Expiration": "ISO8601 timestamp when the credentials expire"
}
  • Versionを追加
  • 各キーの先頭を大文字にする

先程の出力をパイプでjqに繋いで変換します。

export ENDPOINT=abcdefghijklm.credentials.iot.ap-northeast-1.amazonaws.com
export ROLE_ALIAS_NAME=alias-for-roles-anywhere
export CERT_PATH=certificate.pem.crt
export PRIVATE_KEY_PATH=private.pem.key
export THING_NAME=client1
export CA_CERT_PATH=AmazonRootCA1.pem

curl \
 --cert ${CERT_PATH} \
 --key ${PRIVATE_KEY_PATH} \
 -H "x-amzn-iot-thingname: ${THING_NAME}" \
 --cacert ${CA_CERT_PATH} \
 https://${ENDPOINT}/role-aliases/${ROLE_ALIAS_NAME}/credentials \
 | jq '.credentials | {"Version":1, "AccessKeyId":.accessKeyId, "SecretAccessKey":.secretAccessKey, "SessionToken":.sessionToken, "Expiration":.expiration}'

{
  "Version": 1,
  "AccessKeyId": "...",
  "SecretAccessKey": "...",
  "SessionToken": "...",
  "Expiration": "2023-10-21T09:52:49Z"
}

いい感じです。
うまく行ったのでこいつをシェルスクリプトにして保存します。

credential-helper.sh
#!/bin/sh
ENDPOINT=ce4kc59ulqnzy.credentials.iot.ap-northeast-1.amazonaws.com
ROLE_ALIAS_NAME=alias-for-roles-anywhere
CERT_PATH=certificate.pem.crt
PRIVATE_KEY_PATH=private.pem.key
THING_NAME=client1
CA_CERT_PATH=AmazonRootCA1.pem

curl \
 --cert ${CERT_PATH} \
 --key ${PRIVATE_KEY_PATH} \
 -H "x-amzn-iot-thingname: ${THING_NAME}" \
 --cacert ${CA_CERT_PATH} \
 https://${ENDPOINT}/role-aliases/${ROLE_ALIAS_NAME}/credentials \
 | jq '.credentials | {"Version":1, "AccessKeyId":.accessKeyId, "SecretAccessKey":.secretAccessKey, "SessionToken":.sessionToken, "Expiration":.expiration}'

最後に.aws/configに登録します。

.aws/config
[profile iotrolesanywhere]
credential_process = sh <<credential-helper.shのフルパス指定>>

AWSコマンドを実行します。

aws sts get-caller-identity --profile iotrolesanywhere
{
    "UserId": "...",
    "Account": "...",
    "Arn": "arn:aws:sts::...:assumed-role/iot-roles-anywhere-role/..."
}

やったぜ

IAM Roles Anywhereとの違い

良いと思った点

  • IoT Coreだと証明証が無料でマネージド!
    IAM Roles AnywhereではAWS Private CA(有料)もしくは自前管理のプライベートCAが必要
  • 証明書の失効も簡単!

残念な点

  • なんでIoTやねん感
    • しっかりルールを明文化して管理しないと後々困りそう

参考

おまけ

AWS発行のIoT Coreの証明書に使われているRootCA証明書をIAM Roles Anywhereで使おうとするとエラーになりました😝

image.png

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2