get role assignments and userinfo using ARM and Graph API on Functions (2)
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; | |
using System.Text; | |
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 assingments = roleassignments["value"] as List<dynamic>; | |
if (assingments == null) return new JsonResult( new { message = "role assignment is none, or not found" }); | |
var roledefs = await Task.WhenAll( | |
assingments | |
.Select(x => x["properties"]["roleDefinitionId"]) | |
.Distinct() | |
.AsParallel() | |
.Select(async roleid => | |
{ | |
var roledef = Utf8Json.JsonSerializer.Deserialize<dynamic>(await GetRoleDefine(roleid, token.CreateAuthorizationHeader())); | |
return new | |
{ | |
id = roleid, | |
displayName = roledef["properties"]["roleName"] | |
}; | |
}) | |
); | |
// 割り当てユーザー・グループの情報取得 | |
var assignmentusers = assingments? | |
.Select(x => x["properties"]["principalId"] as string) | |
.Distinct() | |
.ToList(); | |
var dirobjjson = Utf8Json.JsonSerializer.Deserialize<dynamic>(await GetObjectInformation(assignmentusers, tokengraph.CreateAuthorizationHeader())); | |
var dirobjs = (dirobjjson["value"] as List<dynamic>)? | |
.Select(x => new { | |
displayName = x["displayName"], | |
mail = x["mail"], | |
id = x["id"], | |
upn = HasPropertyExist(x, "userPrincipalName") ? x["userPrincipalName"] : "", | |
objectType = x["@odata.type"] | |
}) | |
.ToList(); | |
return new JsonResult(assingments.Select(x => new | |
{ | |
role = roledefs.FirstOrDefault(r => r.id == x["properties"]["roleDefinitionId"]), | |
user = dirobjs.FirstOrDefault(u => u.id == x["properties"]["principalId"]) | |
}) | |
.Where(x=>x.user != 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> InvokePostApi(string requesturi, string authheader, string postbody) | |
{ | |
var request = new HttpRequestMessage() | |
{ | |
Method = HttpMethod.Post, | |
RequestUri = new Uri(requesturi), | |
}; | |
request.Headers.Add("Authorization", authheader); | |
request.Content = new StringContent(postbody, Encoding.UTF8, "application/json"); | |
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 | |
); | |
} | |
static async Task<string> GetObjectInformation(List<string> ids, string authheader) | |
{ | |
return await InvokePostApi( | |
$"https://graph.microsoft.com/v1.0/directoryObjects/getByIds", | |
authheader, | |
Utf8Json.JsonSerializer.ToJsonString(new { ids = ids }) | |
); | |
} | |
public static bool HasPropertyExist(dynamic obj, string name) | |
{ | |
if (obj is Dictionary<string, object>) | |
return ((IDictionary<string, object>)obj).ContainsKey(name); | |
try | |
{ | |
return obj[name] != null; | |
} | |
catch (KeyNotFoundException) | |
{ | |
return false; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment