🆔

Azure DevOps と Azure をマネージド IDで連携する (2/2)

2023/11/21に公開

はじめに

今回は、マネージド ID を利用して、Azure DevOps と Azure コンポーネントを連携したいと思います。Azure DevOps には REST API が提供されており、下記のようにいくつかの認証方式がありますが、本記事では マネージド ID に焦点を当てていきたいと思います。
後編 Logic Apps の記事となります。

前編はこちらを参照ください。
https://zenn.dev/yutakaosada/articles/39890c09bdcda2

方式 説明
Personal Access Tokens (PATs) 最も一般的な認証方法の1つです。Azure DevOps Servicesで独自のトークンを作成し、それを使用してAPIにアクセスします。これらのトークンは特定の権限と有効期限を持ち、安全にAPIを呼び出すために使用されます。
Basic Authentication 資格情報(ユーザー名とパスワード、またはPersonal Access Token)をHTTPヘッダーに埋め込む方法です。ただし、この方法は安全性の観点から推奨されません。使用する場合は、HTTPS経由でのみAPIを呼び出す必要があります。
Entra ID Integrated Authentication Azure DevOps ServicesとEntra IDを連携させることで、Entra IDの認証機能を使用してAPIにアクセスすることができます。
OAuth 2.0 Azure DevOps ServicesはOAuth 2.0をサポートしており、サードパーティのアプリケーションがユーザーの代わりにAzure DevOps Servicesにアクセスすることを許可します。
マネージド ID Azureのマネージド IDは、Azureリソースに自動的にアクセスするための資格情報を提供するサービスです。この方式を使用することで、Azure DevOps と他のAzureリソース間の認証やアクセス管理を自動化し、セキュリティを高めることができます。資格情報のローテーションや管理が不要になり、開発者や運用チームがセキュリティを維持しながら、簡単にリソースにアクセスできるようになります。

PAT や ServicePrincipal を利用した実装イメージは、前回の記事をご参照ください。
https://zenn.dev/yutakaosada/articles/1a61b2741e0644

なお、今回の検証についての Azure 側のコンポーネントは下記を利用します。

# コンポーネント 用途
1 Resource Groups Azure ソリューションの関連するリソースを保持するコンテナ
2 Logic Apps クラウド上でビジネスプロセスの自動化を簡単に実現するサービス

本記事の Azure Bicep の ソースコードは、Gitに登録しています。

https://github.com/yutaka-art/AzDORestApiInspections

今回肝となる、マネージド ID の詳細については下記のドキュメントを参照ください。
https://learn.microsoft.com/ja-jp/entra/identity/managed-identities-azure-resources/overview

では後編をはじめていきます。

アーキテクチャ構成

アーキテクチャ構成はこんな感じです。

Azure コンポーネントの作成

各種コンポーネントを Azure CLI と Bicep を利用して作成していきます。

まずはリソースグループを作成します。

cli
az group create --name rg-zenn-92c051f79f4b79 --location japaneast

リソースグループが作成されるとAzure Portalではこんな感じに見えます

次にリソースグループの中にリソースを作成していきます。

Bicep を使って、マネージド ID をデプロイします。managedIdentity.bicep では、マネージド IDのリソースのみを定義します。
マネージド ID を作成してからでないと、Logic Apps に マネージド ID を関連付けることができないため、output パラメータを出力させ、次の logicapps.bicep のコードの中でそのパラメータを指定することで、依存関係が発生しデプロイの順序が担保されます。

managedIdentity.bicep
param environmentName string = 'zenn-92c051f79f4b79'
param managedIdName string = 'id-${environmentName}'
param location string = resourceGroup().location

// Managed Identity
resource managedId 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
  name: managedIdName
  location: location
}

output outManagedIdName string = managedId.name

続いて、logicapps.bicep では、Logic Apps のリソースを定義します。マネージド ID を動的に関連付けている部分がポイントです。

logicapps.bicep
param environmentName string = 'zenn-92c051f79f4b79'
param subscriptionId string = '{your subscription id}'
param logicAppsName string = 'logic-${environmentName}'
param managedIdName string = 'id-${environmentName}'
param location string = resourceGroup().location

resource logicApps 'Microsoft.Logic/workflows@2019-05-01' = {
  name: logicAppsName
  location: location
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${managedIdName}': {
      }
    }
  }
  properties: {
    state: 'Enabled'
    definition: {
      '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#'
      contentVersion: '1.0.0.0'
      parameters: {
      }
      triggers: {
        request: {
          type: 'Request'
          kind: 'Http'
          inputs: {
            schema: {
              properties: {
                itemid: {
                  type: 'string'
                }
                organization: {
                  type: 'string'
                }
                project: {
                  type: 'string'
                }
              }
              type: 'object'
            }
          }
        }
      }
      actions: {
        'HTTP:Azure_DevOps_Rest_API_Workitem取得': {
          runAfter: {
          }
          type: 'Http'
          inputs: {
            authentication: {
              audience: '499b84ac-1321-427f-aa17-267ca6975798'
              identity: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/${managedIdName}'
              type: 'ManagedServiceIdentity'
            }
            headers: {
              'Content-Type': 'application/json-patch+json'
            }
            method: 'GET'
            uri: 'https://dev.azure.com/@{triggerBody()?[\'organization\']}/@{triggerBody()?[\'project\']}/_apis/wit/workitems/@{triggerBody()?[\'itemid\']}?api-version=7.1-preview.3'
          }
        }
        Response: {
          runAfter: {
            'HTTP:Azure_DevOps_Rest_API_Workitem取得': [
              'Succeeded'
            ]
          }
          type: 'Response'
          inputs: {
            body: '@body(\'HTTP:Azure_DevOps_Rest_API_Workitem取得\')'
            statusCode: 200
          }
        }
      }
      outputs: {
      }
    }
    parameters: {
    }
  }
}

main02.bicep では、それぞれの Bicep ファイルをモジュールとして定義します。

main02.bicep
param environmentName string = 'zenn-92c051f79f4b79'
param subscriptionId string = '{your subscription id}'
param location string = resourceGroup().location

// Managed Identity
module managedId 'managedIdentity.bicep' = {
  name: 'managedId'
  params: {
    environmentName: environmentName
    location: location
  }
}

// Logic Apps
module LogicApps 'logicapps.bicep' = {
  name: 'LogicApps'
  params: {
    environmentName: environmentName
    managedIdName: managedId.outputs.outManagedIdName
    subscriptionId: subscriptionId
    location: location
  }
}

Azure CLI を使って、デプロイします。

cli
az deployment group create --resource-group rg-zenn-92c051f79f4b79 --template-file deploy/main02.bicep --parameters environmentName=zenn-92c051f79f4b79 subscriptionId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

作成されたリソースはこんな感じです。

いずれも、Azure Portal から ノーコード で直接作成することもできます。

マネージド ID を Azure DevOps へ設定

設定方法は、前回記事の 4. マネージド ID を Azure DevOps へ設定 を参照ください。
https://zenn.dev/yutakaosada/articles/39890c09bdcda2#4.-マネージド-id-を-azure-devops-へ設定

Azure DevOps REST APIとの連携: Logic Apps の HTTP コネクタ認証方法

Logic Apps の HTTP コネクタを利用して、Azure DevOps Rest API を呼び出している例です。
認証タイプとしてマネージドIDを選択した場合、対象ユーザはAzure DevOpsのCoreサービスIDである 499b84ac-1321-427f-aa17-267ca6975798 に固定されます。

マネージド ID を使用する際は、認可プロセスのためにトークン取得が必要ですが、HTTP コネクタを使用すると、このプロセスが Logic Apps によって内部的に処理されます。これにより、手動でのトークン管理の必要がなく、処理が簡素化されます。Logic Appsは自動的に必要なトークンを取得し、管理するため、開発者は API のコールに集中できます。

動かしてみる

デプロイした Logic Apps を起動し、Azure DevOps より、WorkItem が取得できるか確認していきましょう。

作成した、Logic Apps を開き、ペイロードロードで実行をクリックし、右側にパラメータを指定します。存在する workitemid、Oraganization、Project を指定し、実行します。

json
{
    "itemid": "705",
    "organization": "osatest",
    "project": "Alpha"
}

マネージド ID を経由して Azure DevOps Rest API が実行されるとレスポンスが返却されます。

まとめ

この記事では、マネージドID を利用して Azure DevOps と Azure コンポーネントを連携する方法について見ていきました。具体的には、Azure DevOps の REST API との連携に焦点を当て、様々な認証方式(PAT、基本認証、Entra ID OAuth 2.0、マネージド ID)の中で マネージド ID の利用法を深堀りしました。

主要なポイント(サマリ)は下記の通りです。

  • マネージド ID の優位性:Azureのマネージド ID を使用することで、Azure DevOpsと他のAzureリソース間の認証やアクセス管理を自動化し、セキュリティを強化することができます。

  • Azure コンポーネントのデプロイ:Azure CLI と Bicep を使用して、リソースグループや Logic Appsなどの Azure コンポーネントを効率的にデプロイしました。

  • Logic Apps との連携:Logic Apps の HTTP コネクタを使用して Azure DevOps REST API を呼び出し、マネージドID を利用した認証方法を採用しました。この方法では、トークンの取得と管理が自動化され、開発者は API の呼び出しに集中できます。

  • 実践的な適用:実際に Logic Apps をデプロイし、 Azure DevOps から WorkItem を取得するプロセスを実行しました。これにより、マネージド ID を利用した Azure DevOps との効果的な連携が実証されました。

このシリーズの前編と後編を通じて、Azure DevOps と Azure の間での マネージドID を用いたセキュアな連携方法を詳細に説明しました。読んでいる方がこの記事を通じて、Azure のリソース管理とDevOps プロセスの両方において、セキュリティと効率性を高める方法の参考になりましたら幸いです。

References

https://learn.microsoft.com/ja-jp/azure/devops/integrate/get-started/authentication/service-principal-managed-identity?view=azure-devops

https://learn.microsoft.com/ja-jp/rest/api/azure/devops/?view=azure-devops-rest-7.2

GitHubで編集を提案

Discussion