From 1bf2a172dade87b0fff633bfcf77038d811419e4 Mon Sep 17 00:00:00 2001 From: JhontSouth Date: Wed, 11 Oct 2023 13:25:15 -0500 Subject: [PATCH 1/2] add SNI authentication .net sample --- README.md | 2 + .../AdapterWithErrorHandler.cs | 50 +++ .../AuthSNIBot.csproj | 21 + .../Bots/AuthCertificateBot.cs | 33 ++ .../Bots/DialogBot.cs | 50 +++ .../Controllers/BotController.cs | 35 ++ ...ameters-for-template-AzureBot-with-rg.json | 33 ++ ...arameters-for-template-BotApp-with-rg.json | 48 ++ .../DeployUseExistResourceGroup/readme.md | 48 ++ .../template-AzureBot-with-rg.json | 121 +++++ .../template-BotApp-with-rg.json | 191 ++++++++ ...rameters-for-template-AzureBot-new-rg.json | 39 ++ ...parameters-for-template-BotApp-new-rg.json | 48 ++ .../DeployWithNewResourceGroup/readme.md | 45 ++ .../template-AzureBot-new-rg.json | 160 +++++++ .../template-BotApp-new-rg.json | 213 +++++++++ .../85.bot-authentication-sni/Program.cs | 29 ++ .../Properties/launchSettings.json | 27 ++ .../85.bot-authentication-sni/README.md | 126 ++++++ .../85.bot-authentication-sni/Startup.cs | 102 +++++ .../appsettings.json | 7 + .../wwwroot/default.htm | 417 ++++++++++++++++++ .../csharp_dotnetcore/csharp_dotnetcore.sln | 10 + 23 files changed, 1855 insertions(+) create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/AdapterWithErrorHandler.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/DialogBot.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Controllers/BotController.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/readme.md create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/readme.md create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Program.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Properties/launchSettings.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/README.md create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/appsettings.json create mode 100644 samples/csharp_dotnetcore/85.bot-authentication-sni/wwwroot/default.htm diff --git a/README.md b/README.md index 1dc5e191e4..fb3122d682 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ Samples are designed to illustrate functionality you'll need to implement to bui |24|MSGraph authentication | Demonstrates bot authentication capabilities of Azure Bot Service. Demonstrates utilizing the Microsoft Graph API to retrieve data about the user.|[.NET Core][cs#24] |[JavaScript][js#24] |[Python][py#24]|[Java][java#24] |46|Teams authentication | Demonstrates how to use authentication for a bot running in Microsoft Teams. | [.NET Core](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/csharp) | [JavaScript](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js) |[Python](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/python)|[Java](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/java) |84|Certificate authentication | Demonstrates how to use Certificates to authenticate the bot | |[JavaScript][js#84] | | +|85|Subject name/issuer authentication | Demonstrates how to use the subject name/issuer authentication in a bot | [.NET Core][cs#85] | | | ### Custom question answering samples @@ -141,6 +142,7 @@ A [collection of **experimental** samples](./experimental) exist, intended to pr [cs#80]:samples/csharp_dotnetcore/80.skills-simple-bot-to-bot [cs#81]:samples/csharp_dotnetcore/81.skills-skilldialog [cs#82]:samples/csharp_dotnetcore/82.skills-sso-cloudadapter +[cs#85]:samples/csharp_dotnetcore/85.bot-authentication-sni [wa#13]:samples/csharp_webapi/13.core-bot diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/AdapterWithErrorHandler.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/AdapterWithErrorHandler.cs new file mode 100644 index 0000000000..6761e30a1d --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/AdapterWithErrorHandler.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; +using Microsoft.Bot.Builder.TraceExtensions; +using Microsoft.Bot.Connector.Authentication; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + public class AdapterWithErrorHandler : CloudAdapter + { + public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ILogger logger, ConversationState conversationState = default) + : base(auth, logger) + { + OnTurnError = async (turnContext, exception) => + { + // Log any leaked exception from the application. + // NOTE: In production environment, you should consider logging this to + // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how + // to add telemetry capture to your bot. + logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); + + // Send a message to the user + await turnContext.SendActivityAsync("The bot encountered an error or bug."); + await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); + + if (conversationState != null) + { + try + { + // Delete the conversationState for the current conversation to prevent the + // bot from getting stuck in a error-loop caused by being in a bad state. + // ConversationState should be thought of as similar to "cookie-state" in a Web pages. + await conversationState.DeleteAsync(turnContext); + } + catch (Exception e) + { + logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); + } + } + + // Send a trace activity, which will be displayed in the Bot Framework Emulator + await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); + }; + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj b/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj new file mode 100644 index 0000000000..a2a846376c --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + latest + + + + + + + + + + + + + Always + + + diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs new file mode 100644 index 0000000000..463bd2e6ef --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + public class AuthCertificateBot : ActivityHandler + { + protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) + { + foreach (var member in turnContext.Activity.MembersAdded) + { + if (member.Id != turnContext.Activity.Recipient.Id) + { + await turnContext.SendActivityAsync(MessageFactory.Text("Welcome to the Bot with Subject Name/Issuer Authentication."), cancellationToken); + } + } + } + + protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) + { + var replyText = "Running dialog with bot authenticated"; + await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken); + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/DialogBot.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/DialogBot.cs new file mode 100644 index 0000000000..5136835d99 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/DialogBot.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + // This IBot implementation can run any type of Dialog. The use of type parameterization is to allows multiple different bots + // to be run at different endpoints within the same project. This can be achieved by defining distinct Controller types + // each with dependency on distinct IBot types, this way ASP Dependency Injection can glue everything together without ambiguity. + // The ConversationState is used by the Dialog system. The UserState isn't, however, it might have been used in a Dialog implementation, + // and the requirement is that all BotState objects are saved at the end of a turn. + public class DialogBot : ActivityHandler where T : Dialog + { + protected readonly BotState ConversationState; + protected readonly Dialog Dialog; + protected readonly ILogger Logger; + protected readonly BotState UserState; + + public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger> logger) + { + ConversationState = conversationState; + UserState = userState; + Dialog = dialog; + Logger = logger; + } + + public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) + { + await base.OnTurnAsync(turnContext, cancellationToken); + + // Save any state changes that might have occurred during the turn. + await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken); + await UserState.SaveChangesAsync(turnContext, false, cancellationToken); + } + + protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) + { + Logger.LogInformation("Running dialog with Message Activity."); + + // Run the Dialog with the new message Activity. + await Dialog.RunAsync(turnContext, ConversationState.CreateProperty(nameof(DialogState)), cancellationToken); + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Controllers/BotController.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Controllers/BotController.cs new file mode 100644 index 0000000000..fa4ea81324 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Controllers/BotController.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; + +namespace Microsoft.BotBuilderSamples +{ + // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot + // implementation at runtime. Multiple different IBot implementations running at different endpoints can be + // achieved by specifying a more specific type for the bot constructor argument. + [Route("api/messages")] + [ApiController] + public class BotController : ControllerBase + { + private readonly IBotFrameworkHttpAdapter _adapter; + private readonly IBot _bot; + + public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) + { + _adapter = adapter; + _bot = bot; + } + + [HttpPost] + public async Task PostAsync() + { + // Delegate the processing of the HTTP POST to the adapter. + // The adapter will invoke the bot. + await _adapter.ProcessAsync(Request, Response, _bot); + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json new file mode 100644 index 0000000000..c2c03ef307 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "azureBotId": { + "value": "" + }, + "azureBotSku": { + "value": "S1" + }, + "azureBotRegion": { + "value": "global" + }, + "botEndpoint": { + "value": "" + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json new file mode 100644 index 0000000000..c4b2909008 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "appServiceName": { + "value": "" + }, + "existingAppServicePlanName": { + "value": "" + }, + "existingAppServicePlanLocation": { + "value": "" + }, + "newAppServicePlanName": { + "value": "" + }, + "newAppServicePlanLocation": { + "value": "" + }, + "newAppServicePlanSku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + } + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "appSecret": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/readme.md b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/readme.md new file mode 100644 index 0000000000..628f0a9546 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/readme.md @@ -0,0 +1,48 @@ +# Usage +The BotApp must be deployed prior to AzureBot. + +Command line: +- az login +- az deployment group create --resource-group --template-file --parameters @ + +# parameters-for-template-BotApp-with-rg: + +- **appServiceName**:(required) The Name of the Bot App Service. + +- (choose an existingAppServicePlan or create a new AppServicePlan) + - **existingAppServicePlanName**: The name of the App Service Plan. + - **existingAppServicePlanLocation**: The location of the App Service Plan. + - **newAppServicePlanName**: The name of the App Service Plan. + - **newAppServicePlanLocation**: The location of the App Service Plan. + - **newAppServicePlanSku**: The SKU of the App Service Plan. Defaults to Standard values. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** + +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. + +- **appSecret**:(required for MultiTenant and SingleTenant) Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. + +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. + +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. + +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource + + + +# parameters-for-template-AzureBot-with-rg: + +- **azureBotId**:(required) The globally unique and immutable bot ID. +- **azureBotSku**: The pricing tier of the Bot Service Registration. **Allowed values are: F0, S1(default)**. +- **azureBotRegion**: Specifies the location of the new AzureBot. **Allowed values are: global(default), westeurope**. +- **botEndpoint**: Use to handle client messages, Such as https://.azurewebsites.net/api/messages. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json new file mode 100644 index 0000000000..a8a960066f --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "azureBotId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID." + } + }, + "azureBotSku": { + "type": "string", + "defaultValue": "S1", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Allowed values are: F0, S1(default)." + } + }, + "azureBotRegion": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Specifies the location of the new AzureBot. Allowed values are: global(default), westeurope." + } + }, + "botEndpoint": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use to handle client messages, Such as https://.azurewebsites.net/api/messages." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + } + }, + "variables": { + "botEndpoint": "[if(empty(parameters('botEndpoint')), concat('https://', parameters('azureBotId'), '.azurewebsites.net/api/messages'), parameters('botEndpoint'))]", + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "msiResourceId": "" + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "" + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "[variables('msiResourceId')]" + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "msiResourceId": "[variables('appTypeDef')[parameters('appType')].msiResourceId]" + } + }, + "resources": [ + { + "apiVersion": "2021-05-01-preview", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('azureBotId')]", + "location": "[parameters('azureBotRegion')]", + "kind": "azurebot", + "sku": { + "name": "[parameters('azureBotSku')]" + }, + "properties": { + "displayName": "[parameters('azureBotId')]", + "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "msaAppTenantId": "[variables('appType').tenantId]", + "msaAppMSIResourceId": "[variables('appType').msiResourceId]", + "msaAppType": "[parameters('appType')]", + "luisAppIds": [], + "schemaTransformationVersion": "1.3", + "isCmekEnabled": false, + "isIsolated": false + }, + "dependsOn": [] + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json new file mode 100644 index 0000000000..ce3bb6322a --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json @@ -0,0 +1,191 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "appServiceName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The globally unique name of the Web App." + } + }, + "existingAppServicePlanName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Name of the existing App Service Plan used to create the Web App for the bot." + } + }, + "existingAppServicePlanLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "newAppServicePlanName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The name of the new App Service Plan." + } + }, + "newAppServicePlanLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "newAppServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Required for MultiTenant and SingleTenant app types. Defaults to \"\"." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication. Defaults to \"\"." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. Defaults to \"\"." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + } + }, + "variables": { + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "useExistingServicePlan": "[not(empty(parameters('existingAppServicePlanName')))]", + "servicePlanName": "[if(variables('useExistingServicePlan'), parameters('existingAppServicePlanName'), parameters('newAppServicePlanName'))]", + "servicePlanLocation": "[if(variables('useExistingServicePlan'), parameters('existingAppServicePlanLocation'), parameters('newAppServicePlanLocation'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "identity": { "type": "None" } + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "identity": { "type": "None" } + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[variables('msiResourceId')]": {} + } + } + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "identity": "[variables('appTypeDef')[parameters('appType')].identity]" + } + }, + "resources": [ + { + "comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.", + "type": "Microsoft.Web/serverfarms", + "condition": "[not(variables('useExistingServicePlan'))]", + "name": "[variables('servicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[parameters('newAppServicePlanLocation')]", + "sku": "[parameters('newAppServicePlanSku')]", + "properties": { + "name": "[variables('servicePlanName')]" + } + }, + { + "comments": "Create a Web App using an App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "location": "[variables('servicePlanLocation')]", + "kind": "app", + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]" + ], + "name": "[parameters('appServiceName')]", + "identity": "[variables('appType').identity]", + "properties": { + "name": "[parameters('appServiceName')]", + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]", + "siteConfig": { + "appSettings": [ + { + "name": "WEBSITE_NODE_DEFAULT_VERSION", + "value": "10.14.1" + }, + { + "name": "MicrosoftAppType", + "value": "[parameters('appType')]" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + }, + { + "name": "MicrosoftAppTenantId", + "value": "[variables('appType').tenantId]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + }, + "webSocketsEnabled": true + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json new file mode 100644 index 0000000000..44f169e4d5 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "value": "" + }, + "groupLocation": { + "value": "" + }, + "azureBotId": { + "value": "" + }, + "azureBotSku": { + "value": "S1" + }, + "azureBotRegion": { + "value": "global" + }, + "botEndpoint": { + "value": "" + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json new file mode 100644 index 0000000000..8abb03d597 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "value": "" + }, + "groupLocation": { + "value": "" + }, + "appServiceName": { + "value": "" + }, + "appServicePlanName": { + "value": "" + }, + "appServicePlanLocation": { + "value": "" + }, + "appServicePlanSku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + } + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "appSecret": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/readme.md b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/readme.md new file mode 100644 index 0000000000..23bf7a5a51 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/readme.md @@ -0,0 +1,45 @@ +# Usage +The BotApp must be deployed prior to AzureBot. + +Command line: +- az login +- az deployment sub create --template-file --location --parameters @ + +# parameters-for-template-BotApp-new-rg: + +- **groupName**:(required) Specifies the name of the new Resource Group. +- **groupLocation**:(required) Specifies the location of the new Resource Group. + +- **appServiceName**:(required) The location of the App Service Plan. +- **appServicePlanName**:(required) The name of the App Service Plan. +- **appServicePlanLocation**: The location of the App Service Plan. Defaults to use groupLocation. +- **appServicePlanSku**: The SKU of the App Service Plan. Defaults to Standard values. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **appSecret**:(required for MultiTenant and SingleTenant) Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource + + + +# parameters-for-template-AzureBot-new-rg: + +- **groupName**:(required) Specifies the name of the new Resource Group. +- **groupLocation**:(required) Specifies the location of the new Resource Group. + +- **azureBotId**:(required) The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable. +- **azureBotSku**: The pricing tier of the Bot Service Registration. **Allowed values are: F0, S1(default)**. +- **azureBotRegion**: Specifies the location of the new AzureBot. **Allowed values are: global(default), westeurope**. +- **botEndpoint**: Use to handle client messages, Such as https://.azurewebsites.net/api/messages. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json new file mode 100644 index 0000000000..ae073b7939 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json @@ -0,0 +1,160 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "type": "string", + "metadata": { + "description": "Specifies the name of the Resource Group." + } + }, + "groupLocation": { + "type": "string", + "metadata": { + "description": "Specifies the location of the Resource Group." + } + }, + "azureBotId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID." + } + }, + "azureBotSku": { + "type": "string", + "defaultValue": "S1", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." + } + }, + "azureBotRegion": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "" + } + }, + "botEndpoint": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use to handle client messages, Such as https://.azurewebsites.net/api/messages." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + } + }, + "variables": { + "botEndpoint": "[if(empty(parameters('botEndpoint')), concat('https://', parameters('azureBotId'), '.azurewebsites.net/api/messages'), parameters('botEndpoint'))]", + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "msiResourceId": "" + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "" + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "[variables('msiResourceId')]" + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "msiResourceId": "[variables('appTypeDef')[parameters('appType')].msiResourceId]" + } + }, + "resources": [ + { + "name": "[parameters('groupName')]", + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2018-05-01", + "location": "[parameters('groupLocation')]", + "properties": {} + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-05-01", + "name": "storageDeployment", + "resourceGroup": "[parameters('groupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [ + { + "apiVersion": "2021-03-01", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('azureBotId')]", + "location": "[parameters('azureBotRegion')]", + "kind": "azurebot", + "sku": { + "name": "[parameters('azureBotSku')]" + }, + "properties": { + "name": "[parameters('azureBotId')]", + "displayName": "[parameters('azureBotId')]", + "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "msaAppTenantId": "[variables('appType').tenantId]", + "msaAppMSIResourceId": "[variables('appType').msiResourceId]", + "msaAppType": "[parameters('appType')]", + "luisAppIds": [], + "schemaTransformationVersion": "1.3", + "isCmekEnabled": false, + "isIsolated": false + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json new file mode 100644 index 0000000000..560bbbc443 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json @@ -0,0 +1,213 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "type": "string", + "metadata": { + "description": "Specifies the name of the Resource Group." + } + }, + "groupLocation": { + "type": "string", + "metadata": { + "description": "Specifies the location of the Resource Group." + } + }, + "appServiceName": { + "type": "string", + "metadata": { + "description": "The globally unique name of the Web App." + } + }, + "appServicePlanName": { + "type": "string", + "metadata": { + "description": "The name of the App Service Plan." + } + }, + "appServicePlanLocation": { + "type": "string", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "appServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Required for MultiTenant and SingleTenant app types." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + } + }, + "variables": { + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "appServicePlanName": "[parameters('appServicePlanName')]", + "resourcesLocation": "[if(empty(parameters('appServicePlanLocation')), parameters('groupLocation'), parameters('appServicePlanLocation'))]", + "appServiceName": "[parameters('appServiceName')]", + "resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "identity": { "type": "None" } + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "identity": { "type": "None" } + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[variables('msiResourceId')]": {} + } + } + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "identity": "[variables('appTypeDef')[parameters('appType')].identity]" + } + }, + "resources": [ + { + "name": "[parameters('groupName')]", + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2018-05-01", + "location": "[parameters('groupLocation')]", + "properties": {} + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-05-01", + "name": "storageDeployment", + "resourceGroup": "[parameters('groupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [ + { + "comments": "Create a new App Service Plan", + "type": "Microsoft.Web/serverfarms", + "name": "[variables('appServicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[variables('resourcesLocation')]", + "sku": "[parameters('appServicePlanSku')]", + "properties": { + "name": "[variables('appServicePlanName')]" + } + }, + { + "comments": "Create a Web App using the new App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "location": "[variables('resourcesLocation')]", + "kind": "app", + "dependsOn": [ + "[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" + ], + "name": "[variables('appServiceName')]", + "identity": "[variables('appType').identity]", + "properties": { + "name": "[variables('appServiceName')]", + "serverFarmId": "[variables('appServicePlanName')]", + "siteConfig": { + "appSettings": [ + { + "name": "WEBSITE_NODE_DEFAULT_VERSION", + "value": "10.14.1" + }, + { + "name": "MicrosoftAppType", + "value": "[parameters('appType')]" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + }, + { + "name": "MicrosoftAppTenantId", + "value": "[variables('appType').tenantId]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + }, + "webSocketsEnabled": true + } + } + } + ], + "outputs": {} + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Program.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Program.cs new file mode 100644 index 0000000000..15de094baf --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Program.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureLogging((logging) => + { + logging.AddDebug(); + logging.AddConsole(); + }); + webBuilder.UseStartup(); + }); + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Properties/launchSettings.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/Properties/launchSettings.json new file mode 100644 index 0000000000..3a137dd606 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:3978/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + ".NET Core": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:3978/" + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md b/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md new file mode 100644 index 0000000000..c7c293656a --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md @@ -0,0 +1,126 @@ +# Authentication Bot using Subject Name/Issuer + +Bot Framework v4 bot authentication using Subject Name/Issuer + +This bot has been created using [Bot Framework](https://dev.botframework.com/), is shows how to use the bot authentication capabilities of Azure Bot Service. In this sample, we use a local or KeyVault certificate and the MSAL Subject Name/Issuer configuration to create the Bot Framework Authentication. + +## Prerequisites + +- [.NET SDK](https://dotnet.microsoft.com/download) version 6.0 + + ```bash + # determine dotnet version + dotnet --version + ``` + +## To try this sample + +- Clone the repository + + ```bash + git clone https://github.com/microsoft/botbuilder-samples.git + ``` + +- Set app settings variables + + - MicrosoftAppType: Type of the App. + + - MicrosoftAppId: App Id of your bot. + + - MicrosoftAppTenantId: Tenant Id to which your bot belongs. + + - KeyVaultName: Name of the KeyVault containing the certificate. + + - CertificateName: Name of the certificate in the KeyVault. + + +- Run the bot from a terminal or from Visual Studio: + + A) From a terminal, navigate to `samples/csharp_dotnetcore/85.bot-authentication-sni` + + ```bash + # run the bot + dotnet run + ``` + + B) Or from Visual Studio + + - Launch Visual Studio + - File -> Open -> Project/Solution + - Navigate to `samples/csharp_dotnetcore/85.bot-authentication-sni` folder + - Select `AuthSNIBot.csproj` file + - Press `F5` to run the project + +## Testing the bot using Bot Framework Emulator + +[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. + +- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) + +### Connect to the bot using Bot Framework Emulator + +- Launch Bot Framework Emulator +- File -> Open Bot +- Enter a Bot URL of `http://localhost:3978/api/messages` + +## Interacting with the bot + +This sample uses the bot authentication capabilities of Azure Bot Service, providing features to make it easier to develop a bot that authenticates users using digital security certificates. You just need to provide the certificate data linked to the managed identity and run the bot, then communicate with it to validate its correct authentication. + +## SSL/TLS certificate + +An SSL/TLS certificate is a digital object that allows systems to verify identity and subsequently establish an encrypted network connection with another system using the Secure Sockets Layer/Transport Layer Security (SSL/TLS) protocol. Certificates are issued using a cryptographic system known as public key infrastructure (PKI). PKI allows one party to establish the identity of another through the use of certificates if they both trust a third party, known as a certificate authority. SSL/TLS certificates therefore function as digital identity documents that protect network communications and establish the identity of websites on the Internet as well as resources on private networks. + +## How to create an SSL/TLS certificate + +There are two possible options to create SSL/TSL certificate. Below is a step-by-step description of each one: + +### Using local environment + +1. Run the following command in a local PowerShell + +``` +$cert = New-SelfSignedCertificate -CertStoreLocation "" -Subject "CN=" -KeySpec KeyExchange +``` + +1. Then, type _Manage User Certificates_ in the Windows search bar and hit enter + +2. The certificate will be located in the _user certificates_ folder, under _personal_ directory. + +3. Export the certificate to _pfx_ format including the key(The default location is _system32_ folder). + +4. Go to the certificate location and run the following command to generate a _pem_ file: + +``` +OpenSSL pkcs12 -in .pfx -out c:\.pem –nodes +``` + +5. Upload the generated certificate to the Azure app registration. + +### Using KeyVault + +1. Create a KeyVault resource and assign _the KeyVault Administrator_ role to have permission to create a new certificate. + +2. Under the Certificates section, hit on Generate/Import, complete the form, and create the certificate in PEM format. + +3. Go to the details of the certificate that you created and enable it. + +4. Download the certificate in CER format and then upload it to the Azure app registration. + +## Deploy the bot to Azure + +To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. + +## Further reading + +- [Bot Framework Documentation](https://docs.botframework.com) +- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0) +- [Azure Portal](https://portal.azure.com) +- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0) +- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0) +- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0) +- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x) +- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) +- [Azure Portal](https://portal.azure.com) +- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0) +- [SSL/TLS certificates](https://www.digicert.com/tls-ssl/tls-ssl-certificates) diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs new file mode 100644 index 0000000000..ce201c1cdd --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Security.Cryptography.X509Certificates; +using Azure.Identity; +using Azure.Security.KeyVault.Certificates; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; +using Microsoft.Bot.Connector.Authentication; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Identity.Client; + +namespace Microsoft.BotBuilderSamples +{ + public class Startup + { + public readonly IConfiguration _configuration; + + public Startup(IConfiguration configuration) + { + _configuration = configuration; + } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddHttpClient().AddControllers().AddNewtonsoftJson(options => + { + options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth; + }); + + //Set sendX5C value to true to use SNI auhtentication. + var sendX5C = true; + + // Using KeyVault. + // Create a new certificate client using the default credential from Azure.Identity using environment variables previously set, + // including AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID. + var keyVaultUri = $"https://{_configuration["KeyVaultName"]}.vault.azure.net"; + var credential = new DefaultAzureCredential(); + var client = new CertificateClient(new Uri(keyVaultUri), credential); + + //Get certificate in X509Certificate format. + var certificateName = _configuration["CertificateName"]; + var certificate = client.DownloadCertificate(certificateName).Value; + + // Using a local certificate. + //var certificate = X509Certificate2.CreateFromPemFile(@"{Pem file path}"); + + // MSAL certificate auth. + services.AddSingleton( + serviceProvider => ConfidentialClientApplicationBuilder.Create(_configuration["MicrosoftAppId"]) + .WithCertificate(certificate, sendX5C) + .Build()); + + // MSAL credential factory: regardless of secret, cert or custom auth, need to add the line below to enable MSAL. + services.AddSingleton(); + + // Create the Bot Framework Authentication to be used with the Bot Adapter. + services.AddSingleton(); + + // Create the Bot Adapter with error handling enabled. + services.AddSingleton(); + + // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.) + services.AddSingleton(); + + // Create the User state. (Used in this bot's Dialog implementation.) + services.AddSingleton(); + + // Create the Conversation state. (Used by the Dialog system itself.) + services.AddSingleton(); + + // Create the bot as a transient. In this case the ASP Controller is expecting an IBot. + services.AddTransient(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseDefaultFiles() + .UseStaticFiles() + .UseRouting() + .UseAuthorization() + .UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + // app.UseHttpsRedirection(); + } + } +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/appsettings.json b/samples/csharp_dotnetcore/85.bot-authentication-sni/appsettings.json new file mode 100644 index 0000000000..59a3940059 --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/appsettings.json @@ -0,0 +1,7 @@ +{ + "MicrosoftAppType": "", + "MicrosoftAppId": "", + "MicrosoftAppTenantId": "", + "KeyVaultName": "", + "CertificateName": "" +} diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/wwwroot/default.htm b/samples/csharp_dotnetcore/85.bot-authentication-sni/wwwroot/default.htm new file mode 100644 index 0000000000..7533ff633b --- /dev/null +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/wwwroot/default.htm @@ -0,0 +1,417 @@ + + + + + + + Bot Authentication SNI Sample + + + + + +
+
+
+
Bot Authentication SNI Sample
+
+
+
+
+
Your bot is ready!
+
You can test your bot in the Bot Framework Emulator
+ by connecting to http://localhost:3978/api/messages.
+ +
Visit Azure + Bot Service to register your bot and add it to
+ various channels. The bot's endpoint URL typically looks + like this:
+
https://your_bots_hostname/api/messages
+
+
+
+
+ +
+ + diff --git a/samples/csharp_dotnetcore/csharp_dotnetcore.sln b/samples/csharp_dotnetcore/csharp_dotnetcore.sln index 316adbf227..c1eee46092 100644 --- a/samples/csharp_dotnetcore/csharp_dotnetcore.sln +++ b/samples/csharp_dotnetcore/csharp_dotnetcore.sln @@ -82,6 +82,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomQABot", "12.customQAB EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomQABotAllFeatures", "48.customQABot-all-features\CustomQABotAllFeatures.csproj", "{4C855F46-DCA3-4A69-9ED3-3B7491F91CF4}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AuthSNIBot", "85.bot-authentication-sni\AuthSNIBot.csproj", "{95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -344,6 +346,14 @@ Global {4C855F46-DCA3-4A69-9ED3-3B7491F91CF4}.Release|Any CPU.Build.0 = Release|Any CPU {4C855F46-DCA3-4A69-9ED3-3B7491F91CF4}.Release|x64.ActiveCfg = Release|Any CPU {4C855F46-DCA3-4A69-9ED3-3B7491F91CF4}.Release|x64.Build.0 = Release|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Debug|x64.ActiveCfg = Debug|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Debug|x64.Build.0 = Debug|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|Any CPU.Build.0 = Release|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|x64.ActiveCfg = Release|Any CPU + {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From b17694e9e7dbb46cb23d97e55856a79c37ac10c3 Mon Sep 17 00:00:00 2001 From: JhontSouth Date: Thu, 12 Oct 2023 10:21:34 -0500 Subject: [PATCH 2/2] change bot name --- .../Bots/{AuthCertificateBot.cs => AuthSNIBot.cs} | 4 +--- .../csharp_dotnetcore/85.bot-authentication-sni/Startup.cs | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) rename samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/{AuthCertificateBot.cs => AuthSNIBot.cs} (90%) diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs similarity index 90% rename from samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs rename to samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs index 463bd2e6ef..fd8300485a 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthCertificateBot.cs +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs @@ -5,13 +5,11 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Bot.Builder; -using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Schema; -using Microsoft.Extensions.Logging; namespace Microsoft.BotBuilderSamples { - public class AuthCertificateBot : ActivityHandler + public class AuthSNIBot : ActivityHandler { protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) { diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs index ce201c1cdd..a310c4372f 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Security.Cryptography.X509Certificates; using Azure.Identity; using Azure.Security.KeyVault.Certificates; using Microsoft.AspNetCore.Builder; @@ -76,7 +75,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); // Create the bot as a transient. In this case the ASP Controller is expecting an IBot. - services.AddTransient(); + services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.