Uwierzytelnianie w Azure Functions z wykorzystaniem Service Principal
Pisane i publikowane na szybko. Za gramatykę i język nie odpowiadam, do czasu korekty ;-)
Ponad dwa lata temu popełniłem wpis o tym jak przeprowadzić autoryzacje w Azure Functions za pomocą klucza. Dziś pora na uwierzytelnianie za pomocą Azure AD, a dokładniej uwierzytelnianie za pomocą Service Principal, czyli tożsamością aplikacji, a nie użytkownika.
Ważne: uwierzytelnianie != autoryzacja
Na potrzeby testów bardzo prosta funkcja w C#, która loguje i w odpowiedzi zwraca wszystkie nagłówki.
public static class test
{
[FunctionName("test")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
foreach (var header in req.Headers)
{
log.LogInformation($"{header.Key}: {header.Value}");
}
return (ActionResult)new OkObjectResult(req.Headers);
}
}
Wymuszenie uwierzytelniania w Functions włączone za pomocą Authentication / Authorization z Azure AD.
Na potrzeby testów sam SP stworzyłem z az cli: az ad sp create-for-rbac -n funcaaddemo-client --skip-assignment
. Tak naprawdę, można go stworzyć dowolnym sposobem ;-)
Mając to wszystko trzeba uzyskać właściwy token, którym można się przedstawić w aplikacji. W tym wypadku będzie to scenariusz Client Credentials Grant. W tym scenariuszu należy przekazać cztery parametry przy uzyskiwaniu tokenu - grant_type, client_id, client_secret, scope. Cała zabawa polega na prawidłowym zdefiniowaniu scope. Przy tworzonej domyślnie aplikacji będzie to domyślny scope. W tym wypadku będzie on następujący: <Application ID użytej w funkcji (Authentication / Authorization)>/.default
.
Przetestować można to za pomocą najprostszego basha z cURL i jq na pokładzie. Poniżej prosty skrypt z wykorzystaniem tych narzędzi.
tenantID=<id lub nazwa tenanta>
scope="<Application ID użytej w funkcji (Authentication / Authorization)>/.default"
ClientID="<Application ID Service Principal>"
ClientKey="<Secret dla Service Principal>"
url="<Url do funkcji>"
access_token=$(curl -d "scope=$scope&grant_type=client_credentials&client_id=$ClientID&client_secret=$ClientKey" "https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token" | jq '.access_token' -r)
curl -H "Authorization: Bearer ${access_token}" $url | jq