added --list-tenants internal command + unit test (#1538)
* added --list-tenants internal command + unit test * cleaning up imports. * PR fixes
This commit is contained in:
Родитель
4d0fcb6048
Коммит
be2470ed5f
21
All.sln
21
All.sln
|
@ -116,6 +116,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MsIdentity
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-msidentity", "tools\dotnet-msidentity\dotnet-msidentity.csproj", "{1DB98E3A-0749-4ACE-9EF2-EF6BC2C6648B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.MsIdentity.UnitTests.Tests", "test\MsIdentityScaffolding\Microsoft.DotNet.MsIdentity.UnitTests.Tests\Microsoft.DotNet.MsIdentity.UnitTests.Tests.csproj", "{0711777C-64C2-49DC-A9CE-67BD641AA7A6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
debug_x86|Any CPU = debug_x86|Any CPU
|
||||
|
@ -705,6 +707,24 @@ Global
|
|||
{1DB98E3A-0749-4ACE-9EF2-EF6BC2C6648B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1DB98E3A-0749-4ACE-9EF2-EF6BC2C6648B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1DB98E3A-0749-4ACE-9EF2-EF6BC2C6648B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|x64.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|x64.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|x86.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.debug_x86|x86.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -747,6 +767,7 @@ Global
|
|||
{35BA8FDE-4AF3-4EF5-94B3-123B4702AF7E} = {3354705C-5C05-41C3-95E1-31A45141A6C2}
|
||||
{6B863A66-CFFC-42B4-9316-13B168CB6C62} = {49D385E7-A045-4C54-868F-CEA8F67EDBA8}
|
||||
{1DB98E3A-0749-4ACE-9EF2-EF6BC2C6648B} = {4B56CCB9-2693-492A-A0C5-B4D15DDF00A4}
|
||||
{0711777C-64C2-49DC-A9CE-67BD641AA7A6} = {49D385E7-A045-4C54-868F-CEA8F67EDBA8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {26BCDDB3-5505-4903-9D87-C942ED0D03E6}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
"solution": {
|
||||
"path": "All.sln",
|
||||
"projects": [
|
||||
"src\\MsIdentityScaffolding\\Microsoft.DotNet.MsIdentity\\Microsoft.DotNet.MsIdentity.csproj",
|
||||
"tools\\dotnet-msidentity\\dotnet-msidentity.csproj",
|
||||
"test\\MsIdentityScaffolding\\Microsoft.DotNet.MsIdentity.Tests\\Microsoft.DotNet.MsIdentity.Tests.csproj"
|
||||
"src\\MsIdentityScaffolding\\Microsoft.DotNet.MsIdentity\\Microsoft.DotNet.MsIdentity.csproj",
|
||||
"test\\MsIdentityScaffolding\\Microsoft.DotNet.MsIdentity.Tests\\Microsoft.DotNet.MsIdentity.Tests.csproj",
|
||||
"test\\MsIdentityScaffolding\\Microsoft.DotNet.MsIdentity.UnitTests.Tests\\Microsoft.DotNet.MsIdentity.UnitTests.Tests.csproj",
|
||||
"tools\\dotnet-msidentity\\dotnet-msidentity.csproj"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
set VERSION=0.0.1-dev
|
||||
set DEFAULT_NUPKG_PATH=%userprofile%/.nuget/packages
|
||||
set SRC_DIR=%cd%
|
||||
set NUPKG=artifacts/packages/Debug/Shipping/
|
||||
|
||||
|
@ -8,8 +7,8 @@ call rd /Q /S artifacts
|
|||
|
||||
call dotnet build MsIdentityScaffolding.slnf
|
||||
call dotnet pack MsIdentityScaffolding.slnf
|
||||
call dotnet tool uninstall -g dotnet-msidentity
|
||||
call dotnet tool uninstall -g Microsoft.dotnet-msidentity
|
||||
|
||||
call cd %SRC_DIR%/%NUPKG%
|
||||
call dotnet tool install -g dotnet-msidentity --add-source %SRC_DIR%\%NUPKG% --version %VERSION%
|
||||
call dotnet tool install -g Microsoft.dotnet-msidentity --add-source %SRC_DIR%\%NUPKG% --version %VERSION%
|
||||
call cd %SRC_DIR%
|
|
@ -6,7 +6,7 @@ NUPKG=artifacts/packages/Debug/Shipping/
|
|||
pkill -f dotnet
|
||||
rm -rf artifacts
|
||||
./build.sh
|
||||
dotnet tool uninstall -g dotnet-msidentity
|
||||
dotnet tool uninstall -g Microsoft.dotnet-msidentity
|
||||
cd $SRC_DIR/$NUPKG
|
||||
dotnet tool install -g dotnet-msidentity --add-source $SRC_DIR/$NUPKG --version $VERSION
|
||||
dotnet tool install -g Microsoft.dotnet-msidentity --add-source $SRC_DIR/$NUPKG --version $VERSION
|
||||
cd "$OLDPWD"
|
|
@ -6,7 +6,7 @@ call taskkill /f /im dotnet.exe
|
|||
call rd /Q /S artifacts
|
||||
call dotnet build Scaffolding.slnf
|
||||
call dotnet pack Scaffolding.slnf
|
||||
call dotnet tool uninstall -g dotnet-scaffold
|
||||
call dotnet tool uninstall -g Microsoft.dotnet-scaffold
|
||||
|
||||
call cd %DEFAULT_NUPKG_PATH%
|
||||
call rd /Q /S microsoft.visualstudio.web.codegeneration
|
||||
|
@ -19,5 +19,5 @@ call rd /Q /S microsoft.visualstudio.web.codegeneration.utils
|
|||
call rd /Q /S microsoft.visualstudio.web.codegenerators.mvc
|
||||
|
||||
call cd %SRC_DIR%/%NUPKG%
|
||||
call dotnet tool install -g dotnet-scaffold --add-source %SRC_DIR%\%NUPKG% --version %VERSION%
|
||||
call dotnet tool install -g Microsoft.dotnet-scaffold --add-source %SRC_DIR%\%NUPKG% --version %VERSION%
|
||||
call cd %SRC_DIR%
|
|
@ -10,7 +10,7 @@ NUPKG=artifacts/packages/Debug/Shipping/
|
|||
pkill -f dotnet
|
||||
rm -rf artifacts
|
||||
./build.sh
|
||||
dotnet tool uninstall -g dotnet-scaffold
|
||||
dotnet tool uninstall -g Microsoft.dotnet-scaffold
|
||||
cd $DEFAULT_NUPKG_PATH
|
||||
rm -rf microsoft.visualstudio.web.codegeneration
|
||||
rm -rf microsoft.visualstudio.web.codegeneration.contracts
|
||||
|
@ -21,5 +21,5 @@ rm -rf microsoft.visualstudio.web.codegeneration.templating
|
|||
rm -rf microsoft.visualstudio.web.codegeneration.utils
|
||||
rm -rf microsoft.visualstudio.web.codegenerators.mvc
|
||||
cd "$OLDPWD"/$NUPKG
|
||||
dotnet tool install -g dotnet-scaffold --add-source $SRC_DIR/$NUPKG --version $VERSION
|
||||
dotnet tool install -g Microsoft.dotnet-scaffold --add-source $SRC_DIR/$NUPKG --version $VERSION
|
||||
cd "$OLDPWD"
|
|
@ -0,0 +1,59 @@
|
|||
using Azure.Core;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.DotNet.MsIdentity.DeveloperCredentials
|
||||
{
|
||||
internal class AzureManagementAuthenticationProvider : IAzureManagementAuthenticationProvider
|
||||
{
|
||||
readonly TokenCredential _tokenCredentials;
|
||||
readonly string[] _initialScopes;
|
||||
private const string AzureManagementAPIDefault = "https://management.azure.com/.default";
|
||||
private const string AzureManagementTenantsAPI = "https://management.azure.com/tenants?api-version=2020-01-01";
|
||||
|
||||
public AzureManagementAuthenticationProvider(TokenCredential tokenCredentials)
|
||||
{
|
||||
_tokenCredentials = tokenCredentials;
|
||||
_initialScopes = new string[] { AzureManagementAPIDefault };
|
||||
}
|
||||
|
||||
private async Task<HttpRequestMessage> AuthenticateRequestAsync(HttpRequestMessage request)
|
||||
{
|
||||
HttpRequestMessage authenticatedRequest = request;
|
||||
TokenRequestContext context = new TokenRequestContext(_initialScopes);
|
||||
AccessToken token = await _tokenCredentials.GetTokenAsync(context, CancellationToken.None);
|
||||
authenticatedRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
|
||||
return authenticatedRequest;
|
||||
}
|
||||
|
||||
public async Task<string> ListTenantsAsync()
|
||||
{
|
||||
string content = string.Empty;
|
||||
var httpRequest = new HttpRequestMessage()
|
||||
{
|
||||
RequestUri = new Uri(AzureManagementTenantsAPI),
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
|
||||
httpRequest = await AuthenticateRequestAsync(httpRequest);
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var task = await client.SendAsync(httpRequest)
|
||||
.ContinueWith(async (taskWithMssg) =>
|
||||
{
|
||||
var response = taskWithMssg.Result;
|
||||
response.EnsureSuccessStatusCode();
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
content = await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
});
|
||||
await task;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.DotNet.MsIdentity.DeveloperCredentials
|
||||
{
|
||||
public interface IAzureManagementAuthenticationProvider
|
||||
{
|
||||
Task<string> ListTenantsAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace Microsoft.DotNet.MsIdentity.MicrosoftIdentityPlatformApplication
|
||||
{
|
||||
internal class TenantInformation
|
||||
{
|
||||
public string? TenantId { get; set; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? DefaultDomain { get; set; }
|
||||
public string? TenantType { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.DotNet.MsIdentity.UnitTests.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("dotnet-msidentity, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
|
@ -4,9 +4,10 @@ namespace Microsoft.DotNet.MsIdentity
|
|||
{
|
||||
public const string LIST_AAD_APPS_COMMAND = "--list-aad-apps";
|
||||
public const string LIST_SERVICE_PRINCIPALS_COMMAND = "--list-service-principals";
|
||||
public const string LIST_TENANTS_COMMAND = "--list-tenants";
|
||||
public const string REGISTER_APPLICATIION_COMMAND = "--register-application";
|
||||
public const string UPDATE_APPLICATION_COMMAND = "--update-application";
|
||||
public const string UNREGISTER_COMMAND = "--unregister";
|
||||
public const string VALIDATE_APP_PARAMS_COMMAND = "--validate-app-params";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,61 +6,66 @@ using System.Linq;
|
|||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Graph;
|
||||
using Microsoft.DotNet.MsIdentity;
|
||||
using Microsoft.DotNet.MsIdentity.AuthenticationParameters;
|
||||
using Microsoft.DotNet.MsIdentity.DeveloperCredentials;
|
||||
using Microsoft.DotNet.MsIdentity.MicrosoftIdentityPlatformApplication;
|
||||
|
||||
namespace Microsoft.DotNet.MsIdentity
|
||||
{
|
||||
public class MsAADTool : IMsAADTool
|
||||
internal class MsAADTool : IMsAADTool
|
||||
{
|
||||
private ProvisioningToolOptions ProvisioningToolOptions { get; set; }
|
||||
private string _commandName { get; set; }
|
||||
private GraphServiceClient _graphServiceClient;
|
||||
private MsalTokenCredential _tokenCredential;
|
||||
public IGraphServiceClient GraphServiceClient { get; set; }
|
||||
public IAzureManagementAuthenticationProvider AzureManagementAPI { get; set;}
|
||||
private MsalTokenCredential TokenCredential { get; set; }
|
||||
|
||||
public MsAADTool(string commandName, ProvisioningToolOptions provisioningToolOptions)
|
||||
{
|
||||
ProvisioningToolOptions = provisioningToolOptions;
|
||||
_commandName = commandName;
|
||||
_tokenCredential = new MsalTokenCredential(provisioningToolOptions.TenantId, provisioningToolOptions.Username);
|
||||
_graphServiceClient = new GraphServiceClient(new TokenCredentialAuthenticationProvider(_tokenCredential));
|
||||
TokenCredential = new MsalTokenCredential(ProvisioningToolOptions.TenantId, ProvisioningToolOptions.Username);
|
||||
GraphServiceClient = new GraphServiceClient(new TokenCredentialAuthenticationProvider(TokenCredential));
|
||||
AzureManagementAPI = new AzureManagementAuthenticationProvider(TokenCredential);
|
||||
}
|
||||
|
||||
public async Task<ApplicationParameters?> Run()
|
||||
{
|
||||
if (_tokenCredential != null && _graphServiceClient != null)
|
||||
string outputJsonString = string.Empty;
|
||||
if (TokenCredential != null && GraphServiceClient != null)
|
||||
{
|
||||
var graphObjects = await _graphServiceClient.Me.OwnedObjects
|
||||
.Request()
|
||||
.GetAsync();
|
||||
|
||||
if (graphObjects.Any())
|
||||
switch(_commandName)
|
||||
{
|
||||
switch(_commandName)
|
||||
{
|
||||
//--list-aad-apps
|
||||
case Commands.LIST_AAD_APPS_COMMAND:
|
||||
PrintApplicationsList(graphObjects.ToList(), ProvisioningToolOptions.Json ?? false);
|
||||
break;
|
||||
//--list-service-principals
|
||||
case Commands.LIST_SERVICE_PRINCIPALS_COMMAND:
|
||||
PrintServicePrincipalList(graphObjects.ToList(), ProvisioningToolOptions.Json ?? false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//--list-aad-apps
|
||||
case Commands.LIST_AAD_APPS_COMMAND:
|
||||
outputJsonString = await PrintApplicationsList();
|
||||
break;
|
||||
//--list-service-principals
|
||||
case Commands.LIST_SERVICE_PRINCIPALS_COMMAND:
|
||||
outputJsonString = await PrintServicePrincipalList();
|
||||
break;
|
||||
//list-tenants
|
||||
case Commands.LIST_TENANTS_COMMAND:
|
||||
outputJsonString = await PrintTenantsList();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ProvisioningToolOptions.Json.HasValue && ProvisioningToolOptions.Json.Value)
|
||||
{
|
||||
Console.WriteLine(outputJsonString);
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void PrintApplicationsList(IList<DirectoryObject> graphObjects, bool outputJson)
|
||||
internal async Task<string> PrintApplicationsList()
|
||||
{
|
||||
string outputJsonString = string.Empty;
|
||||
var graphObjects = await GraphServiceClient.Me.OwnedObjects
|
||||
.Request()
|
||||
.GetAsync();
|
||||
IList<Application> applicationList = new List<Application>();
|
||||
if (graphObjects != null)
|
||||
if (graphObjects != null && graphObjects.Any())
|
||||
{
|
||||
foreach (var graphObj in graphObjects)
|
||||
{
|
||||
|
@ -74,11 +79,9 @@ namespace Microsoft.DotNet.MsIdentity
|
|||
|
||||
if (applicationList.Any())
|
||||
{
|
||||
if (outputJson)
|
||||
if (ProvisioningToolOptions.Json.HasValue && ProvisioningToolOptions.Json.Value)
|
||||
{
|
||||
string outputString = JsonSerializer.Serialize(applicationList);
|
||||
Console.WriteLine(outputString);
|
||||
}
|
||||
outputJsonString = JsonSerializer.Serialize(applicationList); }
|
||||
else
|
||||
{
|
||||
Console.Write(
|
||||
|
@ -92,12 +95,17 @@ namespace Microsoft.DotNet.MsIdentity
|
|||
}
|
||||
}
|
||||
}
|
||||
return outputJsonString;
|
||||
}
|
||||
|
||||
private void PrintServicePrincipalList(IList<DirectoryObject> graphObjects, bool outputJson)
|
||||
internal async Task<string> PrintServicePrincipalList()
|
||||
{
|
||||
string outputJsonString = string.Empty;
|
||||
IList<ServicePrincipal> servicePrincipalList = new List<ServicePrincipal>();
|
||||
if (graphObjects != null)
|
||||
var graphObjects = await GraphServiceClient.Me.OwnedObjects
|
||||
.Request()
|
||||
.GetAsync();
|
||||
if (graphObjects != null && graphObjects.Any())
|
||||
{
|
||||
foreach (var graphObj in graphObjects)
|
||||
{
|
||||
|
@ -106,13 +114,11 @@ namespace Microsoft.DotNet.MsIdentity
|
|||
servicePrincipalList.Add(servicePrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
string outputString = string.Empty;
|
||||
if (servicePrincipalList.Any())
|
||||
{
|
||||
if (outputJson)
|
||||
if (ProvisioningToolOptions.Json.HasValue && ProvisioningToolOptions.Json.Value)
|
||||
{
|
||||
outputString = JsonSerializer.Serialize(servicePrincipalList);
|
||||
outputJsonString = JsonSerializer.Serialize(servicePrincipalList);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -125,10 +131,66 @@ namespace Microsoft.DotNet.MsIdentity
|
|||
Console.WriteLine($"{app.DisplayName.PadRight(35)}\t\t{app.AppId}");
|
||||
}
|
||||
}
|
||||
//TODO do we need an else scenario where we list Service Principals for the command line experience.
|
||||
}
|
||||
Console.WriteLine(outputString);
|
||||
}
|
||||
return outputJsonString;
|
||||
}
|
||||
|
||||
internal async Task<string> PrintTenantsList()
|
||||
{
|
||||
string outputJsonString = string.Empty;
|
||||
IList<TenantInformation> tenantList = new List<TenantInformation>();
|
||||
if (AzureManagementAPI != null)
|
||||
{
|
||||
var tenantsJsonString = await AzureManagementAPI.ListTenantsAsync();
|
||||
if (!string.IsNullOrEmpty(tenantsJsonString))
|
||||
{
|
||||
using (JsonDocument document = JsonDocument.Parse(tenantsJsonString))
|
||||
{
|
||||
if (document.RootElement.TryGetProperty("value", out JsonElement jsonTenantElement))
|
||||
{
|
||||
var jsonTenantEnumerator = jsonTenantElement.EnumerateArray();
|
||||
if (jsonTenantEnumerator.Any())
|
||||
{
|
||||
while (jsonTenantEnumerator.MoveNext())
|
||||
{
|
||||
JsonElement current = jsonTenantEnumerator.Current;
|
||||
string? tenantId = current.GetProperty("tenantId").GetString();
|
||||
string? tenantType = current.GetProperty("tenantType").GetString();
|
||||
string? defaultDomain = current.GetProperty("defaultDomain").GetString();
|
||||
string? displayName = current.GetProperty("displayName").GetString();
|
||||
|
||||
tenantList.Add(
|
||||
new TenantInformation()
|
||||
{
|
||||
TenantId = tenantId,
|
||||
TenantType = tenantType,
|
||||
DefaultDomain = defaultDomain,
|
||||
DisplayName = displayName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ProvisioningToolOptions.Json.HasValue && ProvisioningToolOptions.Json.Value)
|
||||
{
|
||||
outputJsonString = JsonSerializer.Serialize(tenantList);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write(
|
||||
"--------------------------------------------------------------------------------------------------------------------------------\n" +
|
||||
"Display Name\t\t\tDefault Domain\t\t\t\tTenant Type\tTenant Id\n" +
|
||||
"--------------------------------------------------------------------------------------------------------------------------------\n\n");
|
||||
foreach(var tenant in tenantList)
|
||||
{
|
||||
Console.WriteLine($"{(tenant.DisplayName ?? string.Empty).PadRight(16)}\t\t{(tenant.DefaultDomain ?? string.Empty).PadRight(20)}\t\t{(tenant.TenantType ?? string.Empty).PadRight(10)}\t{(tenant.TenantId ?? string.Empty)}");
|
||||
}
|
||||
}
|
||||
return outputJsonString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,14 @@ Usage:
|
|||
dotnet-msidentity [command] [options]
|
||||
|
||||
Commands:
|
||||
--list--aad-apps Lists AAD Applications for a given tenant/username.
|
||||
--list-service-principals Lists AAD Service Principals.
|
||||
--register-application Registers/unregisters/updates an AAD/AAD B2C Application in Azure.
|
||||
- Updates the appsettings.json file.
|
||||
|
||||
Internal Commands (These commands have little do with registering AAD/AAD B2C apps but are nice helpers):
|
||||
--list--aad-apps Lists AAD Applications for a given tenant + username.
|
||||
--list-service-principals Lists AAD Service Principals for a given tenant + username.
|
||||
--list-tenants Lists AAD + AAD B2C tenants for a given username.
|
||||
|
||||
Options:
|
||||
--tenant-id <tenant-id> Azure AD or Azure AD B2C tenant in which to create/update the app.
|
||||
- If specified, the tool will create the application in the specified tenant.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<Project>
|
||||
<Import Project="..\..\Directory.Build.props" />
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DeveloperBuildTestTfms>net5.0</DeveloperBuildTestTfms>
|
|
@ -1,5 +1,5 @@
|
|||
<Project>
|
||||
<Import Project="..\..\Directory.Build.targets" />
|
||||
<Import Project="..\Directory.Build.targets" />
|
||||
|
||||
<PropertyGroup>
|
||||
<GeneratedTestProjectFile>$(IntermediateOutputPath)MSBuildProjectStrings.cs</GeneratedTestProjectFile>
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)src\MsIdentityScaffolding\Microsoft.DotNet.MsIdentity\Microsoft.DotNet.MsIdentity.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,59 @@
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.DotNet.MsIdentity.DeveloperCredentials;
|
||||
using Microsoft.DotNet.MsIdentity.MicrosoftIdentityPlatformApplication;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.DotNet.MsIdentity.UnitTests.Tests
|
||||
{
|
||||
public class MsAADToolTests
|
||||
{
|
||||
string tenantsJson =
|
||||
"{\"value\":[" +
|
||||
"{ \"id\":\"/tenants/AAAAAA-bbbbbb-CCCCCC-dddd-EEEEEEEE\",\"tenantId\":\"AAAAAA-bbbbbb-CCCCCC-dddd-EEEEEEEE\",\"countryCode\":\"US\",\"displayName\":\"NET AAD App\",\"domains\":[\"netaadapp.onmicrosoft.com\"],\"tenantCategory\":\"Home\",\"defaultDomain\":\"netaadapp.onmicrosoft.com\",\"tenantType\":\"AAD\"}," +
|
||||
"{ \"id\":\"/tenants/EEEEEE-dddddd-CCCCCC-bbbb-AAAAAAAA\",\"tenantId\":\"EEEEEE-dddddd-CCCCCC-bbbb-AAAAAAAA\",\"countryCode\":\"US\",\"displayName\":\"NET AAD B2C App\",\"domains\":[\"netaadb2capp.onmicrosoft.com\"],\"tenantCategory\":\"Home\",\"defaultDomain\":\"netaadb2capp.onmicrosoft.com\",\"tenantType\":\"AAD B2C\"}]}";
|
||||
|
||||
public static ProvisioningToolOptions ToolOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ProvisioningToolOptions
|
||||
{
|
||||
TenantId = "abcdefg",
|
||||
Username = "testUser",
|
||||
Json = true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void TestPrintTenantsList()
|
||||
{
|
||||
string path = Assembly.GetExecutingAssembly().Location;
|
||||
MsAADTool jsonTenantTool = new MsAADTool(Commands.LIST_TENANTS_COMMAND, ToolOptions);
|
||||
Mock<IAzureManagementAuthenticationProvider> azureMngProviderMock = new Mock<IAzureManagementAuthenticationProvider>();
|
||||
azureMngProviderMock.Setup(_ => _.ListTenantsAsync()).Returns(Task.FromResult(tenantsJson));
|
||||
jsonTenantTool.AzureManagementAPI = azureMngProviderMock.Object;
|
||||
string tenantsJsonFormatted = await jsonTenantTool.PrintTenantsList();
|
||||
if (string.IsNullOrEmpty(tenantsJsonFormatted))
|
||||
{
|
||||
Assert.True(false, "Formatting tenants from Azure Management failed");
|
||||
}
|
||||
var tenantJsonList = JsonSerializer.Deserialize<TenantInformation[]>(tenantsJsonFormatted);
|
||||
Assert.True(tenantJsonList.Any());
|
||||
Assert.True(tenantJsonList.Length == 2);
|
||||
var aadApp = tenantJsonList.Where(x => x.DisplayName.Equals("NET AAD App")).FirstOrDefault();
|
||||
var aadB2CApp = tenantJsonList.Where(x => x.DisplayName.Equals("NET AAD B2C App")).FirstOrDefault();
|
||||
Assert.True(aadApp != null && aadB2CApp != null);
|
||||
|
||||
Assert.True(aadApp.TenantType.Equals("AAD"));
|
||||
Assert.True(!string.IsNullOrEmpty(aadApp.TenantId));
|
||||
|
||||
Assert.True(aadB2CApp.TenantType.Equals("AAD B2C"));
|
||||
Assert.True(!string.IsNullOrEmpty(aadB2CApp.TenantId));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.DotNet.MsIdentity;
|
||||
|
||||
namespace Microsoft.DotNet.MsIdentity.Tool
|
||||
{
|
||||
internal static class MsAADToolFactory
|
||||
|
@ -13,6 +8,7 @@ namespace Microsoft.DotNet.MsIdentity.Tool
|
|||
{
|
||||
case Commands.LIST_AAD_APPS_COMMAND:
|
||||
case Commands.LIST_SERVICE_PRINCIPALS_COMMAND:
|
||||
case Commands.LIST_TENANTS_COMMAND:
|
||||
return new MsAADTool(commandName, provisioningToolOptions);
|
||||
default:
|
||||
return new AppProvisioningTool(provisioningToolOptions);
|
||||
|
|
|
@ -15,14 +15,26 @@ namespace Microsoft.DotNet.MsIdentity.Tool
|
|||
var rootCommand = MsIdentityCommand();
|
||||
var listAadAppsCommand = ListAADAppsCommand();
|
||||
var listServicePrincipalsCommand = ListServicePrincipalsCommand();
|
||||
var listTenantsCommand = ListTenantsCommand();
|
||||
var provisionApplicationCommand = ProvisionApplicationCommand();
|
||||
|
||||
//hide internal commands.
|
||||
listAadAppsCommand.IsHidden = true;
|
||||
listServicePrincipalsCommand.IsHidden = true;
|
||||
listTenantsCommand.IsHidden = true;
|
||||
|
||||
listAadAppsCommand.Handler = CommandHandler.Create<ProvisioningToolOptions>(HandleListApps);
|
||||
listServicePrincipalsCommand.Handler = CommandHandler.Create<ProvisioningToolOptions>(HandleListServicePrincipals);
|
||||
listTenantsCommand.Handler = CommandHandler.Create<ProvisioningToolOptions>(HandleListTenants);
|
||||
provisionApplicationCommand.Handler = CommandHandler.Create<ProvisioningToolOptions>(HandleProvisionApplication);
|
||||
|
||||
//add all commands to root command.
|
||||
rootCommand.AddCommand(listAadAppsCommand);
|
||||
rootCommand.AddCommand(listServicePrincipalsCommand);
|
||||
rootCommand.AddCommand(listTenantsCommand);
|
||||
rootCommand.AddCommand(provisionApplicationCommand);
|
||||
|
||||
//if no args are present, show default help.
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
args = new string[] { "-h" };
|
||||
|
@ -46,6 +58,17 @@ namespace Microsoft.DotNet.MsIdentity.Tool
|
|||
return -1;
|
||||
}
|
||||
|
||||
private static async Task<int> HandleListTenants(ProvisioningToolOptions provisioningToolOptions)
|
||||
{
|
||||
if (provisioningToolOptions != null)
|
||||
{
|
||||
IMsAADTool msAADTool = MsAADToolFactory.CreateTool(Commands.LIST_TENANTS_COMMAND, provisioningToolOptions);
|
||||
await msAADTool.Run();
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static async Task<int> HandleListServicePrincipals(ProvisioningToolOptions provisioningToolOptions)
|
||||
{
|
||||
if (provisioningToolOptions != null)
|
||||
|
@ -90,6 +113,14 @@ namespace Microsoft.DotNet.MsIdentity.Tool
|
|||
TenantOption(), UsernameOption(), JsonOption(), ProjectPathOption()
|
||||
};
|
||||
|
||||
private static Command ListTenantsCommand()=>
|
||||
new Command(
|
||||
name: Commands.LIST_TENANTS_COMMAND,
|
||||
description: "Lists AAD and AAD B2C tenants for a given user.")
|
||||
{
|
||||
UsernameOption(), JsonOption()
|
||||
};
|
||||
|
||||
private static Command ProvisionApplicationCommand()=>
|
||||
new Command(
|
||||
name: Commands.REGISTER_APPLICATIION_COMMAND,
|
||||
|
@ -176,10 +207,10 @@ namespace Microsoft.DotNet.MsIdentity.Tool
|
|||
new Option<string>(
|
||||
aliases: new[] {"-u", "--username"},
|
||||
description:"Username to use to connect to the Azure AD or Azure AD B2C tenant." +
|
||||
"\n\t- It's only needed when you are signed-in in Visual Studio, or Azure CLI with several identities." +
|
||||
"\n\t- In that case, the username param is used to disambiguate which identity to use to create the app in the tenant.")
|
||||
{
|
||||
IsRequired = false
|
||||
};
|
||||
"\n- It's only needed when you are signed-in in Visual Studio, or Azure CLI with several identities." +
|
||||
"\n- In that case, the username param is used to disambiguate which identity to use to create the app in the tenant.")
|
||||
{
|
||||
IsRequired = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче