Jump to content

Private Endpoint & Direct Line App Service Extension Configuration with Bot Services and App Service


Recommended Posts

Guest Shekhar
Posted

Private Endpoint and Direct Line App Service Extension Configuration with Azure Bot Service and Azure App Service.

 

We must place all the resources in the same region and under the same resource group.

 

Let's first create a simple Azure Bot and App Service and get the Bot working.

 

 

Please follow the steps below to create and configure Bot Service and App Service.

 

 

 

Create an App Service:

 

 

 

  • largevv2px999.thumb.png.5e9ced01ff7c3fb7a7ae73ff9204aa21.png
    Here I am creating a new resource group (directlineextension-RG) which we will use for all other resources we will create.
     
     
  • Runtime Stack: .NET 7 because I am going to use Bot sample code of .NET
  • OS - Windows
  • Region: East US
  • Keep rest of the settings default and Review + Create.

 

Create a Bot Service:

 

largevv2px999.thumb.png.8c712f6be8629e4821f7ca40ef35d638.png

 

  • Resource Group: directlineextension-RG
  • Type of App: Single Tenant (You can use Multi-Tenant or User Assigned Managed Identity)
  • Keep rest of the settings default and Review + Create.

 

Update the Messaging Endpoint of Bot:

 

 

Download the sample Bot code from below GitHub repository:

 

GitHub - microsoft/BotBuilder-Samples: Welcome to the Bot Framework samples repository. Here you will find task-focused samples in C#, JavaScript and TypeScript to help you get started with the Bot Framework SDK!

 

 

 

I am going to use Echo-Bot sample for .NET Core.

 

Open the code in your editor (I am using VS code) and update below 4 property values available at appsettings.json file:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

{

"MicrosoftAppType": "",

"MicrosoftAppId": "",

"MicrosoftAppPassword": "",

"MicrosoftAppTenantId": ""

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Please follow below steps to get the values for above properties:

 

  • Go to Bot Service -> Configuration
  • largevv2px999.png.a7adb3e2904db02ad24e288a6e50d5eb.png
    Copy Bot Type as value for "MicrosoftAppType"
     
     
  • Copy Microsoft App ID as value for "MicrosoftAppId"
  • Copy App Tenant ID as value for "MicrosoftAppTenantId"
  • To get the value for "MicrosoftAppPassword" (Needed only when Bot Type is either Single-Tenant or Multi-Tenant):
    • Go to Manage Passwordlargevv2px999.png.cd2224e3ee2d28c45d5e274362a6817d.png

    • Generate a new secret and copy the valuelargevv2px999.png.c4214d192b84203ec0c1b07a8177fa75.png
       
       

    • Save appsettings.json file and deploy the code to App Service.
       

 

Once code is deployed successfully to App Service, test the Bot using "Test in Web Chat".

 

largevv2px999.thumb.png.89bca700d4ac5a9a8cfdead9e4b85462.png

 

 

 

If everything is working as expected then we are good to go to next step.

 

 

 

Configure .NET bot for extension:

 

 

We will follow below article to configure .NET bot for extension:

 

Configure .NET bots for the Direct Line App Service extension in the Bot Framework SDK - Bot Service | Microsoft Learn

 

 

 

If your requirement is to use Nodejs bot then you must follow below document to configure Nodejs bot for extension:

 

Configure Node.js bots for Direct Line App Service extension in the Bot Framework SDK - Bot Service | Microsoft Learn

 

Prerequisites

 

 

 

 

  • A .NET bot deployed in Azure.
  • Bot Framework SDK for .NET, 4.14.1 or later.

 

We have fullfilled the prerequirsites.

 

 

 

Enable Direct Line App Service extension:

 

 

This section describes how to enable the Direct Line App Service extension using the App Service extension key from your bot's Direct Line channel configuration.

 

Update bot code

 

 

 

 

Spoiler (Highlight to read)

 

Note

 

The Microsoft.Bot.Builder.StreamingExtensions NuGet preview packages have been deprecated. Starting with v4.8, the SDK contains a Microsoft.Bot.Builder.Streaming namespace. If a bot previously made use of the preview packages, they must be removed before following the steps below.

 

Note The Microsoft.Bot.Builder.StreamingExtensions NuGet preview packages have been deprecated. Starting with v4.8, the SDK contains a Microsoft.Bot.Builder.Streaming namespace. If a bot previously made use of the preview packages, they must be removed before following the steps below.

  • open your bot project.
  • Allow your app to use named pipes:

    • Open the Startup.cs file.
       
       
    • Add a reference to the Microsoft.Bot.Builder.Integration.AspNet.Core NuGet package.
      using Microsoft.Bot.Builder.Integration.AspNet.Core;
    • add a call to the UseNamedPipes method as below:
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
      if (env.IsDevelopment())
      {
      app.UseDeveloperExceptionPage();
      }
       
      app.UseDefaultFiles()
      .UseStaticFiles()
      .UseWebSockets()
      // Allow the bot to use named pipes.
      .UseNamedPipes(System.Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_SITE_NAME") + ".directline")
      .UseRouting()
      .UseAuthorization()
      .UseEndpoints(endpoints =>
      {
      endpoints.MapControllers();
      });
       
      // app.UseHttpsRedirection();
      }

    • Save the Startup.cs file.
       
       
    • Now we need to change the hosting model from inproc to outofproc, please follow below steps:
    • Open .csproj file -> Add below line to the PropertyGroup
      <AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
    • As below:
      <PropertyGroup>
      <TargetFramework>netcoreapp3.1</TargetFramework>
      <LangVersion>latest</LangVersion>
      <AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
      </PropertyGroup>
    • Save the .csproj file.

    [*]Deploy your updated bot to Azure.

Enable bot Direct Line App Service extension

 

  • Go to your Azure Bot resource.
    • Under Settings select Channels to configure the channels your bot accepts messages from.
    • If it isn't already enabled, select the Direct Line channel from the list of Available channels to enable the channel.
    • After enabling Direct Line, select it again from the Channels page.
    • Select the App Service extension tab.
    • Under App Service Extension Keys, select the eye icon next to the corresponding key and copy.
    • largevv2px999.png.e65c9f2366a5bdaa50517054a3a233e4.png

    [*]Go to your App Service:


    • In the Settings section, select the Configuration menu item, add below "New application setting"
       
      Name Value
      DirectLineExtensionKey The value of the App Service extension key you copied earlier.
      DIRECTLINE_EXTENSION_VERSION latest
      DirectLineExtensionABSEndpoint https://<your_azure_bot>.privatelink.directline.botframework.com/v3/extension

       
       
       
       
    • Replace <your_azure_bot> with your Bot Service name (directlineextension in my case)

    • From within the Configuration section, select the General settings section and turn on Web sockets.
       
       
    • largevv2px999.png.4a2b3db38fbe19915ed4b391e0ae3834.png
      Select Save to save the settings. This restarts the Azure App Service.
       

Confirm the Direct Line extension and the bot are configured

 

 

In your browser, go to https://<your_app_service>.azurewebsites.net/.bot. If everything is correct, the page will return the following JSON content:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

{"v":"123","k":true,"ib":true,"ob":true,"initialized":true}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • v shows the build version of the Direct Line App Service extension.
  • k indicates whether the extension was able to read an extension key from its configuration.
  • initialized indicates whether the extension was able to download bot metadata from Azure Bot Service.
  • ib indicates whether the extension was able to establish an inbound connection to the bot.
  • ob indicates whether the extension was able to establish an outbound connection from the bot.

Troubleshooting


  • If the ib and ob values displayed by the .bot endpoint are false, the bot and the Direct Line App Service extension are unable to connect to each other.
     
    1. Double check the code for using named pipes has been added to the bot.
    2. Confirm the bot is able to start up and run. Useful tools are Test in WebChat, connecting an additional channel, remote debugging, or logging.
    3. Restart the entire Azure App Service the bot is hosted within, to ensure a clean start up of all processes.

    [*]

    If the initialized value of the .bot endpoint is false, the Direct Line App Service extension is unable to validate the App Service extension key added to the bot's Application Settings above.

     

    1. Confirm the value was correctly entered.
    2. Switch to the alternate extension key shown on your bot's Configure Direct Line page.


  • Enable the bot to use the out of process hosting model; otherwise, you'll receive an HTTP Error 500.34 - ANCM Mixed Hosting error (where ANCM stands for ASP.NET Core Module). This error occurs because the bot template is using the InProcess hosting model by default. To configure out of process hosting, see Out-of-process hosting model. For more information, see Attributes of the aspNetCore element and Configuration with web.config.
     
     
  • If you attempt to use OAuth with the Direct Line App Service extension and encounter the error "Unable to get the bot AppId from the audience claim", set ClaimsIdentity to AudienceClaim on the BotFrameworkHttpAdapter. To do so, you can subclass the adapter. For example:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

public class AdapterWithStaticClaimsIdentity : BotFrameworkHttpAdapter

{

public AdapterWithStaticClaimsIdentity(IConfiguration configuration, ILogger<BotFrameworkHttpAdapter> logger, ConversationState conversationState = null)

: base(configuration, logger)

{

// Manually create the ClaimsIdentity and create a Claim with a valid AudienceClaim and the AppID for a bot using the Direct Line App Service extension.

var appId = configuration.GetSection(MicrosoftAppCredentials.MicrosoftAppIdKey)?.Value;

ClaimsIdentity = new ClaimsIdentity(new List<Claim>{

new Claim(AuthenticationConstants.AudienceClaim, appId)

});

}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

If everything works as expected till this point then we are good to proceed to next step.

 

Configure network isolation:

 

 

You can add network isolation to an existing Direct Line App Service extension bot. A private endpoint lets your network isolated bot communicate with required Bot Framework services so that the bot can run correctly while being limited to the virtual network.

 

 

 

To add network isolation to your bot:

 

  • Use a virtual network and configure the network to prevent outbound traffic. At this point, your bot will lose the ability to communicate with other Bot Framework services.
  • Configure private endpoints to restore connectivity.
  • Restart you app service and test your bot within your isolated network.
  • Disable public network access to your bot.

Prerequisites

 

  • A working Direct Line App Service extension bot.
    • Your bot uses the Bot Framework SDK for C# or JavaScript, version 4.16 or later.
    • Your bot has named pipes enabled.
    • Your bot's app service has the Direct Line App Service extension enabled.

    [*]A Web Chat control connected to your bot's Direct Line client.

 

To confirm that your existing bot is configured correctly:

 

  • In a browser, open the Direct Line client endpoint for your bot. For example, https://<your-app_service>.azurewebsites.net/.bot
  • Verify the page displays the following
    {"v":"123","k":true,"ib":true,"ob":true,"initialized":true}
     
     
     
     
  • v shows the build version of the Direct Line App Service extension.
  • k indicates whether the extension was able to read an extension key from its configuration.
  • initialized indicates whether the extension was able to download bot metadata from Azure Bot Service.
  • ib indicates whether the extension was able to establish an inbound connection to the bot.
  • ob indicates whether the extension was able to establish an outbound connection from the bot.

Create a virtual network

 

  • Create an Azure Virtual Network resource:largevv2px999.thumb.png.bbd3b4ac435442955f5c93a088566ae9.png

  • Resource Group: directlineextension-RG
     
     
  • Region: East-US
  • Create 3 subnets (usually 2 is needed but we will create an VM to test the bot, for that we need another subnet):largevv2px999.png.3cabb6b17a724bd0dbd1fd496b2db2fa.png

  • Open the app service resource for your bot and enable virtual network integration.
     
     

  • Use the virtual network and subnet from the previous step.
     
    largevv2px999.png.fe6acc947714621d6e10bdc3ffe827a1.png
    largevv2px999.png.aca5ef270f4585d8a5144b717e4633c4.png
     

 

 

 

 

 

 

 

Deny outbound traffic from your network

 

  • Open the network security group associated with your first subnet.

    [*]Under Settings, select Outbound security rules.

    • In the outbound security rules list, enable DenyAllInternetOutbound.largevv2px999.thumb.png.7e4f861056a1c6dd911e2b6a8db3f161.png
       
       

    [*]Configure this new NSG to the subnet (subnet-appservice)largevv2px999.thumb.png.8843acac59a42399c88b864c15fe2179.png

     

     

     

    [*]Go to the app service resource for your bot.

    [*]Restart your app service.

Verify that connectivity is broken

 


  • In a separate browser tab, open the Direct Line client endpoint for your bot. For example, https://<your-app_service>.azurewebsites.net/.bot.
     
     
  • Verify the page displays the following:
    {"v":"123","k":true,"ib":true,"ob":true,"initialized":false}
     
     
     

 

The value of initialized should be false, because your app service and app service extension are unable to connect to other Bot Framework services to initialize itself. Your bot is now isolated in a virtual network for outbound connections.

 

 

 

Create your private endpoint

 

  • Go to your Azure Bot resource
  • Under Settings, select Networking.
    • On the Private access tab and select Create a private endpoint.
      • On the Resource tab, for Target sub-resource, select Bot from the list.
      • On the Virtual Network tab, select your virtual network and the second subnet you created.
      • Save your private endpoint.largevv2px999.png.fc0a62dc17f3a6552b6bcc1f8c926311.png
         
         
        largevv2px999.png.69db3a5cb8109a38967dde0801fabbfd.png
         
         
        largevv2px999.png.f9e718dfbdfe27a30c0e505ff3dca769.png
         
         
        largevv2px999.png.e2a5daa229c7d45515ca946b8351e79f.png

      • Keep the rest settings default and Review + Create.
         
        largevv2px999.png.54607fbc2e2f3e5b49c7eb19a5389310.png
         
         

Add your private endpoint to your bot's app service

 

  • Go to your App Service
  • Settings -> Configuration
  • On the Application settings tab, select New application setting.
    • Set Name to DirectLineExtensionABSEndpoint.
    • Set Value to the private endpoint URL, for example, https://<your_azure_bot>.privatelink.directline.botframework.com/v3/extension.
    • Replace <your_azure_bot> with your Bot Name.
    • Save the new setting.

    [*]Settings -> Networking -> Private Endpoint -> Add -> Create Private endpoint and select any subnet from the configured vnet.largevv2px999.png.06932f4374e47dea8630af289bd1b41a.png

     

     

    largevv2px999.png.aef0d9311398e647bd955e9f70a23530.png

     

     

    largevv2px999.thumb.png.3a1facda5f4ad9b9a4fd942ba0d58d38.png

     

     

 

 

Restart your app service and verify that connectivity is restored

 


  • Restart the app service for your bot.
     
     
  • In a separate browser tab, open the Direct Line client endpoint for your bot. For example, https://<your-app_service>.azurewebsites.net/.bot
  • Verify the page displays the following:
    {"v":"123","k":true,"ib":true,"ob":true,"initialized":true}
     
     
     

 

The value of initialized should be true.

 

If your private endpoint doesn't work correctly, you can add a rule to allow outbound traffic to NSG configured with the App Service subnet (subnet-appservice) specifically to Azure Bot Service.

 

 

 

 

 

 

 

 

 

This will make you virtual network a little less isolated.

 

 

 

 

 

 

 

 

 

 

 

  • Open the network security group associated with your first subnet.
  • Under Settings, select Outbound security rules.
    • In the outbound security rules list, enable AllowAzureBotService.

    [*]Go to the app service resource for your bot.

    [*]Restart your app service.

    [*]

    In a separate browser tab, open the Direct Line client endpoint for your bot again. For example, https://<your-app_service>.azurewebsites.net/.bot.

     

     

    [*]Verify the page displays the following:

    {"v":"123","k":true,"ib":true,"ob":true,"initialized":true}

 

 

 

 

Disable public network access to your bot

 

  • Go to App Service -> Settings -> Networking -> Access restriction -> Uncheck Allow public access checkbox and Save.largevv2px999.png.1c7885ff03db88625b95e8f531390f08.png
     
     

 

If you try to browse the App Service URL and the Pipe URL, you would not get any response.

 

 

 

Now, lets create a client to test the Bot. We will use below article to get the required HTML and replace the required values:

 

Use Web Chat with the Direct Line App Service extension in Bot Framework SDK - Bot Service | Microsoft Learn

 

 

 

Copy the provided HTML:

 

<!DOCTYPE html>

<html lang="en-US">

<head>

<title>Web Chat</title>

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<script

crossorigin="anonymous"

src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"

></script>

<style>

html,

body {

background-color: #f7f7f7;

height: 100%;

}

 

body {

margin: 0;

}

 

#webchat {

box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);

height: 100%;

margin: auto;

max-width: 480px;

min-width: 360px;

}

</style>

</head>

<body>

<div id="webchat" role="main"></div>

<script>

(async function() {

<!-- NOTE: You should replace the below fetch with a call to your own token service as described in step 2 above, to avoid exposing your channel secret in client side code. -->

const res = await fetch('https://<your_app_service>.azurewebsites.net/.bot/v3/directline/tokens/generate',

{

"method": "POST",

"headers": {

"Authorization": "Bearer " + "<Your Bot's Direct Line channel secret>"

},

"body": "{'user': {'id': 'my_test_id', 'name': 'my_test_name'}}"

}

);

const { token } = await res.json();

 

window.WebChat.renderWebChat(

{

directLine: await window.WebChat.createDirectLineAppServiceExtension({

domain: 'https://<your_app_service>.azurewebsites.net/.bot/v3/directline',

token

})

},

document.getElementById('webchat')

);

 

document.querySelector('#webchat > *').focus();

})().catch(err => console.error(err));

</script>

</body>

</html>

 

 

 

Replace <your_app_service> with your App Service name in 2 places hightlighed in the HTML above.

 

Replace <Your Bot's Direct Line channel secret> with the Direct line channel secret:

 

largevv2px999.png.63993dd6c08b8a432ee5d73ed6f618b0.png

 

 

 

Now run the client in the machine, which is part of the same vnet, configured here as part of the private endpoint.

 

 

 

For testing purpose, we will create a Virtual Machine and configure this VM to be part of same vnet which is configured with App Service and Bot Service.

 

 

 

Create a VM:

 

 

largevv2px999.png.45e12bcd7d671805533eeeffc496927b.png

 

  • Resource group: directlineextention-RG (same as Bot and App Service).
  • Region: East US (same as Bot and App Service).

  • largevv2px999.png.df1f4e1283183573f027db0a8bfc0506.png
    In the networking section, configure the same vnet and subnet (subnet-vm) we have created earlier for VM.
     
     
  • Keep rest of the settings as default and Review + Create.

 

Once VM is created successfully, login to VM and take the client HTML created earlier and run inside the VM.

 

It must work without any issue and you must see the expected response from the Bot.

 

largevv2px999.thumb.png.c3827aee4bc1db2ae1e02e7b76a0f0d7.png

 

 

 

You must be albe to use pipe URL too, inside the VM:

 

largevv2px999.png.c8b0fc8ff5f297674651a7d0de2202ab.png

 

Continue reading...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...