function Export-CertificatesToFileSystem { <# .SYNOPSIS Exports certificates from desired stores (My, CertificateAuthority, Root, and TrustedPeople by default) onto the file system. .DESCRIPTION This script will export all public certificates and private keys in a given store to the file system. The certificate chain is also exported in an individualized folder along with the certificate so that you can delineate what certificates are needed for the one exported. A password is generated for private keys, if ADGroups are given they are assigned to the private keys as well. This script also returns a model of the data exported. With this model the file system data is more easily manipulated and was originally intended to be used by a module for uploading these certificates and their chains to individual secrets in secret server. .PARAMETER PodName String Used to create a leaf folder with in which the certificates will be exported and set as a property on the model returned as a result of this cmdlet. .PARAMETER CertRoot String Location that this cmdlet will be working out of. This is set to LocalMachine but could be set to Personal or other certificate providers. .PARAMETER StoresToExport StoreName[] All certificates in these stores will be exported along with their certificate chains and private keys. .PARAMETER ADGroups String[] Any ADGroups or UserAccounts that are given will be assigned to private keys exported. These users will be able to import the private keys without a password, although one is generated and set by this cmdlet regardless .EXAMPLE Export-CertificatesToFileSystem -PodName "Pod 1.1.1" Base usage, will export all certificates in the default stores and their private keys to the Default Export Root Folder under leaf folder 'Pod 1.1.1'. A password will be generated for the private keys and returned to the caller in the model object. .EXAMPLE Export-CertificatesToFileSystem -PodName "Pod 7.0.5" -ADGroups "corp\JSmith","corp\CCarter" -RootExportFolder "C:\Exports" Will export all certificates in the default stores and their private keys to the C:\Exports Folder under leaf folder 'Pod 7.0.5'. Users JSmith and CCarter will be able to import the private keys without the password, however passwords generated for these certificates will be returned with the model object that this cmdlet produces. #> [CmdletBinding()] param( [Parameter(Mandatory = $True)] [string]$PodName, [Parameter(Mandatory = $False)] [string]$CertRoot = "Cert:\LocalMachine\", [Parameter(Mandatory = $False)] [string]$RootExportFolder = "c:\temp\CertExports", [Parameter(Mandatory = $False)] $StoresToExport = @([System.Security.Cryptography.X509Certificates.StoreName]::My, [System.Security.Cryptography.X509Certificates.StoreName]::CertificateAuthority, [System.Security.Cryptography.X509Certificates.StoreName]::Root, [System.Security.Cryptography.X509Certificates.StoreName]::TrustedPeople), [Parameter(Mandatory = $False)] [string[]]$ADGroups = "" ) begin { $logLead = Get-LogLeadName $Pod = [PSObject]@{ PodName = $PodName ExportFolder = (Join-Path $RootExportFolder $PodName) StoresToExport = $StoresToExport CertRoot = $CertRoot Stores = @{ } } if (Test-Path -Path $Pod.ExportFolder) { Write-Host "$logLead : Removing items from $($Pod.ExportFolder) before beginning" Remove-FileSystemItem -Path $Pod.ExportFolder -Recurse -Force -ErrorAction SilentlyContinue | Out-Null } if (-not (Test-Path -PathType Container -Path $Pod.ExportFolder)) { New-Item $Pod.ExportFolder -ItemType Directory | Out-Null } } process { foreach ($storeName in $Pod.StoresToExport) { $store = [PSObject]@{ Name = $storeName ExportStorePath = Join-Path $Pod.ExportFolder $storeName StorePath = Join-Path $Pod.CertRoot $storeName Certificates = @{ } } # Powershell's Paths don't match the X509 enum. So here we do a poor man's lookup. If we ever need more stores than just the CA, this needs to be expanded to something more robust and clean. if ($store.Name -eq "CertificateAuthority") { $store.StorePath = "Cert:\LocalMachine\CA" } $Pod.Stores.Add($storeName, $store) $Pod.Stores | Add-Member -MemberType NoteProperty -Name $storeName -Value $store New-Item $store.ExportStorePath -ItemType Directory | Out-Null #foreach cert in store try { $certificates = Get-ChildItem $store.StorePath; } catch { Write-Warning "Cannot find Certificates in $storeName" } if ($certificates.Count -gt 0) { foreach ($cert in $certificates) { try { $exportInfo = Export-CertificateToFileSystem -cert $cert -exportStorePath $store.ExportStorePath -ADGroups $ADGroups if ($null -eq $exportInfo) { continue } $chainInfo = Export-CertChain -cert $cert -exportStorePath $store.ExportStorePath -exportCertPath $exportInfo.exportCertPath -ADGroups $ADGroups $CertificateChain = [PSObject]@{ Folder = Join-Path $exportInfo.ExportCertPath "ChainedCertificates" Certificates = @{ } } foreach ($chainedCert in $chainInfo) { $CertificateChain.Certificates.Add($chainedCert.certName, $chainedCert) $CertificateChain.Certificates | Add-Member -MemberType NoteProperty -Name $chainedCert.certName -Value $chainedCert } $certificate = [PSObject]@{ Name = $exportInfo.certName FilePath = $exportInfo.exportCertFile Folder = $exportInfo.exportCertPath Password = $exportInfo.certPassword CertificateChain = $CertificateChain ADGroups = $exportInfo.ADGroups ExpirationDate = $exportInfo.ExpirationDate Thumbprint = $exportInfo.Thumbprint } $store.Certificates.Add($certificate.Name, $certificate) $store.Certificates | Add-Member -MemberType NoteProperty -Name $certificate.Name -Value $certificate } catch { Write-Error "Certificate has failed to export Name: $($certificate.Name), FriendlyName: $($cert.FriendlyName), Thumprint: $($cert.Thumbprint), Store: $storeName $($_.Exception) $($_.Message) $($_.ScriptStackTrace)" } } } } } end { return $Pod } }