Overview
This blogs talks about how Bot APIs can be deployed in Intranet scenarios when the hosting environment for Bot API is App Services. App Services provide a straight forward way to deploy and scale bots using App Services capabilities such as publish to web or using CI/CD in Azure Devops and Github Actions. If bots are deployed using docker containers then this article may be helpful.
Customers would like to add bot functionality to intranet or internal applications and all APIs are also deployed internally and not exposed publicly. Even though Bot APIs can be secured in various ways when deployed with public endpoints, customers would still like to enforce a network boundary around BOT APIs.
Here is an architecture that shows this.
Key Components
Here are a few key components:
- Azure App Service Environment
This deploys Azure App Service instances inside a VNET and exposes the web apps over an internal IP address. Note that, public IP addresses can be created using external App Service Environments.
- Direct Line
This is an interface to your Bot API and provided by Azure Bot Service that can integrated into custom web pages using HTML/javascript.
- Direct Line App Service Extension
App Service extensions can be used to extend App Service with additional capabilities such as creating a separate process along side your main web application. Direct Line App Services extension is already pre-installed on all App Service instances but disabled. This needs to be configured.
- Azure Bot Service
This is a global resource that provides integration capabilities through channels to many different applications such as Slack, Teams, Alexa, Facebook etc. It also stores security keys to generate access tokens to bot clients to securely connect to Bot APIs. This also provides Speech to Text and Text to Speech services for IVR integrations.
- Bot API
This encapsulates the core bot functionality by providing the required business functionality and integrates with other services such as Azure Search, LUIS and Q/A maker. It also maintains conversation and user state throughout the bot conversation.
See it in action
If you would like to see this action in your own environment, please see below.
Prerequisites
- VNET with VPN gateway provisioned.
- Subnet for ASE.
- Provision ASE, App Service and App Service Plan.
- Create Azure Web App Bot resource.
- Point to Site configured on laptop to connect to VPN gateway.
- Visual Studio 2019 or later and .NET installed locally to publish Bot API.
- The steps below deploys an echo bot that basically echoes the user input. Just to keep the bot scenario simple.
Once you have this setup you can continue with creating and publishing a Bot API to ASE and access it over a private IP address.
Step 1:
Clone the Echo Bot from Botbuilder-sample github repo.
Step 2:
In startup.cs, add named pipe configuration to Direct Line. Line 21 below. This creates an endpoint for Direct Line which clients like Web Chat can connect to.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
// Set up custom content types - associating file extension to MIME type.
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".lu"] = "application/vnd.microsoft.lu";
provider.Mappings[".qna"] = "application/vnd.microsoft.qna";
// Expose static files in manifests folder for skill scenarios.
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = provider
});
app.UseWebSockets();
app.UseNamedPipes(System.Environment.GetEnvironmentVariable("APPSETTING_WEBSITE_SITE_NAME") + ".directline");
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Step 3:
Connect to the VPN Gateway over Point 2 Site VPN.
Step 4:
Retrieve private IP address from ASE.
Step 5:
Add the below entries to hosts file if your using Windows or to resolv.conf if you are using mac.
<app service name>.<ase name>.appserviceenvironment.net
<app service name>.scm.<ase name>.appserviceenvironment.net
Step 6:
Publish Echobot to Azure Web App created in the ASE using Visual Studio. You might need to import publishprofile from App Services in the Azure portal.
Step 7:
Configure Direct Line App Service Extension.
From Azure Web App Bot resource page in Azure Portal, create a channel for Direct Line and copy one of the keys in the App Service extension section.
Step 8:
Navigate to Azure Web App published in Step 6, under configuration create two settings, one for DIRECTLINE_EXTENSION_VERSION with value "latest" and another DirectLineExtensionKey with value of the key copied in step 7. Also enable Web Sockets.
Step 9:
This should configure the Bot API and Direct Line App Service extension. While still connected to VPN, navigate to the url below to verify if Bot API and Direct Line are connected and working correctly.
https://<app service name>.<ase name>.appserviceenvironment.net/.bot
You should get this response.
{"v":"1.0.0.0.55fa54091a1e3b168628d4000ee2b06a88bbc2ac","k":true,"ib":true,"ob":true,"initialized":true}
Step 10:
Create custom HTML page to host web chat and see it in action. Modify the bearer token and app service endpoint in the HTML below.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Full-featured bundle with Direct Line Speech channel</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--
This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to using Web Chat's latest bits:
https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
-->
<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 () {
// In this demo, we are using Direct Line token from MockBot.
// To talk to your bot, you should use the token exchanged using your Direct Line secret.
// You should never put the Direct Line secret in the browser or client app.
// https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
const res = await fetch('https://anildwaaseapp1.anildwaasev3.appserviceenvironment.net/.bot/v3/directline/tokens/generate', {
method: 'POST',
headers:{'Authorization':'Bearer ' + '<secret key from Direct Line channel in Azure Bot Service>'}
});
const { token } = await res.json();
window.WebChat.renderWebChat(
{
directLine: await window.WebChat.createDirectLineAppServiceExtension({
domain: 'https://<app service name >.<ase name>.appserviceenvironment.net/.bot/v3/directline',
token
})
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
})();
</script>
</body>
</html>
Step 11:
With laptop connected to VPN, browse to the HTML page and see the web chat in action.
When VPN is disconnected, the web chat is no longer able to connect to Bot API.
Conclusion
With the above approach we are able to deploy Bot APIs to ASEs in intranet scenarios, thus achieving the same fast deployment times enabled through few configuration steps and also enabling customers to deploy the Bot API in existing network boundaries.