APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

BicepでEntra IDの「アプリの登録」を実現する

朗報 BicepがMicrosft Graphのサポート

みなさんこんにちは。少し前の2024年5月20日、Bicep templateでMicrosoft Graphのpublic previewが公開されました。

techcommunity.microsoft.com

本当に長いこと(といってもBicepが世に出てまだ数年ですが)待ち望んでいました。

BicepでAzure Resourceからそこで動くアプリケーションのデプロイまで実現しようとすると、どこかでEntra IDの「アプリ」を登録しなければならないことがあります。

また、様々なシステムをBicepでプロビジョニング・デプロイするとGitHub ActionsなどからCDができるようにするために、Federationを登録するなんてこともたびたび発生します。

いつもAzure Portalや az CLIを使ってやっていましたが、やっとBicepでもそれが実現できるようになります。

ということで今回は、やってみた系でBicepでEntra IDの「アプリの登録」を実現しようと思います。

やってみた

事前準備

まずは公式情報のありかです。

learn.microsoft.com

この投稿の最初にあるとおり、まだプレビューなので、 bicepconfig.json というファイルでプレビュー機能を有効にする必要があります。 bicepファイルと同じフォルダに作成してください。

{
  "experimentalFeaturesEnabled": {
      "extensibility": true
  }
}

Appの登録

それではまず、Entra IDに「アプリの登録」とAzure Contaiiner RegistryへのRoleの割当をやってみます。

provider microsoftGraph

@description('Application name, unique globally. Can not change after create it')
param appName string
@description('Applicaton displayname, default value is same as appName')
param displayName string = appName
@description('Name for container registry')
param acrName string

resource app 'Microsoft.Graph/applications@v1.0' = {
  displayName: displayName
  uniqueName: appName
}

resource sp 'Microsoft.Graph/servicePrincipals@v1.0' = {
  appId: app.appId
}

resource acr 'Microsoft.ContainerRegistry/registries@2023-07-01' existing = {
  name: acrName
}

var acrRoles = [
  '8311e382-0749-4cb8-b61a-304f252e45ec'  // ACR push
]

resource assignRolesToAcr 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in acrRoles: {
  name: guid(appName, resourceGroup().id, role)
  scope: acr
  properties: {
    principalId: sp.id
    principalType: 'ServicePrincipal'
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', role)
}
}]

解説その1

最初の行に provider microsoftGraph とあります。これは Microsoft Graph型が含まれているということを宣言してるものです。 これがないと利用できません。

解説その2

resource app 'Microsoft.Graph/applications@v1.0' = {
  displayName: displayName
  uniqueName: appName
}

resource sp 'Microsoft.Graph/servicePrincipals@v1.0' = {
  appId: app.appId
}

ロールを割り当てる場合、Service Principalが必要になります。Azure Portalで「Entra アプリ」を作成すると自動的に必要となるService Principalが作成されますが、Bicepでは「アプリ」と「Service Principal」が分かれているのでその両方をここで作成しています。

解説その3

これで「アプリの登録」は作成できました。あとは従来と同じようにService Principalにロールを割り当てるといった作業を行っていけます。

フェデレーションの作成

では、もう1つMicrosoft.Graphの例としてフェデレーションを登録していきます。 公式ドキュメントはこちらです。

learn.microsoft.com

GitHub ActionsなどからAzure Resourceにアクセスする際にフェデレーションを登録するケースも多いかと思います。

techblog.ap-com.co.jp

上記の投稿でAzure Portalで実行していた部分をBicepで実現していきます。

provider microsoftGraph

@description('Application name, unique globally. Can not change after create it')
param appName string
@description('Federation name')
param federationName string
@description('Federaton description')
param descriptoin string?
@description('GitHub organization name')
param organization string
@description('GitHub repository name')
param repository string
@description('GitHub environment in repository')
param environmentName string

func generateDeployId(name string) string => substring(guid(name), 0, 8)

resource app 'Microsoft.Graph/applications@v1.0' existing = {
  uniqueName: appName
}

var subjectIdentifier = 'repo:${organization}/${repository}:environment:${environmentName}'

resource appliedApp 'Microsoft.Graph/applications@v1.0' = {
  displayName: app.displayName
  uniqueName: app.uniqueName

  resource fed 'federatedIdentityCredentials@v1.0' = {
    audiences: [
      'api://AzureADTokenExchange'
    ]
    description: descriptoin
    issuer: 'https://token.actions.githubusercontent.com'
    name: '${app.uniqueName}/${federationName}'
    subject: subjectIdentifier
  }
  
}

解説その4

プレビュー版だからなのか、それともこれが正式になるのかわかりませんが、現時点では Microsoft.Graph/applications の子要素としてMicrosoft.Graph/applications/federatedIdentityCredentials を指定するようになっています。

Microsoft.Graph/applications/federatedIdentityCredentials を単独しようといくつか試みたのですが、私の試し方がわるかったのかうまくいきませんでした。ということで今回は上記のように入れ子の構造になっています。

解説その5

audienceは原則この内容固定です。issuerはGitHub固有のもの、subjectはGitHub Environmentを利用する際のものです。 どういった内容を指定すべきかはAzure Portalで作成した結果や、それぞれのProviderの資料をご確認ください。

解説その6

実はこの部分が今回の中で一番時間のかかった部分です。federatedIdentityCredentialsのなかの名前の指定方法です。

最初以下のように記述していました。

name: '${federationName}'

そうするとスクリプト実行時にIdentifierが不正とエラーになります。

ドキュメントなどにもあまり記載がないのですが、調べていく中で次のように <appの名前>/<federationの名前> と記載しなければならないことがわかりました。(この指定方法に気づくまでに1時間近くかかった)

name: '${app.uniqueName}/${federationName}'

このスクリプトを実行したらフェデレーションも作成できました。

実際にGitHub Actionsからこの指定を使ってACRへのPushもできました。めでたしめでたし。

最後に

Bicepを利用する際のミッシングリンクの1つ、Microsoft Graphがまだpublic previewではありますがやっとサポートされました。 これでIaC化もさらに一歩前進です。ぜひ皆さんお試しください。 そしてこの投稿が少しでも皆さんのご参考になれば幸いです。