Share via


チュートリアル: Azure Device Provisioning Service を Github Actions で自動化する

GitHub Actions のような自動化ツールを使用して、IoT デバイスのライフサイクルを管理します。 このチュートリアルでは、Azure Device Provisioning Service (DPS) を使用してデバイスを IoT ハブに接続する GitHub Actions ワークフローについて説明します。

このチュートリアルでは、以下の内容を学習します。

  • 認証資格情報をリポジトリ シークレットとして保存します。
  • IoT Hub と Device Provisioning Service のリソースをプロビジョニングするワークフローを作成します。
  • ワークフローを実行し、シミュレートされたデバイスが IoT Hub に接続するのを監視します。

前提条件

  • Azure サブスクリプション

    Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。

  • Azure CLI

    • Azure Cloud Shell で Bash 環境を使用します。

    • CLI リファレンス コマンドをローカルで実行したい場合は、Azure CLI をインストールしてください。 Windows または macOS で実行している場合は、Docker コンテナーで Azure CLI を実行することを検討してください。

      • ローカル インストールを使用する場合は、az login コマンドを使用して Azure CLI にサインインします。

      • az version を実行し、インストールされているバージョンおよび依存ライブラリを検索します。 最新バージョンにアップグレードするには、az upgrade を実行します。

  • 自分が所有するリポジトリと管理者アクセス権があるリポジトリのいずれかを持つ GitHub アカウント。 詳細については、「Github で開始する」を参照してください。

1 - リポジトリ シークレットの作成

次のセクションで定義するワークフローでは、リソースを作成および管理するために Azure サブスクリプションにアクセスする必要があります。 この情報を保護されていないファイルに置くと発見される可能性があるので、代わりにリポジトリ シークレットを使用してこの情報を保管しつつ、ワークフローで環境変数としてアクセスできるようにしましょう。 詳細については、「暗号化されたシークレット」を参照してください。

リポジトリ シークレットを管理できるのは、リポジトリの所有者と管理者だけです。

サービス プリンシパルの作成

個人のアクセス資格情報を提供するのではなく、サービス プリンシパルを作成し、それらの資格情報をリポジトリ シークレットとして追加することにします。 Azure CLI を使用して、新しいサービス プリンシパルを作成します。 詳細については、Azure サービス プリンシパルの作成に関するページを参照してください。

  1. az ad sp create-for-rbac コマンドを使用して、特定のリソース グループに対する contributor のアクセス権を持ったサービス プリンシパルを作成します。 <SUBSCRIPTION_ID><RESOURCE_GROUP_NAME> は、実際の情報に置き換えてください。

    このコマンドには、サブスクリプションの所有者またはユーザー アクセス管理者ロールが必要です。

    az ad sp create-for-rbac --name github-actions-sp --role contributor --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME>
    
  2. 次のセクションで使用するために、サービス プリンシパル作成コマンドの出力から次の項目をコピーします。

    • clientId
    • clientSecret。 これはサービス プリンシパル用に生成されたパスワードであり、後で確認することはできません。
    • tenantId
  3. az role assignment create コマンドを使用して、"Device Provisioning Service データ共同作成者" および "IoT Hub データ共同作成者" の 2 つの追加アクセス ロールをサービス プリンシパルに割り当てます。 <SP_CLIENT_ID> は、前のコマンドの出力からコピーした clientId の値に置き換えます。

    az role assignment create --assignee "<SP_CLIENT_ID>" --role "Device Provisioning Service Data Contributor" --resource-group "<RESOURCE_GROUP_NAME>"
    
    az role assignment create --assignee "<SP_CLIENT_ID>" --role "IoT Hub Data Contributor" --resource-group "<RESOURCE_GROUP_NAME>"
    

サービス プリンシパルの資格情報をシークレットとして保存する

  1. GitHub.com で、リポジトリの [設定] に移動します。

  2. ナビゲーション メニューから [シークレット] を選択して、[アクション] を選択します。

  3. [New repository secret](新しいリポジトリ シークレット) を選択します。

  4. サービス プリンシパル ID のシークレットを作成します。

    • 名前: APP_ID
    • シークレット: サービス プリンシパル作成コマンドの出力からコピーした clientId を貼り付けます。
  5. [シークレットの追加] を選択し、[新しいリポジトリ シークレット] を選択して 2 つ目のシークレットを追加します。

  6. サービス プリンシパル パスワードのシークレットを作成します。

    • 名前: SECRET
    • シークレット: サービス プリンシパル作成コマンドの出力からコピーした clientSecret を貼り付けます。
  7. [シークレットの追加] を選択し、[新しいリポジトリ シークレット] を選択して最後のシークレットを追加します。

  8. Azure テナントのシークレットを作成します。

    • 名前: TENANT
    • シークレット: サービス プリンシパル作成コマンドの出力からコピーした tenantId を貼り付けます。
  9. [Add secret](シークレットの追加) を選択します。

2 - ワークフローを作成する

GitHub Actions の"ワークフロー"は、"イベント"によってトリガーされたとき実行されるタスクを定義します。 ワークフローには 1 つ以上の"ジョブ"が含まれており、これらは順次に、または並列で実行できます。 詳細については、GitHub Actions の理解に関するページを参照してください。

このチュートリアルでは、以下の各タスクのジョブを含むワークフローを 1 つ作成します。

  • IoT Hub インスタンスと DPS インスタンスをプロビジョニングします。
  • IoT Hub と DPS のインスタンスを相互にリンクします。
  • DPS インスタンスに個別の登録を作成し、対称キー認証を使用して DPS 登録で IoT ハブにデバイスを登録します。
  • デバイスを 5 分間シミュレートし、IoT ハブのイベントを監視します。

ワークフローは、リポジトリの .github/workflows/ ディレクトリにある YAML ファイルです。

  1. GitHub リポジトリで、[アクション] タブに移動します。

  2. [アクション] ウィンドウで、[新しいワークフロー] を選択します。

  3. [ワークフローの選択] ページでは、使用する事前構築済みテンプレートを選択できます。 このチュートリアルで独自のワークフローを作成するため、[自分で ワークフローを設定する] を選択します。

  4. GitHub によって新しいワークフロー ファイルが自動的に作成されます。 .github/workflows/ ディレクトリにあることに注目してください。 新しいファイルに、dps-tutorial.yml のようなわかりやすい名前を付けます。

  5. name パラメーターを追加して、ワークフローに名前を付けます。

    name: DPS Tutorial
    
  6. on.workflow_dispatch パラメーターを追加します。 on パラメーターは、ワークフローがいつ実行されるかを定義します。 workflow_dispatch パラメーターは 、ワークフローを手動でトリガーすることを示します。 このパラメーターで、ワークフローへ各実行時に渡される inputs を定義することができますが、このチュートリアルでは使用しません。

    on: workflow_dispatch
    
  7. ワークフローで作成しているリソースの環境変数を定義します。 これらの変数は、ワークフロー内のすべてのジョブで利用可能になります。 環境変数を個々のジョブや、ジョブ内の個々のステップに定義することもできます。

    プレースホルダーの値は、実際の値に置き換えます。 サービス プリンシパルがアクセスできるリソースグループと同じものを指定するようにしてください。

    env:
      HUB_NAME: <Globally unique IoT hub name>
      DPS_NAME: <Desired Device Provisioning Service name>
      DEVICE_NAME: <Desired device name>
      RESOURCE_GROUP: <Solution resource group where resources will be created>
    
  8. 前のセクションで作成したシークレットの環境変数を定義します。

      SP_USER: ${{ secrets.APP_ID }}
      SP_SECRET: ${{ secrets.SECRET }}
      SP_TENANT: ${{ secrets.TENANT }}
    
  9. jobs パラメーターをワークフロー ファイルに追加します。

    jobs:
    
  10. ワークフローの最初のジョブを定義し、provision ジョブと呼ぶことにします。 このジョブは、IoT Hub と DPS のインスタンスをプロビジョニングします。

      provision:
        runs-on: ubuntu-latest
        steps:
          - name: Provision Infra
            run: |
              az --version
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az iot hub create -n "$HUB_NAME" -g "$RESOURCE_GROUP"
              az iot dps create -n "$DPS_NAME" -g "$RESOURCE_GROUP"
    

    このジョブで実行されるコマンドの詳細については、次を参照してください。

  11. DPS インスタンスと IoT Hub インスタンスを configure するジョブを定義します。 このジョブが使用する needs パラメーターに注目してください。つまり、configure ジョブは、一覧表示されたジョブがそれぞれの実行を正常に完了するまで実行されません。

      configure:
        runs-on: ubuntu-latest
        needs: provision
        steps:
          - name: Configure Infra
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az iot dps linked-hub create --dps-name "$DPS_NAME" --hub-name "$HUB_NAME"   
    

    このジョブで実行されるコマンドの詳細については、次を参照してください。

  12. register という名前のジョブを定義するとそれにより個々の登録が作成され、その登録を使用してデバイスを IoT Hub に登録します。

      register:
        runs-on: ubuntu-latest
        needs: configure
        steps:
          - name: Create enrollment
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot dps enrollment create -n "$DPS_NAME" --eid "$DEVICE_NAME" --attestation-type symmetrickey --auth-type login
          - name: Register device
            run: |
              az iot device registration create -n "$DPS_NAME" --rid "$DEVICE_NAME" --auth-type login   
    

    Note

    このジョブと他のジョブでは、一部のコマンドでパラメーター --auth-type login を使用して、現在の Microsoft Entra セッションのサービス プリンシパルを操作で使用する必要があることを示します。 代わりの --auth-type key ではサービス プリンシパルの構成は必要ありませんが、安全性は低くなります。

    このジョブで実行されるコマンドの詳細については、次を参照してください。

  13. IoT デバイスを simulate するジョブを定義し、このデバイスが IoT ハブに接続して、サンプルのテレメトリ メッセージを送信します。

      simulate:
        runs-on: ubuntu-latest
        needs: register
        steps:
          - name: Simulate device
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot device simulate -n "$HUB_NAME" -d "$DEVICE_NAME"
    

    このジョブで実行されるコマンドの詳細については、次を参照してください。

  14. イベントの IoT Hub エンドポイントを monitor するジョブを定義し、シミュレートされたデバイスから送られてくるメッセージを監視します。 シミュレート ジョブとモニター ジョブの両方で、needs パラメーターに登録ジョブが定義されていることに注目してください。 この構成は、登録ジョブが正常に完了すると、両方のジョブが並列で実行されることを意味します。

      monitor:
        runs-on: ubuntu-latest
        needs: register
        steps:
          - name: Monitor d2c telemetry
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot hub monitor-events -n "$HUB_NAME" -y   
    

    このジョブで実行されるコマンドの詳細については、次を参照してください。

  15. 完全なワークフロー ファイルは次の例のようになります。環境変数のプレースホルダー値があなたの情報で置き換えられています。

    name: DPS Tutorial
    
    on: workflow_dispatch
    
    env:
      HUB_NAME: <Globally unique IoT hub name>
      DPS_NAME: <Desired Device Provisioning Service name>
      DEVICE_NAME: <Desired device name>
      RESOURCE_GROUP: <Solution resource group where resources will be created>
      SP_USER: ${{ secrets.APP_ID }}
      SP_SECRET: ${{ secrets.SECRET }}
      SP_TENANT: ${{ secrets.TENANT }}
    
    jobs:
      provision:
        runs-on: ubuntu-latest
        steps:
          - name: Provision Infra
            run: |
              az --version
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az iot hub create -n "$HUB_NAME" -g "$RESOURCE_GROUP"
              az iot dps create -n "$DPS_NAME" -g "$RESOURCE_GROUP"
      configure:
        runs-on: ubuntu-latest
        needs: provision
        steps:
          - name: Configure Infra
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az iot dps linked-hub create --dps-name "$DPS_NAME" --hub-name "$HUB_NAME"
      register:
        runs-on: ubuntu-latest
        needs: configure
        steps:
          - name: Create enrollment
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot dps enrollment create -n "$DPS_NAME" --eid "$DEVICE_NAME" --attestation-type symmetrickey --auth-type login
          - name: Register device
            run: |
              az iot device registration create -n "$DPS_NAME" --rid "$DEVICE_NAME" --auth-type login
      simulate:
        runs-on: ubuntu-latest
        needs: register
        steps:
          - name: Simulate device
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot device simulate -n "$HUB_NAME" -d "$DEVICE_NAME"
      monitor:
        runs-on: ubuntu-latest
        needs: register
        steps:
          - name: Monitor d2c telemetry
            run: |
              az login --service-principal -u "$SP_USER" -p "$SP_SECRET" --tenant "$SP_TENANT"
              az extension add --name azure-iot
              az iot hub monitor-events -n "$HUB_NAME" -y
    
  16. この新しいファイルを保存してコミットし、GitHub リポジトリにプッシュします。

3 - ワークフローを実行する

  1. GitHub リポジトリの [アクション] タブに移動します。

  2. [アクション] ウィンドウで、ワークフロー ファイルで定義した名前である [DPS チュートリアル] を選択し、[ワークフローの実行] ドロップダウン ボックスを選択します。

    Screenshot of the action tab where you can select a workflow and run it.

  3. main 以外のブランチでワークフローを作成した場合はブランチを変更して、[ワークフローの実行] を選択します。

  4. 新しいワークフロー実行が進行中に表示されます。 名前を選択すると、その実行の詳細が表示されます。

  5. ワークフロー概要では、各ジョブの開始と完了を確認できます。 ジョブ名を選択するとその詳細が表示されます。 シミュレートされたデバイス ジョブは 5 分間実行されて、テレメトリを IoT Hub に送信します。 この間に、デバイスから送信されているメッセージを監視するシミュレート ジョブと、これらのメッセージが IoT Hub によって受信されるのを監視するモニター ジョブを選択します。

  6. すべてのジョブが正常に完了すると、それぞれに緑色のチェックマークが表示されます。

    Screenshot of a successfully completed workflow.

リソースをクリーンアップする

このチュートリアルで作成したこれらのリソースを引き続き使用する予定がなければ、次の手順で削除します。

Azure CLI を使用する場合:

  1. リソース グループ内のリソースを一覧表示します。

    az resource list --resource-group <RESOURCE_GROUP_NAME>
    
  2. 個々のリソースを削除するには、リソース ID を使用します。

    az resource delete --resource-group <RESOURCE_GROUP_NAME> --ids <RESOURCE_ID>
    
  3. リソース グループ全体とその中のすべてのリソースを削除したい場合は、次のコマンドを実行します。

    az group delete --resource-group <RESOURCE_GROUP_NAME>
    

Azure portal を使用する:

  1. Azure portal で、新しいリソースを作成したリソース グループに移動します。
  2. リソース グループ全体を削除するか、削除する個々のリソースを選択してから [削除] を選択します。

次のステップ

他の自動化ツールを使用して DPS インスタンスをプロビジョニングする方法について説明します。