Skip to content

Commit 0408d0e

Browse files
authored
Add bi-direction serverless sample together with msi and key vault reference (#136)
* Add sample * Add msi * Add sample of keyvault reference * Update local setting * Update gitignore * Revert changed * Update
1 parent d03d942 commit 0408d0e

17 files changed

+871
-0
lines changed

samples/BidirectionChat/README.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Azure function bidirectional chatroom sample
2+
3+
This is a chatroom sample that demonstrates bidirectional message pushing between Azure SignalR Service and Azure Function in serverless scenario. It leverages the [**upstream**](https://docs.microsoft.com/azure/azure-signalr/concept-upstream) provided by Azure SignalR Service that features proxying messages from client to upstream endpoints in serverless scenario. Azure Functions with SignalR trigger binding allows you to write code to receive and push messages in several languages, including JavaScript, Python, C#, etc.
4+
5+
- [Prerequisites](#prerequisites)
6+
- [Run sample in Azure](#run-sample-in-azure)
7+
- [Use Key Vault secret reference](#use-key-vault-secret-reference)
8+
- [Enable AAD Token on upstream](#enable-aad-token-on-upstream)
9+
10+
<a name="prerequisites"></a>
11+
12+
## Prerequisites
13+
14+
The following softwares are required to build this tutorial.
15+
* [.NET SDK](https://dotnet.microsoft.com/download) (Version 3.1, required for Functions extensions)
16+
* [Azure Functions Core Tools](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#install-the-azure-functions-core-tools) (Version 3)
17+
* [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
18+
19+
<a name="run-sample-in-azure"></a>
20+
21+
## Run sample in Azure
22+
23+
It's a quick try of this sample. You will create an Azure SignalR Service and an Azure Function app to host sample. And you will launch chatroom locally but connecting to Azure SignalR Service and Azure Function.
24+
25+
### Create Azure SignalR Service
26+
27+
1. Create Azure SignalR Service using `az cli`
28+
29+
```bash
30+
az signalr create -n <signalr-name> -g <resource-group-name> --service-mode Serverless --sku Free_F1
31+
```
32+
33+
For more details about creating Azure SignalR Service, see the [tutorial](https://docs.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-azure-functions-javascript#create-an-azure-signalr-service-instance).
34+
35+
### Deploy project to Azure Function
36+
37+
1. Deploy with Azure Functions Core Tools
38+
1. [Install Azure Functions Core Tools](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#install-the-azure-functions-core-tools)
39+
2. [Create Azure Function App](https://docs.microsoft.com/en-us/azure/azure-functions/scripts/functions-cli-create-serverless#sample-script) (code snippet shown below)
40+
41+
```bash
42+
#!/bin/bash
43+
44+
# Function app and storage account names must be unique.
45+
storageName=mystorageaccount$RANDOM
46+
functionAppName=myserverlessfunc$RANDOM
47+
region=westeurope
48+
49+
# Create a resource group.
50+
az group create --name myResourceGroup --location $region
51+
52+
# Create an Azure storage account in the resource group.
53+
az storage account create \
54+
--name $storageName \
55+
--location $region \
56+
--resource-group myResourceGroup \
57+
--sku Standard_LRS
58+
59+
# Create a serverless function app in the resource group.
60+
az functionapp create \
61+
--name $functionAppName \
62+
--storage-account $storageName \
63+
--consumption-plan-location $region \
64+
--resource-group myResourceGroup \
65+
--functions-version 3
66+
```
67+
68+
3. Publish the sample to the Azure Function you created before.
69+
70+
```bash
71+
cd <root>/bidirectional-chat/csharp
72+
// If prompted function app version, use --force
73+
func azure functionapp publish <function-app-name>
74+
```
75+
76+
2. Update application settings
77+
78+
```bash
79+
az functionapp config appsettings set --resource-group <resource_group_name> --name <function_name> --setting AzureSignalRConnectionString="<signalr_connection_string>"
80+
```
81+
82+
3. Update Azure SignalR Service Upstream settings
83+
84+
Open the Azure Portal and nevigate to the Function App created before. Find `signalr_extension` key in the **App keys** blade.
85+
86+
![Overview with auth](getkeys.png)
87+
88+
Copy the `signalr_extensions` value and use Azure Portal to set the upstream setting.
89+
- In the *Upstream URL Pattern*, fill in the `<function-url>/runtime/webhooks/signalr?code=<signalr_extension-key>`
90+
> [!NOTE]
91+
> The `signalr_extensions` code is required by Azure Function but the trigger does not only use this code but also Azure SignalR Service connection string to validate requests. If you're very serious about the code, use KeyVault secret reference feature to save the code. See [Use Key Vault secret reference](#use-keyvault-secret-reference).
92+
93+
![Upstream](upstream-portal.png)
94+
95+
### Use a chat sample website to test end to end
96+
97+
1. Use browser to visit `<function-app-url>/api/index` for the web page of the demo.
98+
99+
2. Try send messages by entering them into the main chat box.
100+
![Chatroom](chatroom-noauth.png)
101+
102+
## Use Key Vault secret reference
103+
104+
The url of upstream is not encryption at rest. If you have any sensitive information, you can use Key Vault to save these sensitive information. Basically, you can enable managed identity of Azure SignalR Service and then grant a read permission on a Key Vault instance and use Key Vault reference instead of plaintext in `Upstream URL Pattern`.
105+
106+
The following steps demonstrate how to use Key Vault secret reference to save `signalr_extensions`.
107+
108+
1. Enable managed identity.
109+
110+
1. Enable managed identity with system assigned identity.
111+
112+
Open portal and navigate to **Identity**, and switch to **System assigned** page. Switch **Status** to **On**.
113+
114+
![SystemAssignedIdentity](system-assigned-identity.png)
115+
116+
2. Create a Key Vault instance.
117+
118+
```bash
119+
az keyvault create --name "<your-unique-keyvault-name>" --resource-group "myResourceGroup" --location "EastUS"
120+
```
121+
122+
3. Save `signalr_extensions` to secret.
123+
124+
```bash
125+
az keyvault secret set --name "signalrkey" --vault-name "<your-unique-keyvault-name>" --value "<signalr_extension_code_copied_from_azure_function>"
126+
```
127+
128+
4. Grant **Secret Read** permission to the Key Vault.
129+
130+
```bash
131+
az keyvault set-policy --name "<your-unique-keyvault-name>" --object-id "<object-id-shown-in-system-assigned-identity>" --secret-permissions get
132+
```
133+
134+
5. Get the secret identity of the secret.
135+
136+
```bash
137+
az keyvault secret show --name "signalrkey" --vault-name "<your-unique-keyvault-name>" --query id -o tsv
138+
```
139+
140+
6. Update **Upstream URL Pattern** with Key Vault reference. You need to follow the syntax `{@Microsoft.KeyVault(SecretUri=<secret-identity>)}`. As shown below:
141+
142+
![KeyVaultReference](key-vault-reference.png)
143+
144+
## Enable AAD Token on upstream
145+
146+
You can set **ManagedIdentity** as the **Auth** setting in upstream. After that, SignalR Service will set an AAD Token into the `Authorization` for each upstream request.
147+
148+
1. Make sure you have enabled managed identity.
149+
150+
2. Click the asterisk in *Hub Rules* and a new page pops out as shown below.
151+
![Upstream details](upstream-details-portal.png)
152+
153+
3. Select *Use Managed Identity* under *Upstream Authentication* and *Use default value* under *Auth Resource ID*.
154+
155+
4. Use browser to visit `<function-app-url>/api/index` for the web page of the demo
156+
157+
5. Try send messages by entering them into the main chat box. You can verify the `Authorization` has set from the `with Authorization: true`
158+
![Chatroom](chatroom.png)
30.2 KB
Loading
27.6 KB
Loading

samples/BidirectionChat/cors.png

102 KB
Loading

0 commit comments

Comments
 (0)