microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OAuth Provider Model for Azure ARM Template (Azure AD B2C)

jlind0 opened this issue · comments

So I am getting very close to being able to deploy my Botnet Framework "filtered channels" with Azure ARM Templates:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
  "parameters": {
    "botServices_courseware_coach_name": {
      "defaultValue": "courseware-coach",
      "type": "String"
    },
    "userAssignedIdentities_courseware_coach_externalid": {
      "defaultValue": "/subscriptions/a13458f4-4794-420a-8c6f-991cd3965346/resourceGroups/courseware-coach/providers/Microsoft.ManagedIdentity/userAssignedIdentities/courseware-coach",
      "type": "String"
    },
    "botType": {
      "defaultValue": "courseware-coach",
      "type": "String"
    },
    "subject": {
      "defaultValue": "courseware-coach",
      "type": "String"
    },
    "appId": {
      "defaultValue": "courseware-coach",
      "type": "String"
    },
    "clientSecret": {
      "defaultValue": "courseware-coach",
      "type": "String"
    }
  },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.BotService/botServices",
            "apiVersion": "2023-09-15-preview",
            "name": "[parameters('botServices_courseware_coach_name')]",
            "location": "global",
            "sku": {
                "name": "S1"
            },
            "kind": "azurebot",
          "properties": {
            "displayName": "[parameters('botServices_courseware_coach_name')]",
            "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
            "endpoint": "[concat('https://coursewarecoachbot.azurewebsites.net/api/messages?botType=', parameters('botType'), '&subject=', parameters('subject'))]",
            "msaAppId": "[parameters('appId')]",
            "msaAppTenantId": "88c25c7a-38aa-45d5-bd8d-e939dd68c4f2",
            "msaAppType": "UserAssignedMSI",
            "msaAppMSIResourceId": "[parameters('userAssignedIdentities_courseware_coach_externalid')]",
            "luisAppIds": [],
            "isStreamingSupported": true,
            "schemaTransformationVersion": "1.3",
            "tenantId": "88c25c7a-38aa-45d5-bd8d-e939dd68c4f2",
            "isCmekEnabled": false,
            "disableLocalAuth": false
          }
        },
        {
            "type": "Microsoft.BotService/botServices/channels",
            "apiVersion": "2023-09-15-preview",
            "name": "[concat(parameters('botServices_courseware_coach_name'), '/DirectLineChannel')]",
            "location": "global",
            "dependsOn": [
                "[resourceId('Microsoft.BotService/botServices', parameters('botServices_courseware_coach_name'))]"
            ],
            "properties": {
                "properties": {
                    "sites": [
                        {
                            "siteName": "Default Site",
                            "isEnabled": true,
                            "isV1Enabled": true,
                            "isV3Enabled": true,
                            "isSecureSiteEnabled": false,
                            "isBlockUserUploadEnabled": false
                        }
                    ],
                    "extensionKey1": "hbICYHvpMFw.bwCvSl9fiWBecIvmBDoYMaLKcA0vgOwg_S00vaPrVu8",
                    "extensionKey2": "hbICYHvpMFw.dXQW4hZrjdzDxN0jLGIoQUcLSahT4hy1lrKlrH8mkrU"
                },
                "etag": "W/\"2bb7433d23b1380c59ffbc6041efaf274/22/2024 9:34:35 AM\"",
                "channelName": "DirectLineChannel",
                "location": "global"
            }
        },
        {
            "type": "Microsoft.BotService/botServices/channels",
            "apiVersion": "2023-09-15-preview",
            "name": "[concat(parameters('botServices_courseware_coach_name'), '/WebChatChannel')]",
            "location": "global",
            "dependsOn": [
                "[resourceId('Microsoft.BotService/botServices', parameters('botServices_courseware_coach_name'))]"
            ],
            "properties": {
                "properties": {
                    "sites": [
                        {
                            "siteName": "Default Site",
                            "isEnabled": true,
                            "isWebchatPreviewEnabled": true,
                            "isBlockUserUploadEnabled": false
                        }
                    ]
                },
                "etag": "W/\"28160aeb414ff237c2653db978c8d58f4/22/2024 9:34:35 AM\"",
                "channelName": "WebChatChannel",
                "location": "global"
            }
        },
        {
            "type": "Microsoft.BotService/botServices/connections",
            "apiVersion": "2023-09-15-preview",
            "name": "[concat(parameters('botServices_courseware_coach_name'), '/Azure AD B2C')]",
            "location": "global",
            "dependsOn": [
                "[resourceId('Microsoft.BotService/botServices', parameters('botServices_courseware_coach_name'))]"
            ],
          "properties": {
            "serviceProviderDisplayName": "Azure Active Directory B2C",
            "id": "d86f045f-7ae7-8207-ddae-725dd8c2c35c_b7f05545-56ce-6cd4-e15a",
            "name": "Azure AD B2C",
            "clientId": "4a456ce3-bae5-4911-8042-4a17632644d1",
            "clientSecret": "[parameters('clientSecret')]"
          }
        }
    ]
}

Screenshot 2024-04-22 072015

The question I have is for those attributes what are the corresponding property names in the ARM template?

The following code deploys the ARM, however (obviously) the OAuth Provider is not configured properly.

public async Task<string?> DeployBot(string name, Guid subject, string botType = "coach", CancellationToken token = default)
{
    try
    {
        string clientId = Config["Portal:ClientId"] ?? throw new InvalidDataException();
        string clientSecret = Config["Portal:ClientSecret"] ?? throw new InvalidDataException();
        string tenantId = Config["Portal:TenantId"] ?? throw new InvalidDataException();
        string subscriptionId = Config["Portal:SubscriptionId"] ?? throw new InvalidDataException();
        string resourceGroupName = Config["Portal:ResourceGroupName"] ?? throw new InvalidDataException();
        string templateJson = File.ReadAllText("bot_template.json");
        string parametersJson = File.ReadAllText("bot_parameters.json");
        parametersJson = parametersJson.Replace("{{botType}}", botType);
        parametersJson = parametersJson.Replace("{{name}}", name);
        parametersJson = parametersJson.Replace("{{subject}}", subject.ToString());
        parametersJson = parametersJson.Replace("{{appId}}", Guid.NewGuid().ToString().ToLower());
        var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
        var azure = Microsoft.Azure.Management.Fluent.Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credentials).WithSubscription(subscriptionId);
        //var parameters = <Dictionary<string, Dictionary<string, object>>>(parametersJson, new JsonSerializerSettings());
        var deployment = await azure.Deployments.Define($"botDeployment{Guid.NewGuid()}")
            .WithExistingResourceGroup(resourceGroupName)
            .WithTemplate(templateJson)
            .WithParameters(JObject.Parse(parametersJson).GetValue("parameters"))
            .WithMode(DeploymentMode.Incremental)
            .CreateAsync();
        return deployment.CorrelationId;
    }
    catch(Exception ex)
    {
        Logger.LogError(ex, ex.Message);
        return null;
    }

}

@jlind0 While we use ARM templates ourselves, we are not the best source to get help from. We are consumers of it like yourself.