MSAppProxy.ps1
# This file contains functions for Microsoft App Proxy # Export proxy agent certificates from the local computer # Mar 8th 2022 # Aug 17th 2022: Added support for exporting from NETWORK SERVICE personal store function Export-ProxyAgentCertificates { <# .SYNOPSIS Export certificates of all MS App Proxy agents from the local computer. .DESCRIPTION Export certificates of all MS App Proxy agents from the local computer. The filename of the certificate is <server FQDN>_<tenant id>_<agent id>_<cert thumbprint>.pfx .Example Export-AADIntProxyAgentCertificates WARNING: Elevating to LOCAL SYSTEM. You MUST restart PowerShell to restore PTA01\Administrator rights. Certificate saved to: PTA01.company.com_ea664074-37dd-4797-a676-b0cf6fdafcd4_4b6ffe82-bfe2-4357-814c-09da95399da7_A3457AEAE25D4C513BCF37CB138628772BE1B52.pfx #> [cmdletbinding()] Param() Process { # Get all certificates from LocalMachine Personal store $certificates = @(Get-Item Cert:\LocalMachine\My\*) # Internal function to parse PTA & Provisioning agent configs function Parse-ConfigCert { [cmdletbinding()] Param( [String]$ConfigPath ) Process { # Check if we have a PTA or provisioning agent configuration and get the certificate if stored in NETWORK SERVICE personal store [xml]$trustConfig = Get-Content "$env:ProgramData\Microsoft\$ConfigPath\Config\TrustSettings.xml" -ErrorAction SilentlyContinue if($trustConfig) { $thumbPrint = $trustConfig.ConnectorTrustSettingsFile.CloudProxyTrust.Thumbprint # Check where the certificate is stored if($trustConfig.ConnectorTrustSettingsFile.CloudProxyTrust.IsInUserStore.ToLower().equals("true")) { # Certificate is stored in NETWORK SERVICE personal store so we need to parse it from there Write-Verbose "Parsing certificate: $($thumbPrint)" Parse-CertBlob -Data (Get-BinaryContent "$env:windir\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates\$thumbPrint") } } } } if($PTACert = Parse-ConfigCert -ConfigPath "Azure AD Connect Authentication Agent") { $binCert = $PTACert.DER $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([byte[]]$binCert) $PTAKeyName = $PTACert.KeyIdentifier $certificates += $certificate } if($ProvCert = Parse-ConfigCert -ConfigPath "Azure AD Connect Provisioning Agent") { $binCert = $ProvCert.DER $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([byte[]]$binCert) $ProvKeyName = $ProvCert.KeyIdentifier $certificates += $certificate } foreach($certificate in $certificates) { Write-Verbose "Reading certificate: $($certificate.Thumbprint)" $oids = Parse-CertificateOIDs -Certificate $certificate if($oids.AgentId) { # Extract agent and tenant IDs $agentId = $oids.AgentId $tenantId = [guid] $certificate.Subject.Split("=")[1] Write-Verbose " Tenant Id: $tenantId, Agent Id: $agentId" # Get the certificate $binCert = $certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert) $paths = @( "$env:ALLUSERSPROFILE\Microsoft\Crypto\RSA\MachineKeys" "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys" "$env:windir\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-20" ) # Get the correct key name if($PTACert) { # If stored in NETWORK SERVICE store, PTA Agent's key name can't be readed from the certificate $privateKey = Find-PrivateKey -KeyName $PTAKeyName -Paths $paths -Elevate } elseif($ProvCert) { # If stored in NETWORK SERVICE store, Provisioning Agent's key name can't be readed from the certificate $privateKey = Find-PrivateKey -KeyName $ProvKeyName -Paths $paths -Elevate } else { # Read the key file name from the certificate $fileName = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate).key.uniquename $privateKey = Find-PrivateKey -FileName $fileName -Paths $paths -Elevate } # Save to pfx file $machineName = Get-ComputerName -FQDN $fileName = "$($machineName)_$($tenantId)_$($agentId)_$($certificate.Thumbprint).pfx" Set-BinaryContent -Path $fileName -Value (New-PfxFile -RSAParameters ($privateKey.RSAParameters) -X509Certificate $binCert) # Set the modified date (Get-Item -Path $fileName).LastWriteTime = $certificate.NotBefore Write-Host "Certificate saved to: $fileName" } } } } |