Skip to content

Commit

Permalink
Add access policy creation/deletion to vault viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
anthturner committed Jan 18, 2016
1 parent a7e2c86 commit 09966e2
Show file tree
Hide file tree
Showing 7 changed files with 336 additions and 9 deletions.
7 changes: 7 additions & 0 deletions AzureKeyVaultManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@
<Compile Include="BlankViewer.xaml.cs">
<DependentUpon>BlankViewer.xaml</DependentUpon>
</Compile>
<Compile Include="CreateAccessPolicy.xaml.cs">
<DependentUpon>CreateAccessPolicy.xaml</DependentUpon>
</Compile>
<Compile Include="CreateKey.xaml.cs">
<DependentUpon>CreateKey.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -209,6 +212,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="CreateAccessPolicy.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="CreateKey.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
36 changes: 36 additions & 0 deletions AzureServiceAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Azure;
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Microsoft.Azure.ActiveDirectory.GraphClient.Extensions;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Management.KeyVault;
using Microsoft.Azure.Management.Resources;
Expand Down Expand Up @@ -57,6 +59,40 @@ public KeyVaultClient CreateKeyVaultClient()
return new KeyVaultClient(GetKeyVaultAccessTokenCallback);
}

public async Task<List<IDirectoryObject>> GetAllDirectoryObjects(string searchString)
{
var objects = new List<IDirectoryObject>();
var tasks = new List<Task>();
tasks.Add(SearchServicePrincipals(searchString).ContinueWith(t => objects.AddRange(t.Result)));
tasks.Add(SearchUsers(searchString).ContinueWith(t => objects.AddRange(t.Result)));
await Task.WhenAll(tasks);
return objects;
}

private async Task<List<IServicePrincipal>> SearchServicePrincipals(string searchString)
{
var adClient = new ActiveDirectoryClient(new Uri(GraphAuthority), () => Task.FromResult(this.GetAuthenticationResult(Authority, GraphUri)?.AccessToken));
var initialPage = await adClient.ServicePrincipals.Where(p => p.DisplayName.StartsWith(searchString)).ExecuteAsync();
return await EnumeratePagedCollection(initialPage);
}

private async Task<List<IUser>> SearchUsers(string searchString)
{
var adClient = new ActiveDirectoryClient(new Uri(GraphAuthority), () => Task.FromResult(this.GetAuthenticationResult(Authority, GraphUri)?.AccessToken));
var initialPage = await adClient.Users.Where(p => p.DisplayName.StartsWith(searchString)).ExecuteAsync();
return await EnumeratePagedCollection(initialPage);
}

private async Task<List<T>> EnumeratePagedCollection<T>(IPagedCollection<T> collection, List<T> listSoFar = null)
{
if (listSoFar == null)
listSoFar = new List<T>();
listSoFar.AddRange(collection.CurrentPage);
if (collection.MorePagesAvailable)
await EnumeratePagedCollection<T>(await collection.GetNextPageAsync(), listSoFar);
return listSoFar;
}

public async Task<string> GetClientObjectId()
{
if (ClientAuthenticatedMode)
Expand Down
126 changes: 126 additions & 0 deletions CreateAccessPolicy.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<controls:MetroWindow x:Class="AzureKeyVaultManager.CreateAccessPolicy"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AzureKeyVaultManager"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
BorderBrush="{StaticResource AccentColorBrush}"
WindowStartupLocation="CenterOwner"
Title="Create Access Policy" Height="450" Width="400">
<Window.Resources>
<Style x:Key="defaultMessageStyle" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox Text="{Binding Text, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Enter Azure Active Directory 'Display Name' search"
Margin="5,0,5,0"
Foreground="#FF808080"
FontStyle="Italic"
IsHitTestVisible="False"
x:Name="UserMessage"
Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Text" Value=""/>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="UserMessage" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition MinHeight="100" Height="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="searchFilter" Style="{StaticResource defaultMessageStyle}" TextChanged="FilterTextChanged"></TextBox>
<ListBox Name="adObjects" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding ObjectType}" />
<TextBlock Grid.Column="2" Text="{Binding DisplayName}" />
<TextBlock Grid.Column="4" Text="{Binding ObjectId}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<GridSplitter Grid.Row="2" Height="10" ResizeDirection="Rows" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />

<StackPanel Orientation="Vertical" Grid.Row="3">
<GroupBox Header="Keys" Name="keyGroup">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding CanEncrypt}">Encrypt</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding CanDecrypt}">Decrypt</CheckBox>
<CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{Binding CanWrap}">Wrap</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="1" IsChecked="{Binding CanUnwrap}">Unwrap</CheckBox>
<CheckBox Grid.Row="0" Grid.Column="2" IsChecked="{Binding CanSign}">Sign</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="2" IsChecked="{Binding CanVerify}">Verify</CheckBox>

<CheckBox Grid.Row="2" Grid.Column="0" IsChecked="{Binding CanCreate}">Create</CheckBox>
<CheckBox Grid.Row="2" Grid.Column="1" IsChecked="{Binding CanUpdate}">Update</CheckBox>
<CheckBox Grid.Row="2" Grid.Column="2" IsChecked="{Binding CanDelete}">Delete</CheckBox>

<CheckBox Grid.Row="3" Grid.Column="0" IsChecked="{Binding CanBackup}">Backup</CheckBox>
<CheckBox Grid.Row="3" Grid.Column="1" IsChecked="{Binding CanRestore}">Restore</CheckBox>
<CheckBox Grid.Row="3" Grid.Column="2" IsChecked="{Binding CanImport}">Import</CheckBox>
</Grid>
</GroupBox>

<GroupBox Header="Secrets" Name="secretGroup">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding CanGet}">Get</CheckBox>
<CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{Binding CanList}">List</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding CanSet}">Set</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="1" IsChecked="{Binding CanDelete}">Delete</CheckBox>
</Grid>
</GroupBox>
<Button Width="120" Click="CreateClicked">Create</Button>
</StackPanel>
</Grid>
</controls:MetroWindow>
84 changes: 84 additions & 0 deletions CreateAccessPolicy.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using AzureKeyVaultManager.KeyVaultWrapper.Policies;
using MahApps.Metro.Controls;
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Application = Microsoft.Azure.ActiveDirectory.GraphClient.Application;

namespace AzureKeyVaultManager
{
/// <summary>
/// Interaction logic for CreateAccessPolicy.xaml
/// </summary>
public partial class CreateAccessPolicy : MetroWindow
{
public string ObjectId { get; set; }
public string ApplicationId { get; set; }
public KeyAccessPolicy KeyAccessPolicy { get; set; }
public SecretAccessPolicy SecretAccessPolicy { get; set; }

private Timer FilterChangedTimer { get; }
private bool FilterChangedTimerElapsed { get; set; }
private string LastRequest { get; set; }

public CreateAccessPolicy()
{
InitializeComponent();

FilterChangedTimer = new Timer(1000);
FilterChangedTimer.Elapsed += (sender, args) =>
{
FilterChangedTimer.Enabled = false;
FilterChangedTimerElapsed = true;
Dispatcher.Invoke(() =>
{
if (LastRequest != searchFilter.Text)
FilterTextChanged(null, null);
});
};
FilterChangedTimer.Enabled = true;

Loaded += (sender, args) =>
{
keyGroup.DataContext = new KeyAccessPolicy();
secretGroup.DataContext = new SecretAccessPolicy();
};
}

private async void FilterTextChanged(object sender, TextChangedEventArgs e)
{
if (!FilterChangedTimer.Enabled)
FilterChangedTimer.Enabled = true;
else
{
FilterChangedTimer.Enabled = false;
FilterChangedTimer.Enabled = true;
return;
}

LastRequest = searchFilter.Text;

if (searchFilter.Text != null && !string.IsNullOrWhiteSpace(searchFilter.Text) && searchFilter.Text.Length > 4)
adObjects.ItemsSource = await AzureServiceAdapter.Instance.GetAllDirectoryObjects(searchFilter.Text);
}

private void CreateClicked(object sender, RoutedEventArgs e)
{
KeyAccessPolicy = (KeyAccessPolicy) keyGroup.DataContext;
SecretAccessPolicy = (SecretAccessPolicy)secretGroup.DataContext;

var selectedObject = (IDirectoryObject) adObjects.SelectedItem;
if (selectedObject is Application)
ApplicationId = ((Application) selectedObject).AppId;
if (selectedObject is ServicePrincipal)
ApplicationId = ((ServicePrincipal)selectedObject).AppId;

ObjectId = selectedObject.ObjectId;

DialogResult = true;
this.Close();
}
}
}
2 changes: 2 additions & 0 deletions CreateKey.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
xmlns:local="clr-namespace:AzureKeyVaultManager"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
BorderBrush="{StaticResource AccentColorBrush}"
WindowStartupLocation="CenterOwner"
Title="CreateKey" Height="320" Width="300">
<Grid Margin="3">
<Grid.ColumnDefinitions>
Expand Down
10 changes: 10 additions & 0 deletions VaultViewer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@
</Grid.RowDefinitions>

<ListBox Name="policyItems" Grid.Row="0">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add New" Click="CreateNewAccessPolicy" />
</ContextMenu>
</ListBox.ContextMenu>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete" Click="DeleteAccessPolicy" />
</ContextMenu>
</Grid.ContextMenu>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="10" />
Expand Down
Loading

0 comments on commit 09966e2

Please sign in to comment.