Skip to content

Commit c922140

Browse files
authored
Merge pull request #230377 from MicrosoftDocs/main
Publish to live, Sunday 4PM PST, 3/12
2 parents c86ffe5 + f0a2188 commit c922140

33 files changed

+455
-273
lines changed

articles/azure-fluid-relay/how-tos/azure-function-token-provider.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Using [Azure Functions](../../azure-functions/functions-overview.md) is a fast w
3434

3535
This example demonstrates how to create your own **HTTPTrigger Azure Function** that fetches the token by passing in your tenant key.
3636

37+
# [TypeScript](#tab/typescript)
38+
3739
```typescript
3840
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
3941
import { ScopeType } from "@fluidframework/azure-client";
@@ -88,6 +90,103 @@ export default httpTrigger;
8890

8991
The `generateToken` function, found in the `@fluidframework/azure-service-utils` package, generates a token for the given user that is signed using the tenant's secret key. This method enables the token to be returned to the client without exposing the secret. Instead, the token is generated server-side using the secret to provide scoped access to the given document. The example ITokenProvider below makes HTTP requests to this Azure Function to retrieve the tokens.
9092

93+
# [C#](#tab/csharp)
94+
95+
```cs
96+
using System;
97+
using System.IO;
98+
using System.Threading.Tasks;
99+
using Microsoft.AspNetCore.Mvc;
100+
using Microsoft.Azure.WebJobs;
101+
using Microsoft.Azure.WebJobs.Extensions.Http;
102+
using Microsoft.AspNetCore.Http;
103+
using Microsoft.Extensions.Logging;
104+
using Newtonsoft.Json;
105+
using Newtonsoft.Json.Linq;
106+
using System.Text;
107+
108+
using Microsoft.IdentityModel.Tokens;
109+
using System.IdentityModel.Tokens.Jwt;
110+
111+
namespace dotnet_tokenprovider_functionsapp
112+
{
113+
public static class AzureFunction
114+
{
115+
// NOTE: retrieve the key from a secure location.
116+
private static readonly string key = "myTenantKey";
117+
118+
[FunctionName("AzureFunction")]
119+
public static async Task<IActionResult> Run(
120+
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log)
121+
{
122+
string content = await new StreamReader(req.Body).ReadToEndAsync();
123+
JObject body = !string.IsNullOrEmpty(content) ? JObject.Parse(content) : null;
124+
125+
string tenantId = (req.Query["tenantId"].ToString() ?? body["tenantId"]?.ToString()) as string;
126+
string documentId = (req.Query["documentId"].ToString() ?? body["documentId"]?.ToString() ?? null) as string;
127+
string userId = (req.Query["userId"].ToString() ?? body["userId"]?.ToString()) as string;
128+
string userName = (req.Query["userName"].ToString() ?? body["userName"]?.ToString()) as string;
129+
string[] scopes = (req.Query["scopes"].ToString().Split(",") ?? body["scopes"]?.ToString().Split(",") ?? null) as string[];
130+
131+
if (string.IsNullOrEmpty(tenantId))
132+
{
133+
return new BadRequestObjectResult("No tenantId provided in query params");
134+
}
135+
136+
if (string.IsNullOrEmpty(key))
137+
{
138+
return new NotFoundObjectResult($"No key found for the provided tenantId: ${tenantId}");
139+
}
140+
141+
// If a user is not specified, the token will not be associated with a user, and a randomly generated mock user will be used instead
142+
var user = (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(userId)) ?
143+
new { name = Guid.NewGuid().ToString(), id = Guid.NewGuid().ToString() } :
144+
new { name = userName, id = userId };
145+
146+
// Will generate the token and returned by an ITokenProvider implementation to use with the AzureClient.
147+
string token = GenerateToken(
148+
tenantId,
149+
key,
150+
scopes ?? new string[] { "doc:read", "doc:write", "summary:write" },
151+
documentId,
152+
user
153+
);
154+
155+
return new OkObjectResult(token);
156+
}
157+
158+
private static string GenerateToken(string tenantId, string key, string[] scopes, string? documentId, dynamic user, int lifetime = 3600, string ver = "1.0")
159+
{
160+
string docId = documentId ?? "";
161+
DateTime now = DateTime.Now;
162+
163+
SigningCredentials credentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)), SecurityAlgorithms.HmacSha256);
164+
165+
JwtHeader header = new JwtHeader(credentials);
166+
JwtPayload payload = new JwtPayload
167+
{
168+
{ "documentId", docId },
169+
{ "scopes", scopes },
170+
{ "tenantId", tenantId },
171+
{ "user", user },
172+
{ "iat", new DateTimeOffset(now).ToUnixTimeSeconds() },
173+
{ "exp", new DateTimeOffset(now.AddSeconds(lifetime)).ToUnixTimeSeconds() },
174+
{ "ver", ver },
175+
{ "jti", Guid.NewGuid() }
176+
};
177+
178+
JwtSecurityToken token = new JwtSecurityToken(header, payload);
179+
180+
return new JwtSecurityTokenHandler().WriteToken(token);
181+
}
182+
}
183+
}
184+
```
185+
186+
The `GenerateToken` function is built off of the `@fluidframework/azure-service-utils` npm package, and it generates a token for the given user that is signed using the tenant's secret key. This function enables the token to be returned to the client without exposing the secret. Instead, the token is generated server-side using the secret to provide scoped access to the given document. The example ITokenProvider below makes HTTP requests to this Azure Function to retrieve the tokens.
187+
188+
---
189+
91190
### Deploy the Azure Function
92191

93192
Azure Functions can be deployed in several ways. For more information, see the **Deploy** section of the [Azure Functions documentation](../../azure-functions/functions-continuous-deployment.md) for more information about deploying Azure Functions.

articles/azure-monitor/essentials/azure-monitor-workspace-manage.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ ms.date: 01/19/2023
1212

1313
This article shows you how to create and delete an Azure Monitor workspace. When you configure Azure Monitor managed service for Prometheus, you can select an existing Azure Monitor workspace or create a new one.
1414

15+
> [!NOTE]
16+
> When you create an Azure Monitor workspace, by default a data collection rule and a data collection endpoint in the form `<azure-workspace-name>` will automatically be created in a resource group in the form `MA_<azure-workspace-name>_<location>_managed`.
17+
1518
## Create an Azure Monitor workspace
1619
### [Azure portal](#tab/azure-portal)
1720

0 commit comments

Comments
 (0)