azuredeploy.json

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.45.15.27210",
      "templateHash": "6350892555839482704"
    },
    "maesterCloud": {
      "deploymentModel": "aca-self-host",
      "schemaVersion": 4
    }
  },
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Azure region for the customer-owned deployment."
      }
    },
    "version": {
      "type": "string",
      "defaultValue": "private-preview",
      "metadata": {
        "description": "Release version recorded on the deployment and exposed by the health endpoint."
      }
    },
    "entraTenantId": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Tenant id of the customer-owned single-tenant Entra application. Leave empty until sign-in is configured."
      }
    },
    "entraClientId": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Client id of the customer-owned single-tenant Entra application. Leave empty until sign-in is configured."
      }
    },
    "entraApplicationObjectId": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Object id of the customer-owned single-tenant Entra application. Leave empty until sign-in is configured."
      }
    },
    "entraApiIdentifierUri": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Identifier URI of the API exposed by the customer-owned Entra application. Leave empty until sign-in is configured."
      }
    },
    "entraInitialOwnerObjectId": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Object id of the first Maester Cloud Owner. Leave empty until sign-in is configured."
      }
    },
    "entraTenantDisplayName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Display name of the Entra tenant, cached so the setup app can label an existing deployment without directory read permission. Display only; never used for authorization."
      }
    },
    "entraApplicationDisplayName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Display name of the customer-owned Entra application, cached so the setup app can label an existing deployment without directory read permission. Display only; never used for authorization."
      }
    },
    "entraInitialOwnerDisplayName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Sign-in name of the first Maester Cloud Owner, cached so the setup app can label an existing deployment without directory read permission. Display only; never used for authorization."
      }
    },
    "appImage": {
      "type": "string",
      "defaultValue": "maester.azurecr.io/maester-cloud:private-preview",
      "metadata": {
        "description": "Version-pinned Maester Cloud application image, served anonymously by the Maester Cloud distribution registry. Release artifacts replace this default with an immutable digest."
      }
    },
    "runnerImage": {
      "type": "string",
      "defaultValue": "maester.azurecr.io/maester-cloud-runner:private-preview",
      "metadata": {
        "description": "Version-pinned Maester Cloud runner image, served anonymously by the Maester Cloud distribution registry. Release artifacts replace this default with an immutable digest."
      }
    },
    "setupAppOrigins": {
      "type": "string",
      "defaultValue": "https://setup.maester.cloud",
      "metadata": {
        "description": "Extra https origins allowed to call the API with a bearer token, besides the loopback origins the PowerShell-launched setup app uses. Defaults to the hosted Maester Cloud Setup app; set to an empty string to allow loopback only."
      }
    },
    "defaultTimeZone": {
      "type": "string",
      "defaultValue": "UTC",
      "metadata": {
        "description": "IANA or Windows timezone id new run schedules start with. Each schedule keeps its own copy and may override it in the portal."
      }
    },
    "maesterAccountId": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Pseudonymous Maester Cloud account id, carried from the setup wizard so this instance can be correlated with the subscription that paid for it. Not a credential and identifies no person."
      }
    },
    "telemetryEnabled": {
      "type": "bool",
      "defaultValue": true,
      "metadata": {
        "description": "Send diagnostics to Maester for error logging and support. Set false to send nothing; the in-product support widget keeps working either way."
      }
    },
    "telemetryHost": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Diagnostics ingest origin (a Maester-operated reverse proxy). Empty disables diagnostics regardless of telemetryEnabled."
      }
    },
    "telemetryKey": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Public, write-only diagnostics project token. Empty disables diagnostics regardless of telemetryEnabled."
      }
    }
  },
  "variables": {
    "workloadName": "maestercloud",
    "storageName": "[format('st{0}{1}', variables('workloadName'), take(uniqueString(subscription().subscriptionId, resourceGroup().id), 10))]",
    "keyVaultName": "[format('kv-mc-{0}', take(uniqueString(subscription().subscriptionId, resourceGroup().id), 13))]",
    "appName": "[format('ca-{0}', variables('workloadName'))]",
    "environmentName": "[format('cae-{0}', variables('workloadName'))]",
    "runnerJobName": "[format('caj-{0}-runner', variables('workloadName'))]",
    "uploadContainerName": "incoming-reports",
    "runnerLogsContainerName": "runner-logs",
    "containerAppsApiVersion": "2024-03-01",
    "authenticationEnvironment": "[if(and(and(and(and(not(empty(parameters('entraTenantId'))), not(empty(parameters('entraClientId')))), not(empty(parameters('entraApplicationObjectId')))), not(empty(parameters('entraApiIdentifierUri')))), not(empty(parameters('entraInitialOwnerObjectId')))), createArray(createObject('name', 'AAD_TENANT_ID', 'value', parameters('entraTenantId')), createObject('name', 'AAD_CLIENT_ID', 'value', parameters('entraClientId')), createObject('name', 'MaesterCloud__ApplicationObjectId', 'value', parameters('entraApplicationObjectId')), createObject('name', 'MaesterCloud__ApiIdentifierUri', 'value', parameters('entraApiIdentifierUri')), createObject('name', 'MaesterCloud__AllowedIssuer', 'value', format('{0}{1}/v2.0', environment().authentication.loginEndpoint, parameters('entraTenantId'))), createObject('name', 'MaesterCloud__AllowedAudience', 'value', parameters('entraClientId')), createObject('name', 'MaesterCloud__AllowedTenantId', 'value', parameters('entraTenantId')), createObject('name', 'MaesterCloud__InitialOwnerObjectId', 'value', parameters('entraInitialOwnerObjectId'))), createArray())]",
    "displayNameEnvironment": "[concat(if(empty(parameters('entraTenantDisplayName')), createArray(), createArray(createObject('name', 'MaesterCloud__TenantDisplayName', 'value', parameters('entraTenantDisplayName')))), if(empty(parameters('entraApplicationDisplayName')), createArray(), createArray(createObject('name', 'MaesterCloud__ApplicationDisplayName', 'value', parameters('entraApplicationDisplayName')))), if(empty(parameters('entraInitialOwnerDisplayName')), createArray(), createArray(createObject('name', 'MaesterCloud__InitialOwnerDisplayName', 'value', parameters('entraInitialOwnerDisplayName')))))]",
    "tags": {
      "MaesterCloud": "self-hosted",
      "MaesterCloudVersion": "[parameters('version')]"
    },
    "instanceId": "[take(uniqueString(subscription().subscriptionId, resourceGroup().id, 'maester-instance'), 32)]",
    "telemetryEnvironment": [
      {
        "name": "MaesterCloud__Telemetry__Enabled",
        "value": "[string(parameters('telemetryEnabled'))]"
      },
      {
        "name": "MaesterCloud__Telemetry__InstanceId",
        "value": "[variables('instanceId')]"
      },
      {
        "name": "MaesterCloud__AccountId",
        "value": "[parameters('maesterAccountId')]"
      },
      {
        "name": "MaesterCloud__Telemetry__Host",
        "value": "[parameters('telemetryHost')]"
      },
      {
        "name": "MaesterCloud__Telemetry__Token",
        "value": "[parameters('telemetryKey')]"
      }
    ]
  },
  "resources": [
    {
      "type": "Microsoft.OperationalInsights/workspaces",
      "apiVersion": "2023-09-01",
      "name": "[format('log-{0}', variables('workloadName'))]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "properties": {
        "sku": {
          "name": "PerGB2018"
        },
        "retentionInDays": 30,
        "publicNetworkAccessForIngestion": "Enabled",
        "publicNetworkAccessForQuery": "Enabled"
      }
    },
    {
      "type": "Microsoft.Insights/components",
      "apiVersion": "2020-02-02",
      "name": "[format('appi-{0}', variables('workloadName'))]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "kind": "web",
      "properties": {
        "Application_Type": "web",
        "WorkspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', format('log-{0}', variables('workloadName')))]",
        "IngestionMode": "LogAnalytics",
        "publicNetworkAccessForIngestion": "Enabled",
        "publicNetworkAccessForQuery": "Enabled"
      },
      "dependsOn": [
        "[resourceId('Microsoft.OperationalInsights/workspaces', format('log-{0}', variables('workloadName')))]"
      ]
    },
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-05-01",
      "name": "[variables('storageName')]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "sku": {
        "name": "Standard_ZRS"
      },
      "kind": "StorageV2",
      "properties": {
        "allowBlobPublicAccess": false,
        "allowSharedKeyAccess": false,
        "defaultToOAuthAuthentication": true,
        "minimumTlsVersion": "TLS1_2",
        "publicNetworkAccess": "Enabled",
        "supportsHttpsTrafficOnly": true
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/blobServices",
      "apiVersion": "2023-05-01",
      "name": "[format('{0}/{1}', variables('storageName'), 'default')]",
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
      ]
    },
    {
      "type": "Microsoft.Storage/storageAccounts/blobServices/containers",
      "apiVersion": "2023-05-01",
      "name": "[format('{0}/{1}/{2}', variables('storageName'), 'default', variables('uploadContainerName'))]",
      "properties": {
        "publicAccess": "None"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('storageName'), 'default')]"
      ]
    },
    {
      "type": "Microsoft.Storage/storageAccounts/blobServices/containers",
      "apiVersion": "2023-05-01",
      "name": "[format('{0}/{1}/{2}', variables('storageName'), 'default', variables('runnerLogsContainerName'))]",
      "properties": {
        "publicAccess": "None"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('storageName'), 'default')]"
      ]
    },
    {
      "type": "Microsoft.App/managedEnvironments",
      "apiVersion": "2024-03-01",
      "name": "[variables('environmentName')]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "properties": {
        "appLogsConfiguration": {
          "destination": "log-analytics",
          "logAnalyticsConfiguration": {
            "customerId": "[reference(resourceId('Microsoft.OperationalInsights/workspaces', format('log-{0}', variables('workloadName'))), '2023-09-01').customerId]",
            "sharedKey": "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces', format('log-{0}', variables('workloadName'))), '2023-09-01').primarySharedKey]"
          }
        },
        "workloadProfiles": [
          {
            "name": "Consumption",
            "workloadProfileType": "Consumption"
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.OperationalInsights/workspaces', format('log-{0}', variables('workloadName')))]"
      ]
    },
    {
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
      "apiVersion": "2023-01-31",
      "name": "[format('id-{0}-app', variables('workloadName'))]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]"
    },
    {
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
      "apiVersion": "2023-01-31",
      "name": "[format('id-{0}-runner', variables('workloadName'))]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]"
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]",
      "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'storage-blob-data-contributor')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
      ]
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]",
      "name": "[guid(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'storage-table-data-contributor')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
      ]
    },
    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "2023-07-01",
      "name": "[variables('keyVaultName')]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "properties": {
        "tenantId": "[tenant().tenantId]",
        "sku": {
          "family": "A",
          "name": "standard"
        },
        "enableRbacAuthorization": true,
        "enableSoftDelete": true,
        "softDeleteRetentionInDays": 90,
        "publicNetworkAccess": "Enabled",
        "networkAcls": {
          "defaultAction": "Allow",
          "bypass": "AzureServices"
        }
      }
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
      "name": "[guid(resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'key-vault-certificates-officer')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
      ]
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
      "name": "[guid(resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'key-vault-crypto-user')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
      ]
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', variables('storageName'), 'default', variables('runnerLogsContainerName'))]",
      "name": "[guid(resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', variables('storageName'), 'default', variables('runnerLogsContainerName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), 'storage-blob-data-contributor')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName')))]",
        "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', variables('storageName'), 'default', variables('runnerLogsContainerName'))]"
      ]
    },
    {
      "type": "Microsoft.App/jobs",
      "apiVersion": "2024-03-01",
      "name": "[variables('runnerJobName')]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))))]": {}
        }
      },
      "properties": {
        "environmentId": "[resourceId('Microsoft.App/managedEnvironments', variables('environmentName'))]",
        "configuration": {
          "triggerType": "Manual",
          "replicaTimeout": 7200,
          "replicaRetryLimit": 0,
          "manualTriggerConfig": {
            "parallelism": 1,
            "replicaCompletionCount": 1
          }
        },
        "template": {
          "containers": [
            {
              "name": "maester-runner",
              "image": "[parameters('runnerImage')]",
              "resources": {
                "cpu": "[json('1.0')]",
                "memory": "2Gi"
              },
              "env": [
                {
                  "name": "AZURE_CLIENT_ID",
                  "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').clientId]"
                },
                {
                  "name": "MC_STORAGE_ACCOUNT",
                  "value": "[variables('storageName')]"
                }
              ]
            }
          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.App/managedEnvironments', variables('environmentName'))]",
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName')))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
      ]
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "scope": "[resourceId('Microsoft.App/jobs', variables('runnerJobName'))]",
      "name": "[guid(resourceId('Microsoft.App/jobs', variables('runnerJobName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'container-apps-jobs-operator')]",
      "properties": {
        "principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9a307c4-5aa3-4b52-ba60-2b17c136cd7b')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.App/jobs', variables('runnerJobName'))]"
      ]
    },
    {
      "type": "Microsoft.App/containerApps",
      "apiVersion": "2024-03-01",
      "name": "[variables('appName')]",
      "location": "[parameters('location')]",
      "tags": "[variables('tags')]",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "[format('{0}', resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))))]": {}
        }
      },
      "properties": {
        "environmentId": "[resourceId('Microsoft.App/managedEnvironments', variables('environmentName'))]",
        "configuration": {
          "activeRevisionsMode": "Single",
          "ingress": {
            "allowInsecure": false,
            "external": true,
            "targetPort": 8080,
            "transport": "auto"
          }
        },
        "template": {
          "containers": [
            {
              "name": "maester-cloud",
              "image": "[parameters('appImage')]",
              "resources": {
                "cpu": "[json('0.5')]",
                "memory": "1Gi"
              },
              "env": "[concat(createArray(createObject('name', 'ASPNETCORE_URLS', 'value', 'http://+:8080'), createObject('name', 'AZURE_CLIENT_ID', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').clientId), createObject('name', 'APPLICATIONINSIGHTS_CONNECTION_STRING', 'value', reference(resourceId('Microsoft.Insights/components', format('appi-{0}', variables('workloadName'))), '2020-02-02').ConnectionString), createObject('name', 'ConnectionStrings__blobs', 'value', reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), '2023-05-01').primaryEndpoints.blob), createObject('name', 'ConnectionStrings__tables', 'value', reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), '2023-05-01').primaryEndpoints.table), createObject('name', 'MaesterCloud__AllowDevelopmentAuth', 'value', 'false'), createObject('name', 'MaesterCloud__UploadContainerName', 'value', variables('uploadContainerName')), createObject('name', 'MaesterCloud__AuditTableName', 'value', 'RunAudit'), createObject('name', 'MaesterCloud__TestResultsTableName', 'value', 'TestResults'), createObject('name', 'MaesterCloud__Version', 'value', parameters('version')), createObject('name', 'MaesterCloud__HostTenantId', 'value', tenant().tenantId), createObject('name', 'MaesterCloud__SubscriptionName', 'value', subscription().displayName), createObject('name', 'MaesterCloud__ContainerAppName', 'value', variables('appName')), createObject('name', 'MaesterCloud__StackIdentityObjectId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId), createObject('name', 'Drift__PortalBaseUrl', 'value', format('https://{0}.{1}', variables('appName'), reference(resourceId('Microsoft.App/managedEnvironments', variables('environmentName')), '2024-03-01').defaultDomain)), createObject('name', 'ManagedRunner__SubscriptionId', 'value', subscription().subscriptionId), createObject('name', 'ManagedRunner__ResourceGroupName', 'value', resourceGroup().name), createObject('name', 'ManagedRunner__JobName', 'value', variables('runnerJobName')), createObject('name', 'ManagedRunner__JobApiVersion', 'value', variables('containerAppsApiVersion')), createObject('name', 'ManagedRunner__RunnerImage', 'value', parameters('runnerImage')), createObject('name', 'ManagedRunner__ApiBaseUrl', 'value', format('https://{0}.{1}', variables('appName'), reference(resourceId('Microsoft.App/managedEnvironments', variables('environmentName')), '2024-03-01').defaultDomain)), createObject('name', 'ManagedRunner__RunnerManagedIdentityClientId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').clientId), createObject('name', 'ManagedRunner__RunnerManagedIdentityPrincipalId', 'value', reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').principalId), createObject('name', 'KeyVault__VaultUri', 'value', reference(resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName')), '2023-07-01').vaultUri), createObject('name', 'ManagedRunner__StorageAccountName', 'value', variables('storageName')), createObject('name', 'ManagedRunner__LogsContainerName', 'value', variables('runnerLogsContainerName')), createObject('name', 'ManagedRunner__SchedulerEnabled', 'value', 'true'), createObject('name', 'ManagedRunner__DefaultTimeZone', 'value', parameters('defaultTimeZone')), createObject('name', 'MaesterCloud__SetupAppOrigins', 'value', parameters('setupAppOrigins'))), variables('authenticationEnvironment'), variables('displayNameEnvironment'), variables('telemetryEnvironment'))]",
              "probes": [
                {
                  "type": "Liveness",
                  "httpGet": {
                    "path": "/health/live",
                    "port": 8080,
                    "scheme": "HTTP"
                  },
                  "initialDelaySeconds": 60,
                  "periodSeconds": 30,
                  "failureThreshold": 5
                }
              ]
            }
          ],
          "scale": {
            "minReplicas": 1,
            "maxReplicas": 1
          }
        }
      },
      "dependsOn": [
        "[extensionResourceId(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), 'Microsoft.Authorization/roleAssignments', guid(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'storage-blob-data-contributor'))]",
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName')))]",
        "[resourceId('Microsoft.Insights/components', format('appi-{0}', variables('workloadName')))]",
        "[extensionResourceId(resourceId('Microsoft.App/jobs', variables('runnerJobName')), 'Microsoft.Authorization/roleAssignments', guid(resourceId('Microsoft.App/jobs', variables('runnerJobName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'container-apps-jobs-operator'))]",
        "[extensionResourceId(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), 'Microsoft.Authorization/roleAssignments', guid(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), 'storage-table-data-contributor'))]",
        "[resourceId('Microsoft.App/managedEnvironments', variables('environmentName'))]",
        "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]",
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName')))]",
        "[resourceId('Microsoft.App/jobs', variables('runnerJobName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
      ]
    }
  ],
  "outputs": {
    "portalUrl": {
      "type": "string",
      "value": "[format('https://{0}', reference(resourceId('Microsoft.App/containerApps', variables('appName')), '2024-03-01').configuration.ingress.fqdn)]"
    },
    "containerAppFqdn": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.App/containerApps', variables('appName')), '2024-03-01').configuration.ingress.fqdn]"
    },
    "containerAppName": {
      "type": "string",
      "value": "[variables('appName')]"
    },
    "managedEnvironmentName": {
      "type": "string",
      "value": "[variables('environmentName')]"
    },
    "storageAccountName": {
      "type": "string",
      "value": "[variables('storageName')]"
    },
    "keyVaultName": {
      "type": "string",
      "value": "[variables('keyVaultName')]"
    },
    "keyVaultUri": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName')), '2023-07-01').vaultUri]"
    },
    "runnerJobName": {
      "type": "string",
      "value": "[variables('runnerJobName')]"
    },
    "appManagedIdentityClientId": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').clientId]"
    },
    "appManagedIdentityPrincipalId": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-app', variables('workloadName'))), '2023-01-31').principalId]"
    },
    "runnerManagedIdentityClientId": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').clientId]"
    },
    "runnerManagedIdentityPrincipalId": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format('id-{0}-runner', variables('workloadName'))), '2023-01-31').principalId]"
    }
  }
}