get role assignments and userinfo using ARM and Graph API on Functions (2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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