クイック スタート: Bicep を使用して Azure マネージド アプリケーションの定義を作成および発行する

このクイックスタートでは、Bicep を使用して Azure マネージド アプリケーション定義を作成し、サービス カタログに発行する方法について説明します。 サービス カタログ内の 定義は、組織のメンバーが使用できます。

マネージド アプリケーション定義を作成してサービス カタログに発行するには、次の操作を行う必要があります。

  • Bicep を使用してテンプレートを開発し、Azure Resource Manager テンプレート (ARM テンプレート) に変換します。 このテンプレートは、マネージド アプリケーションによってデプロイされる Azure リソースを定義します。
  • Bicep build コマンドを使用して Bicep を JSON に変換します。 ファイルを JSON に変換した後に、コードの正確性を確認することをお勧めします。
  • マネージド アプリケーションをデプロイするときに、ポータルのユーザー インターフェイス要素を定義する。
  • 必要な JSON ファイルを含む .zip パッケージを作成する。 .zip パッケージ ファイルには、サービス カタログのマネージド アプリケーション定義に対して 120 MB の制限があります。
  • マネージド アプリケーション定義を発行し、サービス カタログで使用できるようにする。

マネージド アプリケーション定義が 120 MB を超える場合、または組織のコンプライアンス上の理由から独自のストレージ アカウントを使用する場合は、「クイック スタート: 独自のストレージを使用して Azure Managed Applications の定義を作成および発行する」を参照してください。

Bicep を使用して、サービス カタログからマネージド アプリケーション定義をデプロイすることもできます。 詳細については、Bicep を使用した Azure マネージド アプリケーション定義のデプロイに関するクイックスタートを参照してください。

前提条件

この記事のタスクを完了するには、次のものが必要です。

Bicep ファイルを作成する

各マネージ アプリケーション定義には、mainTemplate.json というファイルが含まれています。 このテンプレートは、デプロイする Azure リソースを定義し、通常の ARM テンプレートと同じ方法で定義します。 Bicep を使用してテンプレートを開発し、Bicep ファイルを JSON に変換できます。

Visual Studio Code を開き、大文字と小文字を区別する名前 mainTemplate.bicep のファイルを作成して保存します。

次の Bicep コードを追加し、ファイルを保存します。 それにより、App Service、App Service プラン、ストレージ アカウントをデプロイするためのマネージド アプリケーションのリソースを定義します。

param location string = resourceGroup().location

@description('App Service plan name.')
@maxLength(40)
param appServicePlanName string

@description('App Service name prefix.')
@maxLength(47)
param appServiceNamePrefix string

@description('Storage account name prefix.')
@maxLength(11)
param storageAccountNamePrefix string

@description('Storage account type allowed values')
@allowed([
  'Premium_LRS'
  'Standard_LRS'
  'Standard_GRS'
])
param storageAccountType string

var appServicePlanSku = 'F1'
var appServicePlanCapacity = 1
var appServiceName = '${appServiceNamePrefix}${uniqueString(resourceGroup().id)}'
var storageAccountName = '${storageAccountNamePrefix}${uniqueString(resourceGroup().id)}'
var appServiceStorageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};Key=${storageAccount.listKeys().keys[0].value}'

resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: appServicePlanSku
    capacity: appServicePlanCapacity
  }
}

resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
  name: appServiceName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
    siteConfig: {
      appSettings: [
        {
          name: 'AppServiceStorageConnectionString'
          value: appServiceStorageConnectionString
        }
      ]
    }
  }
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: storageAccountType
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}

output appServicePlan string = appServicePlan.name
output appServiceApp string = appServiceApp.properties.defaultHostName
output storageAccount string = storageAccount.properties.primaryEndpoints.blob

Bicep から JSON に変換する

PowerShell または Azure CLI を使用して mainTemplate.json ファイルをビルドします。 Bicep ファイルを保存したディレクトリに移動し、build コマンドを実行します。

bicep build mainTemplate.bicep

詳細については、Bicep ビルドに関するページを参照 してください。

Bicep ファイルを JSON に変換した後、mainTemplate.json ファイルは次の例と一致している必要があります。 versiontemplateHashmetadata プロパティの値が異なる場合があります。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.17.1.54307",
      "templateHash": "1234567891234567890"
    }
  },
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "appServicePlanName": {
      "type": "string",
      "maxLength": 40,
      "metadata": {
        "description": "App Service plan name."
      }
    },
    "appServiceNamePrefix": {
      "type": "string",
      "maxLength": 47,
      "metadata": {
        "description": "App Service name prefix."
      }
    },
    "storageAccountNamePrefix": {
      "type": "string",
      "maxLength": 11,
      "metadata": {
        "description": "Storage account name prefix."
      }
    },
    "storageAccountType": {
      "type": "string",
      "allowedValues": [
        "Premium_LRS",
        "Standard_LRS",
        "Standard_GRS"
      ],
      "metadata": {
        "description": "Storage account type allowed values"
      }
    }
  },
  "variables": {
    "appServicePlanSku": "F1",
    "appServicePlanCapacity": 1,
    "appServiceName": "[format('{0}{1}', parameters('appServiceNamePrefix'), uniqueString(resourceGroup().id))]",
    "storageAccountName": "[format('{0}{1}', parameters('storageAccountNamePrefix'), uniqueString(resourceGroup().id))]"
  },
  "resources": [
    {
      "type": "Microsoft.Web/serverfarms",
      "apiVersion": "2022-03-01",
      "name": "[parameters('appServicePlanName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[variables('appServicePlanSku')]",
        "capacity": "[variables('appServicePlanCapacity')]"
      }
    },
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2022-03-01",
      "name": "[variables('appServiceName')]",
      "location": "[parameters('location')]",
      "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
        "httpsOnly": true,
        "siteConfig": {
          "appSettings": [
            {
              "name": "AppServiceStorageConnectionString",
              "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};Key={2}', variables('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2022-09-01').keys[0].value)]"
            }
          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    },
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    }
  ],
  "outputs": {
    "appServicePlan": {
      "type": "string",
      "value": "[parameters('appServicePlanName')]"
    },
    "appServiceApp": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Web/sites', variables('appServiceName')), '2022-03-01').defaultHostName]"
    },
    "storageAccount": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2022-09-01').primaryEndpoints.blob]"
    }
  }
}

ポータル エクスペリエンスを定義する

マネージド アプリケーションを作成するためのポータル エクスペリエンスは、発行者が定義します。 ポータルのユーザー インターフェイスは、createUiDefinition.json ファイルによって生成されます。 ドロップダウンやテキスト ボックスなどのコントロール要素を使用して、各パラメーターの入力をユーザーがどのように提供するかを定義します。

この例では、ユーザー インターフェイスから、App Service の名前のプレフィックス、App Service プランの名前、ストレージ アカウントのプレフィックス、ストレージ アカウントの種類を入力するよう求められます。 デプロイ中、mainTemplate.json 内の変数で uniqueString 関数を使用して、名前のプレフィックスに 13 文字の文字列を追加し、名前が Azure 全体でグローバルに一意になるようにします。

Visual Studio Code を開き、大文字と小文字を区別する名前 createUiDefinition.json のファイルを作成して保存します。

次の JSON コードをファイルに追加し、保存します。

{
  "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
  "handler": "Microsoft.Azure.CreateUIDef",
  "version": "0.1.2-preview",
  "parameters": {
    "basics": [
      {}
    ],
    "steps": [
      {
        "name": "webAppSettings",
        "label": "Web App settings",
        "subLabel": {
          "preValidation": "Configure the web app settings",
          "postValidation": "Completed"
        },
        "elements": [
          {
            "name": "appServicePlanName",
            "type": "Microsoft.Common.TextBox",
            "label": "App Service plan name",
            "placeholder": "App Service plan name",
            "defaultValue": "",
            "toolTip": "Use alphanumeric characters or hyphens with a maximum of 40 characters.",
            "constraints": {
              "required": true,
              "regex": "^[a-z0-9A-Z-]{1,40}$",
              "validationMessage": "Only alphanumeric characters or hyphens are allowed, with a maximum of 40 characters."
            },
            "visible": true
          },
          {
            "name": "appServiceName",
            "type": "Microsoft.Common.TextBox",
            "label": "App Service name prefix",
            "placeholder": "App Service name prefix",
            "defaultValue": "",
            "toolTip": "Use alphanumeric characters or hyphens with minimum of 2 characters and maximum of 47 characters.",
            "constraints": {
              "required": true,
              "regex": "^[a-z0-9A-Z-]{2,47}$",
              "validationMessage": "Only alphanumeric characters or hyphens are allowed, with a minimum of 2 characters and maximum of 47 characters."
            },
            "visible": true
          }
        ]
      },
      {
        "name": "storageConfig",
        "label": "Storage settings",
        "subLabel": {
          "preValidation": "Configure the storage settings",
          "postValidation": "Completed"
        },
        "elements": [
          {
            "name": "storageAccounts",
            "type": "Microsoft.Storage.MultiStorageAccountCombo",
            "label": {
              "prefix": "Storage account name prefix",
              "type": "Storage account type"
            },
            "toolTip": {
              "prefix": "Enter maximum of 11 lowercase letters or numbers.",
              "type": "Available choices are Standard_LRS, Standard_GRS, and Premium_LRS."
            },
            "defaultValue": {
              "type": "Standard_LRS"
            },
            "constraints": {
              "allowedTypes": [
                "Premium_LRS",
                "Standard_LRS",
                "Standard_GRS"
              ]
            },
            "visible": true
          }
        ]
      }
    ],
    "outputs": {
      "location": "[location()]",
      "appServicePlanName": "[steps('webAppSettings').appServicePlanName]",
      "appServiceNamePrefix": "[steps('webAppSettings').appServiceName]",
      "storageAccountNamePrefix": "[steps('storageConfig').storageAccounts.prefix]",
      "storageAccountType": "[steps('storageConfig').storageAccounts.type]"
    }
  }
}

詳細については、CreateUiDefinition の概要に関するページを参照してください。

ファイルのパッケージ化

app.zip という名前のパッケージ ファイルに 2 つのファイルを追加します。 2 つのファイルは .zip ファイルのルートに配置する必要があります。 これらのファイルがフォルダー内にある場合、マネージド アプリケーション定義を作成するときに、必要なファイルが存在しないことを示すエラーが発生します。

マネージド アプリケーションの定義をデプロイするときに使用できるように、app.zip を Azure ストレージ アカウントにアップロードします。 ストレージ アカウント名は Azure 全体でグローバルに一意である必要があり、長さは小文字と数字のみで 3 から 24 文字にする必要があります。 コマンドで、山かっこ (<>) を含むプレースホルダー <demostorageaccount> を一意のストレージ アカウント名に置き換えます。

Visual Studio Code で、新しい PowerShell ターミナルを開き、Azure サブスクリプションにサインインします。

Connect-AzAccount

コマンドを実行すると、既定のブラウザーが開き、Azure にサインインするよう求められます。 詳細については、「Azure PowerShell を使用してサインインする」を参照してください。

接続後、次のコマンドを実行します。

New-AzResourceGroup -Name packageStorageRG -Location westus3

$storageAccount = New-AzStorageAccount `
  -ResourceGroupName packageStorageRG `
  -Name "<demostorageaccount>" `
  -Location westus3 `
  -SkuName Standard_LRS `
  -Kind StorageV2 `
  -AllowBlobPublicAccess $true

$ctx = $storageAccount.Context

New-AzStorageContainer -Name appcontainer -Context $ctx -Permission blob

Set-AzStorageBlobContent `
  -File "app.zip" `
  -Container appcontainer `
  -Blob "app.zip" `
  -Context $ctx

パッケージ ファイルの URI を packageuri という名前の変数に格納するには、次のコマンドを使用します。 この変数の値は、マネージド アプリケーション定義をデプロイするときに使用します。

$packageuri=(Get-AzStorageBlob -Container appcontainer -Blob app.zip -Context $ctx).ICloudBlob.StorageUri.PrimaryUri.AbsoluteUri

マネージド アプリケーション定義の作成

このセクションでは、Microsoft Entra ID から ID 情報を取得し、リソース グループを作成して、マネージド アプリケーション定義をデプロイします。

グループ ID とロール定義 ID を取得する

次の手順として、顧客のリソースを管理するためのユーザー、セキュリティ グループ、またはアプリケーションを選択します。 この ID には、割り当てられているロールに従って、管理対象リソース グループに対するアクセス許可が付与されています。 そのロールには、Azure の組み込みロール (所有者、共同作成者など) をどれでも使用できます。

この例ではセキュリティ グループを使用しており、Microsoft Entra アカウントはグループのメンバーである必要があります。 グループのオブジェクト ID を取得するには、山かっこ (<>) を含むプレースホルダー <managedAppDemo> をグループの名前に置き換えます。 この変数の値は、マネージド アプリケーション定義をデプロイするときに使用します。

新しい Microsoft Entra グループを作成するには、[Microsoft Entra グループとグループ メンバーシップの管理] に移動します。

$principalid=(Get-AzADGroup -DisplayName <managedAppDemo>).Id

次に、ユーザー、グループ、またはアプリケーションへのアクセス権を付与する Azure の組み込みロールのロール定義 ID を取得します。 この変数の値は、マネージド アプリケーション定義をデプロイするときに使用します。

$roleid=(Get-AzRoleDefinition -Name Owner).Id

定義のデプロイ テンプレートを作成する

Bicep ファイルを使用して、マネージド アプリケーション定義をサービス カタログにデプロイします。

Visual Studio Code を開き、deployDefinition.bicep という名前でファイルを作成して保存します。

次の Bicep コードを追加し、ファイルを保存します。

param location string = resourceGroup().location

@description('Name of the managed application definition.')
param managedApplicationDefinitionName string

@description('The URI of the .zip package file.')
param packageFileUri string

@description('Publishers Principal ID that needs permissions to manage resources in the managed resource group.')
param principalId string

@description('Role ID for permissions to the managed resource group.')
param roleId string

var definitionLockLevel = 'ReadOnly'
var definitionDisplayName = 'Sample Bicep managed application'
var definitionDescription = 'Sample Bicep managed application that deploys web resources'

resource managedApplicationDefinition 'Microsoft.Solutions/applicationDefinitions@2021-07-01' = {
  name: managedApplicationDefinitionName
  location: location
  properties: {
    lockLevel: definitionLockLevel
    description: definitionDescription
    displayName: definitionDisplayName
    packageFileUri: packageFileUri
    authorizations: [
      {
        principalId: principalId
        roleDefinitionId: roleId
      }
    ]
  }
}

テンプレートのプロパティの詳細については、Microsoft.Solutions/applicationDefinitions を参照してください。

管理対象リソース グループの lockLevel によって、このリソース グループに対して問題となるような操作を顧客が実行できないようにします。 現在サポートされているロック レベルは ReadOnly だけです。 ReadOnly を指定すると、顧客は管理対象リソース グループに存在するリソースの読み取りしか実行できません。 管理対象リソース グループへのアクセス権が付与されている発行元 ID は、ロック レベルの対象外となります。

パラメーター ファイルを作成する

マネージド アプリケーション定義のデプロイ テンプレートを使用するには、いくつかのパラメーターに対して入力が必要です。 デプロイ コマンドで値の入力が求められます。または、自分で値のパラメーター ファイルを作成できます。 この例では、パラメーター ファイルを使用して、パラメーター値をデプロイ コマンドに渡します。

Visual Studio Code で、deployDefinition.parameters.json という名前の新しいファイルを作成し、保存します。

このパラメーター ファイルに以下を追加し、保存します。 次に、山かっこ (<>) を含む <placeholder values> を、実際の値に置き換えます。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "managedApplicationDefinitionName": {
      "value": "sampleBicepManagedApplication"
    },
    "packageFileUri": {
      "value": "<placeholder for the packageFileUri>"
    },
    "principalId": {
      "value": "<placeholder for principalid value>"
    },
    "roleId": {
      "value": "<placeholder for roleid value>"
    }
  }
}

マネージド アプリケーション定義のパラメーター値について次の表で説明します。

パラメーター
managedApplicationDefinitionName マネージド アプリケーション定義の名前。 この例では、sampleBicepManagedApplication を使用します。
packageFileUri .zip パッケージ ファイルの URI を入力します。 packageuri 変数の値を使用します。 形式は https://yourStorageAccountName.blob.core.windows.net/appcontainer/app.zip です。
principalId 管理対象リソース グループ内のリソースを管理するためのアクセス許可が必要なパブリッシャー プリンシパル ID。 principalid 変数の値を使用します。
roleId 管理対象リソース グループに対するアクセス許可のロール ID。 たとえば、所有者、共同作成者、閲覧者などです。 roleid 変数の値を使用します。

変数の値を取得するには:

  • Azure PowerShell: PowerShell で、「$variableName」と入力して変数の値を表示します。
  • Azure CLI: Bash で、「echo $variableName」と入力して変数の値を表示します。

定義をデプロイする

マネージド アプリケーションの定義は、デプロイするとサービス カタログで使用できるようになります。 このプロセスでは、マネージド アプリケーションのリソースはデプロイされません。

bicepDefinitionRG という名前のリソース グループを作成し、マネージド アプリケーション定義をデプロイします。

New-AzResourceGroup -Name bicepDefinitionRG -Location westus3

New-AzResourceGroupDeployment `
  -ResourceGroupName bicepDefinitionRG `
  -TemplateFile deployDefinition.bicep `
  -TemplateParameterFile deployDefinition.parameters.json

結果を確認する

次のコマンドを実行して、定義がサービス カタログに発行されていることを確認します。

Get-AzManagedApplicationDefinition -ResourceGroupName bicepDefinitionRG

Get-AzManagedApplicationDefinition は、指定されたリソース グループ内で使用可能なすべての定義 (sampleBicepManagedApplication など) を一覧表示します。

ユーザーが定義にアクセスできるようにする

自身がアクセスできるマネージ アプリケーション定義に、組織の他のユーザーもアクセスできることを確認する必要があります。 定義に対して閲覧者以上のロールをユーザーに付与してください。 ユーザーはこのレベルのアクセスをサブスクリプションまたはリソース グループから継承している場合があります。 定義にアクセスできるユーザーを確認したり、ユーザーやグループを追加したりするには、「Azure portal を使用して Azure ロールを割り当てる」を参照してください。

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

これから定義をデプロイする場合は、記事にリンクしている「次の手順」セクションに進んで Bicep で定義をデプロイします。

マネージド アプリケーションの定義が終了したら、作成した packageStorageRG および bicepDefinitionRG という名前のリソース グループを削除できます。

コマンドを実行すると、リソース グループを削除することを確認するメッセージが表示されます。

Remove-AzResourceGroup -Name packageStorageRG

Remove-AzResourceGroup -Name bicepDefinitionRG

次のステップ

マネージド アプリケーション定義を発行しました。 次の手順では、その定義のインスタンスをデプロイする方法を確認します。