Create and publish a managed application definition


This article has been updated to use the new Azure PowerShell Az module. You can still use the AzureRM module, which will continue to receive bug fixes until at least December 2020. To learn more about the new Az module and AzureRM compatibility, see Introducing the new Azure PowerShell Az module. For Az module installation instructions, see Install Azure PowerShell.

You can create and publish Azure managed applications that are intended for members of your organization. For example, an IT department can publish managed applications that fulfill organizational standards. These managed applications are available through the service catalog, not the Azure marketplace.

To publish a managed application for the service catalog, you must:

  • Create a template that defines the resources to deploy with the managed application.
  • Define the user interface elements for the portal when deploying the managed application.
  • Create a .zip package that contains the required template files.
  • Decide which user, group, or application needs access to the resource group in the user's subscription.
  • Create the managed application definition that points to the .zip package and requests access for the identity.

For this article, your managed application has only a storage account. It's intended to illustrate the steps of publishing a managed application. For complete examples, see Sample projects for Azure managed applications.

The PowerShell examples in this article require Azure PowerShell 6.2 or later. If needed, update your version.

Create the resource template

Every managed application definition includes a file named mainTemplate.json. In it, you define the Azure resources to deploy. The template is no different than a regular Resource Manager template.

Create a file named mainTemplate.json. The name is case-sensitive.

Add the following JSON to your file. It defines the parameters for creating a storage account, and specifies the properties for the storage account.

    "$schema": "",
    "contentVersion": "",
    "parameters": {
        "storageAccountNamePrefix": {
            "type": "string"
        "storageAccountType": {
            "type": "string"
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
    "variables": {
        "storageAccountName": "[concat(parameters('storageAccountNamePrefix'), uniqueString(resourceGroup().id))]"
    "resources": [
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            "apiVersion": "2016-01-01",
            "location": "[parameters('location')]",
            "sku": {
                "name": "[parameters('storageAccountType')]"
            "kind": "Storage",
            "properties": {}
    "outputs": {
        "storageEndpoint": {
            "type": "string",
            "value": "[reference(resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob]"

Save the mainTemplate.json file.

Defining your create experience using CreateUiDefinition.json

As a publisher, you define your create experience using the createUiDefinition.json file which generates the interface for users creating managed applications. You define how users provide input for each parameter using control elements including drop-downs, text boxes, and password boxes.

Create a file named createUiDefinition.json (This name is case-sensitive)

Add the following starter JSON to the file and save it.

   "$schema": "",
   "handler": "Microsoft.Azure.CreateUIDef",
   "version": "0.1.2-preview",
   "parameters": {
        "basics": [
        "steps": [
                "name": "storageConfig",
                "label": "Storage settings",
                "subLabel": {
                    "preValidation": "Configure the infrastructure settings",
                    "postValidation": "Done"
                "bladeTitle": "Storage settings",
                "elements": [
                        "name": "storageAccounts",
                        "type": "Microsoft.Storage.MultiStorageAccountCombo",
                        "label": {
                            "prefix": "Storage account name prefix",
                            "type": "Storage account type"
                        "defaultValue": {
                            "type": "Standard_LRS"
                        "constraints": {
                            "allowedTypes": [
        "outputs": {
            "storageAccountNamePrefix": "[steps('storageConfig').storageAccounts.prefix]",
            "storageAccountType": "[steps('storageConfig').storageAccounts.type]",
            "location": "[location()]"

To learn more, see Get started with CreateUiDefinition.

Package the files

Add the two files to a .zip file named The two files must be at the root level of the .zip file. If you put them in a folder, you receive an error when creating the managed application definition that states the required files aren't present.

Upload the package to an accessible location from where it can be consumed.

New-AzResourceGroup -Name storageGroup -Location eastus
$storageAccount = New-AzStorageAccount -ResourceGroupName storageGroup `
  -Name "mystorageaccount" `
  -Location eastus `
  -SkuName Standard_LRS `
  -Kind Storage

$ctx = $storageAccount.Context

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

Set-AzStorageBlobContent -File "D:\myapplications\" `
  -Container appcontainer `
  -Blob "" `
  -Context $ctx 

Create the managed application definition

Create an Azure Active Directory user group or application

The next step is to select a user group or application for managing the resources on behalf of the customer. This user group or application has permissions on the managed resource group according to the role that is assigned. The role can be any built-in Role-Based Access Control (RBAC) role like Owner or Contributor. You also can give an individual user permission to manage the resources, but typically you assign this permission to a user group. To create a new Active Directory user group, see Create a group and add members in Azure Active Directory.

You need the object ID of the user group to use for managing the resources.

$groupID=(Get-AzADGroup -DisplayName mygroup).Id

Get the role definition ID

Next, you need the role definition ID of the RBAC built-in role you want to grant access to the user, user group, or application. Typically, you use the Owner or Contributor or Reader role. The following command shows how to get the role definition ID for the Owner role:

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

Create the managed application definition

If you don't already have a resource group for storing your managed application definition, create one now:

New-AzResourceGroup -Name appDefinitionGroup -Location westcentralus

Now, create the managed application definition resource.

$blob = Get-AzStorageBlob -Container appcontainer -Blob -Context $ctx

New-AzManagedApplicationDefinition `
  -Name "ManagedStorage" `
  -Location "westcentralus" `
  -ResourceGroupName appDefinitionGroup `
  -LockLevel ReadOnly `
  -DisplayName "Managed Storage Account" `
  -Description "Managed Azure Storage Account" `
  -Authorization "${groupID}:$ownerID" `
  -PackageFileUri $blob.ICloudBlob.StorageUri.PrimaryUri.AbsoluteUri

Make sure users can see your definition

You have access to the managed application definition, but you want to make sure other users in your organization can access it. Grant them at least the Reader role on the definition. They may have inherited this level of access from the subscription or resource group. To check who has access to the definition and add users or groups, see Use Role-Based Access Control to manage access to your Azure subscription resources.

Next steps