* Enable app token auth

* Read partner tenant id from config

* Update readme

* Fix dup issue with export
This commit is contained in:
harshabacharaju 2023-03-16 13:52:10 -07:00 коммит произвёл GitHub
Родитель ecdae11638
Коммит 3a44c23afd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 128 добавлений и 56 удалений

Просмотреть файл

@ -33,4 +33,9 @@ internal record AppSettings
return this.Upn[++index..];
}
}
/// <summary>
/// Gets or sets a flag indicating whether to use app only token.
/// </summary>
public bool UseAppToken { get; set; }
}

Просмотреть файл

@ -22,6 +22,9 @@
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Просмотреть файл

@ -141,7 +141,7 @@ internal class NewCommerceMigrationProvider : INewCommerceMigrationProvider
var inputBaseMigrationRequests = inputMigrations.Where(m => !m.AddOn);
var inputAddOnMigrationRequests = inputMigrations.Where(m => m.AddOn);
var baseSubscriptionIds = inputBaseMigrationRequests.Select(b => b.LegacySubscriptionId).ToList();
var baseSubscriptionIds = inputMigrations.Select(b => b.LegacySubscriptionId).ToList();
var addOnsWithoutBase = inputAddOnMigrationRequests.Where(a => !baseSubscriptionIds.Contains(a.BaseSubscriptionId));

Просмотреть файл

@ -5,33 +5,40 @@
// -----------------------------------------------------------------------
Console.WriteLine("Welcome to NCE Bulk Migration Tool!");
string? appId;
string? upn;
string? appId = null;
string? upn = null;
if (args.Length == 2)
{
appId = args[0];
upn = args[1];
}
else
{
AppId:
Console.WriteLine("Enter AppId");
appId = Console.ReadLine();
var configurationManager = new ConfigurationManager();
configurationManager.AddJsonFile("appsettings.json");
var useAppToken = configurationManager.GetValue<bool>("useAppToken");
if (string.IsNullOrWhiteSpace(appId) || !Guid.TryParse(appId, out _))
if (!useAppToken)
{
if (args.Length == 2)
{
Console.WriteLine("Invalid input, Please try again!");
goto AppId;
appId = args[0];
upn = args[1];
}
Upn:
Console.WriteLine("Enter Upn");
upn = Console.ReadLine();
if (string.IsNullOrWhiteSpace(upn))
else
{
Console.WriteLine("Invalid input, Please try again!");
goto Upn;
AppId:
Console.WriteLine("Enter AppId");
appId = Console.ReadLine();
if (string.IsNullOrWhiteSpace(appId) || !Guid.TryParse(appId, out _))
{
Console.WriteLine("Invalid input, Please try again!");
goto AppId;
}
Upn:
Console.WriteLine("Enter Upn");
upn = Console.ReadLine();
if (string.IsNullOrWhiteSpace(upn))
{
Console.WriteLine("Invalid input, Please try again!");
goto Upn;
}
}
}
@ -39,11 +46,37 @@ var appSettings = new AppSettings()
{
AppId = appId,
Upn = upn,
UseAppToken = useAppToken
};
bool stopExecution = false;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((services) =>
.ConfigureAppConfiguration(c => c.AddJsonFile("appsettings.json"))
.ConfigureServices((hostBuilder, services) =>
{
var config = hostBuilder.Configuration;
if (appSettings.UseAppToken)
{
if (string.IsNullOrWhiteSpace(config.GetValue<string>("clientId")))
{
Console.WriteLine("Please provide clientId in the appsettings file.");
stopExecution = true;
}
if (string.IsNullOrWhiteSpace(config.GetValue<string>("clientSecret")))
{
Console.WriteLine("Please provide clientSecret in the appsettings file.");
stopExecution = true;
}
if (string.IsNullOrWhiteSpace(config.GetValue<string>("tenantId")))
{
Console.WriteLine("Please provide tenantId in the appsettings file.");
stopExecution = true;
}
}
services.AddSingleton(appSettings);
services.AddSingleton<ITokenProvider, TokenProvider>();
services.AddSingleton<ICustomerProvider, CustomerProvider>();
@ -52,6 +85,12 @@ using IHost host = Host.CreateDefaultBuilder(args)
services.AddSingleton<INewCommerceMigrationScheduleProvider, NewCommerceMigrationScheduleProvider>();
}).Build();
if (stopExecution)
{
await host.StopAsync();
Environment.Exit(Environment.ExitCode);
}
await RunAsync(host.Services);
await host.RunAsync();

Просмотреть файл

@ -14,15 +14,17 @@ internal class SubscriptionProvider : ISubscriptionProvider
private static string partnerTenantId = string.Empty;
private readonly ITokenProvider tokenProvider;
private readonly IConfiguration configuration;
private long subscriptionsCntr = 0;
/// <summary>
/// SubscriptionProvider constructor.
/// </summary>
/// <param name="tokenProvider"></param>
public SubscriptionProvider(ITokenProvider tokenProvider)
public SubscriptionProvider(ITokenProvider tokenProvider, IConfiguration configuration)
{
this.tokenProvider = tokenProvider;
this.configuration = configuration;
}
/// <inheritdoc/>
@ -38,7 +40,7 @@ internal class SubscriptionProvider : ISubscriptionProvider
var failedCustomersBag = new ConcurrentBag<CompanyProfile>();
var authenticationResult = await this.tokenProvider.GetTokenAsync();
partnerTenantId = authenticationResult.TenantId;
partnerTenantId = authenticationResult.TenantId ?? this.configuration.GetValue<string>("tenantId");
var httpClient = new HttpClient
{
@ -99,7 +101,7 @@ internal class SubscriptionProvider : ISubscriptionProvider
var failedCustomersBag = new ConcurrentBag<CompanyProfile>();
var authenticationResult = await this.tokenProvider.GetTokenAsync();
partnerTenantId = authenticationResult.TenantId;
partnerTenantId = authenticationResult.TenantId ?? this.configuration.GetValue<string>("tenantId");
var httpClient = new HttpClient
{

Просмотреть файл

@ -15,12 +15,14 @@ internal class TokenProvider : ITokenProvider
/// TokenProvider constructor.
/// </summary>
/// <param name="appSettings">The app settings.</param>
public TokenProvider(AppSettings appSettings)
public TokenProvider(AppSettings appSettings, IConfiguration configuration)
{
this.appSettings = appSettings;
this.configuration = configuration;
}
private readonly AppSettings appSettings;
private readonly IConfiguration configuration;
private AuthenticationResult? authenticationResult;
/// <inheritdoc/>
@ -31,42 +33,57 @@ internal class TokenProvider : ITokenProvider
return authenticationResult;
}
var scopes = new string[] { $"https://api.partnercenter.microsoft.com/.default" };
var app = PublicClientApplicationBuilder.Create(this.appSettings.AppId)
.WithAuthority("https://login.microsoftonline.com", this.appSettings.Domain, true)
.WithRedirectUri("http://localhost")
.Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
if (appSettings.UseAppToken)
{
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
.ExecuteAsync();
var authenticationBuilder = ConfidentialClientApplicationBuilder.Create($"{this.configuration.GetValue<string>("clientId")}")
.WithAuthority($"https://login.microsoftonline.com/{this.configuration.GetValue<string>("tenantId")}")
.WithClientSecret($"{this.configuration.GetValue<string>("clientSecret")}")
.Build();
var scopes = new List<string> { $"https://graph.windows.net/.default" };
authenticationResult = await authenticationBuilder.AcquireTokenForClient(scopes)
.ExecuteAsync();
return authenticationResult;
}
catch (MsalUiRequiredException)
else
{
var scopes = new string[] { $"https://api.partnercenter.microsoft.com/.default" };
var app = PublicClientApplicationBuilder.Create(this.appSettings.AppId)
.WithAuthority("https://login.microsoftonline.com", this.appSettings.Domain, true)
.WithRedirectUri("http://localhost")
.Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
result = await app.AcquireTokenInteractive(scopes)
.WithLoginHint(this.appSettings.Upn)
.WithPrompt(Prompt.NoPrompt)
.ExecuteAsync();
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
.ExecuteAsync();
}
catch (MsalException msalex)
catch (MsalUiRequiredException)
{
throw msalex;
try
{
result = await app.AcquireTokenInteractive(scopes)
.WithLoginHint(this.appSettings.Upn)
.WithPrompt(Prompt.NoPrompt)
.ExecuteAsync();
}
catch (MsalException msalex)
{
throw msalex;
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception while generating token {ex}");
throw;
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception while generating token {ex}");
throw;
}
authenticationResult = result;
authenticationResult = result;
return result;
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
{
"useAppToken": false,
"clientId": "",
"clientSecret": "",
"tenantId": ""
}

Просмотреть файл

@ -58,7 +58,7 @@ Note that steps six through nine are only for scheduled migrations.
## Prerequisites
* In order to build and run the BAM tool, .NET 6.0 SDK is required.
* AAD AppId that is onboarded to access Partner Center Apis. The batch migration (BAM) tool is not configured for multitenant apps. When registering the App please use single tenant app.
* AAD AppId that is onboarded to access Partner Center Apis.
* Follow the below steps to create an app if not already exists.
1. Login to Partner Center and navigate to Account Settings.
2. Select App Management and then select “Native App” tab.