Azure DevOpsでサービスコネクションを作ってAzureテナントを跨いでAzureのリソースを使用する
テナントを跨いでAzure DevOpsからAzureのリソースにアクセスしたい
Azure DevOpsでサービスコネクションを作ってAzureテナントを跨いでサービスプリンシパルを使用する方法を紹介します。
こんな感じでソースコードを管理しているAzure DevOpsをホストしているAzureテナントと、Azureのリソースを管理しているテナントが違うのでコンテナアプリのデプロイができなかったりCD piepleineが作れなくて困ってる(´;ω;`)というご相談を頂きました。
- ソースコードを管理しているAzure DevOpsのProject Alpha, BravoはテナントAというAzureのテナントでホストされている
- Azure DevOps以外のAzureリソースはテナントBという別のAzureのテナントでホストされている
- テナントAでは色んな事情で権限がなくて、サービスプリンシパルが作れない。
- ソースコード管理&コラボレーションをしているAzure DevOpsのテナントとAzureリソースを管理&運用しているテナントが違うので、コンテナアプリのリビジョン作成とかデプロイができないとか、CD pipeline作れなくて困ってるのでどうにかしたい
Azure DevOpsでAzureのリソースを使う:同一テナントの場合
Azure DevOpsでAzureのリソースを使用するには、ざっくり以下のようなステップでサービスプリンシパルを作成してAzure DevOpsのpipelineで利用したりすることができます。
- Azureでサービスプリンシパルを作成する
- Azure DevOpsのOrganization Settingsで作成したサービスプリンシパルをUserとして登録する
- Pipelineの中でサービスプリンシパルに対してアクセストークンをリクエストして、そのトークンを使ってサービスプリンシパルが作成されているAzureのリソースにアクセスする
Azure DevOpsでのサービスプリンシパルの利用については、こちらのdocsを参考にして下さい。
また、こちらの記事ではサービスプリンシパルをAzure DevOpsで利用する方法と、C#でサービスプリンシパルを利用してAzure DevOps REST APIを操作する方法がめちゃくちゃわかりやすく記載されています。
※Azureでサービスプリンシパルを作成するには、最低でもEntraの管理者からEntraでのアプリの登録が許可されている必要があります。
アプリの登録と必要な権限に関して、詳細はこちらのdocsをご覧ください。
Azure DevOpsのテナントの向き先を変えてみよう
Azure DevOpsのOrganization Settings > General > Azure Active Directoryにいけば今接続されていAzure ADのテナントの確認と、Swtich directoryで変更ができるので、これでAzure DevOpsをホストしているテナントの向き先を変えればよいのでは?ともなりましたが、今回のご相談では現在のテナントで権限がなくてテナントの向き先変えるのはダメでした。
いっそのことテナントを寄せてしまう?
一番いいのはAzure DevOpsをテナントBに移して、Azureのリソース管理・運用とAzure DevOpsのホストも全部テナントBでやってしまうのが一番構成としてはすっきりしますが、その場合Azure DevOpsの全リソース(ソースコード、Boards、etc...)のお引越しが必要になり、結構大変です。
work itemをお引越しさせるツールはあるものの、結構インパクトが大きい、、、
サービスコネクションを使ってテナント跨ぎでサービスプリンシパルを使う
今回はこんな感じでサービスコネクションとサービスプリンシパルを作成して、Azure DevOpsでテナントを跨いでテナントBのAzureリソースにアクセスするようにしてみます。
- Azureのリソース管理・運用を行っているテナントBで、テナントBのAzureリソースにアクセス
できるサービスプリンシパルを作成 - テナントAでホストされているAzure DevOpsのProject Alphaで、テナントBのサービスプリンシパルへのサービスコネクションを作成して、それを経由してテナントを跨いでAzureリソースにアクセス
テナントBでサービスプリンシパルを作成する
ではまずAzureのリソース管理・運用をしているテナントBでサービスプリンシパルを作ります。
Azure portalにサインインして、Microsoft Entra IDを選択
左メニューで「アプリの登録」を選択
「アプリケーションの登録」で「名前」でサービスプリンシパルの名称を入力して、「登録」を押下
サービスプリンシパルができます。
「証明書とシークレット」を選択して、このサービスプリンシパルを使用するためのシークレットを定義します。
「クライアントシークレット」を選択して、「新しいクライアントシークレット」を選択
クライアントシークレットの説明と有効期限を設定して「追加」を押下
※Max2年まで設定可能
クライアントシークレットが作成される。
この「値」をシークレットキーとしてAzure DevOpsでサービスコネクションを作成する際に使用するので、コピーして大事に保存してください。
アクセス許可を設定する
作成したサービスプリンシパルにリソースへのアクセス許可を与えます。
サービスプリンシパルの「APIのアクセス許可」にいって、「アクセス許可の追加」を選択します。
「APIアクセス許可の要求」で使用したいリソースへのアクセス許可を構成します。
これで、サービスプリンシパルに対してリソースのアクセス許可を与えることができます。
サブスクリプションにサービスプリンシパルに対する使用権限を与える
サービスプリンシパルを作成したので、それを使えるようにサブスクリプションに対して権限を与えてサービスプリンシパルを使用できるようにします。
Azure portal > サブスクリプション > 使用中のサブスクリプションを選択 > アクセス制御(IAM) > ロールの割り当て に移動
「+追加 」から「ロールの割り当て」を選択
「特権管理者ロール」のタブを選択。
ここでの与えるロールは、以下の記事に従って「共同作成者(Contributer)」しておきます。
※サービスプリンシパルにはContributorロールが割り当てられるから、サブスクで権限与える場合もContibutorがいいでしょう
「アクセスの割り当て先」で「ユーザー、グループ、またはサービスプリンシパル」を選択
「メンバーを選択」を押下、作成したサービスプリンシパルを検索して選択し、「選択」を押下
「レビューと割り当て」を押下
これでサービスプリンシパルにContributor(共同作成者)のロールの割り当てが完了しました。
このサービスプリンシパルを使うことによって、テナントBのAzureリソースへのアクセスができるようになります。
Other Option: Resource Group単位でサービスプリンシパルに対する権限を与える
Infra Engineerの方から「サブスク単位だと権限が広すぎるのでリソースグループ単位で権限付与はできますか?」というお問い合わせがあったので検証してみました。
サブスク単位ではなくRG単位でロールの割り当てをしたい場合、サブスクにロールを与えたときと同じステップで、対象のリソースグループの「アクセス制御(IAM)」で「ロールの割り当て」を選択して、サービスプリンシパルに共同作成者のロールを与えてください。
Azure DevOpsでARMのサービスコネクションを作成してサービスプリンシパルと接続する
テナントBでのサービスプリンシパルの作成と権限割り当てまでいけたので、テナントAのAzure DevOpsでテナントBに作ったサービスプリンシパルへのサービスコネクションを作成します。
用意するもの:
- テナントBで作ったサービスプリンシパルのアプリケーションID
- サービスプリンシパルのID
- サービスプリンシパルのシークレット(作ったときに大事に保存しないと二度と表示されないやつ)
- サービスプリンシパルの作成を行ったAzureのサブスクリプションのIDと名前
- テナントBのテナントID
Microsoft Entra > アプリの登録 > すべてのアプリケーション > 作成したサービスプリンシパルを選択。1, 5は概要の箇所で取得できる
2はサービスプリンシパルの 証明書とシークレット> クライアントシークレットの箇所で取得できる。
4はAzure portal > サブスクリプションで、使用中のサブスクリプションを選択すると表示されるのでここから取得
Azure DevOpsのProject Settings > Piepelines > Service Connectionsに移動
New Service Connectionを押下
Azure Resource Managerを選択して次へ
Service principal(manual)を選択して次へ
以下のように設定する
Service connection nameでサービスコネクションの名称を、
Descriptionにサービスコネクションの説明を記載。
全て設定したら、Verifyで接続を検証します。
成功するとこうなります!
verify and Saveで保存してください。
できました。
サービスコネクションの使用
実際テナント跨いでApp Serviceにデプロイの検証、まで行きたかったですが力尽きたのでまた今度、、、<m(__)m>
とりあえずこちらのdocsに使い方が書いてあったので置いておきます
こんな感じでサービスコネクション名をpipelineのymlのazureSubscriptionでサービスコネクション名指定して使うみたいです。
ちなみに、サービスプリンシパルを使う場合は、こんな感じでサービスコネクションに対してリクエストを投げて、返ってきたトークンを使うことによってリソースへのアクセスができます。
curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token \ #サービスプリンシパルがいるテナントのIDを指定
-d 'client_id=<client-id>' \ #サービスプリンシパルのIDを指定
-d 'grant_type=client_credentials' \
-d 'scope=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d%2F.default' \
-d 'client_secret=<client-secret>' #サービスプリンシパルのキーを指定
これのレスポンスで、こんな感じでaccess_token
でtokenが返ってくるので、これを使います。
サービスコネクションを作らないでテナント跨いでサービスプリンシパルの使用はできないんですか?
できます。できますが、それをするにはサービスプリンシパルをゲストユーザーとしてAzure DevOpsのOrganizationに追加する必要があります。
(同一テナントでサービスプリンシパルをAzure DevOpsで使用する際にもそうする。このステップによってサービスプリンシパルはmanaged identityとして機能し、Azure上のサービスプリンシパルとAzure DevOpsとの連携が実現される。詳しくはこちらをCheck)
そのためには、両方のテナントでそこそこ強い権限(おそらく最低でもアクセス許可管理の管理者)が必要になります。
別テナントにいるサービスプリンシパルを使って、Azure DevOpsのOrganization/Projectにいるソースの同期はできますか?
この部分ですね。
理論的には、ソースがいるOrganizationにUserとしてサービスプリンシパルを追加することができれば、他のユーザーと同様にAzure DevOpsのアイデンティティとして機能します。
ユーザー追加の際に、Basic、Project Contribuorのアクセス権を与えれば、そのサービスプリンシパルはソースコードへの貢献ができます。
以上のステップで、ユーザー登録の際の権限でもってPAT(Personal Access Token)と同様に同期をすることができるでしょう。
※PATを使ったreposの同期については、過去のこちらの記事を参照してください。
こちらのMSのdevlogで記載されているように、PATには漏洩のリスクや管理のコストがあるため、サービスプリンシパルを用いた認証に移行することをお勧めします。
Additionally, PATs are bearer tokens, which can be leaked easily and fall into the wrong hands. (Remember to always secure your secrets in a key management solution, like Azure Key Vault!) This leaked PAT can then be used to wreak havoc for the remaining duration of the PAT’s lifetime, or until revoked.
テナント跨ぎの場合、別のテナントにいるサービスプリンシパルをそのまま追加することはできないので、上述のようにゲストユーザーとして登録することが必要になります。
結論:Azure-Azure DevOpsのテナント跨ぎはそもそもしんどい
ということがわかりました(´;ω;`)
Azure DevOpsでタスク管理のAzure Boardsとかソースコード管理ツールとしてAzure ReposでRepos作ってSrcバージョン管理してチーム開発できるようにして、、、ぐらいの局面で使ってると意識しないけど、今回のご相談のようにCD pipeline作りたいとか、Application InsightとAzDOを連携してダッシュボードにメトリック構成したいとか、DevOpsのリリース→運用→feedbackの取得 らへんをまじめに考え出すと、Azureと連携したいっていうのは避けられないし、その過程でAzDOとAzureリソース切り離していちいち鍵(認証)ないとアクセスできない、みたいなのはしんどいな、、、と思いました。
というわけで、Azure DevOpsを使って上記のようなことまでやりたいなって場合は、AzureのリソースがいるテナントでAzure DevOpsを作成するのがベストなんだろうなと思います。
To.yutakaosadaさん
検証お手伝いしてくださってありがとうございます!!!
クロステナントの場合のユースケース ※2023/12/11 追記
と書いたものの、Azure-Azure DevOpsで連携する場合、必ずしも同一テナントにするのがべスプラであるというわけでもなく、場合によってはクロステナントで運用することも想定されます。
例えば、
- 制御するスコープをテナントごとにキレイに分けたい等
※下記スレ参照
https://x.com/1115_lilium/status/1724045533516546421?s=20
ただ、特にマルチテナント構成にする意図がない場合はAzure, Azure DevOpsは同一テナントで構成するのをおすすめします(今回のようなテナント跨ぎの作業が必要になるので)。
クロステナント構成にした場合、この記事でご紹介したサービスコネクションを使用してみてください。
Other References
Discussion
クロステナントのユースケースについて追記