0

Lookup and Replace Certificate Contacts (UI)

I was experimenting with the ability to put a UI on a powershell script and came up with the below. Using this you can pull back all object DNs by a contact assigned by entering the full Contact UID in the Contact UID field.

Once you have run the search you can then replace that Contact UID by Entering a different UID in the Replacement UID field by pressing the Update Contact button. You can also export the results of the search to a csv file, if you wanted to get more infomation into the csv file you could just edit this line to include the information you wanted: $global:Export+=$i+","+$Contacts.Values+"`r`n"

The UI is actually really simple to build in  Visual Studio.

Here is the UI:

Here is the code (just save as a .ps1 file and run with powershell):

$inputXML = @"
<Window x:Class="WpfApplication1.MainWindow"
        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:WpfApplication1"
        mc:Ignorable="d"
        Title="Find Certs by Contact UID" Height="760" Width="700">
    <Grid>

        <TextBox x:Name="Username" HorizontalAlignment="Left" Height="29" Margin="127,14,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="206"/>
        <PasswordBox x:Name="Password" HorizontalAlignment="Left" Height="29" Margin="127,48,0,0" VerticalAlignment="Top" Width="206"/>
        <TextBox x:Name="ContactUID" HorizontalAlignment="Left" Height="29" Margin="127,83,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="369"/>
        <TextBox x:Name="ServerName" HorizontalAlignment="Left" Height="29" Margin="472,14,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="200"/>

        <Button x:Name="Search" Content="Search..." HorizontalAlignment="Left" Margin="597,164,0,0" VerticalAlignment="Top" Width="75"/>
        <Button x:Name="Export" Content="Export Results" HorizontalAlignment="Left" Margin="542,623,0,0" VerticalAlignment="Top" Width="130"/>
        <Button x:Name="Update" Content="Update Contact" HorizontalAlignment="Left" Margin="542,660,0,0" VerticalAlignment="Top" Width="130"/>
        <Label x:Name="UsernameLabel" Content="UserName" HorizontalAlignment="Left" Height="29" Margin="20,14,0,0" VerticalAlignment="Top" Width="120"/>
        <Label x:Name="PasswordLabel" Content="Password" HorizontalAlignment="Left" Height="29" Margin="20,48,0,0" VerticalAlignment="Top" Width="120"/>
        <Label x:Name="SerialNumberLabel" Content="Contact UID" HorizontalAlignment="Left" Height="29" Margin="20,83,0,0" VerticalAlignment="Top" Width="120"/>
        <Label x:Name="CertificateDetailsLabel" Content="Certificate Details:" HorizontalAlignment="Left" Height="30" Margin="22,179,0,0" VerticalAlignment="Top" Width="272"/>
        <Label x:Name="ObjectClassLabel" Content="Object Class" HorizontalAlignment="Left" Height="29" Margin="20,119,0,0" VerticalAlignment="Top" Width="120"/>
        <Label x:Name="ServerNameLabel" Content="Server Name/IP" HorizontalAlignment="Left" Height="29" Margin="376,14,0,0" VerticalAlignment="Top" Width="120"/>
        <ListView x:Name="listview" HorizontalAlignment="Left" Height="400" Margin="22,203,0,0" VerticalAlignment="Top" Width="650">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Object DN" DisplayMemberBinding ="{Binding 'Key'}" Width="200"/>
                    <GridViewColumn Header="Value" DisplayMemberBinding ="{Binding 'Value'}" Width="450"/>
                </GridView>
            </ListView.View>
        </ListView>
        <Label x:Name="ExportPathLabel" Content="Path to save file" HorizontalAlignment="Left" Height="29" Margin="20,620,0,0" VerticalAlignment="Top" Width="100"/>
        <TextBox x:Name="ExportPath" HorizontalAlignment="Left" Height="29" Margin="130,620,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="380"/>
        <Label x:Name="ReplacementLabel" Content="Replacement UID" HorizontalAlignment="Left" Height="29" Margin="20,660,0,0" VerticalAlignment="Top" Width="120"/>
        <TextBox x:Name="ReplacementContact" HorizontalAlignment="Left" Height="29" Margin="127,660,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="380"/>
        <ComboBox x:Name="ObjectClasses" HorizontalAlignment="Left" Height="27" Margin="127,121,0,0" VerticalAlignment="Top" Width="369" SelectedIndex="1">
            <ComboBoxItem Content="Device" HorizontalAlignment="Left" Width="367"/>
            <ComboBoxItem Content="X509 Server Certificate" HorizontalAlignment="Left" Width="367"/>
            <ComboBoxItem Content="X509 Device Certificate" HorizontalAlignment="Left" Width="367"/>
            <ComboBoxItem Content="X509 Certificate" HorizontalAlignment="Left" Width="367"/>
        </ComboBox>
   </Grid>
</Window>
"@       
 
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N'  -replace '^<Win.*', '<Window'
 
 
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML
 
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
  try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."}
 
#===========================================================================
# Load XAML Objects In PowerShell
#===========================================================================
 
$xaml.SelectNodes("//*[@Name]") | %{Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name)}
 
Function Get-FormVariables{
get-variable WPF*
}

Get-FormVariables
$WPFUsername.Text="eg. local:admin"
#$WPFPassword.Password="uncomment to save the password"
$WPFServerName.Text="eg. test.venafiad.com"
$WPFExportPath.Text="c:\temp\test.csv"

#API Function

Function Get-API
{
#Define Credentials
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$Server = 'https://'+$WPFServerName.Text+'/vedsdk'
$uri = $Server+'/authorize'
#$Password = Read-Host -AsSecureString 'Password'
$hashobject = @{ Username = $WPFUsername.Text; Password = $WPFPassword.Password}

#Request API Key and store the API Key in $headers for further requests.
$json = $hashobject | ConvertTo-Json
$response = Invoke-RestMethod -Method Post -uri $uri -body $json -ContentType 'application/json'
$headers = New-Object -TypeName 'System.Collections.Generic.Dictionary[[String], [String]]'
$headers.Add('X-Venafi-Api-Key', $response.APIKey)

#Return DN for all Certificates
$uri = $Server+'/Config/FindObjectsofClass'
$hashobject = @{Class=$WPFObjectClasses.Text;}
$json = $hashobject | ConvertTo-Json
$global:CertVaultIDs = Invoke-RestMethod -Method Post -Headers $headers -uri $uri -body $json -ContentType 'application/json'
#echo $CertVaultIDs
$uri = $Server+'/Config/ReadEffectivePolicy'
$global:Export = "sep=,`r`nObjectDN, Contact`r`n"
Set-Variable -Name $global:Export -Value @() -Scope Global

#Retreive Contacts for each DN
foreach($i in $global:CertVaultIDs.Objects.DN){
$hashobject = @{ObjectDN=$i; AttributeName="Contact";}
$json = $hashobject | ConvertTo-Json
$Contacts = Invoke-RestMethod -Method Post -Headers $headers -uri $uri -body $json -ContentType 'application/json'

#If UID field is populated return all DNs for that contact, else return all DNs with contacts.
If($Contacts.Values -match $WPFContactUID.Text){
$Testing = New-Object -TypeName 'System.Collections.Generic.Dictionary[[String], [String]]'
$Testing.Add($i,$Contacts.Values)
echo $Testing
$global:Export+=$i+","+$Contacts.Values+"`r`n"
}
}
}


Function Replace-Contact
{
#Define Credentials
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$Server = 'https://'+$WPFServerName.Text+'/vedsdk'
$uri = $Server+'/authorize'
#$Password = Read-Host -AsSecureString 'Password'
$hashobject = @{ Username = $WPFUsername.Text; Password = $WPFPassword.Password}

#Request API Key and store the API Key in $headers for further requests.
$json = $hashobject | ConvertTo-Json
$response = Invoke-RestMethod -Method Post -uri $uri -body $json -ContentType 'application/json'
$headers = New-Object -TypeName 'System.Collections.Generic.Dictionary[[String], [String]]'
$headers.Add('X-Venafi-Api-Key', $response.APIKey)

#Return DN for all Certificates
#$uri = $Server+'/Config/FindObjectsofClass'
#$hashobject = @{Class=$WPFObjectClasses.Text;}
#$json = $hashobject | ConvertTo-Json
#$CertVaultIDs = Invoke-RestMethod -Method Post -Headers $headers -uri $uri -body $json -ContentType 'application/json'
#echo $CertVaultIDs
$uri = $Server+'/Config/ReadEffectivePolicy'
#$global:Export = "sep=,`r`nObjectDN, Contact`r`n"
#Set-Variable -Name $global:Export -Value @() -Scope Global

#Retreive Contacts for each DN
foreach($i in $global:CertVaultIDs.Objects.DN){
$hashobject = @{ObjectDN=$i; AttributeName="Contact";}
$json = $hashobject | ConvertTo-Json
$Contacts = Invoke-RestMethod -Method Post -Headers $headers -uri $uri -body $json -ContentType 'application/json'

#Lets replace some Contacts.
If($Contacts.Values -match $WPFContactUID.Text){
$uri2 = $Server+'/Config/RemoveValue'
$hashobject = @{ObjectDN=$i; AttributeName="Contact";Value=$WPFContactUID.Text}
$json = $hashobject | ConvertTo-Json
$ContactReplace = Invoke-RestMethod -Method Post -Headers $headers -uri $uri2 -body $json -ContentType 'application/json'

$uri3 = $Server+'/Config/AddValue'
$hashobject = @{ObjectDN=$i; AttributeName="Contact";Value=$WPFReplacementContact.Text}
$json = $hashobject | ConvertTo-Json
$ContactReplace = Invoke-RestMethod -Method Post -Headers $headers -uri $uri3 -body $json -ContentType 'application/json'
}
}
}

#Search Button (Execute Get-API function and pipe to WPFlistview)
$WPFSearch.Add_Click({
Get-API | % {$WPFlistview.AddChild($_)}
})

#Export Button - send it to a CSV
$WPFExport.Add_Click({
$Export | Out-File $WPFExportPath.Text
})

#Replace Contact Button
$WPFUpdate.Add_Click({
Replace-Contact
})

$Form.ShowDialog() | out-null

Any questions, feel free to ask.

1 comment

Please sign in to leave a comment.