Injection enhancements and bugfixes (#43)

* Features added

- Updated injection logic to support new features/fix bugs
  - Added support to resume an injection without having to stop a current injection and start it again when an SRT/RTMP source is disconnected and reconnected.
    - When a user starts an injection but the injection pipeline doesn't receive content, the injection remains in `Ready` state, and the bot only injects the static image. Once the injection pipeline starts receiving content,  the injection goes from `Ready` to `Receiving` state and the bot switches the injection from the static image to the actual content.
    - If the injection pipeline stops receiving content (e.g.: because the source dropped), the injection goes from `Receiving` to `Not Receiving` state, and the bot starts injecting the static image again. Once the injection pipeline starts receiving content again,  the injection goes from `Not Receiving` to `Receiving` state and the bot switches the injection from the static image to the actual content.
- Added support to change the injection's volume.
- Added support to hide/display an injection without stopping the injection (closing the SRT/RTMP connection).
- Added support to remove the bot from the meeting after a configurable time (in seconds) without participants.
- Fixed the bug where the bot's mute state wasn't updated where it was muted from Microsoft Teams client.
- Updated to the latest version of the **Microsoft Graph Communications** SDKs (v1.2.0.4161) and its dependencies.
- Updated to the latest version of the **Microsoft.Skype.Bots.Media**  (1.23.0.49-alpha)
- Configuration management
  - Added Key Vault and moved the domain certificate and secrets there. Now the Web App Service and Function App service use Key Vault references. Regarding the Bot Service hosted in the virtual machine, we remove its settings from the storage account. Now the bot gets the non-sensitive settings from a local appSettings.json and the secrets from the Key Vault.
- Added **Swashbuckle.AspNetCore** package in Management API to expose Swagger Documentation
This commit is contained in:
Federico Bridger 2022-05-09 10:39:54 -03:00 коммит произвёл GitHub
Родитель 5625235ba3
Коммит a7880443df
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
168 изменённых файлов: 3451 добавлений и 1845 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -355,4 +355,5 @@ src/ManagementApi/Properties/launchSettings.json
src/BotService/cache
src/ManagementApi/appsettings.**.json
src/BotService/appsettings.**.json
**/local.settings.json
**/local.settings.json
src/BotService/.config/dotnet-tools.json

Просмотреть файл

@ -12,11 +12,27 @@ The code in this repository is provided "AS IS", without any warranty of any kin
To upgrade from one version to the next one you simply need to deploy the new version to the resources you already have in Azure. However, some configuration settings might change between one version and the next one. You can find a quick summary of what settings have changed between each version in the [upgrade path documentation](docs/upgrade_path.md).
## 0.6.0-dev
- Updated injection logic to support new features/fix bugs
- Added support to resume an injection without having to stop a current injection and start it again when an SRT/RTMP source is disconnected and reconnected.
- When a user starts an injection but the injection pipeline doesn't receive content, the injection remains in `Ready` state, and the bot only injects the static image. Once the injection pipeline starts receiving content, the injection goes from `Ready` to `Receiving` state and the bot switches the injection from the static image to the actual content.
- If the injection pipeline stops receiving content (e.g.: because the source dropped), the injection goes from `Receiving` to `Not Receiving` state, and the bot starts injecting the static image again. Once the injection pipeline starts receiving content again, the injection goes from `Not Receiving` to `Receiving` state and the bot switches the injection from the static image to the actual content.
- Added support to change the injection's volume.
- Added support to hide/display an injection without stopping the injection (closing the SRT/RTMP connection).
- Added support to remove the bot from the meeting after a configurable time (in seconds) without participants.
- Fixed the bug where the bot's mute state wasn't updated where it was muted from Microsoft Teams client.
- Updated to the latest version of the **Microsoft Graph Communications** SDKs (v1.2.0.4161) and its dependencies.
- Updated to the latest version of the **Microsoft.Skype.Bots.Media** (1.23.0.49-alpha)
- Configuration management
- Added Key Vault and moved the domain certificate and secrets there. Now the Web App Service and Function App service use Key Vault references. Regarding the Bot Service hosted in the virtual machine, we remove its settings from the storage account. Now the bot gets the non-sensitive settings from a local appSettings.json and the secrets from the Key Vault.
- Added **Swashbuckle.AspNetCore** package in Management API to expose Swagger Documentation
## 0.5.0-dev
- Fixed an issue where some participants in the call were not able to see the video injected by the bot.
- Note that this fix is actually a workaround for a behavior in Microsoft Teams where the Teams client didn't render the video if the injection was started more than 3 minutes after the bot was joined to the meeting. The bot now shows a **slate** in the meeting when no injection is active to prevent the video socket in the Teams client from closing.
- You can personalize this slate following the instructions in the [Customize the Broadcast Development Kit Slate image](docs/common/customize_bdk_slate_image.md) document.
- Note that this fix is actually a workaround for a behavior in Microsoft Teams where the Teams client didn't render the video if the injection was started more than 3 minutes after the bot was joined to the meeting. The bot now shows a **slate** in the meeting when no injection is active to prevent the video socket in the Teams client from closing.
- You can personalize this slate following the instructions in the [Customize the Broadcast Development Kit Slate image](docs/common/customize_bdk_slate_image.md) document.
- Added support for extracting video from the call using the RTMP/RTMPS protocols in pull mode. Previously, only push mode was supported for extractions with RTMP/RTMPS.
- Updated to the latest version of the **Microsoft Graph Communications** SDKs (v1.2.0.3144).
- Changed how the status of the service is managed to separate the state of the **BotService** from the state of the underlying virtual machine.

Просмотреть файл

@ -35,6 +35,7 @@ The solution supports multiple extractions at a time, allowing to stream any com
To provide the best possible experience during a meeting, Microsoft Teams automatically changes the frame size and frame rate of each participant stream based on the network conditions of the participant. However, this can cause issues with using those streams in streaming services of video production solutions. To avoid these issues **Broadcast Development Kit** automatically upscales the video feed to **1080p at 30FPS**. This reduces the complexity of having to work with a variable frame size and frame rate.
Extraction of any of those streams can be done with the following configurations:
- SRT in "caller" mode (you have a SRT listener waiting to receive a connection from this solution).
- SRT in "listener" mode (the solution will wait for a SRT caller to connect and get the content).
- RTMP / RTMPS in "push" mode (you have a RTMP URL you want to push the stream to).
@ -47,6 +48,7 @@ A feed with audio and video can be injected to the Microsoft Teams meeting. Insi
**Broadcast Development Kit** supports receiving video and audio in several resolutions and frame rates. It will automatically transform the video feed to **1080p and 30FPS** before injecting it into the Microsoft Teams call.
Injection is supported in the following configurations:
- SRT in "caller" mode (you have an SRT listener waiting for a client to connect).
- SRT in "listener" mode (the solution will wait for a SRT caller to connect and send the content)
- RTMP / RTMPS in "pull" mode (you have an RTMP server waiting for a client to connect and pull the content)
@ -76,7 +78,7 @@ If you have media content that can be streamed through SRT or RTMP such as live
There are some known issues in the current version of this solution:
- When injecting content into a meeting using an RTMPS source in pull mode (i.e. you give BDK an RTMPS URL to pull the content from it), if the source stops transmitting content while the injection is still active, then an exception is thrown in the Gstreamer pipeline once the injection is stopped in the BDK. This exception causes the Bot Service running in the VM to crash, and you will need to restart the service manually or restart the VM. This issue only occurs when using RTMPS in pull mode. Other combinations (e.g. SRT, RTMP, push mode, etc.) do not present this issue.
- When injecting content into a meeting using an RTMPS source in pull mode (i.e. you give BDK an RTMPS URL to pull the content from it), if the source stops transmitting content while the injection is still active, then an exception is thrown in the GStreamer pipeline once the injection is stopped in the BDK. This exception causes the Bot Service running in the VM to crash, and you will need to restart the service manually or restart the VM. This issue only occurs when using RTMPS in pull mode. Other combinations (e.g. SRT, RTMP, push mode, etc.) do not present this issue.
This solution currently has some limitations:
@ -99,12 +101,14 @@ This solution currently has some limitations:
This section will guide you through the process of configuring the solution to run it locally and/or in azure.
### How to run the solution
Please follow these documents to build and configure this solution:
- [Prerequisites](docs/prerequisites/README.md)
- [How to run the solution locally](docs/how-to-run-the-solution-locally/README.md)
- [How to run the solution in Azure](docs/how-to-run-the-solution-in-azure/README.md)
You can find how to use the APIs in this solution in the following document:
- [How to use the Management API](docs/how-to-use-the-solution/README.md)
### Adding an UI
@ -117,10 +121,11 @@ This solution doesn't include any UI that can be used to operate the application
### Exploring the repository
The repository is structured in the following directories:
- **src**: Contains the source code of the application.
- **BotService**: Contains the core component that connects to the meeting and extracts and injects media feeds from and to the meeting.
- **ManagementApi**: Contains the main API that is used to interact with the service.
- **OrchestratorFunction**: Contains the Azure function in charge of managing the status of the VMs.
- **BotService**: Contains the core component that connects to the meeting and extracts and injects media feeds from and to the meeting.
- **ManagementApi**: Contains the main API that is used to interact with the service.
- **OrchestratorFunction**: Contains the Azure function in charge of managing the status of the VMs.
- **docs**: Contains the documentation on the solution.
### Architecture
@ -150,7 +155,7 @@ Any use of third-party trademarks or logos are subject to those third-party's po
## Acknowledgments
This project was implemented using the samples in the [Microsoft Graph Communications API and Samples](https://github.com/microsoftgraph/microsoft-graph-comms-samples) repository as a base.
This project was implemented using the samples in the [Microsoft Graph Communications API and Samples](https://github.com/microsoftgraph/microsoft-graph-comms-samples) repository as a base.
The architecture used in the solution was inspired by the samples in [Azure-Samples/PartitionedRepository](https://github.com/Azure-Samples/PartitionedRepository) and [ShawnShiSS/clean-architecture-azure-cosmos-db](https://github.com/ShawnShiSS/clean-architecture-azure-cosmos-db).

Просмотреть файл

@ -0,0 +1,49 @@
# Azure Bot app registration
This documents explains how to create and configure the Azure Bot app registration you will use to configure the Azure Bot resource.
## Creation of the app registration
To create the app registrations, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
## Setup of the app registration
### API permissions
From the Azure Bot app registration view, go to the **API permissions** option that is in the resource blade, click the **Add a permission** button, select the **Microsoft APIs** tab, **Microsoft Graph** and then **Application permissions**.
Once there, add the permissions shown in the table below:
API / Permission name | Type | Display | Description | Admin consent
----------|----------|----------|----------|----------
Calls.AccessMedia.All | Application | Access media streams in a call as an app preview. | Allows the app to get direct access to media streams in a call, without a signed-in user. | Yes
Calls.Initiate.All | Application | Initiate outgoing 1:1 calls from the app preview.| Allows the app to place outbound calls to a single user and transfer calls to users in your organizations directory, without a signed-in user. | Yes
Calls.InitiateGroupCall.All | Application | Initiate outgoing group calls from the app preview | Allows the app to place outbound calls to multiple users and add participants to meetings in your organization, without a signed-in user. | Yes
Calls.JoinGroupCall.All | Application | Join group calls and meetings as an app preview. | Allows the app to join group calls and scheduled meetings in your organization, without a signed-in user. The app is joined with the privileges of a directory user to meetings in your tenant. | Yes
Calls.JoinGroupCallAsGuest.All | Application | Join group calls and meetings as a guest preview. | Allows the app to anonymously join group calls and scheduled meetings in your organization, without a signed-in user. The app is joined as a guest to meetings in your tenant. | Yes
User.Read | Delegated | Sign in and read user profile | Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users | No
User.Read.All | Application | Read all users' full profiles | Allows the app to read user profiles without a signed in user. We use it to retrieve get the user photos | Yes
Several of the permissions that were configured in this application require to be consented by an admin of the Azure AD tenant. To grant this consent, ask an Azure AD administrator to access the following URL and accept the permissions for this application (replace the {{applicationId}} placeholder with the id of the application registration previously created):
- `https://login.microsoftonline.com/common/adminconsent?client_id={{applicationId}}&state=1`
> **Note**: Despite that constructing the Tenant Admin Consent URL requires a configured Redirect URI/Reply URL in the App Registration Portal, to grant consent manually we don't need to add it to the reply URL in the consent URL. To add reply URLs for your bot, access your bot registration, choose Advanced Options > Edit Application Manifest. Add your Redirect URI to the field reply URLs.
### Add a client secret
Finally, you must [add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret).
If you are following the guide to configure and run the solution in Azure, you must copy the secret value and add it to the key vault as a secret with the following names:
- `Settings--BotConfiguration--AadAppSecret`
- `Settings--GraphClientConfiguration--ClientSecret`
If you are following the guide to configure and run the solution locally, just take note of this value and copy it in a secure place, you will use it for later configuration.
[← Back to How to run the solution in Azure](../how-to-run-the-solution-in-azure/README.md#azure-bot) | [Next: Azure Bot →](azure-bot.md#azure-bot)
[← Back to How to run the solution locally](../how-to-run-the-solution-locally/README.md) | [Next: Azure Bot →](azure-bot.md#azure-bot)

30
docs/common/azure-bot.md Normal file
Просмотреть файл

@ -0,0 +1,30 @@
# Azure Bot
To continue with the registration of the calling bot, we must create an [Azure Bot resource](https://docs.microsoft.com/en-us/azure/bot-service/abs-quickstart?view=azure-bot-service-4.0#create-an-azure-bot-resource). While doing so, consider the following settings:
- **Bot handle:** A meaningful name.
- **Subscription** Your Azure subscription.
- **Resource group**: The resource group where you want to create the resource
- **Pricing tier:** F0.
- **Microsoft App ID:**
- **Type of App**: Single Tenant
- **Creation Type**: Click on `Use existing app registration`, then input the client ID, client secret and tenant ID fo the Azure Bot application registration you created in previous steps.
- Leave the rest of the settings as-is.
Once the Azure Bot is created, apply the following changes to the resource:
1. In the resource blade, click `Channels`, then go to the `Available channels` section, select the `Microsoft Teams` channel, and agree the Terms of Service.
2. In the `Messaging` tab, select Microsoft Teams Commercial.
3. Go to the `Calling` tab and check the `Enable calling` checkbox. In the `Webhook` URL, if you are configuring the solution to run it locally, add a dummy value. If you are configuring the solution to run it in Azure, add the path to the following route using your domain name:
- `https://{domain-name}/api/calling`
4. Click `Apply` to save the changes.
> **Optional:** You can go to `Bot profile` section and upload an icon for this bot or change the name that it will show inside the meetings.
[← Back to How to run the solution in Azure](../how-to-run-the-solution-in-azure/README.md#azure-bot) | [Next: Deployments →](../how-to-run-the-solution-in-azure/README.md#deployments)
[← Back to How to run the solution locally](../how-to-run-the-solution-locally/README.md#azure-bot) | [Next: Tools →](../how-to-run-the-solution-locally/README.md#tools)

Просмотреть файл

@ -1,6 +1,7 @@
# Customize the Broadcast Development Kit Slate image
## Getting Started
## Getting Started
When the BDK is joined into a Microsoft Teams call, it starts rendering a "Slate" image on the bot spot in the Microsoft Teams client while no media content injection is active.
By default, the `Slate` image rendered on the Microsoft client is an image provided in the BDK solution, placed on the BDK `BotService` root solution folder. Once the bot is joined into a meeting the following image is displayed on the Microsoft Teams client.
@ -13,7 +14,7 @@ By default, the `Slate` image rendered on the Microsoft client is an image provi
The `Slate` image rendered by the bot on the Microsoft Teams client can be customized. You only need to change the default image provided in the solution with one of your choosing.
To do so, please go to the `BotService` solution folder, find the `PNG` file called `slate.png` and replace it with an image of your choosing.
To do so, please go to the `BotService` solution folder, find the `PNG` file called `slate.png` and replace it with an image of your choosing.
|![BDK default slate image route](images/default-slate-image-solution-route.png)|
|:--:|
@ -22,7 +23,7 @@ To do so, please go to the `BotService` solution folder, find the `PNG` file cal
The `Slate` image you need to provide must have the following characteristics:
- ***Format***: The image format must be PNG.
- ***Name***: The image name must be named `slate`.
- ***Name***: The image name must be named `slate`.
- ***Width***: The image width must be 1920px.
- ***Height***: The image height must be 1080px.

Просмотреть файл

@ -1,11 +1,8 @@
# How to Install and configure NGINX with RTMP module on Windows
## Getting Started
To support RTMP injection in {{insert the name of the solution}} we need to configure NGINX in the host machine. The objective of this guide is to explain how to correctly install and configure NGINX with the RTMP module in Windows, how to inject a live broadcast locally, and how to run NGINX as a Windows service.
> **NOTE**: We are going to use NGINX version 1.14.1. It has not been tested with recent versions.
> **NOTE**: We are going to use NGINX version 1.14.1. It has not been tested with recent versions.
## Installation
@ -15,7 +12,6 @@ Download as a zip NGINX with RTMP module from the following [GitHub repository](
|:--:|
|*NGINX with RTMP module repository*|
Before editing the `nginx.config` file, to support RTMPS we must copy the SSL certificate (we've mentioned as prerequisite [here](../prerequisites/README.md)) and its key into the host machine. (e.g.: C:\certs)
| ![Certs](images/cert-files.png)|
@ -434,8 +430,6 @@ rtmp {
application test-endpoint {
live on;
record off;
on_publish http://localhost/api/bot/validate-stream-key;
}
}
}
@ -461,8 +455,7 @@ http {
## Test NGINX server configuration
> **NOTE**: To test the NGINX server we will use GStreamer to create a pipeline that captures the audio and video of our PC and pushes it into the NGINX server. If you want to use other tool like OBS, feel free to skip this section.
> **NOTE**: To test the NGINX server we will use GStreamer to create a pipeline that captures the audio and video of our PC and pushes it into the NGINX server. If you want to use other tool like OBS, feel free to skip this section.
To start testing the NGINX server, we must open a terminal window, navigate to the NGINX root folder and execute `nginx.exe`.
@ -489,17 +482,18 @@ Once we identified the device and copied its id value, we need to run the follow
```bash
gst-launch-1.0 wasapisrc device="{{device-strid}}" ! audioconvert ! avenc_aac ! aacparse ! queue ! mux. autovideosrc ! "video/x-raw, format=YUY2, width=320, height=180, framerate=30/1" ! videoconvert ! x264enc tune=zerolatency key-int-max=60 bitrate=2500 ! queue ! mux. flvmux name=mux streamable=true latency=500000000 ! rtmpsink location=rtmp://localhost:1936/test-endpoint/1
```
> **NOTE:** Replace the placheholder **{{device-strid}}** with the **device.strid** value we copied before.
To validate the server and GStreamer are correctly working, we must start consuming the live endpoint with a player.
**Using GStreamer**
#### Using GStreamer
```bash
gst-launch-1.0 rtmpsrc location=rtmp://localhost:1936/test-endpoint/1 ! decodebin name=decoder ! queue ! videoconvert ! autovideosink decoder. ! queue ! audioconvert ! audioresample ! autoaudiosink
```
Or
Or
```bash
gst-launch-1.0 playbin uri=rtmp://localhost:1936/test-endpoint/1
@ -507,25 +501,29 @@ gst-launch-1.0 playbin uri=rtmp://localhost:1936/test-endpoint/1
![Using GStreamer](images/nginx_using_gstreamer.png)
**Ffplay**
##### Ffplay
```bash
ffplay.exe rtmp://localhost:1936/test-endpoint/1
```
![Ffplay](images/nginx_ffplay.png)
**VLC Player**
#### VLC Player
> **NOTE**: Make sure you have a sufficiently recent version of VLC. RTMP streaming is supported in VLC versions 1.1 and later; you can download the most recent version by pointing your browser to [videolan.org](https://www.videolan.org/) and clicking **Download VLC**. Follow the on-screen instructions to download and install the program.
Once VLC is installed, follow these steps:
1. Open VLC's ***Media*** menu and click **Open Network Stream**, or simply hold down **CTRL** and press **N**.
1. Paste the URL of the stream you want to watch, with the following format: `rtmp://localhost:1936/test-endpoint/1` in the **Please enter a network URL** box.
![](images/nginx_vlc_player.png)
2. Paste the URL of the stream you want to watch, with the following format: `rtmp://localhost:1936/test-endpoint/1` in the **Please enter a network URL** box.
![vlc](images/nginx_vlc_player.png)
1. Click the **Play** button.
3. Click the **Play** button.
## Run NGINX as a Windows Service
In order to run NGINX as Windows Service is necessary to wrap the executable file into a Windows Service using an external program.
To do so, we can use the [nssm](https://nssm.cc/) tool and execute it in the PC or VM where we want to install the service. Download the nssm tool ([download link](https://nssm.cc/download)), unzip the package, and execute the tool from the command line.
@ -536,4 +534,8 @@ Once the tool is open, set the path for the NGINX executable file and click on t
The first time, the service does not run automatically. We must initialize the service from the Windows services manager or, restart the machine.
![](images/nginx_as_windows_service.png)
![nginxws](images/nginx_as_windows_service.png)
[← Back to How to run the solution in Azure](../how-to-run-the-solution-in-azure/README.md#provision-azure-resources)
[← Back to How to run the solution locally](../how-to-run-the-solution-locally/README.md#nginx) | [Next: Ngrok →](../how-to-run-the-solution-locally/README.md#ngrok)

Просмотреть файл

@ -1,43 +1,47 @@
# Manual installation of your domain certificate
## About
This document explains how to manually install your domain certificate in your virtual machine or local environment.
## Installing the certificate
Copy the [pfx certificate mentioned in the prerequisites](../prerequisites/README.md) to your virtual machine or local environment and double click on it to run the certificate import wizard.
On the first screen, select `Local machine` as the Store Location and click `Next` (Windows may ask for administrator rights).
|![Import Certificate](images/import_certificate.png)|
|:--:|
|*Certificate Import Wizard*|
Click `Next` on the File to import step.
In the Privacy Key Protection step, the wizard will ask for the password to read the certificate's private key, complete it and leave the rest of the settings as-is and click next.
|![Import Certificate](images/certificate_password.png)|
|:--:|
|*Complete the password to read the certificate*|
Finally, in the Certificate Store selection, click on `Browse` and select `Personal`. Then continue with the rest of the wizard.
## Obtaining the certificate thumbprint
Later it will be necessary to obtain the certificate thumbprint to complete the botservice configuration. To obtain it press Win+R keys, complete the input with `certlm.msc` and press `Ok`.
|![Run Certificate](images/run_certificate.png)|
|:--:|
|*Complete the input and press Ok*|
Navigate to `Certificates - Local Computer\Personal\Certificates`, search for the name of the certificate and open it (Either by double clicking or left click and open).
|![Run Certificate](images/certificate_personal.png)|
|:--:|
|*Search the certificate and open it*|
Go to details tab and search for Thumbprint field, select it, and copy its value.
|![Run Certificate](images/certificate_thumbprint.png)|
|:--:|
|*Copy the thumbprint of the certificate*|
# Manual installation of your domain certificate
This document explains how to manually install your domain certificate in your virtual machine or local environment.
## Installing the certificate
Copy the `.pfx` domain's certificate to your virtual machine or local environment and double click on it to run the certificate import wizard.
On the first screen, select `Local machine` as the Store Location and click `Next` (Windows may ask for administrator rights).
|![Import Certificate](images/import_certificate.png)|
|:--:|
|*Certificate Import Wizard*|
Click `Next` on the File to import step.
In the Privacy Key Protection step, the wizard will ask for the password to read the certificate's private key, complete it and leave the rest of the settings as-is and click next.
|![Import Certificate](images/certificate_password.png)|
|:--:|
|*Complete the password to read the certificate*|
Finally, in the Certificate Store selection, click on `Browse` and select `Personal`. Then continue with the rest of the wizard.
## Obtaining the certificate thumbprint
Later it will be necessary to obtain the certificate thumbprint to complete the botservice configuration. To obtain it press Win+R keys, complete the input with `certlm.msc` and press `Ok`.
|![Run Certificate](images/run_certificate.png)|
|:--:|
|*Complete the input and press Ok*|
Navigate to `Certificates - Local Computer\Personal\Certificates`, search for the name of the certificate and open it (Either by double clicking or left click and open).
|![Run Certificate](images/certificate_personal.png)|
|:--:|
|*Search the certificate and open it*|
Go to details tab and search for Thumbprint field, select it, and copy its value.
|![Run Certificate](images/certificate_thumbprint.png)|
|:--:|
|*Copy the thumbprint of the certificate*|
[← Back to How to run the solution in Azure](../how-to-run-the-solution-in-azure/README.md#provision-azure-resources)
[← Back to How to run the solution locally](../how-to-run-the-solution-locally/README.md#domain-certificate)

Просмотреть файл

@ -1,77 +1,86 @@
# How to Run the Solution in Azure
# How to run the solution in Azure
## Introduction
## Prerequisites
This document describes the resources that must be created and configured to run the solution in Azure. This includes:
Before configuring the solution to run it locally and/or in azure you must have the following prerequisites:
- App Registrations for authentication in different components in Azure AD tenant:
- [App Registrations](app_registrations.md#app-registrations):
- [Bot Service API](app_registrations.md#how-to-setup-bot-service-api-application-registration).
- [Bot Service Client](app_registrations.md#how-to-setup-bot-service-client-application-registration).
- [Management API](app_registrations.md#how-to-setup-management-api-application-registration).
- [Azure SDK Service Principal](azure_sdk_service_principal.md).
- [Security Group](security_group.md).
- Resource groups used to deploy and configure the solution:
- Architecture resource group:
- [Application Insights](application_insights.md).
- [Storage account](storage_account.md).
- [Cosmos DB](cosmos_db.md).
- [App Service Plan](service_plan.md).
- [Web App](web_app_and_app_service_plan.md).
- [Function App](function_app_and_app_service_plan.md).
- Virtual Machine resource group:
- [Virtual Machine](virtual_machine.md).
- [Event Grid](configure_event_grid.md).
- Components Deployment:
- [Deploy the Bot Service into the Virtual Machine](deploy_bot_service.md).
- [Deploy the Web App into the Azure App Service](deploy_web_app.md).
- [Deploy the Function App into the Azure Function App Service](deploy_function_app.md).
- Testing the environment:
- [How to configure/register the Service](add_service.md).
- [How to test the Management API](test_web_app.md)
- [How to test the Orchestrator Function](test_function_app.md)
- A **domain name** - This domain name will be used to host the solution's core components.
- An **SSL wildcard certificate** - A valid wildcard certificate for the domain mentioned in the previous point. This is required to establish a TLS/TCP control channel between the bot's media platform and the calling clouds. The certificate must be in .pem and .pfx formats.
- An **Office 365 tenant with Microsoft Teams** enabled - If the organization is already using Microsoft Teams for their meetings, then you already have an Office 365 tenant configured.
- Note that you need the create an app registration in this tenant with permissions to join meetings and send and receive audio and video in those meetings. These permissions will need to be approved by your Office 365 tenant administrator.
- If your organization doesn't want to provide the necessary permissions for the solution to connect to the meetings, or you just want to test this solution in an isolated tenant, you can obtain a new testing tenant using Office 365's [Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program).
- If you plan to deploy this solution to the cloud then you will need an **Azure subscription** to create the required resources to host the solution. Also, Azure AD needs to be used to created several app registrations for authentication and authorization.
## General prerequisites
## Provision Azure resources
Before deploying the solution in Azure, please make sure you have the all the prerequisites listed in [Prerequisites](..\prerequisites\README.md).
Before provisioning main Azure resources, you must create a resource group for them ([How to create a resource group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#create-resource-groups)) and then create the following resources under that resource group.
Also, if you haven't already, make sure you have setup your [Azure Bot](..\prerequisites\azure_bot.md) too.
1. [Application Insights](application-insights.md#application-insights)
2. [App Service Plan](app-service-plan.md#app-service-plan)
3. [Web App](web-app.md#web-app)
4. [Function App](function-app.md#function-app)
5. [Virtual Machine](virtual-machine.md#virtual-machine)
6. [Azure Key Vault](azure-key-vault.md#azure-key-vault)
7. [Cosmos DB](cosmos-db.md#cosmos-db)
8. [Storage Account](storage-account.md#storage-account)
## App Registrations for authentication in different components in Azure AD tenant
To secure and connect several of the resources used for the solution, we need to create several app registrations, each with its own permissions and settings. Several of the following instructions include creating application credentials. We recommend creating a Key Vault resource in Azure to store these credentials securely. We also recommend keeping track of the application IDs generated for each app registration to simplify the configuration of the applications during the project.
## Setup DNS for the Virtual Machine
- [App Registrations](app_registrations.md#app-registrations).
- [Security Group](security_group.md).
After creating and configuring the virtual machine, you must add a record to your DNS provider/server with the static IP of the virtual machine, and take note of the record name, you will use it later.
## Resources used to deploy and configure the solution:
If you don't have a DNS provider, you can use [Azure DNS](https://azure.microsoft.com/services/dns/). To create an Azure DNS Zone, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/dns/dns-getstarted-portal).
### Resource Groups
To prepare the cloud environment, we need to create multiple resources which must be separated according to the different components of the solution. For that, it is necessary to create two **resource groups**, both in the same **region** (e.g., **West US 2**).
If you chose Azure DNS, you will have to visit your domain name registrar to replace the name server records with the Azure DNS name servers. More info, [host your domain in Azure DNS](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain).
- **`resource-group-name`-bot**: This group will contain the rest of the resources related to the APIs, functions, database, and web UI used to operate the solution.
## Configure authentication resources
- **`resource-group-name`-bot-vm**: This group will be used to contain the resources related to the virtual machine that will host the core components of the application in Azure.
To configure authentication in the solution, secure and connect several of the solution's resources, you to create app registrations for the corresponding components, and a security group.
> NOTE: It is suggested that `resource-group-name` be replaced by a name in line with the project.
### App Registrations
While creating/configuring the application registrations, you must create client secrets and use the Azure Key Vault created in previous steps to store them. We also recommend keeping track of the application IDs generated for each app registration to simplify the configuration of the applications during the project.
To create the resource groups, check the [Create resource groups](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#create-resource-groups) documentation.
> **NOTE**: If you are using a O365 Developer tenant for Microsoft Teams and a separate Azure subscription tenant to create the Azure resources, the Azure SDK app registration must be created in the Azure subscription tenant, while the rest can be created in the developer tenant.
### Architecture resource group
- [How to create/configure Bot Service API app registration](bot-service-api-app-registration.md#bot-service-api-app-registration)
- [How to create/configure Bot Service Client app registration](bot-service-client-app-registration.md#bot-service-client-app-registration)
- [How to create/configure Management API app registration](management-api-app-registration.md#management-api-app-registration)
- [How to create/configure Azure SDK app registration](azure-sdk-app-registration.md#azure-sdk-app-registration)
The following resources are used to manage the application and the bot. All these resources should be created in the `resource-group-name`-bot resource group:
### Security Group
- [Application Insights](application_insights.md).
- [Storage account](storage_account.md).
- [Cosmos DB](cosmos_db.md#cosmos-db-database).
- [Web App and App service plan](web_app_and_app_service_plan.md).
- [Function App and App service plan](function_app_and_app_service_plan.md).
If you want to restrict the access to the solution to certain users, you must create a security group and assign the corresponding users to it. If don't, you can skip this step.
- [How to create/configure the security group](security-group.md#security-group)
### Virtual Machine resource group
## Azure Bot
The following resources form the core part of the solution, which is charge of connecting to the call and extract and inject the media feeds from the Teams Meeting call.
All these resources should be created in the `resource-group-name`-bot-vm resource group.
The app registration that was created to manage the state of the VM must be given access to this resource group with the Contributor role. This can be done in the **Access control (IAM)** menu of the resource group.
In order to configure the solution and add calling capabilities to the bot, you must create an Azure Bot resource. To do so, before creating the Azure Bot, you need to create an app registration with the required permissions the Azure Bot will use to authenticate against the Microsoft Graph API and get access to the different resources.
- [Virtual Machine](virtual_machine.md).
- [Event Grid](configure_event_grid.md##how-to-configure-event-grid).
- [How to create/configure Azure Bot app registration](../common/azure-bot-app-registration.md#azure-bot-app-registration)
- [How to create/configure Azure Bot](../common/azure-bot.md#azure-bot)
## Deployments
After provisioning and configuring the Azure resources, you are able to start deploying the different backend components. In this section will list the `How to` documents to deploy them.
- [How to deploy the Bot Service into the virtual machine](bot-service-deploy.md#bot-service-deploy)
- [How to deploy the Management API into the Azure App Service](management-api-deploy.md#management-api-deploy)
- [How to deploy the Function App into the Azure Function App Service](function-app-deploy.md#function-app-deploy.md)
## Configure Event Grid/Event Grid handler
To keep the state of the bot service virtual machine consistent is Cosmos DB, we we must configure an event grid subscription to execute an Azure Function that updates its register in Cosmos DB, every time that it is being started/stopped from an external event, e.g.: A user starts/stops the virtual machine from Azure Portal or has scheduled auto-shutdown. To do so, please review the following document:
- [How to configure event grid](event-grid.md#event-grid)
## Register the service in Cosmos DB
In order to start using the Azure environment once all the components have been deployed and configured, it is necessary to configure/register a service into the Cosmos DB.
- [How to register the service](register-service.md)
## Test the environment
- [Quick test the Management API](test-web-app.md#how-to-test-the-management-api)
- [Quick test the Azure Function](test-function-app.md#how-to-test-the-orchestrator-function)

Просмотреть файл

@ -0,0 +1,13 @@
# App Service Plan
This App Service Plan will define the resources available to execute the Management API and Azure function. To create the App Service Plan, please review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/app-service/app-service-plan-manage#create-an-app-service-plan) and use the following settings:
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Name:*** A meaningful name.
- ***Operating System:*** Windows.
- ***Region:*** Same region as the rest of the resources.
- ***Pricing Tier***
- ***Sku and size:*** Basic B1.
> **NOTE**: The tier (Shared D1) can be used to reduce costs during the test. However note that this can cause issues, like the Azure Functions not processing the messages from the queues.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Web App →](web-app.md#web-app)

Просмотреть файл

@ -1,167 +0,0 @@
# App Registrations
## Getting Started
To enable authentication in the solution, we must create the different **app registrations**, and apply some configuration settings between them in Azure Active Directory.
We need to create app registrations for the following items:
- BotService API.
- BotService Client.
- Management API.
- Azure SDK Service Principal.
To create the necessary app registrations, review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings for each of them:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
> **NOTE**: Please follow the steps to register the app registration and return to this document to apply the corresponding settings.
Once you've registered the app registration you must [add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret), copy the value and save it together with the application client id in a secure place, we will need them for future steps.
> **NOTE**: You'll need this secret later to configure the project. This key value will not be displayed again, nor retrievable by any other means, so record it as soon as it is visible from the Azure portal.
## Authentication Setup
With the **App Registrations** created in the previous steps, we must proceed we the setup of each of them. While doing so, take into consideration that there are some dependencies between some app registrations and the resources.
- [How to Setup Bot Service API app registration](#how-to-setup-bot-service-api-app-registration)
- [How to Setup Bot Service Client app registration](#how-to-setup-bot-service-client-app-registration)
- [How to Setup Management API app registration](#how-to-setup-management-api-app-registration)
### How to Setup Bot Service API app registration
> **IMPORTANT**: it's necessary to have already created BotService API app registration.
This section explains how to configure the BotService API app registration to enable Client Credential Authentication between APIs.
#### Manifest
In the BotService API Application Manifest editor, we need to change the value `accessTokenAcceptedVersion` field from null (which defaults to: 1) to 2 (for v2.0 tokens).
![Manifest Bot Service API](./images/manifest_botservice_api.png)
Finally, click on the **Save** button.
#### App Roles
> **NOTE**: Next, we will create a new Role, which will serve as a mechanism to demand authorization from the application.
From the BotService API app registration view, go to the App roles option that is in the resource blade, click the **Create app role** button. Fill the following information with the values suggested.
- ***Display name***: AccessAll.
- ***Allowed member types***: Applications.
- ***Values***: BotService.AccessAll.
- ***Description***: Meaningful description e.g., Access to BotService API.
![App Roles](./images/create_role_bot_service_api.png)
Finally, click on the Apply button.
#### Expose an API
From the resource blade of the app registration view, go to the **Expose an API** option and click **Set** next to the Application ID URI to generate a URI that is unique for this app (in the form of api://{clientId}).
### How to Setup Bot Service Client app registration
> **IMPORTANT**: To complete this section it is necessary to have the role in the BotService API created.
This section explains how to configure the BotService Client app registration to enable authentication.
#### API permissions
From the BotService Client app registration view, go to the **API permissions** option that is in the resource blade, click the **Add a permission** button and then ensure that the **APIs my organization** uses tab is selected. Search for the **BotService API** and click on the search result.
![Search API permissions](./images/search_api_permissions.png)
Then inside BotService select **AccessAll** and click on **Add permissions**.
![Request API permissions.png](./images/request_api_permissions.png)
> **NOTE**: If your user does not have the necessary permissions to enable the add-on permission. You must ask a user with the required permission to enable it.
![Add permissions](./images/bot_service_client_enabled_permissions.png)
### How to Setup Management API app registration
**IMPORTANT**: it's necessary to have already created Management API app registration.
This section explains how to configure the Management API app registration to enable authentication.
#### Manifest
In the Management API Application Manifest editor, you need to apply the same change in the manifest as you did for the previous app registration. Change the `accessTokenAcceptedVersion` field from null (which defaults to: 1) to 2 (for v2.0 tokens).
#### API Graph permissions
From the API app registration view, go to the **API permissions** option that is in the resource blade, click the **Add a permission** button and then ensure that the **Microsoft APIs** tab is selected.
![API Graph permissions](./images/appi_graph_permissions.png)
In the Commonly used Microsoft APIs section, click on **Microsoft Graph**. Then click in the **Delegated permissions** section and ensure that the right permissions are checked (`User.Read` and `offline_access`) and click the **Add permissions** button.
![Add Graph permissions](./images/add_graph_permissions.png)
#### App Roles
> **NOTE**: Next, we will create a new Role, which will serve as a mechanism to demand authorization from other applications.
From the Management API app registration view, go to the App roles option that is in the resource blade, click the **Create app role** button. Fill the following information with the values suggested.
- ***Display name***: AccessAll.
- ***Allowed member types***: Applications.
- ***Values***: ManagementAPI.AccessAll.
- ***Description***: Meaningful description e.g., Access to Management API.
![App Roles](./images/create_role_management_api.png)
Finally, click on the Apply button.
#### Expose an API
From the resource blade of the app registration view, go to the **Expose an API** option and click **Set** next to the Application ID URI to generate a URI that is unique for this app (in the form of api://{clientId}). Then click **Add scope**, complete the form following the parameters listed below, and finally click **Add scope** button.
#### Parameters
> **NOTE**: This `Scope` name is going to be used to develop/configure auth in the extension and they must match.
- ***Scope name***: use `access_as_producer`.
- ***Who can consent***: Admin and users.
- Admin consent display name: enter a meaningful name. E.g.: `Access Broadcaster for Teams as producer`.
- **Admin consent description**: enter a meaningful description.
- **User consent display name**: enter a meaningful name. E.g.: `Access Broadcaster for Teams as producer`.
- **User consent description**: enter a meaningful description.
- **State**: Enabled
![Add Scope](./images/management_api_add_scope.png)
#### Manifest
In order to enable RBAC through a security group, it is necessary to modify the app registration manifest to allow the application to include in the token all the security groups the user belongs to.
From the resource blade of the app registration view, go to the **Manifest** option. We need to modify the manifest and add/modify the following key-values:
```json
"groupMembershipClaims": "SecurityGroup",
"optionalClaims":{
"idToken": [
{
"name":"groups",
"source": null,
"essential": false,
"additionalProperties": [
"emit_as_roles"
]
}
],
"accessToken":[],
"saml2Token":[]
}
```
![Security group claim](./images/management_api_optional_claims_of_manifest.png)
Click the **Save** button to finish.
> **NOTE**: The Azure SDK Service Principal app registration will be configured later after creating the resource group that will host the virtual machine.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -0,0 +1,12 @@
# Application Insights
This Application Insights instance will be used to log all the events happening in the solution. To create the Application Insights, please review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-workspace-resource), and use the following settings:
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Name:*** A meaningful name.
- ***Region:*** Same region as the rest of the resources.
- ***Resource mode:*** Classic.
Once the **Application Insights** has been created, within the **Overview** option on the left panel we can view the Instrumentation key. The **instrumentation key** identifies the resource that you want to associate your telemetry data with. You will need to copy the **instrumentation key** to use it later.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: App Service Plan →](app-service-plan.md#app-service-plan)

Просмотреть файл

@ -1,27 +0,0 @@
# Application Insights
## Getting Started
This instance will be used to log all the events happening in the solution.
## Dependencies
To continue with the Application Insights, the following dependencies need to be created:
- [Resource Group](resource_group.md).
### Settings.
Create this Application Insights with the following settings:
- ***Resource Group:*** Select the resource group created for the solution architecture.
- ***Name:*** A meaningful name.
- ***Region:*** Same region as the rest of the resources.
- ***Resource mode:*** Classic.
To create the Application Insights, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-workspace-resource).
Once the **Application Insights** has been created, within the **Overview** option on the left panel we can view the Instrumentation key. The **instrumentation key** identifies the resource that you want to associate your telemetry data with. You will need to copy the **instrumentation key** and add it to your component settings.
![](./images/instrumentation_key_of_the_application_insights.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,35 +1,37 @@
# Get Authorization Token
## Introduction
In order to make requests to the Management API deployed in Azure, you need to generate an authorization token. This token must be sent in the request by adding the `Authorization` header to it.
In order to make requests to the Management API deployed in Azure, you need to generate an authorization token. This token must be sent in the request by adding the `Authorization` header to it.
Following the steps in this document, you will be able to generate an authorization token using the Azure CLI.
1. Download and install the Azure CLI, please review the Microsoft [documentation](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli) to install it.
1. Download and install the Azure CLI, please review the [Microsoft documentation](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli) to install it.
1. After installing the Azure CLI, in a terminal window execute the command `az login` and enter your credentials in the browser displayed.
2. After installing the Azure CLI, in a terminal window execute the command `az login` and enter your credentials in the browser displayed.
1. In the [Azure Portal](https://portal.azure.com/), go to the app registration you want to obtain the authorization token in Azure AD, in this case, the app registration for the Management API.
3. In the [Azure Portal](https://portal.azure.com/), go to the app registration you want to obtain the authorization token in Azure AD, in this case, the app registration for the Management API.
1. On the left pane, click on **Expose an API**.
4. On the left pane, click on **Expose an API**.
1. Click on **Add a client application**.
5. Click on **Add a client application**.
![Add client application](./images/app_registration_add_client_application.png)
1. Add the application Id you want to add in the **Client ID**.
6. Add the application Id you want to add in the **Client ID**.
>**NOTE**: In this case, you need to authorize the `Azure CLI` application to allow to generate the authorization token from this application. The Id of this application is `04b07795-8ddb-461a-bbee-02f9e1bf7b46`.
1. Select the **Authorized scopes**, and finally click on **Add application**.
7. Select the **Authorized scopes**, and finally click on **Add application**.
![Add client application blade](./images/app_registration_add_client_application_blade.png)
1. Go to a terminal window and execute this command: `az account get-access-token --resource {{managementApiAppRegistrationId}}`. Replace the placeholder with the client Id of the app registration created for the [Management API](app_registrations.md).
8. Go to a terminal window and execute this command: `az account get-access-token --resource {{managementApiAppRegistrationId}}`. Replace the placeholder with the client Id of the app registration created for the [Management API](management-api-app-registration.md).
![Authorization token obtained from Azure CLI](./images/az_cli_authorization_token_output.png)
1. Copy the `accessToken` value.
9. Copy the `accessToken` value.
>**NOTE**: This token is valid for one hour. After that, you will need to generate a new one. In that case, you only need to execute the last step in this document.
[← Back to How to test the Management API](test_web_app.md#how-to-test-the-management-api)
[← Back to Register Service in Cosmos DB](register-service.md#example-of-how-to-use-this-endpoint)
[← Back to How to test the Orchestrator Function](test_function_app.md#how-to-test-the-orchestrator-function)
[← Back to How to test the Management API](test-web-app.md#how-to-test-the-management-api)
[← Back to How to test the Orchestrator Function](test-function-app.md#how-to-test-the-orchestrator-function)

Просмотреть файл

@ -0,0 +1,36 @@
# Azure Key Vault
The Azure Key Vault instance will be used to store the solution's secrets and the SSL certificate. To create the Application Insights, please review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/key-vault/general/quick-create-portal#create-a-vault), and use the following settings:
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Key vault name:*** A meaningful name.
- ***Region:*** Same region as the rest of the resources.
- ***Pricing tier:*** Standard.
## Domain certificate
As part of the configuration, you must import the domain certificate key vault, and add its password and thumbprint as secrets.
### Import domain certificate
To import the SSL certificate with .pfx file format into key vault, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/key-vault/certificates/tutorial-import-certificate?tabs=azure-portal#import-a-certificate-to-your-key-vault)
### Add certificate secrets
To add the password and the thumbprint as secrets, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/key-vault/secrets/quick-create-portal#add-a-secret-to-key-vault), and consider the following names for both secrets:
- **Password:** `Settings--BotConfiguration--CertificatePassword`
- **Thumbprint:** `Settings--BotConfiguration--CertificateThumbprint`
## Assign access policies for Web App Service, Azure Function App Service and Virtual Machine
In order to allow to both app services and the virtual machine to get access to the Key Vault secrets, it is necessary to assign access policies for the app services and the virtual machine. To know how to do it, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/key-vault/general/assign-access-policy?tabs=azure-portal#assign-an-access-policy), and consider the following settings:
- **Key Permissions:** Get, List
- **Secret Permissions:** Get, List
- **Certificate Permissions:** Get, List
- **Select Principal**: Object (principal) Id of the Web App Service/Function App service system managed identity
> NOTE: You must repeat this process for each app service and the virtual machine.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Cosmos DB →](cosmos-db.md#cosmos-db)

Просмотреть файл

@ -0,0 +1,23 @@
# Azure SDK app registration
This documents explains how to create and configure the Azure SDK app registration to enable the backend components to get access to Azure resources through Azure SDK.
## Creation of the app registration
To create the app registrations, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
## Setup of the app registration
### Add a client secret
Finally, you must [add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret), copy the value and add it to the key vault as a secret with the following name:
`Settings--AzServicePrincipalConfiguration--ApplicationClientSecret`.
## Give access to the virtual machine
In order to allow to the backend components to turn on/off the virtual machine through Azure SDK, you give the app registration access to the virtual machine with `Contributor Role` through **Access control (IAM)** menu of the virtual machine resource.
[← Back to How to run the solution in Azure](README.md#app-registrations) | [Next: Security Group →](README.md#security-group)

Просмотреть файл

@ -1,17 +0,0 @@
# Azure SDK Service Principal
## Getting Started
The solution has components that require interaction with Azure resources using the Azure SDK. To allow this interaction, we need to create a Service Principal for the solution and assign it `Contributor` access to the specified Azure Resources. In this guide, we are going to explain how to assing the role to the app registration created in previous steps.
## Dependencies
To continue with the Azure SDK Service Principal documentation, the following dependencies need to be created:
- [Resource Group](resource_group.md).
### Assign Contributor Role
For the time being, the solution needs to interact with the virtual machine where the Bot Service API is hosted (to turn on/turn off the virtual machine). To make this assignment, you must go to the **resource group** where the **virtual machine** was created and through **Access Control (IAM)** assign `Contributor` role to the application, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal?tabs=current).
![Assign Contributor Role](./images/assign_contributor_role.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -0,0 +1,39 @@
# Bot Service API app registration
This documents explains how to create and configure the BotService API app registration to enable Client Credential Authentication between APIs.
## Creation of the app registration
To create the app registrations, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
## Setup of the app registration
### Manifest
In the BotService API Application Manifest editor, we need to change the value `accessTokenAcceptedVersion` field from null (which defaults to: 1) to 2 (for v2.0 tokens).
![Manifest Bot Service API](./images/manifest_botservice_api.png)
Finally, click on the **Save** button.
### App Roles
From the BotService API app registration view, go to the App roles option that is in the resource blade, click the **Create app role** button. Fill the following information with the values suggested.
- ***Display name***: AccessAll.
- ***Allowed member types***: Applications.
- ***Values***: BotService.AccessAll.
- ***Description***: Meaningful description e.g., Access to BotService API.
![App Roles](./images/create_role_bot_service_api.png)
Finally, click on the **Apply** button.
### Expose an API
From the resource blade of the app registration view, go to the **Expose an API** option and click **Set** next to the Application ID URI to generate a URI that is unique for this app (in the form of api://{clientId}).
[← Back to How to run the solution in Azure](README.md#app-registrations) | [Next: BotService Client app registration →](bot-service-client-app-registration.md#bot-service-client-app-registration)

Просмотреть файл

@ -0,0 +1,33 @@
# Bot Service Client app registration
This documents explains how to create and configure the BotService Client app registration to enable Client Credential Authentication between APIs.
## Creation of the app registration
To create the app registrations, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
## Setup of the app registration
### API permissions
From the BotService Client app registration view, go to the **API permissions** option that is in the resource blade, click the **Add a permission** button and then ensure that the **APIs my organization** uses tab is selected. Search for the **BotService API** and click on the search result.
![Search API permissions](./images/search_api_permissions.png)
Then inside BotService select **AccessAll** and click on **Add permissions**.
![Request API permissions.png](./images/request_api_permissions.png)
> **NOTE**: If your user does not have the necessary permissions to enable the add-on permission. You must ask a user with the required permission to enable it.
![Add permissions](./images/bot_service_client_enabled_permissions.png)
### Add a client secret
Finally, you must [add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret), copy the value and add it to the key vault as a secret with the following name:
`Settings--BotServiceAuthenticationConfiguration--ClientSecret`.
[← Back to How to run the solution in Azure](README.md#app-registrations) | [Next: Management API app registration →](management-api-app-registration.md#management-api-app-registration)

Просмотреть файл

@ -0,0 +1,144 @@
# Bot Service deploy
This document describes how to deploy and install the Bot Service into a pre-configured virtual machine.
## Deploying the service
At the moment, there isn't automated deployment for the Bot Service so you need to manually copy and install the compiled version of the Bot Service in your virtual machine. To do this you can use one of the released versions of the Bot Service or compile the code manually in Visual Studio.
### Using a released version
To deploy the latest released version (0.6.0-dev) of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version (0.6.0-dev) of the Bot Service that you want to use.
Then copy the Zip file to your VM and un-zip the files into the folder where you want to install your Bot Service.
### Building from the source code
Open the solution in Visual Studio. Then, go to the solution explorer, right-click on BotService project and click **Publish**.
![Publish Bot Service](./images/publish_bot_service.png)
In the publish tab, configure the Target Location (a folder in your local machine), and edit the following settings:
- **Configuration:** Release
- **Target Framework:** net472
- **Target Runtime:** win7-x64
![Configuration to Publish Bot Service](./images/configuration_to_publish_bot_service.png)
Check the configuration and to finish publishing, press the **Save** button.
![Configuration to Publish Bot Service](./images/save_publish_from_bot_service.png)
After that, we can publish the project, and copy the files from the Target Location folder into the virtual machine. Later, we will explain how to configure the settings and how to run it from the command line or as a Windows Service.
## Updating appSettings.json
After unzipping/copying the bot service into the virtual machine, you must update the `appSettings.json` with the corresponding settings:
```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"HttpServer":{
"Endpoints":{
"Https":{
"Host": "{{virtualMachineDnsCname}}",
"Port": 443,
"Scheme": "https"
}
}
},
"Settings": {
"GraphClientConfiguration": {
"TenantId": "{{tenantIdAzureBotAppRegistration}}",
"ClientId": "{{clientIdAzureBotAppRegistration}}",
"ClientSecret": ""
},
"CosmosDbConfiguration": {
"EndpointUrl": "{{cosmosDbEndpointUrl}}",
"PrimaryKey": "",
"DatabaseName": "{{cosmosDbDatabaseName}}",
},
"BotConfiguration": {
"ServiceDnsName": "{{virtualMachineDnsCname}}",
"ServiceCname": "{{virtualMachineDnsCname}}",
"PlaceCallEndpointUrl": "https://graph.microsoft.com/beta",
"AadAppId": "{{clientIdAzureBotAppRegistration}}",
"AadAppSecret": "",
"NumberOfMultiviewSockets": 3,
"InstanceInternalPort": 8445,
"InstancePublicPort": 8445,
"ServiceFqdn": "{{virtualMachineDnsCname}}",
"CertificateName": "{{certificateName}}",
"CertificatePassword": "",
"CertificateThumbprint":"",
"MainApiUrl":"{{managementApiUrl}}",
"VirtualMachineName": "{{virtualMachineName}}",
"SecondsWithoutParticipantsBeforeRemove": {{secondsBeforeRemove}}
},
"AzureAdConfiguration": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "{{tenantIdBotServiceApiAppRegistration}}"
},
"BotServiceAuthenticationConfiguration": {
"BotServiceApiClientId": "{{botServiceApiClientId}}",
},
"KeyVaultName": "{{keyVaultName}}",
"KeyVaultEnv": "{{keyVaultEnvPrefix}}"
},
"APPINSIGHTS_INSTRUMENTATIONKEY": "{{appInsightsKey}}"
}
```
> **NOTE:** The Bot Service appsettings will be completed in later steps.
### Placeholder specification table
| Placeholder | Description |
|----------------------------------------|-------------------------------------------------------------------------------------|
| virtualMachineDnsCname | Full domain name assigned to the virtual machine where the bot service is hosted. E.g.: If your wildcard certificate is for *.domain.co and you added the cname botservicevm to the IP address of the virtual machine, the domain name will be botservicevm.domain.co. |
| tenantIdAzureBotAppRegistration | Tenant Id of the [Azure Bot](../common/azure-bot.md#azure-bot) app registration. |
| clientIdAzureBotAppRegistration | Client Id of the [Azure Bot](../common/azure-bot.md#azure-bot) app registration. |
| cosmosDbEndpointUrl | Endpoint URL of the [Cosmos DB](cosmos-db.md#cosmos-db) created. |
| cosmosDbDatabaseName | Database name of the [Cosmos DB](cosmos-db.md#cosmos-db) created. |
| certificateName | **Only needed if you want to delegate the installation of your certificate to the Bot Service**. Name of the certificate on Azure Key Vault. |
| managementApiUrl | URL of the [Management API](web-app.md#web-app) without https:// prefix. |
| secondsBeforeRemove | Seconds before removing the bot from a meeting with no participants. |
| tenantIdBotServiceApiAppRegistration | Tenant Id of the app registration for the [Bot Service API](bot-service-api-app-registration.md#bot-service-api-app-registration). |
| botServiceApiClientId | Client Id of the app registration for the [Bot Service API](bot-service-api-app-registration.md#bot-service-api-app-registration). |
| appInsightsKey | Application Insights key of the [Application Insights](application-insights.md#application-insights) resource. |
| keyVaultName | Name of the [Azure Key Vault](azure-key-vault.md#azure-key-vault) resource created in previous steps |
| keyVaultEnvPrefix | **Optional**: Add it only if you want to get secrets that has a specific prefix |
## Running the bot
You have two alternatives to run the bot, from the command line and as a Windows Service. The first alternative is used when you want to see the logs in the terminal. The second alternative is used to run the Bot Service automatically when the VM starts.
> **NOTE**: The first time you configure the environment, you MUST running it from the command line so windows prompts the firewall rule and we can accept and enable it. If windows doesn't prompt the firewall configuration, you must add the rule manually.
### From command line
In this scenario, you can run the Bot Service by executing the command `.\BotService.exe --console` in a terminal window from the path where the Bot Service is located.
### As a Windows Service
To run the bot every time the virtual machine is turned on, you have to configure it as a Windows Service. Before configuring it, you must validate that the group **ALL APPLICATION PACKAGES** has special permissions in the bot folder (right-click in the bot folder, click on **properties**, select the **security** tab). If the group doesn't have permissions, you must add it by clicking on **Advance****Add****Select a Principal**.
![As a Windows Service](./images/configure_windows_service.png)
![Permission entry bot service](./images/permission_entry_bot_service.png)
Finally, you must run the following Powershell command:
```bash
New-Service -Name "Bot-Service" -BinaryPathName '"C:\{bot-service-path}\BotService.exe"'
```
After completing these steps, you must restart the virtual machine or start the Bot Service from the Windows Services app.
[← Back to How to run the solution in Azure](README.md#deployments) | [Next: Management API deploy →](management-api-deploy.md#management-api-deploy)

Просмотреть файл

@ -0,0 +1,28 @@
# Cosmos DB
The **Azure Cosmos DB** database will be used to store the `Broadcast Development Kit` data. To create the Azure Cosmos DB, please review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/cosmos-db/create-cosmosdb-resources-portal#create-an-azure-cosmos-db-account), and use the following settings:
- ***Select API option:*** choose Core (SQL).
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Account Name***: a meaningful name.
- ***Location***: same region as the rest of the resources.
- ***Capacity mode***: Serverless.
- ***Apply Free Tier Discount***: Apply only if there is no other Cosmos DB using it in the subscription.
Leave the rest of the settings as-is.
After creating the Cosmos DB account, navigate to the **Data Explorer** option on the resource blade you have on the left and create new database and the following containers ([How to add a database and a container](https://docs.microsoft.com/en-us/azure/cosmos-db/sql/create-cosmosdb-resources-portal#add-a-database-and-a-container)):
- ***Call***
- Partition Key: /id
- ***ParticipantStream***
- Partition Key: /id
- ***Service***
- Partition Key: /id
- ***Stream***
- Partition Key: /id
Finally, navigate to the **Keys** option you have under the **Settings** section on the resource blade, take note of the `PRIMARY KEY` and add it to the key vault as a secret with the following name:
`Settings--CosmosDbConfiguration--PrimaryKey`.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Storage Account →](storage-account.md)

Просмотреть файл

@ -1,74 +0,0 @@
# Cosmos DB Database
## Getting Started
We use **Azure Cosmos DB** database store the `Broadcast Development Kit` data. In this document, we will explain you step by step how to create the Azure resource and how to configure it.
To create the Azure Cosmos DB, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/cosmos-db/create-cosmosdb-resources-portal#create-an-azure-cosmos-db-account).
## Dependencies
To continue with the Cosmos DB documentation, the following dependencies need to be created:
- [Resource Group](resource_group.md).
### Settings:
- ***Select API option:*** choose Core (SQL).
- ***Resource Group:*** Select the [resource group](resource_group.md) created for the solution architecture.
- ***Account Name***: a meaningful name.
- ***Location***: same region as the rest of the resources.
- ***Capacity mode***: Provisioned throughput.
- ***Apply Free Tier Discount***: Apply only if there is no other Cosmos DB using it in the subscription.
Leave the rest of the settings as-is.
> **NOTE:** The backend components already create the database and containers when they run for the first time. However, the containers aren't going to havea shared throughput. To save cost, we recommend you to continue with this guide and create database manually.
Once the database is created, browse to the **Data Explorer** in the left panel of the account configuration and create a new database with the following settings:
- Database Id: A meaningful name.
- Throughput: Manual – 400 RU/s.
> Note: To keep the costs down, you are setting the RU to the lowest amount possible.
Click on **OK** button to create the database.
After the database is created, it is necessary to add all the containers needed by the solution. The following list shows the name of the containers to be created and the corresponding partition key name:
- ***Call***
- Partition Key: /id
- ***ParticipantStream***
- Partition Key: /id
- ***Service***
- Partition Key: /id
- ***Stream***
- Partition Key: /id
To create those containers, please follow the next steps:
1. In the `Data explorer` view for Cosmos DB in the Azure Portal, select `New Container`.
1. Fill the `New Container` blade displayed with the following values:
- ***Database id***: Check use existing and select the one created in the previous step.
- ***Container id***: Write the name of the container (e.g. *Call*).
- ***Partition key***: Write the name of the partition key (e.g. for Call container the partition key name is /id).
- ***Provision dedicated throughput for this container***: Keep unchecked to share the database throughput between all the containers created.
1. Click **OK** button to create the container.
The images below show the steps from the Azure Portal.
#### Create `New Container` button.
![Add new container](./images/cosmos_db_create_new_container.png)
#### Create `New Container` blade displayed.
![Fill the data to create the container](./images/cosmos_db_create_new_container_blade.png)
>NOTE: The steps described above can be done through the Microsoft Azure Storage explorer.
Finally, go to the resource blade on the left, go to the setting section click on Keys. Copy and save the `URI` and `PRIMARY KEY` from the values displayed. Those values are required along with the database name to complete the configuration of the Bot Service, Bot Orchestrator and Management API.
![Uri and primary key values to copy](./images/cosmos_db_key_and_connection_string.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,74 +0,0 @@
# Deploy the Bot Service
This document describes how to deploy and install the Bot Service into a pre-configured virtual machine.
## Dependencies
Before following this document, these dependencies need to be created and configured:
- [Virtual Machine](virtual_machine.md).
## Deploying the service
At the moment, there isn't automated deployment for the Bot Service so you need to manually copy and install the compiled version of the Bot Service in your virtual machine. To do this you can use one of the released versions of the Bot Service or compile the code manually in Visual Studio.
### Using a released version
To deploy a released version of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version of the Bot Service that you want to use.
Then copy the Zip file to your VM and un-zip the files into the folder where you want to install you Bot Service.
### Building from the source code
Open the solution in Visual Studio. Then, go to the Solution Explorer, right-click on BotService project and click **Publish**.
![Publish Bot Service](./images/publish_bot_service.png)
In the publish tab, configure the Target Location (a folder in your local machine), and edit the following settings:
- ***Configuration:*** Release
- ***Target Framework:*** net472
- ***Target Runtime:*** win7-x64
![Configuration to Publish Bot Service](./images/configuration_to_publish_bot_service.png)
Check the configuration and to finish publishing, press the **Save** button.
![Configuration to Publish Bot Service](./images/save_publish_from_bot_service.png)
After that, we can publish the project, and copy the files from the Target Location folder into the virtual machine. Later, we will explain how to run it from the command line or as a Windows Service.
## Running the bot
We have two alternatives to run the bot, from the command line and as a Windows Service. The first alternative is used when we want to see the logs in the terminal. There are some GStreamer and external libraries stdout/stderr we can't capture nor log them in application insights. The second alternative is used to run the Bot Service authomatically when the VM starts.
> **NOTE**: The first time we configure the environment, we recommend running it from the command line so windows prompts the firewall rule and we can accept and enable it.
### From command line
In this scenario, you can run the Bot Service by executing the command `.\BotService.exe --console` in a terminal window from the path where the Bot Service is located.
If you want to override the environment settings,
you can create a Powershell script in the root folder of the bot. Below there is a sample of the script to override the default environment variables with other values if necessary.
```bash
$env:BLOB_SAS_QUERY = '?{{sasQuery}}'
$env:STORAGE_ACCOUNT = '{{storageAccountName}}'
$env:BLOB_CONTAINER = '{{containerName}}'
$env:APP_SETTINGS_FILE_NAME = '{{envFileName}}'
$env:CERTIFICATE_FILE_NAME = '{{certFileName}}'
.\BotService.exe --console
```
> **NOTE**: You might need to enable remote signed scripts in Powershell using the command `set-executionpolicy remotesigned`.
### As a Windows Service
To run the bot every time the virtual machine is turned on, we configure it as a Windows Service. Before configuring it, we must validate that the group **ALL APPLICATION PACKAGES** has special permissions in the bot folder (right-click in the bot folder, click on **properties**, select the **security** tab). If the group doesn't have permissions, we must add it by clicking on **Advance****Add****Select a Principal**.
![As a Windows Service](./images/configure_windows_service.png)
![Permission entry bot service](./images/permission_entry_bot_service.png)
Finally, we must run the following Powershell command:
```bash
New-Service -Name "Bot-Service" -BinaryPathName '"C:\{bot-service-path}\BotService.exe"'
```
After completing these steps, we must restart the virtual machine or start the Bot Service from the Windows Services app.
>**NOTE**: Before running the BotServie for the first time, we must complete the settings uploaded into the [Storage Account](storage_account.md#environment-json-file-settings-example).
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,66 +0,0 @@
# Deploy the Function App into the Azure Function App Service.
Once the Function App with the corresponding App service plan was successful created, we can deploy the solution build into it.
## Dependencies
To continue with the Deploy the Function App into the Azure Function App Service documentation, the following dependencies need to be created:
- [Function App](function_app_and_app_service_plan.md).
## Deploying a released version
To deploy a released version of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version of the Bot Orchestrator you want to deploy.
Then, using **Azure CLI** (either locally or in the Azure Portal), run the following command to deploy the Zip file:
```
az functionapp deployment source config-zip -g <resource_group> -n <app_name> --src <zip_file_path>
```
## Building and deploying from the source code
To deploy the Function App into the Azure Function App Service created we can follow this steps:
1. Open the solution in **Visual Studio**.
1. In Solution Explorer, right-click in the project `BotOrchestrator` node and choose **Publish**.
1. In **Publish**, select **Azure** and then **Next**.
![Select Azure](./images/deploy_function_app_select_azure.png)
1. Choose in the **specific destination** the option Azure App Service (Windows).
![Select specific destination](./images/deploy_function_app_select_specific_destination.png)
1. Select your subscription and in the **Function Apps** panel, select the Function App that was created from the Azure Portal, and click **Finish**.
![Select Function App Created](./images/deploy_function_app_select_function_app_created.png)
1. Then in the **Service Dependencies** section, in the **Storage Account**, select the option **Configure**.
![imagen](images/deploy_function_app_sa_config.png)
1. Select your **Subscription** and the [Storage Account](storage_account.md) created in the previous steps, then press the **Next** button.
![Configure Storage Account](images/deploy_function_app_sa_select.png)
1. Then check the **Azure App Settings** option and click on the **Next** button.
![Check Azure App Settings](images/deploy_function_app_sa_check.png)
1. In this section uncheck the **three** Azure Storage options and click on the **Finish** button.
![Uncheck thethre Azure Storage options](images/deploy_function_app_sa_uncheck.png)
1. To finish, on the **Publish** page, select **Publish**. Visual Studio builds, packages, and publishes the app to Azure.
## Configure app settings
After deploying the **Function App**, it is necessary to set the configuration parameters. These are carried out by following the steps below:
1. In the [Azure portal](http://portal.azure.com/), search for and select Function App, and then select your app.
![Application settings](./images/function_app_search.png)
1. Select in the app's left menu, select **Configuration** > **Application settings**.
![New application setting](./images/function_app_configuration_application_settings.png)
1. To add a setting in the portal, select **New application setting** and add the new key-value pair.
It is necessary to create the following application settings:
| Name | Value |
|-------------------------------------------------------------|-------------------------------------------------------------------------|
| AzServicePrincipalConfiguration:ApplicationClientId | Client Id of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| AzServicePrincipalConfiguration:ApplicationClientSecret | Client secret of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| AzServicePrincipalConfiguration:SubscriptionId | Subscription Id of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| AzServicePrincipalConfiguration:TenantId | Tenant Id of [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| AZURE_FUNCTIONS_ENVIRONMENT | Development or Production |
| BuildVersion | Version number deployed e.g. 0.0.0-test |
| CosmosDbConfiguration:DatabaseName | Database name of the [Cosmos DB](cosmos_db.md) created. |
| CosmosDbConfiguration:EndpointUrl | Endpoint URL of the [Cosmos DB](cosmos_db.md) created. |
| CosmosDbConfiguration:PrimaryKey | Primary key of the [Cosmos DB](cosmos_db.md) created. |
1. Finally, click on the **Save** button.
![Save new application settings](./images/function_app_save_new_application_settings.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,42 +1,24 @@
# How to configure Event Grid
## Introduction
# Event grid
To keep the state of the bot service virtual machine consistent is Cosmos DB, we
we must configure an event grid subscription to execute an Azure Function that updates its register in Cosmos DB, every time that it is being started/stopped from an external event, e.g.: A user starts/stops the virtual machine from Azure Portal or has scheduled auto-shutdown.
## Dependencies
To continue with the Virtual Event Grid documentation, the following dependencies need to be created:
- [Cosmos DB](cosmos_db.md).
- [BotOrchestrator deployed](deploy_function_app.md).
## Getting Started
To start configuring Event Grid events, we must create an Event Grid Topic resource.
1. Sign in to [Azure portal](https://portal.azure.com/).
1. In the search bar at the topic, type **Event Grid Topics**, and then select E**vent Grid Topics** from the drop-down list.
![Event Grid search](./images/event_grid_search.png)
1. On the **Event Grid Topics** page, select **+ Add** on the toolbar.
![](./images/add_event_grid_topic_button.png)
1. On the **Create Topic** page, complete the requested information:
2. In the search bar at the topic, type **Event Grid Topics**, and then select **Event Grid Topics** from the drop-down list.
3. On the **Event Grid Topics** page, select **+ Add** on the toolbar.
4. On the **Create Topic** page, complete the requested information:
> **NOTE**: We recommend creating the topic in the same resource group where we are going to subscribe to an event (the resource group of the virtual machine) and the same location where the virtual machine was created.
- ***Subscription:*** The Azure subscription where you want to create the topic.
- ***Resource Group:*** The resource group where you want to create the topic.
- ***Name:*** A meaningful name.
- ***Location:*** The Azure location of the resource.
1. Select **Review + create** at the bottom of the page.
![Review + create](./images/create_custom_topic.png)
1. To finish, check the information loaded in the **Review + create** tab, and click on the **Create** button.
![Create](./images/review-create-page.png)
5. Select **Review + create** at the bottom of the page.
6. To finish, check the information loaded in the **Review + create** tab, and click on the **Create** button.
After creating the topic, to configure an Azure function as an event handler for Event grid events, we must go to the resource group where we created the virtual machine, click on the **Events** option located in the resource blade, and then click on **Event Subscription** button.
![Create event subscription](./images/create_new_event_subscription.png)
While creating the Event Subscription, complete the requested information and click on Create button:
- ***Name:*** A meaningful name.
@ -46,8 +28,4 @@ While creating the Event Subscription, complete the requested information and cl
- ***Endpoint Types:*** Azure function.
- ***Endpoint:*** Select the Azure Function that will handle the Event Grid events. By default, it is created in the environment resource group, under the function app with the name virtual-machine-event-grid-handler.
![Event subscription details](./images/details_of_the_new_event_subscription.png)
![Event grid select_azure_function](./images/event_grid_select_azure_function.png)
[← Back to Running the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to run the solution in Azure](README.md#configure-event-gridevent-grid-handler) | [Next: Register the service in Cosmos DB →](README.md#register-the-service-in-cosmos-db.md)

Просмотреть файл

@ -0,0 +1,79 @@
# Function App Deploy
This document describes how to deploy and configure the Function App into the Azure Function App Service.
## Deploying the Function App
To deploy the Function App, you can use one of the released versions or compile the code manually in Visual Studio and use the IDE to deploy it.
### Deploying a released version
To deploy the current released version (0.6.0-dev) of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version (0.6.0-dev) of the Management API you want to deploy.
Then, using **Azure CLI** (either locally or in the Azure Portal), run the following command to deploy the Zip file:
``` shell
az functionapp deployment source config-zip -g <resource_group> -n <app_name> --src <zip_file_path>
```
### Building and deploying from the source code
To deploy the Function App into the Azure Function App Service created we can follow this steps:
1. Open the solution in **Visual Studio**.
2. In Solution Explorer, right-click in the project `BotOrchestrator` node and choose **Publish**.
3. In **Publish**, select **Azure** and then **Next**.
![Select Azure](./images/deploy_function_app_select_azure.png)
4. Choose in the **specific destination** the option Azure App Service (Windows).
![Select specific destination](./images/deploy_function_app_select_specific_destination.png)
5. Select your subscription and in the **Function Apps** panel, select the Function App that was created from the Azure Portal, and click **Finish**.
![Select Function App Created](./images/deploy_function_app_select_function_app_created.png)
6. Then in the **Service Dependencies** section, in the **Storage Account**, select the option **Configure**.
![Storage account config](images/deploy_function_app_sa_config.png)
7. Select your **Subscription** and the [Storage Account](storage-account.md) created in the previous steps, then press the **Next** button.
![Configure Storage Account](images/deploy_function_app_sa_select.png)
8. Then check the **Azure App Settings** option and click on the **Next** button.
![Check Azure App Settings](images/deploy_function_app_sa_check.png)
9. In this section uncheck the **three** Azure Storage options and click on the **Finish** button.
![Uncheck thethre Azure Storage options](images/deploy_function_app_sa_uncheck.png)
10. To finish, on the **Publish** page, select **Publish**. Visual Studio builds, packages, and publishes the app to Azure.
### Configuring app settings
After deploying the **Function App**, it is necessary to set the configuration parameters. These are carried out by following the steps below:
1. In the [Azure portal](http://portal.azure.com/), search for and select Function App, and then select your app.
![Application settings](./images/function_app_search.png)
2. Select in the app's left menu, select **Configuration** > **Application settings**.
![New application setting](./images/function_app_configuration_application_settings.png)
3. To add a setting in the portal, select **New application setting** and add the new key-value pair.
It is necessary to create the following application settings:
> NOTE: We use [Key Vault references](https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references) to work with secrets in the Azure App Services. In the table below, you will find values with the format `@Microsoft.KeyVault(VaultName={{keyVaultName}};SecretName={{secretName}})` where `{{keyVaultName}}` is a placeholder that you have to replace with the name of the Azure Key Vault resource you have created in previous steps (and remove the `{{}}`), and `{{secretName}}` will be already specified.
| Name | Value |
|-------------------------------------------------------------|-------------------------------------------------------------------------|
| APPINSIGHTS_INSTRUMENTATIONKEY | Key of the [Application Insights](application-insights.md) resource created. |
| AzureWebJobsStorage | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--StorageConfiguration--ConnectionString)** |
| AzServicePrincipalConfiguration:ApplicationClientId | Client Id of the [Azure SDK Service Principal](azure-sdk-app-registration.md) app registration. |
| AzServicePrincipalConfiguration:ApplicationClientSecret | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--AzServicePrincipalConfiguration--ApplicationClientSecret)** |
| AzServicePrincipalConfiguration:SubscriptionId | Subscription Id of the [Azure SDK Service Principal](azure-sdk-app-registration.md) app registration. |
| AzServicePrincipalConfiguration:TenantId | Tenant Id of [Azure SDK Service Principal](azure-sdk-app-registration.md) app registration. |
| AZURE_FUNCTIONS_ENVIRONMENT | Development or Production |
| BuildVersion | Version number deployed e.g. 0.0.0-test |
| CosmosDbConfiguration:DatabaseName | Database name of the [Cosmos DB](cosmos-db.md) created. |
| CosmosDbConfiguration:EndpointUrl | Endpoint URL of the [Cosmos DB](cosmos-db.md) created. |
| CosmosDbConfiguration:PrimaryKey | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--CosmosDbConfiguration--PrimaryKey)** |
4. Finally, click on the **Save** button.
![Save new application settings](./images/function_app_save_new_application_settings.png)
[← Back to How to run the solution in Azure](README.md#deployments) | [Next: Configure event grid →](README.md#configure-event-gridevent-grid-handler)

Просмотреть файл

@ -0,0 +1,23 @@
# Function App
To host the Bot Orchestrator function a Function App must be created in Azure. This document shows how to create the Function App for the Bot Orchestrator. To create the Function App and App Service Plan, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-function-app-portal#create-a-function-app) and use the following settings:
- ***Basic:***
- ***Resource Group:*** Select the resource group created for the main resources.the solution architecture.
- ***Name:*** A meaningful name.
- ***Publish:*** Code.
- ***Runtime stack:*** .NET Core 3.1 (LTS).
- ***Region:*** Same region as the rest of the resources.
- ***Hosting:***
- ***Storage account:*** Select the first [Storage Account](storage_account.md) that was created in the previous steps.
- ***Operative system:*** Windows.
- ***Plan:***
- ***Plan type:*** App Service plan.
- ***Windows Plan:*** Select the [App Service plan](service_plan.md) created in the previous steps.
- ***Monitoring:*** Enable [application insights](application_insights.md) and select the instance that was created in a previous step.
## Enable Managed Identity
To allow to the Azure Function App Service to get access to key vault (through Key Vault References), you have to enable a system assigned managed identity. To do so, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity), and take note of the **Object (principal) ID**, you will need it in future steps to configure the Azure Key Vault.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Virtual machine →](virtual-machine.md#virtual-machine)

Просмотреть файл

@ -1,33 +0,0 @@
# Function App
## Introduction
To host the Bot Orchestrator function a Function App must be created in Azure. This document shows how to create the Function App for the Bot Orchestrator.
## Dependencies
To create the Function App service needed to deploy the Orchestrator function, the following resources must be already created:
- [App Service Plan](service_plan.md).
- [Azure Storage Account](storage_account.md).
- [Application Insights](application_insights.md).
### Settings
Fill the fields in the creation wizard with the following information:
- ***Basic:***
- ***Resource Group:*** Select the [resource group](README.md#architecture-resource-group) created for the solution architecture.
- ***Name:*** A meaningful name.
- ***Publish:*** Code.
- ***Runtime stack:*** .NET Core 3.1 (LTS).
- ***Region:*** Same region as the rest of the resources.
- ***Hosting:***
- ***Storage account:*** Select the first [Storage Account](storage_account.md) that was created in the previous steps.
- ***Operative system:*** Windows.
- ***Plan:***
- ***Plan type:*** App Service plan.
- ***Windows Plan:*** Select the [App Service plan](service_plan.md) created in the previous steps.
- ***Monitoring:*** Enable [application insights](application_insights.md) and select the instance that was created in a previous step.
To create the Function App and App Service Plan, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-function-app-portal#create-a-function-app).
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 159 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 72 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 76 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 48 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 55 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 112 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 30 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 124 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 94 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 40 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 72 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 48 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 49 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 35 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 161 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 120 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 214 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 48 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 52 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 82 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 122 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 78 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 75 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 96 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 63 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 71 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 38 KiB

Просмотреть файл

@ -0,0 +1,86 @@
# Management API app registration
This documents explains how to create and configure the Management API app registration to enable Client Credential Authentication between APIs.
## Creation of the app registration
To create the app registrations, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
- ***Supported account types:*** Accounts in this organizational directory only (`your-organization` only - Single tenant).
## Setup of the app registration
### Manifest
In the Management API Application Manifest editor, you need to apply the same change in the manifest as you did for the previous app registration. Change the `accessTokenAcceptedVersion` field from null (which defaults to: 1) to 2 (for v2.0 tokens).
To allow the application to include in the token all the security groups the user belongs, you have to add/modify the following key-values:
```json
"groupMembershipClaims": "SecurityGroup",
"optionalClaims":{
"idToken": [
{
"name":"groups",
"source": null,
"essential": false,
"additionalProperties": [
"emit_as_roles"
]
}
],
"accessToken":[],
"saml2Token":[]
}
```
![Security group claim](./images/management_api_optional_claims_of_manifest.png)
Click the **Save** button to finish.
#### API Graph permissions
From the API app registration view, go to the **API permissions** option that is in the resource blade, click the **Add a permission** button and then ensure that the **Microsoft APIs** tab is selected.
![API Graph permissions](./images/appi_graph_permissions.png)
In the Commonly used Microsoft APIs section, click on **Microsoft Graph**. Then click in the **Delegated permissions** section and ensure that the right permissions are checked (`User.Read` and `offline_access`) and click the **Add permissions** button.
![Add Graph permissions](./images/add_graph_permissions.png)
#### App Roles
> **NOTE**: Next, we will create a new Role, which will serve as a mechanism to demand authorization from other applications.
From the Management API app registration view, go to the App roles option that is in the resource blade, click the **Create app role** button. Fill the following information with the values suggested.
- ***Display name***: AccessAll.
- ***Allowed member types***: Applications.
- ***Values***: ManagementAPI.AccessAll.
- ***Description***: Meaningful description e.g., Access to Management API.
![App Roles](./images/create_role_management_api.png)
Finally, click on the Apply button.
#### Expose an API
From the resource blade of the app registration view, go to the **Expose an API** option and click **Set** next to the Application ID URI to generate a URI that is unique for this app (in the form of api://{clientId}). Then click **Add scope**, complete the form following the parameters listed below, and finally click **Add scope** button.
#### Parameters
> **NOTE**: This `Scope` name is going to be used to develop/configure auth in the extension and they must match.
- ***Scope name***: use `access_as_producer`.
- ***Who can consent***: Admin and users.
- Admin consent display name: enter a meaningful name. E.g.: `Access Broadcaster for Teams as producer`.
- **Admin consent description**: enter a meaningful description.
- **User consent display name**: enter a meaningful name. E.g.: `Access Broadcaster for Teams as producer`.
- **User consent description**: enter a meaningful description.
- **State**: Enabled
![Add Scope](./images/management_api_add_scope.png)
[← Back to How to run the solution in Azure](README.md#app-registrations) |
[Next: Azure SDK app registration →](azure-sdk-app-registration.md#azure-sdk-app-registration)

Просмотреть файл

@ -1,76 +1,82 @@
# Deploy the Web App into the Azure App Service.
# Management API deploy
Once the Web App with the corresponding Azure App service plan was successful created, we can deploy the solution build into it.
This document describes how to deploy and configure the Management API into the Azure App Service.
## Dependencies
To continue with the Deploy the Web App into the Azure App Service documentation, the following dependencies need to be created:
## Deploying the Management API
- [Web App](web_app_and_app_service_plan.md).
To deploy the Management API, you can use one of the released versions or compile the code manually in Visual Studio and use the IDE to deploy it.
## Deploying a released version
To deploy a released version of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version of the Management API you want to deploy.
### Deploying a released version
To deploy the current released version (0.6.0-dev) of the solution go to the [Releases](https://github.com/microsoft/Broadcast-Development-Kit/releases) page and download the Zip file for the version (0.6.0-dev) of the Management API you want to deploy.
Then, using **Azure CLI** (either locally or in the Azure Portal), run the following command to deploy the Zip file:
```
``` shell
az webapp deployment source config-zip --resource-group <resource_group> --name <app-name> --src <zip_file_path>
```
## Building and deploying from the source code
To deploy the Web App into the Web Azure App Service created we can follow this steps:
1. Open the solution in **Visual Studio**.
1. In Solution Explorer, right-click in the project `ManagementApi` node and choose **Publish**.
1. In **Publish**, select **Azure** and then **Next**.
![Select Azure](./images/deploy_web_app_select_azure.png)
1. Choose in the **specific destination** the option Azure App Service (Windows).
![Select specific destination](./images/deploy_web_app_select_specific_destination.png)
1. Select your subscription and in the **Web Apps** panel, select the Web App that was created from the Azure Portal, and click **Finish**.
![Select Web App Created](./images/deploy_web_app_select_web_app_created.png)
1. In the **Publish** page, select **Publish**. Visual Studio builds, packages, and publishes the app to Azure, and then launches the app in the default browser.
### Building and deploying from the source code
## Configure app settings
After deploying the **Web App**, it is necessary to set the configuration parameters. These are carried out by following the steps below:
To deploy the Web App into the Web Azure App Service created we can follow this steps:
1. Open the solution in **Visual Studio**.
2. In Solution Explorer, right-click in the project `ManagementApi` node and choose **Publish**.
3. In **Publish**, select **Azure** and then **Next**.
![Select Azure](./images/deploy_web_app_select_azure.png)
4. Choose in the **specific destination** the option Azure App Service (Windows).
![Select specific destination](./images/deploy_web_app_select_specific_destination.png)
5. Select your subscription and in the **Web Apps** panel, select the Web App that was created from the Azure Portal, and click **Finish**.
![Select Web App Created](./images/deploy_web_app_select_web_app_created.png)
6. In the **Publish** page, select **Publish**. Visual Studio builds, packages, and publishes the app to Azure, and then launches the app in the default browser.
## Configuring app settings
After deploying the **Web App**, it is necessary to set the configuration parameters.
1. In the [Azure portal](http://portal.azure.com/), search for and select App Services, and then select your app.
![Application settings](./images/web_app_search.png)
1. Select in the app's left menu, select **Configuration** > **Application settings**.
![New application setting](./images/function_app_configuration_application_settings.png)
1. To add a setting in the portal, select **New application setting** and add the new key-value pair.
2. Select in the app's left menu, select **Configuration** > **Application settings**.
![New application setting](./images/web_app_configuration_application_settings.png)
3. To add a setting in the portal, select **New application setting** and add the new key-value pair.
It is necessary to create the following application settings:
> NOTE: We use [Key Vault references](https://docs.microsoft.com/en-us/azure/app-service/app-service-key-vault-references) to work with secrets in the Azure App Services. In the table below, you will find values with the format `@Microsoft.KeyVault(VaultName={{keyVaultName}};SecretName={{secretName}})` where `{{keyVaultName}}` is a placeholder that you have to replace with the name of the Azure Key Vault resource you have created in previous steps (and remove the `{{}}`), and `{{secretName}}` will be already specified.
| Name | Value |
|----------------------------------------------------------------------|------------------------------------------------------------------------|
| APPINSIGHTS_INSTRUMENTATIONKEY | Key of the [Application Insights](application_insights.md) resource created. |
| APPINSIGHTS_INSTRUMENTATIONKEY | Key of the [Application Insights](application-insights.md) resource created. |
| APPINSIGHTS_PROFILERFEATURE_VERSION | disabled |
| APPINSIGHTS_SNAPSHOTFEATURE_VERSION | disabled |
| ApplicationInsightsAgent_EXTENSION_VERSION | ~2 |
| DiagnosticServices_EXTENSION_VERSION | disabled |
| InstrumentationEngine_EXTENSION_VERSION | disabled |
| Logging:LogLevel:Default | Information |
| Settings:AzServicePrincipalConfiguration:ApplicationClientId | Client Id of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| Settings:AzServicePrincipalConfiguration:ApplicationClientSecret | Client secret of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| Settings:AzServicePrincipalConfiguration:SubscriptionId | Subscription Id of the [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| Settings:AzServicePrincipalConfiguration:TenantId | Tenant Id of [Azure SDK Service Principal](azure_sdk_service_principal.md) app registration. |
| Settings:AzServicePrincipalConfiguration:ApplicationClientId | Client Id of the [Azure SDK Service app registration](azure-sdk-app-registration.md) app registration. |
| Settings:AzServicePrincipalConfiguration:ApplicationClientSecret | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--AzServicePrincipalConfiguration--ApplicationClientSecret)** |
| Settings:AzServicePrincipalConfiguration:SubscriptionId | Subscription Id of the [Azure SDK app registration](azure-sdk-app-registration.md) app registration. |
| Settings:AzServicePrincipalConfiguration:TenantId | Tenant Id of [Azure SDK app registration](azure-sdk-app-registration.md) app registration. |
| ASPNETCORE_ENVIRONMENT | Development or Production |
| Settings:AzureAdConfiguration:ClientId | Id of the [Management API](app_registration.md) app registration created in Azure AD. |
| Settings:AzureAdConfiguration:GroupId | Id of the [Security Group](security_group.md) created in Azure AD. |
| Settings:AzureAdConfiguration:Instance | https://login.microsoftonline.com/ |
| Settings:AzureAdConfiguration:ClientId | Id of the [Management API](management-api-app-registration.md) app registration created in Azure AD. |
| Settings:AzureAdConfiguration:GroupId | **Optional**: If you don't want to restrict access to the users using a Security Group, leave this field empty. In contrary case, enter the Id of the [Security Group](security-group.md) created in Azure AD. |
| Settings:AzureAdConfiguration:Instance | <https://login.microsoftonline.com/> |
| Settings:AzureAdConfiguration:TenantId | Tenant Id of Azure AD. |
| Settings:BotServiceAuthenticationConfiguration:BotServiceApiClientId | Client Id of the [Bot Service API](app_registrations.md) app registration. |
| Settings:BotServiceAuthenticationConfiguration:ClientId | Client Id of the [Bot Service Client](app_registrations.md) app registration. |
| Settings:BotServiceAuthenticationConfiguration:ClientSecret | Client secret of the [Bot Service Client](app_registrations.md) app registration. |
| Settings:BuildVersion | verision deployed e.g. 0.0.1-test |
| Settings:CosmosDbConfiguration:DatabaseName | Database name of the [Cosmos DB](cosmos_db.md) created. |
| Settings:CosmosDbConfiguration:EndpointUrl | Endpoint URL of the [Cosmos DB](cosmos_db.md) created. |
| Settings:CosmosDbConfiguration:PrimaryKey | Primary key of the [Cosmos DB](cosmos_db.md) created. |
| Settings:GraphClientConfiguration:ClientId | Client Id of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| Settings:GraphClientConfiguration:ClientSecret | Client secret of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| Settings:GraphClientConfiguration:TenantId | Tenant Id of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| Settings:StorageConfiguration:ConnectionString | Connection string of the [Storage account](storage_account.md) created where the config is stored. |
| Settings:BotServiceAuthenticationConfiguration:BotServiceApiClientId | Client Id of the [Bot Service API](bot-service-api-app-registration.md) app registration. |
| Settings:BotServiceAuthenticationConfiguration:ClientId | Client Id of the [Bot Service Client](bot-service-client-app-registration.md) app registration. |
| Settings:BotServiceAuthenticationConfiguration:ClientSecret | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--BotServiceAuthenticationConfiguration--ClientSecret)** |
| Settings:BuildVersion | version deployed e.g. 0.0.1-test |
| Settings:CosmosDbConfiguration:DatabaseName | Database name of the [Cosmos DB](cosmos-db.md) created. |
| Settings:CosmosDbConfiguration:EndpointUrl | Endpoint URL of the [Cosmos DB](cosmos-db.md) created. |
| Settings:CosmosDbConfiguration:PrimaryKey | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--CosmosDbConfiguration--PrimaryKey)** |
| Settings:GraphClientConfiguration:ClientId | Client Id of the [Azure Bot](../common/azure-bot.md) app registration. |
| Settings:GraphClientConfiguration:ClientSecret | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--GraphClientConfiguration--ClientSecret)** |
| Settings:GraphClientConfiguration:TenantId | Tenant Id of the [Azure Bot](../common/azure-bot.md) app registration. |
| Settings:StorageConfiguration:ConnectionString | **@Microsoft.KeyVault(VaultName=`{{keyVaultName}}`;SecretName=Settings--StorageConfiguration--ConnectionString)** |
| SnapshotDebugger_EXTENSION_VERSION | disabled |
| XDT_MicrosoftApplicationInsights_BaseExtensions | disabled |
| XDT_MicrosoftApplicationInsights_Mode | recommended |
1. Finally, click on the **Save** button.
4. Finally, click on the **Save** button.
![Save new application settings](./images/web_app_save_new_application_settings.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to run the solution in Azure](README.md#deployments) | [Next: Function App deploy →](function-app-deploy.md#function-app-deploy.md)

Просмотреть файл

@ -1,25 +1,18 @@
# How to Add the Service
# Register service
## Introduction
In order to start using the Azure environment once all the components have been deployed and configured, it is necessary to configure/register a service into the Cosmos DB.
## Dependencies
To configure/register the service, the following dependencies need to be created:
- [Management API](deploy_web_app.md).
- [BotOrchestrator deployed](deploy_function_app.md).
- [Cosmos DB](cosmos_db.md).
>**NOTE**: The Web and the Function Apps not only need to be created but also both components (Management API and Orchestrator Function) need to be deployed and configured.
## Configure/Register the service
There are two approaches you can follow to configure/register the service in the database:
1. **Sending a request to the Management API**. This is the recommended approach, but take into account that the API is secured through Azure AD and you will need to generate an access token to use this endpoint.
2. **Manually adding the service in the database**. This approach is easier, but it can be error prone.
Below you can find both approaches.
### Configure/Register using the API
The service is configured/registered through the Management API by making a `POST` request to the `/api/service`. The snippet below shows the `payload` request needed.
```json
@ -36,25 +29,26 @@ The service is configured/registered through the Management API by making a `POS
| Placeholder | Description |
|----------------------------------------|-------------------------------------------------------------------------------------|
| serviceName | A meaningful name for the service to be configured/registered, e.g. `Test service`. |
| virtualMachineResourceGroup | The [resource group](README.md#resource-groups) name where the virtual machine was created. |
| virtualMachineResourceGroup | The resource group name where the virtual machine was created. |
| subscriptionIdOfResourceGroup | The subscription Id where the virtual machine resource group was created. |
| virtualMachineName | The name of the [virtual machine](virtual_machine.md) |
| serviceDefault | Indicates whether the service to be added is the default, set it to `true`. |
#### Example of how to use this endpoint
You can use any HTTP client to configure/register the service to be used by the solution. In this example, the client used is `Postman`.
Open `Postman` and create a new `POST` request pointing to the following endpoint: https://{{webAppUrl}}/api/service
Open `Postman` and create a new `POST` request pointing to the following endpoint: <https://{{webAppUrl}}/api/service>
| Placeholder | Description |
|----------------------------------------|-------------------------------------------------------------------------------------|
| webAppUrl | This is the [Web App](web_app_and_app_service_plan.md) service in Azure URL where the Management API was deployed |
| webAppUrl | This is the [Web App](web-app.md#web-app) service in Azure URL where the Management API was deployed |
In the authorization tab, select `Bearer Token` for `Type` and add the authorization token in the corresponding `Token` input.
![Postman authorization header](./images/postman_add_service_auth_header.png)
To get the authorization token for the Management API resource you can follow the steps described in this [document](authorization_token.md).
To get the authorization token for the Management API resource you can follow the steps described in this [document](authorization-token.md).
In the header tab, add (if it does not exist) a new key `Content-Type` with the value `application/json`.
@ -62,9 +56,10 @@ In the body tab select raw and complete by copying the following
![Postman select body type](./images/postman_add_service_payload.png)
Click on send to configure/register the service.
Click on send to configure/register the service.
### Configure/Register in the database
With the virtual machine running, go to your Cosmos DB database, locate the `Service` container and create a new entry with the following information. Then click `Save` to persist the changes.
```json
@ -104,4 +99,4 @@ With the virtual machine running, go to your Cosmos DB database, locate the `Ser
> Note: In the current implementation, the ID `00000000-0000-0000-0000-000000000000` is the ID of the bot service. Keep that ID in the json object as-is.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to run the solution in Azure](README.md#register-the-service-in-cosmos-db.md) | [Next: Test the environment →](README.md#test-the-environment)

Просмотреть файл

@ -1,12 +0,0 @@
# Resource Group
## Getting Started
To organize the different components of the solution we recommend creating two **resource groups** in your Azure subscription, both in the same **region**(e.g., **West US 2**).
- **resource-group-name-bot** – This group will contain the rest of the resources related to the APIs, functions, database, and web UI used to operate the solution.
- **resource-group-name-bot-vm** – This group will be used to contain the resources related to the virtual machine that will host the core components of the application in Azure
To create the resource groups, check the [Create resource groups](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#create-resource-groups) documentation.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,25 +1,21 @@
# Security Group
## Getting Started
The Security Group will be used to grant access and permissions to predefined users to the application.
The Security Group will be used to grant access and permissions to predefined users to the application.
To create the **Security Group** and **add members**, review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal#create-a-basic-group-and-add-members), and consider the following settings:
To create the **Security Group** and **add members**, review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal#create-a-basic-group-and-add-members).
### Settings:
- ***GroupType:*** Select the group type **Security**.
- ***Group name:*** A meaningful name.
- ***GroupType:*** Select the group type **Security**.
- ***Group name:*** A meaningful name.
- ***Group description:*** A meaningful description (optional).
- ***Membership type:*** Select **Assigned** membership for the group.
> **NOTE:** You will need the `Group Id` later to configure the project, so register it as soon as it is visible from the Azure portal.
> **NOTE:** You will need the `Group Id` later to configure the solution, so take note of it.
## Add Member to the Security Group
Once the **Security Group** has been created, it is necessary to add the members of the group that will be able to operate the solution. To add members, it is suggested to carry out the following steps:
1. Enter the **Security Group** created and select the *Members* option on the left panel.
![Add Members](images/security_group_add_members.png)
1. Then click on the **+ Add members** button and start searching for members to add to your group, and click on the **Select** button to add them.
![](images/security_group_select_members.png)
2. Then click on the **+ Add members** button and start searching for members to add to your group, and click on the **Select** button to add them.
![Add Members](images/security_group_select_members.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to run the solution in Azure](README.md#security-group) | [Next: Azure Bot →](README.md#azure-bot)

Просмотреть файл

@ -1,39 +0,0 @@
# App Service Plan
## Introduction
To run the Management API and Bot Orchestrator function in Azure an you must created an App Service Plan. This App Service Plan will define the resources available to execute the apps.
## Dependencies
To continue with the App Service Plan, the following dependencies need to be created:
- [Resource Group](resource_group.md).
### Settings
Fill the fields in the creation wizard with the following information:
- ***Resource Group:*** Select the [resource group](README.md#architecture-resource-group) created for the solution architecture.
- ***Name:*** A meaningful name.
- ***Operating System:*** Windows.
- ***Region:*** Same region as the rest of the resources.
- ***Pricing Tier***
- ***Sku and size:*** Basic B1.
> **NOTE**: The tier (Shared D1) can be used to reduce costs during the test. However note that this can cause issues, like the Azure Functions not processing the messages from the queues.
### Create App Service Plan in Azure.
1. In the [Azure Portal](https://portal.azure.com/), click **Create a resource**, and in the search bar enter **application service plan**. Then click on **Create** button.
![Search application service plan](images/service_plan_search.png)
1. Select the subscription and complete the fields following the indications in the previous section. Then in the **Pricing Tier** section click on **Change size**.
![Complete the fields](images/service_plan_information.png)
1. Next, in the **Recommended pricing tiers** panel, select the **Dev/Test** tab, then select the **B1** tier, and click on **Apply**.
![Recommended pricing tiers](images/service_plan_select_tier.png)
1. Then press the tab **Create** button to finish with the creation.
![Create](images/service_plan_create.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -0,0 +1,14 @@
# Storage Account
The Storage Account will be used by the Azure function you are going to setup later. To create a Storage account in Azure, please review the following [Microsoft documentation](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal) and use the following settings:
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Storage account Name***: A meaningful name.
- ***Region***: Same region as the rest of the resources.
- ***Performance***: Standard.
- ***Redundancy***: Locally-redundant storage (LRS).
Finally, navigate to the **Access keys** option you have under the **Settings** section on the resource blade, take note of the `Connection string` and add it to the key vault as a secret with the following name:
`Settings--StorageConfiguration--ConnectionString`.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Setup DNS for the virtual machine →](README.md#setup-dns-for-the-virtual-machine)

Просмотреть файл

@ -1,151 +0,0 @@
# Storage Account
## Getting Started
This document shows how to create and configure the Storage account for the solution core components. This Storage account will be used to store the environment settings in `json` format and the queues that are consumed by the Azure Functions. If you want to delegate the installation of the wildcard SSL certificate to the Bot Service, you will also store the certificate in `pfx` format in this storage account.
To create a Storage account in Azure, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal).
## Dependencies
Although there are no dependencies with other Azure resources to create this resource, note that some configuration values from other resources will be required.
The following list shows the resources required to complete the configuration of this Storage account:
- [Azure Bot app registration](../prerequisites/azure_bot.md).
- [Cosmos DB](cosmos_db.md).
- [SSL Certificate](../prerequisites/README.md).
- [Azure Virtual Machine (where the bot service is hosted)](virtual_machine.md).
- [Management API](web_app_and_app_service_plan.md).
- [Bot Service API app registration](app_registrations.md#how-to-setup-bot-service-api-app-registration).
- [Application Insights](application_insights.md).
### Settings
Create this storage account with the following settings:
- ***Resource Group:*** Select the [resource group](README.md#architecture-resource-group) created for the solution architecture.
- ***Storage account Name***: A meaningful name.
- ***Region***: Same region as the rest of the resources.
- ***Performance***: Standard.
- ***Redundancy***: Locally-redundant storage (LRS).
> **NOTE:** You will need the **Access keys** (`key1` and `Connection string`) later to configure the project, so register them as soon as it is visible from the Azure portal.
Leave the rest of the settings as-is.
Once this Storage account is created, create a new container with the following settings:
- ***Name***: config.
- ***Public access level***: private.
To create a new Container, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-portal#create-a-container)
Once the config container is created, upload the Bot Service settings in it. If you plan to delegate the installation of the certificate to the Bot Service, will need to upload the wildcard SSL certificate files to it too.
### Environment ***.json*** file settings example:
Below there is a json file template with placeholders values you need to complete and upload to storage account before using the bot for the first time.
```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"HttpServer":{
"Endpoints":{
"Http":{
"Host": "{{virtualMachineDnsCname}}",
"Port": 80,
"Scheme": "http"
},
"Https":{
"Host": "{{virtualMachineDnsCname}}",
"Port": 443,
"Scheme": "https"
}
}
},
"Settings": {
"GraphClientConfiguration": {
"TenantId": "{{tenantIdAzureBotAppRegistration}}",
"ClientId": "{{clientIdAzureBotAppRegistration}}",
"ClientSecret": "{{clientSecretAzureBotAppRegistration}}"
},
"CosmosDbConfiguration": {
"EndpointUrl": "{{cosmosDbEndpointUrl}}",
"PrimaryKey": "{{cosmosDbPrimareyKey}}",
"DatabaseName": "{{cosmosDbDatabaseName}}",
},
"BotConfiguration": {
"ServiceDnsName": "{{virtualMachineDnsCname}}",
"ServiceCname": "{{virtualMachineDnsCname}}",
"PlaceCallEndpointUrl": "https://graph.microsoft.com/beta",
"AadAppId": "{{clientIdAzureBotAppRegistration}}",
"AadAppSecret": "{{clientSecretAzureBotAppRegistration}}",
"NumberOfMultiviewSockets": 3,
"InstanceInternalPort": 8445,
"InstancePublicPort": 8445,
"ServiceFqdn": "{{virtualMachineDnsCname}}",
"CertificatePassword": "{{pfxCertificatePassword}}",
"CertificateThumbprint":"{{pfxCertificateThumbprint}}",
"MainApiUrl":"{{managementApiURl}}",
"VirtualMachineName": "{{virtualMachineName}}"
},
"AzureAdConfiguration": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "{{tenantIdAzureBotServiceApiClientId}}"
},
"BotServiceAuthenticationConfiguration": {
"BotServiceApiClientId": "{{botServiceApiClientId}}",
}
},
"APPINSIGHTS_INSTRUMENTATIONKEY": "{{appInsightsKey}}"
}
```
> **NOTE:** The Bot Service appsettings will be completed in later steps.
### Placeholder specification table
| Placeholder | Description |
|----------------------------------------|-------------------------------------------------------------------------------------|
| virtualMachineDnsCname | Full domain name assigned to the virtual machine where the bot service is hosted. E.g.: If your wildcard certificate is for *.domain.co and you added the cname botservicevm to the IP address of the virtual machine, the domain name will be botservicevm.domain.co. |
| tenantIdAzureBotAppRegistration | Tenant Id of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| clientIdAzureBotAppRegistration | Client Id of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| clientIdAzureBotAppRegistration | Client secret of the [Azure Bot](../prerequisites/azure_bot.md) app registration. |
| cosmosDbEndpointUrl | Endpoint URL of the [Cosmos DB](cosmos_db.md) created. |
| cosmosDbPrimareyKey | Primary key of the [Cosmos DB](cosmos_db.md) created. |
| cosmosDbDatabaseName | Database name of the [Cosmos DB](cosmos_db.md) created. |
| pfxCertificatePassword | **Only needed if you want to delegate the installation of your certificate to the Bot Service**. Password of the wildcard certificate uploaded to the Storage account. |
| pfxCertificateThumbprint | Thumbprint of the wildcard certificate uploaded to the Storage account. |
| managementApiURl | URL of the [Management API](web_app_and_app_function.md) (without https:// prefix). |
| tenantIdAzureBotServiceApiClientId | Tenant Id of the app registration for the [Bot Service API](app_registrations.md#how-to-setup-bot-service-api-app-registration). |
| botServiceApiClientId | Client Id of the app registration for the [Bot Service API](app_registrations.md#how-to-setup-bot-service-api-app-registration). |
| appInsightsKey | Application Insights key of the [Application Insights](application_insights.md) resource. |
## Upload file to container
Here's explains how to upload the `json file` into the container that was created.
1. From the container created, click on **Upload**.
![Uplaoad container](images/container_upload.png)
1. You must select the `json file` that we created in previous step, and then to finish the upload, click on **Upload**.
![Select file](images/container_select_file.png)
## Generate SAS Token
In order to get access to the container created from the Bot Service API we need to generate a Shared access signature, please review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/cognitive-services/translator/document-translation/create-sas-tokens?tabs=Containers)
Create this SAS tokens with the following settings:
- ***Signing method*** Account key.
- ***Signing key***: Key 1.
- ***Permissions***: Read.
- ***Start and expiry data/time***: Select the Time zone for the Start and Expiry date and time (default is Local).
- ***Redundancy***: Locally-redundant storage (LRS).
- ***Allowed protocols:*** HTTPS only.
> **NOTE:** You will need the `Blob SAS token` later to configure the project, so register it as soon as it is visible from the Azure portal.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,35 +1,33 @@
# How to test the Orchestrator Function
## Getting Started
To verify that the **Bot Orchestrator Function** is executing correctly, we will use [Postman](https://identity.getpostman.com/signup?continue=https%3A%2F%2Fgo.postman.co%2Fbuild) using endpoints of the **Management API** to consult the state of the service, start/stop service, where the calls will place a message in the queue of the [Storage Account](storage-account.md) created in the previous steps, and this will trigger the corresponding function (`start-virtual-machine` and `stop-virtual-machine`).
To verify that the **Orchestrator Function** is executing correctly, we will use [Postman](https://identity.getpostman.com/signup?continue=https%3A%2F%2Fgo.postman.co%2Fbuild) using endpoints of the **Management API** to consult the state of the service, start/stop service, where the calls will place a message in the queue of the [Storage Account](storage_account.md) created in the previous steps, and this will trigger the corresponding function (`start-virtual-machine` and `stop-virtual-machine`).
### Check Service State
## Check Service State
1. Open **Postman** and create a new **GET** request pointing to the following address: `https://{{webAppUrl}}/api/service/{{serviceId}}/state`.
> **NOTE:** Replace the placeholder `{{webAppUrl}}` with the URL of the [Web App](web_app_and_app_service_plan.md) created in the previous steps.For the placeholder `serviceId`, enter the id of the [Service](add_service.md) obtained in the previous steps.
1. You must now obtain the token that allows validation to use the **Management API** endpoints. Check the following [documentation](authorization_token.md), which explains how to obtain the token.
1. Once the token is obtained, in the authorization tab, select `Bearer Token` for `Type` and add the authorization token in the corresponding input.
2. You must now obtain the token that allows validation to use the **Management API** endpoints. Check the following [documentation](authorization-token.md), which explains how to obtain the token.
3. Once the token is obtained, in the authorization tab, select `Bearer Token` for `Type` and add the authorization token in the corresponding input.
![Auht Header](images/test_web_app_postman_add_service_auth_header.png)
1. In the header tab, add (if it does not exist) a new key `Content-Type` with the value `application/json`.
4. In the header tab, add (if it does not exist) a new key `Content-Type` with the value `application/json`.
![Postman Header](../how-to-run-the-solution-locally/images/postman_header.png)
1. In the **Body** tab select **none**.
1. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` Ok and in the property `powerState` of the **json** response you can see the current service status.
5. In the **Body** tab select **none**.
6. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` Ok and in the property `powerState` of the **json** response you can see the current service status.
![Test with Postman](images/test_function_app_postman_send_state.png)
### Start Service
## Start Service
1. You must create **New tab**, within Postman go to **File** > **New Tab**.
1. Create a new **POST** request pointing to the following address: `https://{{webAppUrl}}/api/service/{{serviceId}}/start`.
2. Create a new **POST** request pointing to the following address: `https://{{webAppUrl}}/api/service/{{serviceId}}/start`.
> **NOTE:** Replace the placeholder `{{webAppUrl}}` with the URL of the [Web App](web_app_and_app_service_plan.md) created in the previous steps.For the placeholder `serviceId`, enter the id of the [Service](add_service.md) obtained in the previous steps.
1. Use the same authorization and content-type configurations from the [Check Service State](#check-service-state) section (from steps **2** to **5**).
3. Use the same authorization and content-type configurations from the [Check Service State](#check-service-state) section (from steps **2** to **5**).
1. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` OK. If we wait a few minutes and you go back to [check Service state](#check-service-state), you will notice that in the property` powerState` of the **json** returned it will be `PowerState/running`, which indicates that the Service is started.
4. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` OK. If we wait a few minutes and you go back to [check Service state](#check-service-state), you will notice that in the property `powerState` of the **json** returned it will be `PowerState/running`, which indicates that the Service is started.
![Test with Postman](images/test_function_app_postman_send_start.png)
@ -37,19 +35,17 @@ To verify that the **Orchestrator Function** is executing correctly, we will use
1. You must create **New tab**, within Postman go to **File** > **New Tab**.
1. Create a new **POST** request pointing to the following address: `https://{{webAppUrl}}/api/service/{{serviceId}}/stop`.
2. Create a new **POST** request pointing to the following address: `https://{{webAppUrl}}/api/service/{{serviceId}}/stop`.
> **NOTE:** Replace the placeholder `{{webAppUrl}}` with the URL of the [Web App](web_app_and_app_service_plan.md) created in the previous steps.For the placeholder `serviceId`, enter the id of the [Service](add_service.md) obtained in the previous steps.
1. Use the same authorization and content-type configurations from the [Check Service State](#check-service-state) section (from steps **2** to **5**).
1. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` OK. If we wait a few minutes and you go back to [check Service state](#check-service-state), you will notice that in the property` powerState` of the **json** returned it will be `PowerState/deallocated`, which indicates that the Service is stopped.
3. Use the same authorization and content-type configurations from the [Check Service State](#check-service-state) section (from steps **2** to **5**).
4. Then click the button **Send** and the request will be sent to the API, you should receive a response with the status `200` OK. If we wait a few minutes and you go back to [check Service state](#check-service-state), you will notice that in the property `powerState` of the **json** returned it will be `PowerState/deallocated`, which indicates that the Service is stopped.
![Test with Postman](images/test_function_app_postman_send_stop.png)
### Queue Creations after having started and stoped the Service
### Queue Creations after having started and stopped the Service
Once the endpoints have been called to **start** and **stop** the Service, within our Storage Account in the **Queues** section, we can verify that two queues were created (`start-virtual-machine-queue` and `stop-virtual-machine-queue`) corresponding to each action. They are empty since the messages were dequeued when they were triggered by the corresponding function.
![Queues](images/test_function_app_queues.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,34 +1,35 @@
# How to test the Management API
## Getting Started
To verify that the **Management API** is running properly we will use [Postman](https://identity.getpostman.com/signup?continue=https%3A%2F%2Fgo.postman.co%2Fbuild) to join the bot to a Microsoft Teams meeting.
1. [Create](https://support.microsoft.com/en-us/office/schedule-a-meeting-in-teams-943507a9-8583-4c58-b5d2-8ec8265e04e5) a new Microsoft Teams meeting and join it.
![Microsoft Teams Invite Link](../how-to-run-the-solution-locally/images/invite_link.png)
1. Once you have joined the meeting **copy** the invitation link from the meeting and we will use it to join the bot to that meeting.
1. Open **Postman** and create a new POST request pointing to the following address: `https://{{webAppUrl}}/api/call/initialize-call`.
2. Once you have joined the meeting **copy** the invitation link from the meeting and we will use it to join the bot to that meeting.
3. Open **Postman** and create a new POST request pointing to the following address: `https://{{webAppUrl}}/api/call/initialize-call`.
> **NOTE:** Replace the placeholder `{{webAppUrl}}` with the URL of the [Web App](web_app_and_app_service_plan.md) created in previous steps.
1. You must now obtain the token that allows validation to use the **Management API** endpoints. Check the following [documentation](authorization_token.md), which explains how to obtain the token.
1. Once the token is obtained, in the authorization tab, select `Bearer Token` for `Type` and add the authorization token in the corresponding input.
4. You must now obtain the token that allows validation to use the **Management API** endpoints. Check the following [documentation](authorization_token.md), which explains how to obtain the token.
5. Once the token is obtained, in the authorization tab, select `Bearer Token` for `Type` and add the authorization token in the corresponding input.
![Auht Header](images/test_web_app_postman_add_service_auth_header.png)
1. In the header tab, add (if it does not exist) a new key `Content-Type` with the value `application/json`.
6. In the header tab, add (if it does not exist) a new key `Content-Type` with the value `application/json`.
![Postman Header](../how-to-run-the-solution-locally/images/postman_header.png)
1. In the **Body** tab select **raw** and complete by copying the following:
7. In the **Body** tab select **raw** and complete by copying the following:
```json
{
"MeetingUrl": "{{microsoftTeamsInviteLink}}"
}
```
| Placeholder | Description |
|--------------------------|------------------------------|
| microsoftTeamsInviteLink | Microsoft Teams invite link. |
1. Click on the **Send** button and the request will be sent to the solution, you should receive a response with status `200 Ok` and after a few seconds the bot should join the Microsoft Teams meeting.
8. Click on the **Send** button and the request will be sent to the solution, you should receive a response with status `200 Ok` and after a few seconds the bot should join the Microsoft Teams meeting.
![Test with Postman](images/test_with_postman_web_app.png)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,19 +1,13 @@
# Virtual Machine
## Getting Started
This document explains how to create the virtual machine where the Bot Service API is going to be hosted, and how to configure it.
## Dependencies
To continue with the Virtual Machine documentation, the following dependencies need to be created:
- [Storage Account](storage_account.md).
- [SSL Certificate](../prerequisites/README.md).
## Create the virtual machine in Azure
To create the Virtual Machine, check the following document [Create a Windows Virtual Machine in the Azure Portal](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/quick-create-portal).
While creating the virtual machine, consider the following settings:
- ***Subscription:*** The azure subscription where you want to create the VM.
- ***Resource Group:*** The resource group where you want to create the VM. We recommend creating a specific resource group for the VM, so you can easily identify the VM resources in case of resource deletion.
- ***Virtual Machine Name:*** A meaningful name for the VM.
@ -23,26 +17,26 @@ While creating the virtual machine, consider the following settings:
- ***Password:*** A meaningful password.
### Virtual Machine size
The computational power of the VM must be chosen based on the number of simultaneous streams required. The following table shows some of the Azure VM options where the BDK has been tested.
The computational power of the VM must be chosen based on the number of simultaneous streams required. The following table shows some of the Azure VM options where the BDK has been tested.
| Virtual Machine size | Number of simultaneous active streams | Percentage of CPU usage | Notes |
|-------------------------------------|:-------------------------------------:|:-----------------------:|--------------------------------|
| F4s_v2 (4 vCPUs and 8 GB of RAM) | Up to 2 | 95% | Not recommended for production workloads. Only for testing purpose. |
| F8s_v2 (8 vCPUs and 16 GB of RAM) | Up to 4 | 70% | 4 Stream extractions or 3 Stream extractions + 1 stream Injection. |
| F16s_v2 (16 vCPUs and 32 GB of RAM) | Up to 7 | 70% | 7 Stream extractions or 6 Stream extractions + 1 stream Injection. |
| F32s_v2 (32 vCPUs and 32 GB of RAM) | Up to 10 | 50% | 9 Stream extractions + 1 stream injection |
| F8s_v2 (8 vCPUs and 16 GB of RAM) | Up to 4 | 70% | 4 Stream extractions or 3 Stream extractions + 1 stream Injection. |
| F16s_v2 (16 vCPUs and 32 GB of RAM) | Up to 7 | 70% | 7 Stream extractions or 6 Stream extractions + 1 stream Injection. |
| F32s_v2 (32 vCPUs and 32 GB of RAM) | Up to 10 | 50% | 9 Stream extractions + 1 stream injection |
The results shown in the table above are for reference only. Please take into account the following considerations:
- Stream processing (decoding, normalization, and encoding) is performed by the CPU. It is not recommended to exceed the CPU workload above 70% to guarantee the streams quality.
- The results may vary based on the processing required on each stream to decode, normalize, and encode them. For example, streams with fewer variations in image changes tend to require less CPU consumption in the encoding process.
>**NOTE**: The maximum number of streams that can be simultaneously extracted by the bot can be limited by setting the `NumberOfMultiviewSockets` property in the [Bot Service app settings file](storage_account.md#environment-json-file-settings-example). E.g. If you want to limit the maximum number of extractions to N, just set this property to N - 1.
- Stream processing (decoding, normalization, and encoding) is performed by the CPU. It is not recommended to exceed the CPU workload above 70% to guarantee the streams quality.
- The results may vary based on the processing required on each stream to decode, normalize, and encode them. For example, streams with fewer variations in image changes tend to require less CPU consumption in the encoding process.
### Network Security Group inbound rules
Once the virtual machine is created, we must add inbound rules in the network security group.
Once the virtual machine is created, we must add inbound rules in the network security group, and then change the private IP address to static.
**Inbound rules**
#### Inbound rules
| Name | Port | Protocol | Purpose |
|-----------------|-----------|----------|-------------------------------------------------------------------------|
@ -52,51 +46,42 @@ Once the virtual machine is created, we must add inbound rules in the network se
| RTMP | 1935-1936, 1940-1949 | TCP | Used to inject & extract RTMP content. |
| RTMPS | 2935-2936, 2940-2949 | TCP | Used to inject & extract RTMPS content. |
#### Change private IP address to static
To change the private IP address to static, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/virtual-network/ip-services/virtual-networks-static-private-ip-arm-pportal#change-private-ip-address-to-static).
## Configure the virtual machine
Before starting using the virtual machine, we must install the applications listed below.
> **IMPORTANT**: The disk D:\ is a temporary disk (files are deleted after shutdown/restart of the virtual machine) so you must install all the applications in C:\.
### SSL Certificate
Your wildcard SSL certificate can be installed in the virtual machine using one of these approaches:
1. **Install the SSL certificate manually in the VM.** The main advantage of this is that you won't need to upload your PFX and password to the storage account, but you will need to change the certificate manually once it expires. To use this approach check the instructions in [Manual installation of your domain certificate](../common/install_domain_certificate.md).
1. **Automatically through the Bot Service.** If you have uploaded the SSL certificate to the Azure Key Vault after creating the key vault ([Azure Key Vault](azure-key-vault.md)), the Bot Service will take care of installing the latest certificate. If you haven't uploaded it, consider uploading it or following the approach number two.
2. **Automatically through the Bot Service.** The main advantage is that the Bot Service will take care of installing the latest certificate as long as it is available in the storage account. The downside is that you will need to upload the certificate and password to the storage account. To delegate the installation to the Bot Service, check the instructions in [Storage Account](storage_account.md).
2. **Install the SSL certificate manually in the VM.** The main advantage of this is that you won't need to upload your PFX and password to the Azure Key Vault, but you will need to change the certificate manually once it expires. To use this approach check the instructions in [Manual installation of your domain certificate](../common/install-domain-certificate.md).
### Gstreamer
Download the GStreamer installer from this [link](https://gstreamer.freedesktop.org/data/pkg/windows/1.18.4/mingw/gstreamer-1.0-mingw-x86_64-1.18.4.msi). Once you have downloaded the installer and started the installation process, choose the custom installation and make sure that all modules have been selected and the installation path is in C:\.
### GStreamer
Download the GStreamer installer from this [link](https://gstreamer.freedesktop.org/data/pkg/windows/1.18.6/mingw/gstreamer-1.0-mingw-x86_64-1.18.6.msi). Once you have downloaded the installer and started the installation process, choose the custom installation and make sure that all modules have been selected and the installation path is in C:\.
> **IMPORTANT**: Remember to select all GStreamer modules/plugins while installing GStreamer as a custom installation.
After GStreamer installation, add the GStreamer bin folder path to the path environment variable.
### VCRedist
Download [VCRedist](https://aka.ms/vs/16/release/vc_redist.x64.exe) and install it.
### NGINX
Follow this guide [How to Install and configure NGINX with RTMP module on Windows](../common/install_and_configure_nginx_with_rtmp_module_on_windows.md) to install and configure NGINX with RTMP module on windows, and configure it as a Windows service.
### Environment variables
In order to run the bot, we need to configure some environment variables that the bot will read in order to get access to its configuration settings and certificate.
Follow this guide [How to Install and configure NGINX with RTMP module on Windows](../common/install-and-configure-nginx-with-rtmp-module-on-windows.md) to install and configure NGINX with RTMP module on windows, and configure it as a Windows service.
> **IMPORTANT** Before performing these steps, the storage account with the bot configurations must be already created to set the environment's variables.
## Enable Managed Identity
![Set Environment Variables](./images/set_environment_variables.png)
To allow to the virtual machine to get access to key vault, you have to enable a system assigned managed identity. To do so, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm#enable-system-assigned-managed-identity-on-an-existing-vm), and take note of the **Object (principal) ID**, you will need it in future steps to configure the Azure Key Vault.
![Set Systema Variables](./images/set_system_variables.png)
| **Placer** | **Description** |
|---------------------------|----------------------------------------------------------------------|
| storage account | Name of the [Storage account](app_registrations.md) where the files are being stored. |
| blob container | Name the container of [Storage account](app_registrations.md). |
| blob sas query | SAS key to get access to the container files of [Storage account](app_registrations.md). |
| settings json file name | Name of the bot app settings file uploaded into the config container in the [Storage account](app_registrations.md). |
| certificate pfx file name | Name of `.pfx` [wilcard certificate](../prerequisites/README.md) for the domain. |
> **NOTE**: The `BLOB_SAS_QUERY` must include the '?' at the beginning. This token has an expiration date, be aware of this date to renew the access token.
## Bot Service
For instructions on how to deploy the Bot Service to the virtual machine you created check the [Deploy the Bot Service](deploy_bot_service.md) document.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Azure Key Vault →](azure-key-vault.md#azure-key-vault)

Просмотреть файл

@ -0,0 +1,34 @@
# Web App
To host the Management API a Web App service must be created in Azure. This document shows how to create the Web App for this API. To create the Web App, please review the following the [Create a web app](#create-a-web-app) section.
## Create a web app
Sign in to the [Azure portal](https://portal.azure.com/learn.docs.microsoft.com) using the same account you used to activate the sandbox.
1. On the Azure portal menu, or from the Home page, select Create a resource. Everything you create on Azure is a resource. The Create a resource pane appears. Here, you can search for the resource you want to create, or select one of the popular resources that people create in the Azure portal.
2. In the Create a resource menu, select Web.
3. Select Web App. If you don't see it, in the search box, search for and select Web App. The Create Web App pane appears.
4. On the Basics tab, enter the following settings:
- ***Basic:***
- ***Resource Group:*** Select the resource group created for the main resources.
- ***Name:*** A meaningful name.
- ***Publish:*** Code.
- ***Runtime stack:*** .NET Core 3.1 (LTS).
- ***Operating System:*** Windows.
- ***Region:*** Same region as the rest of the resources.
- ***App Service Plan:***
- ***Windows plan:*** Select the [App Service plan](app-service-plan.md) created in the previous steps.
- ***Monitoring:***
- Enable [application insights](application-insights.md) and select the instance created in previous steps.
5. Select **Review + Create** to go to the review pane, and then select Create. The portal shows the deployment pane, where you can view the status of your deployment.
## Enable Managed Identity
To allow to the App Service to get access to key vault (through Key Vault References), you have to enable a system assigned managed identity. To do so, please review the following [Microsoft Documentation](https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#add-a-system-assigned-identity), and take note of the **Object (principal) ID**, you will need it in future steps to configure the Azure Key Vault.
[← Back to How to run the solution in Azure](README.md#provision-azure-resources) | [Next: Function App →](function-app.md)

Просмотреть файл

@ -1,39 +0,0 @@
# Web App
## Introduction
To host the Management API a Web App service must be created in Azure. This documents shows how to create the Web App for this API.
## Dependencies
To create the Web App needed to deploy the Management API, the following resources must be already created:
- [App Service Plan](service_plan.md).
- [Application Insight](application_insights.md).
### Settings
Fill the fields in the creation wizard with the following information:
- ***Basic:***
- ***Resource Group:*** Select the [resource group](./README.md#architecture-resource-group) created for the solution architecture.
- ***Name:*** A meaningful name.
- ***Publish:*** Code.
- ***Runtime stack:*** .NET Core 3.1 (LTS).
- ***Operating System:*** Windows.
- ***Region:*** Same region as the rest of the resources.
- ***App Service Plan:***
- ***Windows plan:*** Select the [App Service plan](service_plan.md) created in the previous steps.
- ***Monitoring:*** Enable [application insights](./application_insights.md) and select the instance that was created in a previous step.
### Create Web App in Azure
1. In the [Azure Portal](https://portal.azure.com/), click **Create a resource** > **Web** > **Web App**.
![imagen](images/web_app_in_portal.png)
1. Select the subscription and complete the fields following the indications in the previous section, and then press the tab **Monitoring**.
![imagen](images/web_app_create.png)
1. Enable the Application Insights by checking the option **Yes**, and select the Application Insights created in previous steps, then press the button **Review + create**.
![imagen](images/web_app_monitoring_disable.png)
1. Verify the information created and click on the **Create** button to finish with the creation.
[← Back to How to Run the Solution in Azure](README.md#how-to-run-the-solution-in-azure)

Просмотреть файл

@ -1,47 +1,35 @@
# How to run the solution locally
## About
This document details the required software to be installed and the necessary steps you must follow to configure and run the solution locally.
Before configuring the solution to run it locally you must have the following prerequisites:
> **IMPORTANT**: These instructions will configure the solution to run in **Local mode**. This mode is designed to **disable most authentication checks** to make it easier for a developer to run the solution in their local environment. However, these settings should never be used when deploying this solution to Azure. For instructions on how to properly configure this solution in Azure, go to [How to Run the Solution in Azure](../how-to-run-the-solution-in-azure/README.md).
- A **domain name** - This domain name will be used to host the solution's core components.
- An **SSL wildcard certificate** - A valid wildcard certificate for the domain mentioned in the previous point. This is required to establish a TLS/TCP control channel between the bot's media platform and the calling clouds. The certificate must be in .pem and .pfx formats.
- An **Office 365 tenant with Microsoft Teams** enabled - If the organization is already using Microsoft Teams for their meetings, then you already have an Office 365 tenant configured.
- Note that you need the create an app registration in this tenant with permissions to join meetings and send and receive audio and video in those meetings. These permissions will need to be approved by your Office 365 tenant administrator.
- If your organization doesn't want to provide the necessary permissions for the solution to connect to the meetings, or you just want to test this solution in an isolated tenant, you can obtain a new testing tenant using Office 365's [Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program).
## Getting Started
## Azure Bot
- [Requirements](#requirements)
- [General prerequisites](#general-prerequisites)
- [Microsoft Azure Storage Emulator](#microsoft-azure-storage-emulator)
- [Visual Studio 2019](#visual-studio-2019)
- [Cosmos DB Emulator](#cosmos-db-emulator)
- [GStreamer](#gstreamer)
- [NGINX - Optional](#nginx)
- [Ngrok](#ngrok)
- [Domain Certificate](#domain-certificate)
- [Configure the Backend Solution to run locally](#configure-the-backend-solution-to-run-locally)
- [Configure Bot Orchestrator](#configure-bot-orchestrator)
- [Configure Management Api](#configure-management-api)
- [Configure BotService](#configure-botservice)
- [Configure Solution](#configure-solution)
- [Run the solution](#run-the-solution)
- [Testing the application](#testing-the-application)
To run the solution locally and add calling capabilities to the bot, you must create an Azure Bot resource. To do so, before creating the Azure Bot, you must create a resource group for it ([How to create a resource group](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#create-resource-groups)) and then create the following resources:
## Requirements
- [How to create/configure Azure Bot app registration](../common/azure-bot-app-registration.md#azure-bot-app-registration)
- [How to create/configure Azure Bot](../common/azure-bot.md#azure-bot)
### General prerequisites
Before running the solution locally, please make sure you have the all the prerequisites listed in [Prerequisites](..\prerequisites\README.md).
Also, if you haven't already, make sure you have setup your [Azure Bot](..\prerequisites\azure_bot.md) too, as this still needed if you plan to run the solution locally.
## Tools
### Microsoft Azure Storage Emulator
Download and Install [Azure Storage Emulator](https://docs.microsoft.com/en-us/azure/storage/common/storage-use-emulator#get-the-storage-emulator)
### Visual Studio 2019
Download and Install [Visual Studio Community 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
### Visual Studio 2022
* [.NET Core SDK 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) (should be already included with VS)
* [Microsoft Visual C++ 2015-2019 Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) (x64) (should be already included with VS)
Download and Install [Visual Studio Community 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
- [.NET Core SDK 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) (should be already included with VS)
- [Microsoft Visual C++ 2015-2019 Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) (x64) (should be already included with VS)
### Cosmos DB Emulator
Download [Azure Cosmos DB emulator](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator?tabs=ssl-netstd21) and install.
Open the Azure Cosmos DB emulator, it will open a new browser tab and will show the `Quickstart` view.
@ -53,145 +41,36 @@ Open the Azure Cosmos DB emulator, it will open a new browser tab and will show
> Copy the value of the primary key, you will use it later.
### GStreamer
Download and Install [GStreamer MinGW 64-bit 1.18.4](https://gstreamer.freedesktop.org/download/#windows) selecting the `Complete` installation mode.
|![GStreamer Installer](images/gstreamer_installer.png)|
|:--:|
|*GStreamer Installer: Select Complete Mode*|
Once GStreamer is installed you need to verify and copy the path to the bin directory where gstreamer was installed. For example if GStreamer was installed on the C drive the path would look like this: "C:\gstreamer\1.0\mingw_x86_64\bin".
|![Gstreamer Bin Path](images/gstreamer_bin_path.png)|
|:--:|
|*Copy the Gstreamer bin Path*|
After that, you need to add the path of the gstreamer bin directory to the environment variables path. To do so, select the `edit the system environment variables` option in the control panel or press the windows start button, type `environment variables` and select the respective option.
|![System Environment Variables](images/environment_variables_option.png)|
|:--:|
|*Edit System Environment Variables Option*|
Click on the `environment variables` button near the bottom of the window. A new window will open where you must select the path variable and click on the `edit` button.
|![Environmment Variables](images/environment_variables.png)|
|:--:|
|*Environment Variables window*|
Once the window to edit the environment variable is open, click on the `new` button and add the path to the GStreamer bin directory you copied earlier.
|![Path Environment Variable](images/environment_variables_path.png)|
|:--:|
|*Add the GStreamer bin path value to the Path Environment Variable*|
> It is not necessary to repeat this procedure every time you are going to run the solution locally, it should only be done before run it for the first time.
To support the processing of the Teams media (the content injection and content extraction), it is necessary to install and configure [GStreamer](gstreamer.md).
### NGINX
To support RTMP pull mode extractions and RTMP injection features, it is necessary to install and configure [NGINX](../common/install_and_configure_nginx_with_rtmp_module_on_windows.md).
To support RTMP pull mode extractions and RTMP injection features, it is necessary to install and configure [NGINX](../common/install-and-configure-nginx-with-rtmp-module-on-windows.md).
### Ngrok
To run the solution locally you will need to use [Ngrok](https://dashboard.ngrok.com/signup) so it is necessary to create a free account and [download](https://www.ngrok.com/download) it.
Once downloaded, unzip the exe file in a new directory `C:\ngrok`.
Login to Ngrok account and in the left menu, in the `Getting Started` section, select the option `Your Authtoken` and copy it. You will use this token to configure your instance of ngrok.
|![Ngrok AuthToken](images/ngrok_authtoken.png)|
|:--:|
|*Copy the Ngrok Authtoken*|
Go to the directory `C:\ngrok` where you unzipped ngrok and create a new file named `ngrok.yml`. To create the config file you can use your editor of preference, in this example we will use [Visual Studio Code (vscode)](https://code.visualstudio.com/).
### Creating config file
1. Open vscode
2. Go to File -> New file (or press Ctrl+N)
|![Ngrok Config File](images/ngrok_create_config_file_1.png)|
|:--:|
|*Create new file*|
3. Select yaml as language
|![Ngrok Config File](images/ngrok_create_config_file_2.png)|
|:--:|
|*Select language*|
4. Copy the following configuration into the yaml file and replace the text `{{PUT YOUR AUTHTOKEN HERE}}` with the value of the authtoken copied earlier from the Ngrok dashboard.
```json
authtoken: {{PUT YOUR AUTHTOKEN HERE}}
tunnels:
signaling:
addr: 9441
proto: http
media:
addr: 8445
proto: tcp
```
|![Ngrok Config File](images/ngrok_create_config_file_3.png)|
|:--:|
|*Config file example*|
5. Go to File -> Save (or press Ctrl+S), enter the name of your file (ngrok.yml in this example) and save it in ngrok's folder
|![Ngrok Config File](images/ngrok_create_config_file_4.png)|
|:--:|
|*Save file*|
|![Ngrok Config File](images/ngrok_create_config_file_5.png)|
|:--:|
|*Example result*|
>You only need to perform this initial configuration of ngrok the first time you configure the solution, then you do not need to repeat it again.
### Run Ngrok
To run ngrok, go to the `C:\ngrok` directory and open a terminal in that location and run the following command (or open your terminal of preference and navigate to the ngrok's folder):
`ngrok start --all --config ngrok.yml`
> You can open a taerminal window by holding down the shift key and clicking on an empty area of the window and selecting the option "Open PowerShell window here".
>|![Open Console](images/open_console.png)|
>|:--:|
>|*How to open a console in a directory*|
Once this command is executed a message like the following will be displayed, this window should not be closed while using the solution.
|![Ngrok run](images/ngrok_console.png)|
|:--:|
|*Ngrok running on the console*|
>You must run ngrok every time that you want to run the solution locally by executing the command mentioned before.
> ***OPTIONAL:*** Add `C:\ngrok` path where the .exe file is located to the Path environment variable. If you add it, you will not have to change the directory in the terminal every time you want to run ngrok.
To run the solution locally and expose localhost so Microsoft Graph API can send notifications to the bot, it is necessary to install and configure [ngrok](ngrok.md) so we can use it to create the tunnels to localhost.
### Domain Certificate
You will need to install the [pfx certificate mentioned in the prerequisites](../prerequisites/README.md) in your local environment. You can find instructions on how to do this in document [Manual installation of your domain certificate](../common/install_domain_certificate.md).
You will need to install the pfx certificate mentioned in the prerequisites in your local environment. You can find instructions on how to do this in document [Manual installation of your domain certificate](../common/install-domain-certificate.md).
## Configure the Backend Solution to run locally
The solution is composed by 3 main projects:
- **BotOrchestrator:** The Azure Functions used to execute some of the features in the solution.
- **ManagementApi:** The project containing the management API that is used to interact with the solution.
- **BotService:** A self-hosted API/application-hosted media bot that hosts the media session. As part of its core components, it includes the GStreamer pipelines that are in charge of processing the media and deliver it in SRT/RTMP.
Each of the three projects have configuration files that must be updated separately in order to run the solution locally. To do so, run Visual Studio 2019 as administrator, right click on the Visual Studio icon and click the `Run as administrator` option. It is very important to open it as administrator otherwise the solution will not run correctly.
|![Run as Administrator](images/vs_run_as_admin.png)|
|:--:|
|*Select 'Run as administrator' option*|
Each of the three projects have configuration files that must be updated separately in order to run the solution locally. To do so, run Visual Studio 2022 as administrator, right click on the Visual Studio icon and click the `Run as administrator` option. It is very important to open it as administrator otherwise the solution will not run correctly.
In the Visual Studio menu select `"File" > "Open" > "Project / Solution"` and select the `Broadcaster.sln` file in the src folder of the solution.
### Configure Bot Orchestrator
In the solution explorer, go to the `BotOrchestrator` project (under `src/applications`) and create a new configuration file with the name `local.settings.json`
In the solution explorer, go to the `BotOrchestrator` project (under `src/applications`) and create a new configuration file with the name `local.settings.json`
```json
{
@ -218,7 +97,7 @@ In the solution explorer, go to the `BotOrchestrator` project (under `src/applic
}
```
Placeholder | Description
Placeholder | Description
---------|----------
appInsightInstrumentationKey | ***`Optional:`*** by default leave it empty. If you want to store the logs and have an instance of Application Insights you can enter its instrumentation key.
cosmosDbPrimaryKey | [Azure Cosmos DB Emulator primary key, can be found in the data explorer of the emulator](#cosmos-db-emulator).
@ -236,7 +115,6 @@ In the solution explorer, go to the `ManagementApi` project (under `src/applicat
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "local",
"BROADCASTER_ENVIRONMENT": "local"
},
"applicationUrl": "https://localhost:8442;http://localhost:8441"
}
@ -275,12 +153,12 @@ Then, in the root of the project, create a new configuration file with the name
}
```
Placeholder | Description
Placeholder | Description
---------|----------
appInsightInstrumentationKey | ***`Optional:`*** by default leave it empty or if you have an instance of Application Insights you can store the log messages by entering an instrumentation key.
tenantIdAzureBotAppRegistration | Tenant Id of Azure Bot [app registration](../prerequisites/azure_bot.md).
clientIdAzureBotAppRegistration | Client Id of Azure Bot [app registration](../prerequisites/azure_bot.md).
clientSecretAzureBotAppRegistration | Client secret of Azure bot [app registration](../prerequisites/azure_bot.md).
tenantIdAzureBotAppRegistration | Tenant Id of Azure Bot [app registration](#azure-bot).
clientIdAzureBotAppRegistration | Client Id of Azure Bot [app registration](#azure-bot).
clientSecretAzureBotAppRegistration | Client secret of Azure bot [app registration](#azure-bot).
cosmosDbPrimaryKey | [Azure Cosmos DB Emulator primary key, can be found in the data explorer of the emulator](#cosmos-db-emulator).
cosmosDbDatabaseName | Name of the database that the solution will create in Cosmos DB Emulator. E.g.: `BroadcastDevelopmentKitDb`
@ -295,10 +173,7 @@ In the solution explorer, go to the `BotService` project (under `src/application
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"BROADCASTER_ENVIRONMENT": "local",
"ASPNETCORE_ENVIRONMENT": "Development",
"CERTIFICATE_FILE_NAME": "{{certificateName}}",
"GST_DEBUG": "3"
"ASPNETCORE_ENVIRONMENT": "local",
},
"applicationUrl": "https://localhost:9442;http://localhost:9441"
}
@ -306,11 +181,9 @@ In the solution explorer, go to the `BotService` project (under `src/application
}
```
Placeholder | Description
---------|----------
certificateName | Name of the installed Certificate (e.g: `certificate.co.pfx`)
Then, in the root of the project, create a new configuration file with the name `appsettings.{{Configuration}}.json` where ``{{Configuration}}`` has to be replaced with the configuration mode that you want to use, e.g: `Debug` or `Release`. At build time, Visual Studio will get the corresponding file to the selected configuration mode and generate the `appSettings.json`.
Then, in the root of the project, create a new configuration file with the name `appsettings.local.json` and copy the following configuration into it.
Copy the following configuration into it.
```json
{
@ -359,7 +232,8 @@ Then, in the root of the project, create a new configuration file with the name
"ServiceFqdn": "{{serviceFqdn}}",
"CertificatePassword": "",
"CertificateThumbprint": "{{certificateThumbprint}}",
"MainApiUrl": "localhost:8442"
"MainApiUrl": "localhost:8442",
"SecondsWithoutParticipantsBeforeRemove": {{secondsBeforeRemove}}
}
},
"APPINSIGHTS_INSTRUMENTATIONKEY": "{{appInsightInstrumentationKey}}"
@ -370,15 +244,16 @@ Placeholder | Description
|-|-|
botServiceHttpsPort | BotService Https port configured in botService launchsettings
botServiceHttpPort | BotService Http port configured in botService launchsettings
tenantIdAzureBotAppRegistration | Tenant Id of the [app registration](../prerequisites/azure_bot.md).
clientIdAzureBotAppRegistration | Client Id of the [app registration](../prerequisites/azure_bot.md).
clientSecretAzureBotAppRegistration | Client secret of the [app registration](../prerequisites/azure_bot.md).
tenantIdAzureBotAppRegistration | Tenant Id of the [app registration](#azure-bot).
clientIdAzureBotAppRegistration | Client Id of the [app registration](#azure-bot).
clientSecretAzureBotAppRegistration | Client secret of the [app registration](#azure-bot).
cosmosDbPrimaryKey | [Azure Cosmos DB Emulator primary key, can be found in the data explorer of the emulator](#cosmos-db-emulator).
cosmosDbDatabaseName | Name of the database that the solution will create in Cosmos DB Emulator. E.g.: `BroadcastDevelopmentKitDb`
certificateThumbprint | Thumbprint of the installed certificate. If you don't know your certificate thumbprint, follow the instructions [here](../common/install_domain_certificate.md#obtaining-the-certificate-thumbprint) to obtain it.
certificateThumbprint | Thumbprint of the installed certificate. If you don't know your certificate thumbprint, follow the instructions [here](../common/install-domain-certificate.md#obtaining-the-certificate-thumbprint) to obtain it.
secondsBeforeRemove | Seconds before removing the bot from a meeting with no participants.
appInsightInstrumentationKey | ***`Optional:`*** by default leave it empty or if you have an instance of Application Insights you can store the log messages by entering an instrumentation key.
To finish Configure the configuration file you have to use ngrok. The following image serves as a guide to know in a simple way where to take the values.
The settings listed below depends on ngrok static tunnels. Because we suggest to use a free ngrok account and free accounts do not provide static tunnels, tunnels change every time a tunnel is created. So, the following settings must be updated every time that you run ngrok and the solution.
| ![Ngrok Configuration](images/ngrok_configuration.png)|
|:--:|
@ -386,11 +261,9 @@ appInsightInstrumentationKey | ***`Optional:`*** by default leave it empty or if
Placeholder | Description
|-|-|
ngrokUrl | Fill both values of NgrokHttp with the red marked value (1) from the ngrok console (e.g: `66c0b316671d.ngrok.io`)
instancePublicPort | Complete with the value of the port marked in yellow (2) in the ngrok console (e.g: `16186`)
serviceFqdn | Complete with value with value marked with green (3) in the ngrok console and the domain name. (e.g: `4.domain.co`) It is necessary to add a DNS record pointing to ngrok's TCP Url. (e.g: 4.domain.co -> 4.tcp.ngrok.io).
> Since we suggest to use a free ngrok account, you will need to update the Ngrok settings in this file every time you start a new instance of ngrok. Also, you will need to modify the DNS record.
ngrokUrl | Complete with the red marked value (1) from the ngrok console (e.g: `66c0b316671d.ngrok.io`)
instancePublicPort | Complete with the yellow marked value (2) in the ngrok console (e.g: `16186`)
serviceFqdn | Complete with the green marked value (3) in the ngrok console and the domain name. (e.g: `4.domain.co`) It is necessary to add a DNS record pointing to ngrok's TCP Url. (e.g: 4.domain.co -> 4.tcp.ngrok.io).
### Configure solution
@ -401,6 +274,7 @@ In the standard Visual Studio toolbar, click on the down arrow next to the start
|*Select "Set Startup Projects..."*|
A new window will open, select `Multiple startup projects:` option and change the action of the following projects from `None` to `Start`:
- ManagementApi
- BotOrchestrator
- BotService
@ -427,7 +301,7 @@ Open Cosmos DB Data Explorer and in the left menu select explorer and then selec
|![Add new Item to Service](images/cosmos_add_service.png)|
|:--:|
|*Selec in the Service Container and then add a new Item*|
|*Select in the Service Container and then add a new Item*|
Select the `Service` container and then click on the `New Item` button and copy the following settings and click on `Save` button
@ -462,9 +336,10 @@ Press the `Start` button again and wait until all projects start. If the Solutio
## Run the solution
Each time you are going to run the solution you need to perform the following steps:
- ***Run Azure cosmos DB emulator***: you can check that cosmos DB is run by verifying that the crosmos db logo is in the windows taskbar.
- ***Run Ngrok:*** It is necessary to have an instance of ngrok run in order to execute the solution. Once initialized, it is necessary to update the `appsettings.local.json` file of the `BotService` with the new values of the ngrok instance.
- ***Run NGINX*** *`Optional`*: If you want to perform locally RTMP extractions in pull mode or RTMP injection into Microsoft Teams Meeting, you need to run NGINX before runing the solution.
- ***Run Azure cosmos DB emulator***: you can check that cosmos DB is run by verifying that the cosmos db logo is in the windows taskbar.
- ***Run Ngrok:*** It is necessary to have an instance of ngrok run in order to execute the solution. Once initialized, it is necessary to update the `appsettings.Debug.json` file of the `BotService` with the new values of the ngrok instance.
- ***Run NGINX*** *`Optional`*: If you want to perform locally RTMP extractions in pull mode or RTMP injection into Microsoft Teams Meeting, you need to run NGINX before running the solution.
Finally, run Visual Studio as administrator, open the solution and click the `Start` button on the standard Visual Studio toolbar and wait for all projects to start.
@ -488,9 +363,10 @@ In the header tab, add (if it does not exist) a new key `Content-Type` with the
|![Postman Header](images/postman_header.png)|
|:--:|
|*Postmant content-Type header*|
|*Postman content-Type header*|
In the body tab select raw and complete by copying the following
```json
{
"MeetingUrl": "{{microsoftTeamsInviteLink}}"
@ -499,11 +375,10 @@ In the body tab select raw and complete by copying the following
Placeholder | Description
---------|----------
microsoftTeamsInviteLink | Microsoft Teams invite link
microsoftTeamsInviteLink | Microsoft Teams invite link
Click on the `Send` button and the request will be sent to the solution, you should receive a response with status `200 Ok` and after a few seconds the bot should join the Microsoft Teams meeting.
|![Test with Postman](images/test_with_postman.png)|
|:--:|
|*Test the solution with postman*|

Просмотреть файл

@ -0,0 +1,64 @@
# GStreamer
Download and Install [GStreamer MinGW 64-bit 1.18.6](https://gstreamer.freedesktop.org/download/#windows) selecting the `Complete` installation mode.
|![GStreamer Installer](images/gstreamer_installer.png)|
|:--:|
|*GStreamer Installer: Select Complete Mode*|
Once GStreamer is installed you must add the bin directory to the `PATH` environment variable. To do so, you have two approaches:
- [GStreamer](#gstreamer)
- [Using Powershell](#using-powershell)
- [Output](#output)
- [Manually](#manually)
## Using Powershell
If GStreamer was installed in the default location `C:\gstreamer\1.0\mingw_x86_64\bin` then open Powershell and run:
```sh
.\scripts\Add-GStreamer-Path.ps1
```
If GStreamer was installer in a different location (e.g. `C:\Software\gstreamer\1.0\mingw_x86_64\bin`) then open Powershell and run:
```sh
.\scripts\Add-GStreamer-Path.ps1 -GStreamPath "C:\Software\gstreamer\1.0\mingw_x86_64\bin"
```
### Output
```sh
Added 'c:\gstreamer\1.0\mingw_x86_64\bin\' to PATH environment variable
```
## Manually
Once GStreamer is installed you need to verify and copy the path to the bin directory where gstreamer was installed. For example if GStreamer was installed on the C drive the path would look like this: "C:\gstreamer\1.0\mingw_x86_64\bin".
|![GStreamer Bin Path](images/gstreamer_bin_path.png)|
|:--:|
|*Copy the GStreamer bin Path*|
After that, you need to add the path of the gstreamer bin directory to the environment variables path. To do so, select the `edit the system environment variables` option in the control panel or press the windows start button, type `environment variables` and select the respective option.
|![System Environment Variables](images/environment_variables_option.png)|
|:--:|
|*Edit System Environment Variables Option*|
Click on the `environment variables` button near the bottom of the window. A new window will open where you must select the path variable and click on the `edit` button.
|![Environmment Variables](images/environment_variables.png)|
|:--:|
|*Environment Variables window*|
Once the window to edit the environment variable is open, click on the `new` button and add the path to the GStreamer bin directory you copied earlier.
|![Path Environment Variable](images/environment_variables_path.png)|
|:--:|
|*Add the GStreamer bin path value to the Path Environment Variable*|
> It is not necessary to repeat this procedure every time you are going to run the solution locally, it should only be done before run it for the first time.
[← Back to How to run the solution locally](README.md#gstreamer) | [Next: NGINX →](README.md#nginx)

Просмотреть файл

@ -0,0 +1,52 @@
# Ngrok
Go to [Ngrok](https://dashboard.ngrok.com/signup) to create a free account and [download](https://www.ngrok.com/download) it.
## Get Authtoken
Login to Ngrok account and in the left menu, in the `Getting Started` section, select the option `Your Authtoken` and copy it. You will use this token to configure your instance of ngrok.
|![Ngrok AuthToken](images/ngrok_authtoken.png)|
|:--:|
|*Copy the Ngrok Authtoken*|
## Install Ngrok
Unzip the .zip file that you downloaded in a new directory like `C:\ngrok`.
> ***OPTIONAL:*** Add `C:\ngrok` path where the .exe file is located to the Path environment variable. If you add it, you will not have to change the directory in the terminal every time you want to run ngrok.
## Setting up Ngrok
Go to the directory `C:\ngrok` where you unzipped ngrok and create a new file named `ngrok.yml`. To create the config file you can use your editor of preference, in this example we will use [Visual Studio Code (vscode)](https://code.visualstudio.com/).
Open the `.yml` file and copy the following configuration. Then replace the placeholder `{{PUT YOUR AUTHTOKEN HERE}}` with the value of the authtoken copied earlier from the Ngrok dashboard, and save changes.
```json
authtoken: {{PUT YOUR AUTHTOKEN HERE}}
tunnels:
signaling:
addr: 9441
proto: http
media:
addr: 8445
proto: tcp
```
>You only need to perform this initial configuration of ngrok the first time you configure the solution, then you do not need to repeat it again.
## Run Ngrok
To run ngrok, go to the `C:\ngrok` directory and open a terminal in that location and run the following command (or open your terminal of preference and navigate to the ngrok's folder):
`ngrok start --all --config ngrok.yml`
Once this command is executed a message like the following will be displayed, this window should not be closed while using the solution.
|![Ngrok run](images/ngrok_console.png)|
|:--:|
|*Ngrok running on the console*|
> NOTE: You must run ngrok every time that you want to run the solution locally by executing the command mentioned before. Free ngrok account does not provide static tunnels. Tunnels change every time a tunnel is created. So, if using free account, it is recommended to not close ngrok until it's use is completed.
[← Back to How to run the solution locally](README.md#ngrok) | [Next: Domain Certificate →](README.md#domain-certificate)

Просмотреть файл

@ -1,38 +1,45 @@
# How to use the Management API
## Getting Started
This document contains the instructions to operate the Broadcast Development Kit (BDK) using Postman. This includes:
- [How to use the Management API](#how-to-use-the-management-api)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Authorization](#authorization)
- [Client credential flow](#client-credential-flow)
- [Create an App registration](#create-an-app-registration)
- [API permissions](#api-permissions)
- [How to generate an access token](#how-to-generate-an-access-token-with-client-credential-grant-type)
- [API permissions](#api-permissions)
- [How to generate an access token with client credential grant type](#how-to-generate-an-access-token-with-client-credential-grant-type)
- [Implicit grant flow](#implicit-grant-flow)
- [How to generate an access token](#how-to-generate-an-access-token-with-implicit-grant-type)
- [How to generate an access token with implicit grant type](#how-to-generate-an-access-token-with-implicit-grant-type)
- [Call Flow](#call-flow)
- [Swagger](#swagger)
- [Postman](#postman)
- [Operations](#operations)
- [Start the service](#start-the-service)
- [Join the bot into a meeting](#join-the-bot-into-a-meeting)
- [Start an extraction](#start-an-extraction)
- [Start an Injection](#start-an-injection)
- [Start an injection](#start-an-injection)
- [Generate RTMP stream key](#generate-rtmp-stream-key)
- [Disconnect Call](#disconnect-call)
- [Stop service](#stop-service)
## Prerequisites
- Download and Install [Postman](https://www.postman.com/)
## Authorization
As endpoints in the solution are securitized in order to make requests to the API it is necessary to generate an access token and use it in the header of the requests, otherwise, the API will respond to requests with HTTP error code 401 (Unauthorized).
In this section we describe how to generate an access token with the App registration used in the SPA for the [implicit grant flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow) or by creating a new App registration for the [client credential flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).
BDK Management API endpoints are secured. To be able to make API requests, it is necessary to include a valid bearer token in the requests' headers.
In this section we will describe how to generate an access token with the App registration used in the SPA (if you have already configured the [Web UI for the Broadcast Development Kit](https://github.com/microsoft/Broadcast-Development-Kit-Web-UI) for the [implicit grant flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow) or by creating a new App registration for the [client credential flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).
### Client credential flow
#### Create an App registration
Create a new App registration to be able to configure it and thus be able to obtain the `access token`. Review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it, and consider the following settings:
- ***Name:*** Meaningful name.
@ -41,6 +48,7 @@ Create a new App registration to be able to configure it and thus be able to obt
Once you've registered the App registration you must [add a client secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret), copy the value and save it together with the application client id in a secure place, we will need them for future steps.
#### API permissions
From the App registration created view, go to the **API permissions** option that is in the `Manage` menu, click the **Add a permission** button and then ensure the **APIs my organization uses** tab is selected. Search for the App Registration created for the [Management API](../how-to-run-the-solution-in-azure/app_registrations.md#how-to-setup-management-api-app-registration) and click on the search result.
![Search API permissions](./images/search_api_permissions.png)
@ -54,6 +62,7 @@ Then inside App registration created, select **AccessAll** and click on **Add pe
![Add permissions](./images/added_api_permission.png)
#### How to generate an access token with client credential grant type
Once the App registration is created, follow the steps below to generate the `access token` from **Postman**:
1. Open **Postman** and create a new request.
@ -69,13 +78,13 @@ Once the App registration is created, follow the steps below to generate the `ac
| Placeholder | Description |
|-------------|-------------|
| Grant Type | Select the **Client Credentials** option.|
| accessTokenURL | https://login.microsoftonline.com/`{{tenantId}}`/oauth2/v2.0/token`|
| accessTokenURL | `https://login.microsoftonline.com/{{tenantId}}/oauth2/v2.0/token`|
| tenantId | Tenant Id of the subscription. |
| clientId | Client Id of the App registration created. |
| clientSecret | Client Secret of the App registration created. |
| scope | api://`{{clientIdManagementAPI}}`/.default |
| clientIdManagementAPI | Client Id of the [App Registration](../how-to-run-the-solution-in-azure/app_registrations.md#how-to-setup-management-api-app-registration) of the ManagementApi. |
| scope | `api://{{clientIdManagementAPI}}/.default` |
| clientIdManagementAPI | Client Id of the [App Registration](../how-to-run-the-solution-in-azure/app_registrations.md#how-to-setup-management-api-app-registration) of the ManagementApi.|
4. Next, to generate the token, click on the **Get New Access Token** button, a new window will be displayed, and then it will show the generated `access token`. To use this token, click on the button **Use Token**, this will use the `access token` in the created request.
|![Management Access Tokens](./images/management_access_token.png)|
@ -85,10 +94,11 @@ Once the App registration is created, follow the steps below to generate the `ac
### Implicit grant flow
#### How to generate an access token with implicit grant type
> NOTE: It is necessary to use the App registration of the SPA to generate the access token, please review the following [documentation](https://github.com/microsoft/Broadcast-Development-Kit-Web-UI/tree/main/docs/how-to-run-the-solution-in-azure#create-a-new-app-registration).
To generate the access token with implicit grant type, the following steps are suggested:
1. Open **Postman** and create a new request.
2. In the **Authorization** tab, select the type **OAuth2**.
@ -102,9 +112,9 @@ To generate the access token with implicit grant type, the following steps are s
| Placeholder | Description |
|-------------|-------------|
| Grant Type | Select the **Implicit** option.|
| callbackUrl | https://{{spaRedirectUrl}}|
| callbackUrl | `https://{{spaRedirectUrl}}`|
| spaRedirectUrl | [Spa redirect URL](../how-to-run-the-solution-in-azure#configure-the-app-registration) configured. |
| authUrl | https://login.microsoftonline.com/`{{tenantId}}`/oauth2/v2.0/authorize`|
| authUrl | `https://login.microsoftonline.com/{{tenantId}}/oauth2/v2.0/authorize`|
| tenantId | Tenant Id of the subscription. |
| clientId | Client Id of the App registration created. |
| scope | api://`{{clientIdManagementAPI}}`/access_as_producer |
@ -117,23 +127,36 @@ To generate the access token with implicit grant type, the following steps are s
|*Management Access Tokens*|
## Call Flow
The life cycle of a call follows these steps:
1. First, we need to start the service (i.e. the VM) that host the bot using the `Start Service` endpoint.
1. First, we need to start the service (i.e. the VM) that host the bot using the `Start Service` endpoint.
2. After requesting the provisioning of the service, we must poll the `Get Service State` endpoint several times until the service is `Provisioned`.
3. Once the service is provisioned, to invite the bot into a meeting we must use the `Initialize Call` endpoint. The request will return a call with state equals to `0` (Establishing).
4. Then, we must poll the `Get Call Details` endpoint until the state of the call is `1` (Established) and the Participants are available.
3. Once the service is provisioned, to invite the bot into a meeting we must use the `Initialize Call` endpoint. The request will return a call with state equals to `0` (Establishing).
4. Then, we must poll the `Get Call Details` endpoint until the state of the call is `1` (Established) and the Participants are available.
5. After that, we are able to start and stop the streams we want to capture.
6. Once the service is not longer needed in the call and all streams are stopped, we can disconnect it using the `Delete Call` endpoint.
7. After the bot usage is done, it can be terminated using the `Stop Service` endpoint.
8. To make sure that the VM has been stopped, we must poll the `Get Service State` endpoint several times until the service is `Deprovisioned`.
7. After the bot usage is done, it can be terminated using the `Stop Service` endpoint.
8. To make sure that the VM has been stopped, we must poll the `Get Service State` endpoint several times until the service is `Deprovisioned`.
## Swagger
The REST endpoints exposed by the Management API are documented by using OpenAPI specification. To access Swagger UI go to <https://{{MANAGEMENT_API_URL}}/Swagger>
![Managament API Swagger UI](images/management_api_swagger_ui.jpg "Management API Swagger UI")
### Postman
Optionally, you can import the OpenAPI specification in Postman by importing the following JSON <https://{{MANAGEMENT_API_URL}}/swagger/v1/swagger.json>
## Operations
The following instructions are the steps necessary to start the service, join the bot into the meeting, start an extraction or injection, disconnect the call and stop the service.
The following instructions are the steps necessary to start the service, join the bot into the meeting, start an extraction or injection, disconnect the call and stop the service.
It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-us/office/schedule-a-meeting-in-teams-943507a9-8583-4c58-b5d2-8ec8265e04e5) in Microsoft Teams to join the bot in it and also to have already configured the access token in Postman in order to follow the instructions.
### Start the service
1. **Get service state**: We need to verify the state of the service before join the bot into the meeting, check if the service is available or not. If it is not we need to start it.
**Method**: `GET`
@ -144,10 +167,9 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| appServiceUrl | AppService Url |
| serviceId | Service Id (the default id is `00000000-0000-0000-0000-000000000000`)|
**Response:**
**Response:**
``` json
``` json
{
"id": "serviceId",
"resource": {
@ -174,6 +196,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
```
If the provisioningDetails is deprovisioned we need to start the service by calling the start endpoint.
2. **Start Service**:
@ -216,10 +239,11 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
```
After calling the start endpoint the service will start provisioning, it is necessary to check the status until the provisioningDetails changes to `Provisioned`
### Join the bot into a meeting
1. **Initialize Call:** To join the bot into the meeting we will call the initialize-call endpoint with the Teams meeting URL. The service needs to be `Provisioned` to join the bot to the call.
**Method**: `POST`
@ -232,7 +256,8 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
**Headers**: Verify the `Content-type` key has as value `application/json`
**Body**: `raw`
Complete the body in Postman with the following:
Complete the body in Postman with the following:
```json
{
"MeetingUrl": "{{teamsMeetingUrl}}"
@ -250,6 +275,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
|*Steps to get the Teams meeting URL*|
**Response:**
```json
{
"id": "callId",
@ -276,9 +302,10 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
```
The returned status is equals `0` (Establishing) means that the bot is joining the call. To be able to start a stream, the call state has to be in `1` (Established). You can use the `Get Call Details` operation to verify the status of the call. The returned `Id` value must to be copied to be used in the following steps.
2. **Get call details:** The call details endpoind will retrieve call and participants information. If the state of the call is `1` (Established), it means that the bot is joined in the call.
The returned status is equals `0` (Establishing) means that the bot is joining the call. To be able to start a stream, the call state has to be in `1` (Established). You can use the `Get Call Details` operation to verify the status of the call. The returned `Id` value must to be copied to be used in the following steps.
2. **Get call details:** The call details endpoint will retrieve call and participants information. If the state of the call is `1` (Established), it means that the bot is joined in the call.
**Method**: `GET`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}`
@ -288,6 +315,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| callId | Call Id obtained as response in the previous step|
**Response:**
```json
{
"id": "callId",
@ -424,6 +452,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
The list of the participants joined to the call is listed in the streams property of the response.
### Start an extraction
1. **Start extraction stream**: To start the extraction of a participant it is necessary to check if the `isSharingVideo` property of the participant is true. In previous step request response we can see that participant 2 is sharing video.
**Method**: `POST`
@ -436,9 +465,10 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
**Headers**: Verify the `Content-type` key has as value `application/json`
**Body**: `raw`
#### Body for RTMP
**Body for RTMP**
Complete the body in Postman with the following:
Complete the body in Postman with the following:
```json
{
"participantId": "{{participantId}}",
@ -465,9 +495,10 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| timeOverlay | `true` or `false` |
| enableSsl | Enable SSL: `true` or `false` it is in `Pull` mode, use `false` in `Push` mode|
#### Body for SRT
**Body for SRT**
Complete the body in Postman with the following:
Complete the body in Postman with the following:
```json
{
"participantId": "{{participantId}}",
@ -495,8 +526,8 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| timeOverlay | `true` or `false` |
| keyLength | Allowed values: `0`, `16`, `24`, `32`|
| latency | Latency for SRT (eg: `750`)|
#### Table of Availables ResourceTypes
**Table of Available ResourceTypes**
|ResourceType | Value |
|-------------|-------------|
@ -547,12 +578,13 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
2. **Stop extraction stream:**
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/stream/stop-extraction`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/stream/stop-extraction`
**Headers**: Verify the `Content-type` key has as value `application/json`
**Body**: `raw`
Complete the body in Postman with the following:
Complete the body in Postman with the following:
```json
{
"participantId": "{{participantId}}",
@ -560,6 +592,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
"resourceType": 2,
}
```
| Placeholder | Description |
|-------------|-------------|
| participantId | Participant Id |
@ -567,6 +600,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| resourceType |Select a value from ResourceType [table](#table-of-availables-resourcetypes) |
**Response:**
```json
{
"id": "participant2Id",
@ -600,8 +634,9 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
```
### Start an Injection
1. **Start injection stream**:
### Start an injection
1. **Start injection stream**:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/stream/start-injection`
@ -613,7 +648,8 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
**Headers**: Verify the `Content-type` key has as value `application/json`
**Body**: `raw`
#### Body for RTMP
**Body for RTMP**
```json
{
"protocol": 1,
@ -630,7 +666,8 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| streamUrl | RTMP in `Pull` mode, `null` for `Push` mode |
| enableSsl | Enable SSL: `true` or `false` used when mode is `Push`|
#### Body for SRT
**Body for SRT**
```json
{
"protocol": 0,
@ -651,7 +688,6 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| latency | Latency (eg: `750`)|
| keyLength | Allowed values: `0`, `16`, `24`, `32`|
**Response**:
```json
@ -675,9 +711,38 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
```
The id of the response should be copied for later use when stopping the injection.
2. **Stop injection stream**:
2. Optionally, you can use the following operations to control the injection:
- Hide:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/injection/hide`
- Display:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/injection/display`
- Mute:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/mute`
- Un-mute:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/unmute`
- Set Volume:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/injection/set-volume`
> **Note:** Check OpenAPI specification for information about request body
3. **Stop injection stream**:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/stream/{{streamId}}/stop-injection`
@ -688,6 +753,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| streamId | Obtained Stream Id when started the injection |
**Response**
```json
{
"id": "streamId",
@ -709,21 +775,23 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
```
### Generate RTMP stream key
1. **Generate RTMP stream key:** This endpoint updates the streamKey in the privateContext of the call, used key for RTMP injections and extractions. Only need to use this endpoint if you want to change the RMTP key of the current meeting, each meeting has its own RTMP stream key.
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}/generate-stream-key`
| Placeholder | Description |
|-------------|-------------|
| callId | Call Id |
**Headers**: Verify the `Content-type` key has as value `application/json`
**Body**: `raw`
**Response**
```json
{
"callId": "callId",
@ -731,13 +799,15 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
```
### Disconnect Call:
### Disconnect Call
1. **Disconnect the bot from the call**:
**Method**: `DELETE`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}`
**Method**: `DELETE`
**Endpoint**: `https://{{appServiceUrl}}/api/call/{{callId}}`
**Response:**
```json
{
"id": "callid",
@ -766,10 +836,11 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
```
### Stop service
1. **Stop the service**:
**Method**: `POST`
**Endpoint**: `https://{{appServiceUrl}}/api/service/{{serviceId}}/stop`
**Endpoint**: `https://{{appServiceUrl}}/api/service/{{serviceId}}/stop`
| Placeholder | Description |
|-------------|-------------|
@ -777,6 +848,7 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
| serviceId | Service Id (the default id is `00000000-0000-0000-0000-000000000000`)|
**Response:**
```json
{
"id": "serviceId",
@ -804,4 +876,4 @@ It is necessary to have a [scheduled meeting](https://support.microsoft.com/en-u
}
}
}
```
```

Двоичные данные
docs/how-to-use-the-solution/images/management_api_swagger_ui.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 95 KiB

Просмотреть файл

@ -7,16 +7,20 @@ The GStreamer pipelines (where BDK relies on to extract the participants' camera
In this document we will explain how we tested the synchronization between different streams, some expected results, and findings.
## Setup
**Tools**
* _gst-play_
* _OBS Studio_
**Client PC**
**Client PC**
* i7 8700 non-k (6 cores - 12 threads)
* 16 Gb of RAM
* RTX 2080 8 GB VRAM (to take advantage of hardware decoding through GPU for reproducing the streams)
**BDK Host**
* Azure virtual machine with *Standard F16s_v2* sku (16 vCPUs, 32 Gb of RAM)
## Tests
@ -32,6 +36,7 @@ To set default latency, we did a ping to the BDK host server and took the averag
Because we don't have a tool to calculate the bandwidth overhead needed to pick the RTT multiplier, we used the highest RTT multiplier from the guide and calculated a latency of 1296ms (6 * 216ms).
### Streams
* Primary Speaker
* Participant
* Together Mode (the user must enable it inside the meeting)
@ -42,11 +47,12 @@ Because we don't have a tool to calculate the bandwidth overhead needed to pick
To test the synchronization between the four streams, we opened four terminals and ran _gst-play_ with the SRT url of each stream provided by the Broadcast Development Kit.
**Example of command**
```
```sh
gst-play "srt://your-bdk-vm-url:8888?mode=caller&latency=1296"
```
We left the players running for 45 minutes aproximately and took screenshots at different times to compare the running time difference in miliseconds between the streams.
We left the players running for 45 minutes approximately and took screenshots at different times to compare the running time difference in milliseconds between the streams.
**First Screenshot (beginning of the stream)**
@ -74,7 +80,7 @@ We left the players running for 45 minutes aproximately and took screenshots at
|:--:|
|*Second screenshot*|
**Third Screenshot (47 minutes after the beggining of the stream)**
**Third Screenshot (47 minutes after the beginning of the stream)**
| Stream | Running Time|
| ------------- | ------------- |
@ -102,6 +108,7 @@ Also, if we compare in all the screenshots the difference between the stopwatch
To test the synchronization between the four streams with OBS, we added a media source per stream to a scene. To know how to configure a media source please follow this [OBS guide](https://obsproject.com/wiki/Streaming-With-SRT-Protocol).
**Media source settings**
* Local File: unchecked
* Network Buffering: 0 MB
* Input: SRT stream url (E.g.: srt://your-bdk-vm-url:8888?mode=caller&latency=2000)
@ -119,7 +126,7 @@ We left OBS running for 40 minutes approximately, but compared to _gst-play_ the
| Together Mode (bottom-left) | 0:00:56.268 |
| Screenshare (bottom-right) | 0:00:56.298 |
The highest desynchronization difference was about 784 ms, beteween the participant and primary speaker.
The highest desynchronization difference was about 784 ms, between the participant and primary speaker.
![First screenshot](images/obs-example-1.png)|
|:--:|
@ -138,7 +145,7 @@ The highest desynchronization difference was about 784 ms, beteween the particip
|:--:|
|*Second Screenshot (after 30 seconds approximately.)*|
The highest desynchronization difference was about 617 ms, beteween the participant and primary speaker.
The highest desynchronization difference was about 617 ms, between the participant and primary speaker.
**Third Screenshot (after restarting participant media source)**
@ -153,11 +160,12 @@ The highest desynchronization difference was about 617 ms, beteween the particip
|:--:|
|*Third screenshot - after restarting participant media source in OBS*|
After restarting the participant media source in OBS, the highest desynchronization difference was about 86 ms, beteween the participant and together mode.
After restarting the participant media source in OBS, the highest desynchronization difference was about 86 ms, between the participant and together mode.
**Fourth Screenshot (after 19 minutes approximately)**
**OBS**
| Stream | Running Time|
| ------------- | ------------- |
| Participant (top-left) | 0:19:57.494 |
@ -166,6 +174,7 @@ After restarting the participant media source in OBS, the highest desynchronizat
| Screenshare (bottom-right) | 0:19:58.193 |
**gst-play**
| Stream | Running Time|
| ------------- | ------------- |
| Participant (top-left) | 0:19:58.328 |
@ -182,6 +191,7 @@ After 19 minutes approximately, we can see how the streams become desynchronized
**Fifth Screenshot (after restarting the media sources)**
**OBS**
| Stream | Running Time|
| ------------- | ------------- |
| Participant (top-left) | 0:22:14.898 |
@ -190,6 +200,7 @@ After 19 minutes approximately, we can see how the streams become desynchronized
| Screenshare (bottom-right) | 0:22:14.997 |
**gst-play**
| Stream | Running Time|
| ------------- | ------------- |
| Participant (top-left) | 0:22:15.365 |
@ -239,6 +250,7 @@ Here we show some examples with _VLC_ and _gst-play_ playing multiple streams at
|*Example of multiple streams with gst-play (288 ms of difference)*|
### Findings
* The results we shared above may vary between different executions, depending on factors like player, network condition, BDK virtual machine CPU consumption.
* Using SRT and _OBS Studio_, we couldn't achieve the results we achieved with _gst-play_. We don't know how OBS is using ffmpeg, but we had to increase the latency of the streams and had to disable/enable the media sources in OBS to restart the streams to try to keep them synchronized.
* From the different tests and comparisons between _OBS_ and _gst-play_, we can observe that when we restart the streams, they recover their current running time. This indicates that the pipelines are synchronized, but the players/tools have issues to play them synchronized.
* From the different tests and comparisons between _OBS_ and _gst-play_, we can observe that when we restart the streams, they recover their current running time. This indicates that the pipelines are synchronized, but the players/tools have issues to play them synchronized.

Просмотреть файл

@ -1,10 +0,0 @@
# Prerequisites
Before configuring the solution to run it locally and/or in azure you must have the following prerequisites:
- A **domain name** - This domain name will be used to host the solution's core components.
- An **SSL wildcard certificate** - A valid wildcard certificate for the domain mentioned in the previous point. This is required to establish a TLS/TCP control channel between the bot's media platform and the calling clouds. The certificate must be in .pem and .pfx formats.
- An **Office 365 tenant with Microsoft Teams** enabled - If the organization is already using Microsoft Teams for their meetings, then you already have an Office 365 tenant configured.
- Note that you need the create an app registration in this tenant with permissions to join meetings and send and receive audio and video in those meetings. These permissions will need to be approved by your Office 365 tenant administrator. You can find more details about the permissions in the [Azure Bot](azure_bot.md) document.
- If your organization doesn't want to provide the necessary permissions for the solution to connect to the meetings, or you just want to test this solution in an isolated tenant, you can obtain a new testing tenant using Office 365's [Developer Program](https://developer.microsoft.com/en-us/microsoft-365/dev-program).
- [An Azure Bot](azure_bot.md) - This will be used to add calling capabilities to the bot, to authenticate against the Microsoft Graph APIs and connect the solution to the meetings that are hosted in your tenant.
- If you plan to deploy this solution to the cloud then you will need an **Azure subscription** to create the required resources to host the solution. Also, Azure AD needs to be used to created several app registrations for authentication and authorization.

Просмотреть файл

@ -1,73 +0,0 @@
# How to create an Azure Bot
## Useful links
- [How to create an application registration](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application)
- [How to create an Azure Bot resource](https://docs.microsoft.com/en-us/azure/bot-service/abs-quickstart?view=azure-bot-service-4.0#create-an-azure-bot-resource)
## Getting Started
To add calling capabilities to the bot, it's necessary to create an Azure Bot resource. To do so, before creating the Azure Bot, we need to create an application registration with the required permissions the Azure Bot will use to authenticate against the Microsoft Graph API and get access to different resources.
### Bot Application Registration
To create the application registration, review the following Microsoft [documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application) that will explain how to do it.
After reviewing the documentation, create the application registration with the following settings:
* `Name`: A meaningful name for your application registration.
* `Authentication`:
* `Platform configurations:` None.
* `Supported account types:` Accounts in this organizational directory only.
* `Certificates and clients:` A secrets needs to be created for this application and stored in a secure location. Give a long expiration for this secret (check your organizations policies on credential expiration).
* `Token configuration:` None.
* `Expose an API:` None
* `App roles:` None.
* `API permissions:` This app requires several permissions to access the Microsoft Teams calls. Add the permissions shown in the table below.
API / Permission name | Type | Display | Description | Admin consent
----------|----------|----------|----------|----------
Calls.AccessMedia.All | Application | Access media streams in a call as an app preview. | Allows the app to get direct access to media streams in a call, without a signed-in user. | Yes
Calls.Initiate.All | Application | Initiate outgoing 1:1 calls from the app preview.| Allows the app to place outbound calls to a single user and transfer calls to users in your organizations directory, without a signed-in user. | Yes
Calls.InitiateGroupCall.All | Application | Initiate outgoing group calls from the app preview | Allows the app to place outbound calls to multiple users and add participants to meetings in your organization, without a signed-in user. | Yes
Calls.JoinGroupCall.All | Application | Join group calls and meetings as an app preview. | Allows the app to join group calls and scheduled meetings in your organization, without a signed-in user. The app is joined with the privileges of a directory user to meetings in your tenant. | Yes
Calls.JoinGroupCallAsGuest.All | Application | Join group calls and meetings as a guest preview. | Allows the app to anonymously join group calls and scheduled meetings in your organization, without a signed-in user. The app is joined as a guest to meetings in your tenant. | Yes
User.Read | Delegated | Sign in and read user profile | Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users | No
User.Read.All | Application | Read all users' full profiles | Allows the app to read user profiles without a signed in user. We use it to retrieve get the user photos | Yes
Several of the permissions that were configured in this application require to be consented by an admin of the Azure AD tenant. To grant this consent, ask an Azure AD administrator to access the following URL and accept the permissions for this application (replace the {{applicationId}} placeholder with the id of the application registration previously created):
> https://login.microsoftonline.com/common/adminconsent?client_id={{applicationId}}&state=1
> **Note**: Despite that constructing the Tenant Admin Consent URL requires a configured Redirect URI/Reply URL in the App Registration Portal, to grant consent manually we don't need to add it to the reply URL in the consent URL. To add reply URLs for your bot, access your bot registration, choose Advanced Options > Edit Application Manifest. Add your Redirect URI to the field reply URLs.
### Azure Bot
To continue with the registration of the calling bot, we must create an [Azure Bot resource](https://docs.microsoft.com/en-us/azure/bot-service/abs-quickstart?view=azure-bot-service-4.0#create-an-azure-bot-resource). While doing so, consider the following settings:
* `Bot handle:` A meaningful name.
* `Subscription` Your Azure subscription.
* `Resource group`: The resource group where you want to create the resource
* `Pricing tier:` F0.
* `Microsoft App ID:` Click on `Use existing app registration`, then input the client ID and client secret that were created for the bot application registration.
* Leave the rest of the settings as-is.
Once the Azure Bot is created, apply the following changes to the resource:
1. In the resource blade, click `Channels`, then go to the `Connect to channels` section and click edit on the `Microsoft Teams` channel. If this channel is not already added by default, add the `Microsoft Teams` channel first using the options in this page.
|![Azure Bot Service](images/azure-bot-1.png)|
|:--:|
|*Azure Bot Service - Connect to channels*|
2. Once inside, go to the `Calling` tab and check the `Enable calling` checkbox. In the `Webhook` URL add the path to the following route using your domain name:
* `https://{domain-name}/api/calling `
|![Azure Bot Service](images/azure-bot-2.png)|
|:--:|
|*Azure Bot Service - Calling tab*|
3. Click `Save` to impact the changes.
> **Optional:** You can go to `Bot profile` section and upload an icon for this bot or change the name that it will show inside the meetings.

Двоичные данные
docs/prerequisites/images/azure-bot-1.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 48 KiB

Двоичные данные
docs/prerequisites/images/azure-bot-2.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 107 KiB

Просмотреть файл

@ -1,14 +1,19 @@
## Purpose
# Purpose
_Describe the problem or feature in addition to a link to the issues._
## Approach
_How does this change address the problem?_
#### Open Questions and Pre-Merge TODOs
### Open Questions and Pre-Merge TODOs
- [ ] Use github checklists. When solved, check the box and explain the answer.
## Optional
### Learning
_Describe the research stage_
_Links to blog posts, patterns, libraries or addons used to solve this problem_

Просмотреть файл

@ -8,6 +8,49 @@ While all the configuration settings are the same between versions **0.4.0-dev**
- Please review the [inbound rules](how-to-run-the-solution-in-azure/virtual_machine.md#network-security-group-inbound-rules) listed in the documentation and update your VM to match those rules.
- Check the latest [settings for the NGINX server](common/install_and_configure_nginx_with_rtmp_module_on_windows.md#installation) and update your NGINX configuration file in the VM to match these settings.
- Check the latest [settings for the NGINX server](common/install-and-configure-nginx-with-rtmp-module-on-windows.md#installation) and update your NGINX configuration file in the VM to match these settings.
The version **0.5.0-dev** also included an slate image used by the bot when no injection is active. Optionally, you can [change the slate image to one of your choosing](common/customize_bdk_slate_image.md).
## From 0.5.0-dev to 0.6.0-dev
In this release we introduced some breaking changes related to solution's deployment/configuration.
We added Azure Key Vault, migrated the secrets there and change the way the Bot Service get access to its configuration among other features and bug fixes that you can see in the [CHANGELOG](../CHANGELOG.md).
To upgrade from a previous version to the `0.6.0-dev` we highly recommend reviewing the updated documentation to setup an [Azure](how-to-run-the-solution-in-azure/README.md) / [local](how-to-run-the-solution-locally/README.md) environment.
That being said, you will have to:
- [Create an Azure Key Vault](how-to-run-the-solution-in-azure/azure-key-vault.md#azure-key-vault)
- Create azure resource
- Upload domain certificate
- Add certificate secrets
- Assign access policies for Web App Service, Azure Function App Service and Virtual Machine
- Migrate secrets to Key Vault
- Add secret for [Cosmos DB](how-to-run-the-solution-in-azure/cosmos-db.md) primary key with the following name:
- `Settings--CosmosDbConfiguration--PrimaryKey`
- Add secret for [Storage Account](how-to-run-the-solution-in-azure/storage-account.md) Connection string with the following name:
- `Settings--StorageConfiguration--ConnectionString`
- Add secret for [Bot Service Client app registration](how-to-run-the-solution-in-azure/bot-service-client-app-registration.md) with the following name:
- `Settings--BotServiceAuthenticationConfiguration--ClientSecret`
- Add secret for [Azure SDK app registration](how-to-run-the-solution-in-azure/azure-sdk-app-registration.md) with the following name:
- `Settings--AzServicePrincipalConfiguration--ApplicationClientSecret`
- Add secret for [Azure Bot app registration](how-to-run-the-solution-in-azure/azure-bot-app-registration.md) with the following names:
- `Settings--BotConfiguration--AadAppSecret`
- `Settings--GraphClientConfiguration--ClientSecret`
- Virtual Machine
- Update GStreamer from 1.18.4 to 1.18.6 (We highly recommend uninstall the previous version and install the new one)
- **[Optional]** Remove BotService environment variables (review old documentation). Keep GStreamer environment variables.
- **[Optional]** Storage Account
- Remove PFX certificate
- Remove Bot Service settings json
- Deployment
- [Management API](how-to-run-the-solution-in-azure/management-api-deploy.md)
- Publish latest version
- Update App Service configuration settings (review [Configuring app settings](how-to-run-the-solution-in-azure/management-api-deploy.md#configuring-app-settings) section)
- [Function App](how-to-run-the-solution-in-azure/function-app-deploy.md)
- Publish latest version
- Update App Service configuration settings (review [Configuring app settings](how-to-run-the-solution-in-azure/function-app-deploy.md#configuring-app-settings) section)
- [Bot Service](how-to-run-the-solution-in-azure/bot-service-deploy.md)
- Publish latest version
- Update `appSettings.json` configuration settings (review [Updating appSettings.json](how-to-run-the-solution-in-azure/bot-service-deploy.md#updating-appsettingsjson)

Просмотреть файл

@ -0,0 +1,17 @@
Param(
[string] $GStreamerPath = "c:\gstreamer\1.0\mingw_x86_64\bin\"
)
if (-not (Test-Path -Path $GStreamerPath))
{
throw [System.IO.FileNotFoundException] "The GStreamer bin folder ""$GStreamerPath"" does not exist. Verify that GStreamer is installed and use -GStreamerPath parameter to specify the GStream bin path location (default $GStreamerPath)"
}
$RegexAddPath = [regex]::Escape($GStreamerPath)
$UserPath = [Environment]::GetEnvironmentVariable("PATH", [EnvironmentVariableTarget]::User)
$ArrPath = $UserPath -split ';' | Where-Object {$_ -notMatch "^$RegexAddPath\\?"}
$NewPath = ($ArrPath + $GStreamerPath) -join ';'
[Environment]::SetEnvironmentVariable("PATH", $NewPath, [EnvironmentVariableTarget]::User)
Write-Host "Added '$GStreamerPath' to PATH environment variable"

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Copyright>Copyright (c) Microsoft Corporation.</Copyright>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<ItemGroup>
@ -21,13 +22,13 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.1.0" />
<PackageReference Include="Microsoft.Azure.Management.Compute.Fluent" Version="1.36.1" />
<PackageReference Include="Microsoft.Azure.Management.Fluent" Version="1.36.1" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Graph" Version="3.8.0" />
<PackageReference Include="Microsoft.Graph" Version="4.25.0" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.24.0.32949">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

Просмотреть файл

@ -7,6 +7,7 @@ using Application.Interfaces.Common;
using Application.Interfaces.Persistance;
using AutoMapper;
using Domain.Enums;
using Domain.Exceptions;
using FluentValidation;
using MediatR;
@ -58,9 +59,15 @@ namespace Application.Call.Commands
public async Task<RequestEndCallCommandResponse> Handle(RequestEndCallCommand request, CancellationToken cancellationToken)
{
RequestEndCallCommandResponse response = new RequestEndCallCommandResponse();
var response = new RequestEndCallCommandResponse();
var entity = await _callRepository.GetItemAsync(request.CallId);
if (entity == null)
{
throw new EntityNotFoundException(nameof(Domain.Entities.Call), request.CallId);
}
Domain.Entities.Call entity = await _callRepository.GetItemAsync(request.CallId);
entity.State = CallState.Terminating;
await _callRepository.UpdateItemAsync(entity.Id, entity);
@ -68,6 +75,11 @@ namespace Application.Call.Commands
// Getting service base url
var service = await _serviceRepository.GetItemAsync(entity.ServiceId);
if (service == null)
{
throw new EntityNotFoundException(nameof(Domain.Entities.Service), entity.ServiceId);
}
response.Resource = _mapper.Map<CallModel>(entity);
response.Id = entity.Id;

Просмотреть файл

@ -5,7 +5,6 @@ using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Application.Common.Config;
using Application.Common.Models;
using Application.Exceptions;
using Application.Interfaces.Common;
@ -109,6 +108,17 @@ namespace Application.Call.Commands
throw new EntityNotFoundException(nameof(Domain.Entities.Service), serviceId);
}
if (service.State == ServiceState.Busy)
{
var serviceCall = await _callRepository.GetItemAsync(service.CallId);
if (serviceCall?.State == CallState.Established || serviceCall?.State == CallState.Establishing)
{
response.Id = serviceCall.Id;
response.Resource = _mapper.Map<CallModel>(serviceCall);
return response;
}
}
if (service.State != ServiceState.Available)
{
throw new ServiceUnavailableException($"The service {service.Name} is not available");
@ -119,7 +129,7 @@ namespace Application.Call.Commands
throw new ServiceUnavailableException($"The service {service.Name} is not running");
}
Domain.Entities.Call call = _mapper.Map<Domain.Entities.Call>(request);
var call = _mapper.Map<Domain.Entities.Call>(request);
call.State = CallState.Establishing;
call.ServiceId = service.Id;
call.BotFqdn = service.Infrastructure.Dns;

Просмотреть файл

@ -41,7 +41,7 @@ namespace Application.Stream.Commands
var call = await _callRepository.GetItemAsync(request.CallId);
var service = await _serviceRepository.GetItemAsync(call.ServiceId);
_botServiceClient.SetBaseUrl(service.Infrastructure.Dns);
await _botServiceClient.MuteBotAsync();
await _botServiceClient.MuteBotAsync(request.CallId);
return null;
}
}

Просмотреть файл

@ -41,7 +41,7 @@ namespace Application.Call.Commands
var call = await _callRepository.GetItemAsync(request.CallId);
var service = await _serviceRepository.GetItemAsync(call.ServiceId);
_botServiceClient.SetBaseUrl(service.Infrastructure.Dns);
await _botServiceClient.UnmuteBotAsync();
await _botServiceClient.UnmuteBotAsync(request.CallId);
return null;
}
}

Просмотреть файл

@ -56,6 +56,10 @@ namespace Application.Common.Config
public string CertificateThumbprint { get; set; }
public string CertificateName { get; set; }
public string CertificatePassword { get; set; }
public int SecondsWithoutParticipantsBeforeRemove { get; set; } = 300;
}
}

Просмотреть файл

@ -8,6 +8,10 @@ namespace Application.Common.Config
{
string BuildVersion { get; set; }
string KeyVaultName { get; set; }
string KeyVaultEnv { get; set; }
GraphClientConfiguration GraphClientConfiguration { get; }
AzStorageConfiguration StorageConfiguration { get; }

Просмотреть файл

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using Domain.Enums;
namespace Application.Common.Models.Api
{
public class SetInjectionVolumeRequest
{
public StreamVolumeFormat Format { get; set; }
public double Value { get; set; }
}
}

Просмотреть файл

@ -34,6 +34,8 @@ namespace Application.Common.Models
public string GraphId { get; set; }
public bool IsBotMuted { get; set; }
public List<ParticipantStreamModel> Streams { get; set; } = new List<ParticipantStreamModel>();
public StreamModel InjectionStream { get; set; }

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using Application.Common.Converter;
using Application.Common.Models.Api;
using Domain.Enums;
using Newtonsoft.Json;
@ -18,5 +19,11 @@ namespace Application.Common.Models
public string StreamKey { get; set; }
public Protocol Protocol { get; set; }
public SetInjectionVolumeRequest StreamVolume { get; set; } = new SetInjectionVolumeRequest
{
Format = StreamVolumeFormat.Cubic,
Value = 1.0,
};
}
}

Просмотреть файл

@ -34,6 +34,10 @@ namespace Application.Common.Models
public dynamic StreamMode { get; set; }
public StreamVolume StreamVolume { get; set; }
public bool VideoFeedOn { get; set; }
public StreamErrorDetails Error { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System;
using System.Runtime.Serialization;
namespace Application.Exceptions
{
[Serializable]
public class SetStreamVolumeException : CustomBaseException
{
public SetStreamVolumeException(string title, string message)
: base(title, message)
{
}
protected SetStreamVolumeException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System.Net.Http;
using System.Threading.Tasks;
using Application.Common.Models;
using Application.Common.Models.Api;
using static Application.Service.Commands.DoInviteBot;
namespace Application.Interfaces.Common
@ -23,6 +24,12 @@ namespace Application.Interfaces.Common
void StopInjection();
void SetInjectionVolume(SetInjectionVolumeRequest injectionVolumeRequest);
void DisplayInjection();
void HideInjection();
StartStreamExtractionResponse StartExtraction(StartStreamExtractionBody streamBody);
void StopExtraction(StopStreamExtractionBody streamBody);

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT license.
using System.Net.Http;
using System.Threading.Tasks;
using Application.Common.Models.Api;
using Application.Service.Commands;
using Application.Stream.Commands;
@ -17,13 +18,19 @@ namespace Application.Interfaces.Common
Task<DoStopInjection.DoStopInjectionCommandResponse> StoptInjectionAsync(DoStopInjection.DoStopInjectionCommand command);
Task<DoHideInjection.DoHideInjectionCommandResponse> HideInjectionAsync(DoHideInjection.DoHideInjectionCommand command);
Task<DoDisplayInjection.DoDisplayInjectionCommandResponse> DisplayInjectionAsync(DoDisplayInjection.DoDisplayInjectionCommand command);
Task<DoStartExtraction.DoStartExtractionCommandResponse> StartExtractionAsync(DoStartExtraction.DoStartExtractionCommand command);
Task<DoStopExtraction.DoStopExtractionCommandResponse> StopExtractionAsync(DoStopExtraction.DoStopExtractionCommand command);
Task<HttpResponseMessage> MuteBotAsync();
Task<HttpResponseMessage> MuteBotAsync(string callId);
Task<HttpResponseMessage> UnmuteBotAsync();
Task<HttpResponseMessage> UnmuteBotAsync(string callId);
Task<HttpResponseMessage> SetInjectionVolumeAsync(string callId, SetInjectionVolumeRequest setInjectionVolumeRequest);
void SetBaseUrl(string baseUrl);
}

Просмотреть файл

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
using System.Threading;
using System.Threading.Tasks;
using Application.Interfaces.Persistance;
using AutoMapper;
using Domain.Entities;
using Domain.Exceptions;
using MediatR;
using Microsoft.Extensions.Logging;
namespace Application.Participant.Commands
{
public class UpdateBotStatus
{
public class UpdateBotStatusCommand : IRequest<UpdateBotStatusResponse>
{
public string CallId { get; set; }
public bool IsBotMuted { get; set; }
}
public class UpdateBotStatusResponse
{
public string Id { get; set; }
public bool IsBotMuted { get; set; }
}
public class UpdateBotStatusCommandHandler : IRequestHandler<UpdateBotStatusCommand, UpdateBotStatusResponse>
{
private readonly ICallRepository _callRepository;
private readonly ILogger<UpdateBotStatusCommandHandler> _logger;
public UpdateBotStatusCommandHandler(ICallRepository callRepository, ILogger<UpdateBotStatusCommandHandler> logger)
{
_callRepository = callRepository;
_logger = logger;
}
public async Task<UpdateBotStatusResponse> Handle(UpdateBotStatusCommand command, CancellationToken cancellationToken)
{
var call = await _callRepository.GetItemAsync(command.CallId);
if (call.Id == null)
{
_logger.LogInformation("Call {command.CallId} was not found", command.CallId);
throw new EntityNotFoundException(nameof(Call), command.CallId);
}
var response = new UpdateBotStatusResponse()
{
Id = call.Id,
};
call.IsBotMuted = command.IsBotMuted;
await _callRepository.UpdateItemAsync(call.Id, call);
return response;
}
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше