SamplesV1/ADFSecurePublish/SecurePublishForm/MainWindow.xaml.cs (291 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.ADF.Deployment.AdfKeyVaultDeployment;
using Microsoft.ADF.Deployment.AdfKeyVaultDeployment.Models;
using Newtonsoft.Json;
using Path = System.IO.Path;
namespace SecurePublishForm
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, ILogger
{
private SettingsContextManager settingsContextManager;
private List<DataFactoryInfo> dataFactoryList;
private string environment;
private string dataFactory;
private string projName;
private PublishManager publishManager;
private AppSettings settings;
public string ControlVisiblity { get; set; }
private string enterSettingsMsg = "Please close this form and enter the settings through Tools -> Options -> Data Factory -> Secure Publish";
public MainWindow(string projName)
{
this.projName = projName;
InitializeComponent();
dataFactoryListBox.IsEnabled = false;
publishButton.IsEnabled = false;
LoadSettings();
this.DataContext = this;
}
private void LoadSettings()
{
string settingsFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"SecurePublishSettings.json");
if (File.Exists(settingsFile))
{
try
{
settings = JsonConvert.DeserializeObject<AppSettings>(File.ReadAllText(settingsFile));
ControlVisiblity = "Visible";
noSettings.Visibility = Visibility.Hidden;
}
catch
{
ShowNoSettings();
string backUpFile = Path.Combine(Path.GetDirectoryName(settingsFile),
Path.GetFileNameWithoutExtension(settingsFile) + "_BackUp.json");
File.Move(settingsFile, backUpFile);
noSettings.Content =
$"There was a problem reading your user settings. The user settings file is corrupted.\r\nA backup has been saved to {backUpFile}. Please re-enter them again.\r\n" +
enterSettingsMsg;
return;
}
List<string> validationErrors = ValidateSettings();
if (validationErrors.Any())
{
ShowNoSettings();
noSettings.Content =
$"There was a problem reading your user settings.\r\n{string.Join("\r\n", validationErrors)}\r\n{enterSettingsMsg}";
return;
}
settingsContextManager = new SettingsContextManager(settings);
subscriptionList.ItemsSource = settings.Subscriptions.Select(x => x.FriendlyName).ToList();
subscriptionList.SelectedIndex = 0;
}
else
{
ShowNoSettings();
noSettings.Content = "No user settings were found. " + enterSettingsMsg;
}
}
private List<string> ValidateSettings()
{
var validationErrors = new List<string>();
if (settings.Subscriptions == null || !settings.Subscriptions.Any())
{
validationErrors.Add("No subscriptions were found.");
}
if (settings.EnvironmentSettings == null || !settings.EnvironmentSettings.Any())
{
validationErrors.Add("No environments were found.");
}
if (string.IsNullOrEmpty(settings.AdfClientId))
{
validationErrors.Add("The ADF AAD Client ID setting is empty.");
}
if (string.IsNullOrEmpty(settings.KeyVaultCertClientId))
{
validationErrors.Add("The KeyVault Certificate Client ID setting is empty.");
}
if (string.IsNullOrEmpty(settings.AzureTenantId))
{
validationErrors.Add("The Azure Tenant ID setting is empty.");
}
if (string.IsNullOrEmpty(settings.KeyVaultCertThumbprint))
{
validationErrors.Add("The KeyVault Certificate Thumbprint setting is empty.");
}
return validationErrors;
}
private void ShowNoSettings()
{
noSettings.Visibility = Visibility.Visible;
ControlVisiblity = "Hidden";
}
private async void subscriptionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
publishButton.IsEnabled = false;
environmentList.ItemsSource = settings.EnvironmentSettings.Select(x => x.Name);
if (environmentList.SelectedIndex == 0)
{
await RefreshDatafactories();
}
else
{
environmentList.SelectedIndex = 0;
}
}
private async void environmentList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
await RefreshDatafactories();
}
private async Task RefreshDatafactories()
{
SettingsContext settingsContext;
environment = environmentList.SelectedItem as string;
try
{
settingsContext = settingsContextManager.GetSettingsContext(environment);
// Get KeyVault resolver which is used to retreive keyvault secrets based on environment context
IKeyVaultResolver keyVault;
if (!string.IsNullOrEmpty(settingsContext.KeyVaultCertificateThumbprint))
{
var cert = KeyVaultResolver.FindCertificateByThumbprint(settingsContext.KeyVaultCertificateThumbprint);
if (cert == null)
{
Write($"No cert was found using thumbprint {settingsContext.KeyVaultCertificateThumbprint}", "Red");
return;
}
keyVault = new KeyVaultResolver(settingsContext.KeyVaultName, settingsContext.KeyVaultDnsSuffix, settingsContext.KeyVaultCertClientId, cert);
}
else
{
keyVault = new KeyVaultResolver(settingsContext.KeyVaultName, settingsContext.KeyVaultDnsSuffix, settingsContext.KeyVaultCertClientId, settingsContext.KeyVaultCertClientSecret);
}
settingsContext.SubscriptionId = settings.Subscriptions[subscriptionList.SelectedIndex].Id;
try
{
settingsContext.AdfClientSecret = (await keyVault.GetSecret("SecurePublishAdfClientSecret")).Value;
}
catch (Exception ex)
{
Write($"The secret called SecurePublishAdfClientSecret was not found in the KeyVault '{settingsContext.KeyVaultName}'. The ADF Client Secret is a password which was associated with the AAD Client ID '{settingsContext.KeyVaultCertClientId}' when it was originally set up. If you are setting up a new KeyVault and a previous KeyVault has already been used, you can get this value from the previous KeyVault. Otherwise refer to the user documentation on creating a new client ID and associating it with your Azure subscription.", "Red");
WriteError(ex);
return;
}
publishManager = new PublishManager(keyVault, settingsContext, this);
dataFactoryList = await AzureAccessUtilities.GetDataFactories(settingsContext);
}
catch (Exception e)
{
Write(e.Message, "Red");
Dispatcher.Invoke(() =>
{
dataFactoryListBox.IsEnabled = false;
});
return;
}
if (!dataFactoryList.Any())
{
Write("No data factories found in subscription: " + settingsContext.SubscriptionId, "Orange");
Write($"They either do not exist or else you may need to associate the Client ID '{settingsContext.AdfClientId}' with the subscription. To do that, perform the following steps:", "Orange");
Write("1. Open up PowerShell", "Orange");
Write("2. Log in to Azure by typing in the cmd: Login-AzureRmAccount", "Orange");
Write($"3. Change to the subscription you wish to use by typing the cmd: Select-AzureRmSubscription -SubscriptionId '{settingsContext.SubscriptionId}'", "Orange");
Write("4. Associate the Client ID with the Data Factory Contributer role in the current subscription by typing:", "Orange");
Write($"New-AzureRmRoleAssignment -RoleDefinitionName 'Data Factory Contributor' -ServicePrincipalName '{settingsContext.AdfClientId}'", "Orange");
Dispatcher.Invoke(() =>
{
dataFactoryListBox.IsEnabled = false;
});
}
else
{
Dispatcher.Invoke(() =>
{
dataFactoryListBox.IsEnabled = true;
});
}
Dispatcher.Invoke(() =>
{
dataFactoryListBox.ItemsSource = dataFactoryList.Select(x => x.Name);
});
}
private void dataFactoryListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
publishButton.IsEnabled = true;
dataFactory = dataFactoryListBox.SelectedItem as string;
}
private void cancelButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
private async void publishButton_Click(object sender, RoutedEventArgs e)
{
try
{
publishButton.IsEnabled = false;
Write("Starting Secure Publish", "Black");
Write(string.Empty);
DataFactoryInfo choosenDataFactory = dataFactoryList.Single(x => x.Name == dataFactory);
await publishManager.BuildAndSecurePublish(projName, choosenDataFactory);
}
catch (Exception ex)
{
Write("An error occurred: " + ex.Message, "Red");
WriteError(ex);
}
publishButton.IsEnabled = true;
}
public void WriteError(Exception exception)
{
try
{
using (EventLog eventLog = new EventLog("Application"))
{
eventLog.Source = "Secure Publish";
eventLog.WriteEntry(exception.ToString(), EventLogEntryType.Error);
}
}
catch
{
// Output to the form if there was a problem accessing the event log
Write(exception.ToString(), "Red");
}
}
public void Write(string format, params object[] args)
{
Dispatcher.Invoke(() =>
{
if (args != null && args.Length == 1)
{
string color = (string)args[0];
BrushConverter bc = new BrushConverter();
TextRange tr = new TextRange(outputBox.Document.ContentEnd, outputBox.Document.ContentEnd)
{
Text = format
};
try
{
tr.ApplyPropertyValue(TextElement.ForegroundProperty, bc.ConvertFromString(color));
tr.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
}
catch (FormatException)
{
TextRange tr2 = new TextRange(outputBox.Document.ContentEnd, outputBox.Document.ContentEnd)
{
Text = format
};
tr2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
tr2.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
}
}
else
{
TextRange tr = new TextRange(outputBox.Document.ContentEnd, outputBox.Document.ContentEnd)
{
Text = format
};
tr.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
tr.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
}
outputBox.AppendText("\u2028"); // Linebreak, not paragraph break
outputBox.ScrollToEnd();
});
}
}
}