Skip to content

Instantly share code, notes, and snippets.

@buchizo
Created April 23, 2019 06:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save buchizo/ad58de5d9b0c304b8ca2e4f673c4cb63 to your computer and use it in GitHub Desktop.
Save buchizo/ad58de5d9b0c304b8ca2e4f673c4cb63 to your computer and use it in GitHub Desktop.
get role assignments and userinfo using ARM and Graph API on Functions
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
namespace FunctionApp7
{
public static class Function1
{
static Function1()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("local.settings.json", true, false)
.AddJsonFile("secret.settings.json", true, false)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
private static async Task<AuthenticationResult> GetS2SAccessToken(string authority, string resource, string clientId, string clientSecret)
{
var clientCredential = new ClientCredential(clientId, clientSecret);
AuthenticationContext context = new AuthenticationContext(authority, false);
AuthenticationResult authenticationResult = await context.AcquireTokenAsync(
resource,
clientCredential);
return authenticationResult;
}
private static IConfigurationRoot Configuration { get; }
private static HttpClient Client = new HttpClient();
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log)
{
try
{
// トークンの期限は考慮してないので注意
var token = await GetS2SAccessToken(
string.Format("https://login.microsoftonline.com/{0}/", Configuration["Tenant"]),
"https://management.azure.com/",
Configuration["AppId"],
Configuration["AppSecret"]
);
var tokengraph = await GetS2SAccessToken(
string.Format("https://login.microsoftonline.com/{0}/", Configuration["Tenant"]),
"https://graph.microsoft.com/",
Configuration["AppId"],
Configuration["AppSecret"]
);
var subscriptionId = req.Query["subscriptionid"];
// ロール割り当ての取得
var roleassignments = Utf8Json.JsonSerializer.Deserialize<dynamic>(await GetRoleAssignment(subscriptionId, token.CreateAuthorizationHeader()));
var results = await Task.WhenAll(
(roleassignments["value"] as List<dynamic>)?.AsParallel()
.Select(async val =>
{
var assigninfo = new { id = val["id"], principalId = val["properties"]["principalId"], roleid = val["properties"]["roleDefinitionId"] };
// 割り当てられているユーザーの情報を取得
string ui = await GetUserInformation(assigninfo.principalId, tokengraph.CreateAuthorizationHeader());
if (string.IsNullOrWhiteSpace(ui)) return null; // 取れない場合ユーザーじゃない可能性もあり(App/Group他 ※手抜き)
var user = Utf8Json.JsonSerializer.Deserialize<dynamic>(ui);
var roledef = Utf8Json.JsonSerializer.Deserialize<dynamic>(await GetRoleDefine(assigninfo.roleid, token.CreateAuthorizationHeader()));
return new
{
id = assigninfo.principalId,
name = user["displayName"],
upn = user["userPrincipalName"],
mail = user["mail"],
roleid = assigninfo.roleid,
rolename = roledef["properties"]["roleName"]
};
}
)
);
return new JsonResult(results.Where(x => x != null));
}
catch (Exception ex)
{
log.LogError(ex.Message);
throw;
}
}
static async Task<string> InvokeApi(string requesturi, string authheader)
{
var request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(requesturi),
};
request.Headers.Add("Authorization", authheader);
var res = await Client.SendAsync(request);
if (res.StatusCode != System.Net.HttpStatusCode.OK) return null;
return await res.Content.ReadAsStringAsync();
}
static async Task<string> GetRoleAssignment(string subscriptionId, string authheader)
{
return await InvokeApi(
$"https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01",
authheader
);
}
static async Task<string> GetRoleDefine(string roleId, string authheader)
{
return await InvokeApi(
$"https://management.azure.com/{roleId}?api-version=2015-07-01",
authheader
);
}
static async Task<string> GetUserInformation(string userid, string authheader)
{
return await InvokeApi(
$"https://graph.microsoft.com/v1.0/users/{userid}",
authheader
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment