diff --git a/docs/how-to-guides/azure-deployment.md b/docs/how-to-guides/azure-deployment.md index 4df308cdb..635dfb227 100644 --- a/docs/how-to-guides/azure-deployment.md +++ b/docs/how-to-guides/azure-deployment.md @@ -15,10 +15,35 @@ Feathr has native cloud integration and getting started with Feathr is very stra 1. Get the principal ID of your account by running `az ad signed-in-user show --query id -o tsv` in the link below (Select "Bash" if you are asked to choose one), and write down that value (will be something like `b65ef2e0-42b8-44a7-9b55-abbccddeefff`) - [Launch Cloud Shell](https://shell.azure.com/bash) -2. Click the button below to deploy a minimal set of Feathr resources. This is not for production use as we choose a minimal set of resources, but treat it as a template that you can modify for further use. Note that you should have "Owner" access in your subscription to perform some of the actions. + +2. To enable authentication on the Feathr UI (which gets created as part of the deployment script) we need to create an Azure Active Directory (AAD) application. Currently it is not possible to create one through ARM template but you can easily create one by running the following CLI commands in the [Cloud Shell](https://shell.azure.com/bash) + +```bash +# This is the prefix you want to name your resources with, make a note of it, you will need it during deployment. +prefix="YOUR_RESOURCE_PREFIX" + +# Please don't change this name, a corresponding webapp with same name gets created in subsequent steps. +sitename="${prefix}webapp" + +# This will create the Azure AD application, note that we need to create an AAD app of platform type Single Page Application(SPA). By default passing the redirect-uris with create command creates an app of type web. +az ad app create --display-name $sitename --sign-in-audience AzureADMyOrg --web-home-page-url "https://$sitename.azurewebsites.net" --enable-id-token-issuance true + +#Fetch the ClientId, TenantId and ObjectId for the created app +aad_clientId=$(az ad app list --display-name $sitename --query [].appId -o tsv) +aad_objectId=$(az ad app list --display-name $sitename --query [].id -o tsv) +aad_tenantId=$(az account tenant list --query [].tenantId -o tsv) + +# Updating the SPA app created above, currently there is no CLI support to add redirectUris to a SPA, so we have to patch manually via az rest +az rest --method PATCH --uri "https://graph.microsoft.com/v1.0/applications/$aad_objectId" --headers "Content-Type=application/json" --body "{spa:{redirectUris:['https://$sitename.azurewebsites.net/.auth/login/aad/callback']}}" + +# Make a note of the ClientId and TenantId, you will need it during deployment. +echo "AAD_CLIENT_ID: $aad_clientId" +echo "AZURE_TENANT_ID: $aad_tenantId" +``` + +3. Click the button below to deploy a minimal set of Feathr resources. This is not for production use as we choose a minimal set of resources, but treat it as a template that you can modify for further use. Note that you should have "Owner" access in your subscription to perform some of the actions. [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Flinkedin%2Ffeathr%2Fmain%2Fdocs%2Fhow-to-guides%2Fazure_resource_provision.json) diff --git a/docs/how-to-guides/azure_resource_provision.json b/docs/how-to-guides/azure_resource_provision.json index ea7c0ad0e..44dff8b16 100644 --- a/docs/how-to-guides/azure_resource_provision.json +++ b/docs/how-to-guides/azure_resource_provision.json @@ -18,7 +18,7 @@ }, "allowAllConnections": { "defaultValue": "true", - "allowedValues": ["true", "false"], + "allowedValues": [ "true", "false" ], "type": "String", "metadata": { "description": "Specifies whether to allow client IPs to connect to Synapse" @@ -26,7 +26,7 @@ }, "provisionPurview": { "defaultValue": "true", - "allowedValues": ["true", "false"], + "allowedValues": [ "true", "false" ], "type": "String", "metadata": { "description": "Whether or not put purview in the provision script" @@ -34,12 +34,31 @@ }, "provisionEventHub": { "defaultValue": "true", - "allowedValues": ["true", "false"], + "allowedValues": [ "true", "false" ], "type": "String", "metadata": { "description": "Whether or not to deploy eventhub provision script" } - } + }, + "dockerImage": { + "defaultValue": "blrchen/feathr-sql-registry", + "type": "String", + "metadata": { + "description": "The flavor of the registry backend to deploy, current supported types are Azure Purview and Azure SQL" + } + }, + "aadClientId": { + "type": "String", + "metadata": { + "description": "Client Id of the Azure Active Directory (AAD) app provisioned for UI app authentication in the prior step." + } + }, + "aadTenantId": { + "type": "String", + "metadata": { + "description": "Tenant Id of the Azure Active Directory (AAD) app provisioned for UI app authentication in the prior step." + } + } }, "variables": { "location": "[resourceGroup().location]", @@ -62,7 +81,11 @@ "roleDefinitionIdForBlobContributor": "ba92f5b4-2d11-453d-a403-e96b0029c9fe", "roleDefinitionIdForKeyVaultSecretsUser": "4633458b-17de-408a-b874-0445c86b69e6", "roleAssignmentNameForBlobContributor": "[guid(parameters('principalId'), variables('roleDefinitionIdForBlobContributor'), resourceGroup().id)]", - "roleAssignmentNameForKeyVaultSecretsUser": "[guid(parameters('principalId'), variables('roleDefinitionIdForKeyVaultSecretsUser'), resourceGroup().id)]" + "roleAssignmentNameForKeyVaultSecretsUser": "[guid(parameters('principalId'), variables('roleDefinitionIdForKeyVaultSecretsUser'), resourceGroup().id)]", + "webAppName": "[concat(parameters('resourcePrefix'),'webapp' )]", + "webAppPlanName": "[concat(parameters('resourcePrefix'),'appplan' )]", + "webAppPlanSku": "P1v2", + "webAppAPIVersion": "2021-03-01" }, "functions": [], "resources": [ @@ -87,7 +110,7 @@ "apiVersion": "2021-10-01", "name": "[concat(variables('keyVaultName'), '/FEATHR-PREFIX')]", "location": "[resourceGroup().location]", - "dependsOn": ["[variables('keyVault')]"], + "dependsOn": [ "[variables('keyVault')]" ], "properties": { "value": "[parameters('resourcePrefix')]" } @@ -116,7 +139,7 @@ "apiVersion": "2021-10-01", "name": "[concat(variables('keyVaultName'), '/FEATHR-ONLINE-STORE-CONN')]", "location": "[resourceGroup().location]", - "dependsOn": ["[variables('keyVault')]", "[variables('redisCache')]"], + "dependsOn": [ "[variables('keyVault')]", "[variables('redisCache')]" ], "properties": { "value": "[concat(variables('redisCacheName'),'.redis.cache.windows.net:6380,password=', listKeys(concat('Microsoft.Cache/redis/', variables('redisCacheName')), '2021-06-01').primaryKey, ',ssl=True')]" } @@ -126,7 +149,7 @@ "apiVersion": "2021-10-01", "name": "[concat(variables('keyVaultName'), '/REDIS-PASSWORD')]", "location": "[resourceGroup().location]", - "dependsOn": ["[variables('keyVault')]", "[variables('redisCache')]"], + "dependsOn": [ "[variables('keyVault')]", "[variables('redisCache')]" ], "properties": { "value": "[listKeys(concat('Microsoft.Cache/redis/', variables('redisCacheName')), '2021-06-01').primaryKey]" } @@ -153,7 +176,7 @@ "type": "blobServices/containers", "apiVersion": "2021-08-01", "name": "[concat('default/', variables('dlsFsName'))]", - "dependsOn": ["[variables('dlsName')]"], + "dependsOn": [ "[variables('dlsName')]" ], "properties": { "publicAccess": "None" } @@ -196,7 +219,7 @@ "type": "eventhubs", "apiVersion": "2021-11-01", "name": "[variables('eventhubName')]", - "dependsOn": ["[variables('eventhubNameSpace')]"], + "dependsOn": [ "[variables('eventhubNameSpace')]" ], "properties": {} }, { @@ -204,7 +227,6 @@ "type": "Microsoft.KeyVault/vaults/secrets", "apiVersion": "2021-10-01", "name": "[concat(variables('keyVaultName'), '/EVENTHUB-POLICY-KEY')]", - "condition": "[equals(parameters('provisionEventHub'),'true')]", "location": "[resourceGroup().location]", "dependsOn": [ "[variables('keyVault')]", @@ -221,7 +243,7 @@ "apiVersion": "2021-06-01", "name": "[variables('workspaceName')]", "location": "[variables('location')]", - "dependsOn": ["[variables('dlsName')]", "[variables('dlsFsName')]"], + "dependsOn": [ "[variables('dlsName')]", "[variables('dlsFsName')]" ], "identity": { "type": "SystemAssigned" }, @@ -238,7 +260,7 @@ "apiVersion": "2021-06-01", "name": "allowAll", "location": "[variables('location')]", - "dependsOn": ["[variables('workspaceName')]"], + "dependsOn": [ "[variables('workspaceName')]" ], "properties": { "startIpAddress": "0.0.0.0", "endIpAddress": "255.255.255.255" @@ -250,7 +272,7 @@ "apiVersion": "2021-06-01", "name": "AllowAllWindowsAzureIps", "location": "[variables('location')]", - "dependsOn": ["[variables('workspaceName')]"], + "dependsOn": [ "[variables('workspaceName')]" ], "properties": { "startIpAddress": "0.0.0.0", "endIpAddress": "0.0.0.0" @@ -261,7 +283,7 @@ "apiVersion": "2021-06-01", "name": "default", "location": "[variables('location')]", - "dependsOn": ["[variables('workspaceName')]"], + "dependsOn": [ "[variables('workspaceName')]" ], "properties": { "grantSqlControlToManagedIdentity": { "desiredState": "Enabled" @@ -270,12 +292,70 @@ } ] }, + { + "type": "Microsoft.Web/serverfarms", + "apiVersion": "[variables('webAppAPIVersion')]", + "name": "[variables('webAppPlanName')]", + "location": "[variables('location')]", + "sku": { + "name": "[variables('webAppPlanSku')]" + }, + "kind": "linux", + "properties": { + "reserved": true + } + }, + { + "type": "Microsoft.Web/sites", + "apiVersion": "[variables('webAppAPIVersion')]", + "name": "[variables('webAppName')]", + "location": "[variables('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('webAppPlanName'))]" + ], + "kind": "app,linux,container", + "identity": { + "type": "systemAssigned" + }, + "properties": { + "name": "[variables('webAppName')]", + "httpsOnly": "true", + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('webAppPlanName'))]", + "siteConfig": { + "linuxFxVersion": "[concat('DOCKER|', parameters('dockerImage'))]", + "alwaysOn": true, + "ftpsState": "Disabled", + "appSettings": [ + { + "name": "DOCKER_REGISTRY_SERVER_URL", + "value": "https://index.docker.io/v1" + }, + { + "name": "AZURE_CLIENT_ID", + "value": "[parameters('aadClientId')]" + }, + { + "name": "AZURE_TENANT_ID", + "value": "[parameters('aadTenantId')]" + }, + { + "name": "API_BASE", + "value": "api/v1" + }, + { + "name": "CONNECTION_STR", + "value": "TODO_ONCE_SQL_PR_IS_MERGED" + } + ] + } + } + }, { "type": "Microsoft.Synapse/workspaces/bigDataPools", "apiVersion": "2021-06-01", "name": "[concat(variables('workspaceName'), '/', variables('sparkPoolName'))]", "location": "[variables('location')]", - "dependsOn": ["[variables('workspaceName')]"], + "dependsOn": [ "[variables('workspaceName')]" ], "properties": { "autoPause": { "delayInMinutes": 30, @@ -296,7 +376,7 @@ "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2020-10-01-preview", "name": "[variables('roleAssignmentNameForBlobContributor')]", - "dependsOn": ["[variables('dlsAccount')]"], + "dependsOn": [ "[variables('dlsAccount')]" ], "properties": { "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionIdForBlobContributor'))]", "principalId": "[parameters('principalId')]", @@ -307,7 +387,7 @@ "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2020-10-01-preview", "name": "[variables('roleAssignmentNameForKeyVaultSecretsUser')]", - "dependsOn": ["[variables('keyVault')]"], + "dependsOn": [ "[variables('keyVault')]" ], "properties": { "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionIdForKeyVaultSecretsUser'))]", "principalId": "[parameters('principalId')]",