# Created by Lee Trujillo (lee.trujillo@forgerock.com) # # The contents of this file are subject to the terms of the Common Development and # Distribution License (the License). You may not use this file except in compliance with the # License. # # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the # specific language governing permission and limitations under the License. # # When distributing Covered Software, include this CDDL Header Notice in each file and include # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL # Header, with the fields enclosed by brackets [] replaced by your own identifying # information: "Portions Copyright [year] [name of copyright owner]". # # Copyright 2018-2020 ForgeRock AS. # # # NOTE: This "must" be run from within the /opendj/ location. # # This tool collects support data from the ForgeRock DS/OpenDJ instance it is bound to. # # Command options: # # -l, {maxLogFiles} # Maximum number of log files to collect # - Can collect 0 to N log files of each type # - maxLogFiles of 0 collects no log files with the exception of server.out # - When omitted, collects all logs # -o, {outputDirectory} # The folder into which the files will be gathered # # LDAP connection options: # # -D, {bindDN} # DN to use to bind to the server # Default value: cn=Directory Manager # -w, {bindPassword} # Password to use to bind to the server # -j, {bindPasswordFile} # Bind password file # # Note: # * Either -j or -w are required # * Automatically uses the rootDN (cn=Directory Manager) if -D bindDN is not provided # * If more than one rootDN exists, you must specify one using -D {bindDN} param ( [string]$j, [string]$w, [string]$D, [string]$o, [string]$l ) function log { $thisLine=$args[0] Write-Host "$thisLine" echo "$thisLine" | Out-File -Append -Encoding ASCII -FilePath $o\support-data\supportextract.log } function FinalTask { Remove-Item $o\support-data -Recurse } $version = "1.5" Write-Host "--------------------------------------------------------------------------------" Write-Host "ForgeRock Extract Powershell - $version" Write-Host "--------------------------------------------------------------------------------" # Check to see if the data storage path exists If($o){ If(Test-path $o\support-data) {Remove-item $o\support-data} mkdir $o\support-data -Force | Out-Null } else { $o = 'C:\Temp' mkdir $o\support-data -Force | Out-Null } If($l) { $maxLogFiles = $l $accessLogCount = $maxLogFiles $errorLogCount = $maxLogFiles $replLogCount = $maxLogFiles $jsonAccessLogCount = $maxLogFiles } else { If(Test-path logs) { $accessLogCount = (Get-ChildItem -path logs access* | Measure-Object).Count $errorLogCount = (Get-ChildItem -path logs errors* | Measure-Object).Count $replLogCount = (Get-ChildItem -path logs replication* | Measure-Object).Count $jsonAccessLogCount = (Get-ChildItem -path logs ldap-access.audit.json* | Measure-Object).Count } } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO VERSION: ${version}-powershell" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using storage bin $o\support-data" # Check for an instance.loc $binaryPath = (Get-Location).Path If(Test-path instance.loc) { $instancePath = (Get-Content instance.loc) log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using instance.loc ($instancePath)" cd $instancePath } else { $instancePath = (Get-Location).Path } $jvmhome = (cat $instancePath\config\java.properties | Select-String -Pattern "^default.java-home=*") | % { $_ -replace "default.java-home=","" } If(Test-path $jvmhome\bin\keytool.exe) { $keytool = "$jvmhome\bin\keytool.exe" } else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") ERROR * Java keytool not found" } # Find the DS version (for ldapsearch wraping) If(Test-path config\buildinfo) { $shortBaseVersion = (Get-Content .\config\buildinfo -TotalCount 1).SubString(0,1) } # Exit if we encounter a DS version above 6.0.0 If(Test-path config\config.version) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") ERROR * Please run bat\supportextract.bat" FinalTask exit } if ($shortBaseVersion -lt 4){ $wrapArg = '--dontWrap' } # Display the pid $serverPID = tasklist | Select-String java | %{($_ -split "\s+")[1]} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * The instance is running (PID $serverPID)" # Check to see which password option we're using if($j){ if(Test-path $j){ $bindPasswordParam = (Get-ChildItem $j | select -ExpandProperty FullName) log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Password File found ($bindPasswordParam)" } else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") ERROR * Password File Not Found" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using secure password input" Remove-Variable -Name j $secure=Read-Host -AsSecureString -Prompt "$(get-date -f "yyyy-MM-dd HH:mm:ss") REDACTED - Input password, please" $bstr=[Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure) $w=[Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) } } elseif($w){ log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using -w password input" } else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using secure password input" $secure=Read-Host -AsSecureString -Prompt "$(get-date -f "yyyy-MM-dd HH:mm:ss") REDACTED - Input password, please" $bstr=[Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure) $w=[Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) } # Get the rootDN if($D) { $rootDN = $D } else { If(Test-path db\rootUser\rootUser.ldif) { $rootDN = (Get-Content db\rootUser\rootUser.ldif -TotalCount 1).replace('dn: ','') } elseif(Test-path db\rootUser\rootUser0.ldif){ $rootDN = (Get-Content db\rootUser\rootUser0.ldif -TotalCount 1).replace('dn: ','') } else { $rootDN = (Select-String -Path config\config.ldif -Pattern 'ds-cfg-alternate-bind-dn:') | %{($_ -split ":")[4]} $rootDN = $rootDN.Trim() } } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Using rootDN ($rootDN)" mkdir $o\support-data\config -Force | Out-Null mkdir $o\support-data\config\security -Force | Out-Null mkdir $o\support-data\node -Force | Out-Null mkdir $o\support-data\monitor -Force | Out-Null mkdir $o\support-data\processStats -Force | Out-Null mkdir $o\support-data\changelogDbInfo -Force | Out-Null # Get the Admin Port $flag=0 Get-Content config\config.ldif | foreach { Switch -Wildcard ($_){ "*dn: cn=Administration Connector,cn=config*" {$flag=1} "*dn: cn=Alert Handlers,cn=config" {$flag=0} } if ($flag -eq 1){ Out-File $o\support-data\adminPort.txt -InputObject $_ -Append } } $thisString = Select-String -Path $o\support-data\adminPort.txt -Pattern 'ds-cfg-listen-port:' | Get-Unique | %{($_ -split ":")[4]} $adminPort = $thisString.Trim() If(Test-path $o\support-data\adminPort.txt) {Remove-item $o\support-data\adminPort.txt} cd $binaryPath log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting the monitoring info from cn=monitor ($adminPort)" if($j) { .\bat\ldapsearch.bat $wrapArg --port $adminPort --useSsl --trustAll --bindDN $rootDN --bindPasswordFile $bindPasswordParam --baseDN cn=monitor --searchScope sub 'objectClass=*' | Out-File -Encoding ASCII $o\support-data\monitor\monitor.ldif } if($w) { $bindPasswordParam = $w .\bat\ldapsearch.bat $wrapArg --port $adminPort --useSsl --trustAll --bindDN $rootDN --bindPassword $bindPasswordParam --baseDN cn=monitor --searchScope sub 'objectClass=*' | Out-File -Encoding ASCII $o\support-data\monitor\monitor.ldif } if($bindPasswordParam -eq $null) { .\bat\ldapsearch.bat $wrapArg --port $adminPort --useSsl --trustAll --bindDN $rootDN --bindPassword $bindPassword --baseDN cn=monitor --searchScope sub 'objectClass=*' | Out-File -Encoding ASCII $o\support-data\monitor\monitor.ldif } cd $instancePath log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting process statistics" echo "Windows System: Stack not available" | Out-File -Encoding ASCII $o\support-data\processStats/README.txt log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Skipping, Windows system" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting the configuration files" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding config.ldif" If(Test-path config\config.ldif) {copy config\config.ldif $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding admin-backend.ldif" If(Test-path config\admin-backend.ldif) {copy config\admin-backend.ldif $o\support-data\config} If(Test-path db\adminRoot\admin-backend.ldif) {copy db\adminRoot\admin-backend.ldif $o\support-data\config} If(Test-path db\monitorUser\monitorUser.ldif) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding monitorUser.ldif" copy db\monitorUser\monitorUser.ldif $o\support-data\config } If(Test-path db\rootUser\rootUser.ldif) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding rootUser.ldif" copy db\rootUser\rootUser.ldif $o\support-data\config } If(Test-path db\rootUser\rootUser0.ldif) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding rootUser0.ldif" copy db\rootUser\rootUser0.ldif $o\support-data\config } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding java.properties" If(Test-path config\java.properties) {copy config\java.properties $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding buildinfo" If(Test-path config\buildinfo) {copy config\buildinfo $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding tasks.ldif" If(Test-path config\tasks.ldif) {copy config\tasks.ldif $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding schema files" If(Test-path config\schema) {copy -Recurse config\schema $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding HTTP configuration file(s)" If(Test-path config\rest2ldap) {copy -Recurse config\rest2ldap $o\support-data\config} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding archived config files" If(Test-path config\archived-configs) { copy -Recurse config\archived-configs $o\support-data\config\archived-configs $archivedFileCount = ( Get-ChildItem config\archived-configs\* | Measure-Object ).Count; } If(Test-path var\archived-configs) { copy -Recurse var\archived-configs $o\support-data\config\archived-configs $archivedFileCount = ( Get-ChildItem var\archived-configs\* | Measure-Object ).Count; } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * total files $archivedFileCount" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Listing the security stores" $stores = @("keystore","truststore","admin-keystore","admin-truststore","ads-truststore") foreach ($store in $stores) { if ($store -eq "truststore") { $pinfile="keystore.pin" } elseif ($store -eq "admin-truststore") { $pinfile="admin-keystore.pin" } else { $pinfile="$store.pin" } If(Test-path $instancePath\config\$store) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * config\$store" $keypin = Get-Content -Path $instancePath\config\$pinfile & $keytool -list -keystore $instancePath\config\$store -v -storepass $keypin | Out-File -Encoding ASCII $o\support-data\config\security\$store-list } elseif ($shortBaseVersion -eq "6" -AND $store -eq "ads-truststore" ) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * db\ads-truststore\$store" $keypin = Get-Content -Path $instancePath\db\ads-truststore\ads-truststore.pin & $keytool -list -keystore $instancePath\db\ads-truststore\ads-truststore -v -storepass $keypin | Out-File -Encoding ASCII $o\support-data\config\security\ads-truststore-list } else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * config\$store not available" } } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting backend statistics" Get-ChildItem -Path $instancePath\db -Name -Exclude ("admin","adminRoot","ads-truststore","monitorUser","rootUser","schema","tasks") | foreach { mkdir $o\support-data\logs\${_} -Force | Out-Null $dbFileCount = ( Get-ChildItem db\${_}\*jdb | Measure-Object ).Count; log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - ${_}: total jdb files $dbFileCount" echo "jdb-file-count:${dbFileCount}" | Out-File -Encoding ASCII $o\support-data\logs\${_}\backend.states $jeInfoFiles = @("je.config.csv","je.info.0","je.stat.csv") foreach ($jeFile in $jeInfoFiles) { If(Test-path .\db\${_}\$jeFile) {Copy-Item db\${_}\$jeFile -destination $o\support-data\logs\${_}\} } } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting system node information" log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding OS information" Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, OSArchitecture, CSName, WindowsDirectory | Out-File -Encoding ASCII $o\support-data\node\osInfo log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding Network information" Get-WmiObject Win32_NetworkAdapterConfiguration | Where IPEnabled | Select IPSubnet, DNSServerSearchOrder, IpAddress | Out-File -Encoding ASCII $o\support-data\node\networkInfo2 $localHost = (Select-String -Path $o\support-data\node\networkInfo2 -Pattern '{' | %{($_ -split "\s+")[4]}).replace('{','').replace(',','') $hostName = hostname echo "Local Host: $localHost ($hostName)" | Out-File -Encoding ASCII $o\support-data\node\networkInfo.ascii echo "IP: $localHost ($localHost)" | Out-File -Encoding ASCII $o\support-data\node\networkInfo.ascii log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding Disk information" Get-WmiObject -Class Win32_logicaldisk | Out-File -Encoding ASCII $o\support-data\node\diskInfo log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - Adding Processor information" Get-WmiObject Win32_processor | Out-File -Encoding ASCII $o\support-data\node\processorInfo log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting ChangelogDb information" If(Test-path changelogDb\domains.state) { Get-Content -Path .\changelogDb\domains.state | Out-File -Encoding ASCII $o\support-data\changelogDbInfo\domains.state Get-ChildItem -Path changelogDb -Recurse | Out-File -Encoding ASCII $o\support-data\changelogDbInfo\changelogDb.listing } else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - No changelogDb data found" echo "No changelogDb data found. Not replicated" > $o\support-data\changelogDbInfo\README } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Collecting the log files" If($maxLogFiles -eq 0) { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") WARNING - Max Logs set to 0. No logs gathered." If(Test-path logs\server.out) {Get-ChildItem -path logs server.out* | Copy-Item -destination $o\support-data\logs} } Else { log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - access [$accessLogCount files]" If(Test-path logs) {Get-ChildItem -path logs access* | Sort-Object -Descending | select -Last $accessLogCount | Copy-Item -destination $o\support-data\logs} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - errors [$errorLogCount files]" If(Test-path logs) {Get-ChildItem -path logs errors* | Sort-Object -Descending | select -Last $errorLogCount | Copy-Item -destination $o\support-data\logs} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - replication [$replLogCount files]" If(Test-path logs) {Get-ChildItem -path logs replication* | Sort-Object -Descending | select -Last $replLogCount | Copy-Item -destination $o\support-data\logs} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - server.out [1 file]" If(Test-path logs\server.out) {Get-ChildItem -path logs server.out* | Copy-Item -destination $o\support-data\logs} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO - ldap-access.audit.json [$jsonAccessLogCount files]" If(Test-path logs) {Get-ChildItem -path logs ldap-access.audit.json* | Sort-Object -Descending | select -Last $jsonAccessLogCount | Copy-Item -destination $o\support-data\logs} } log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Capturing GC logging information" If(Test-path logs) {Get-ChildItem -path logs *gc* | Copy-Item -destination $o\support-data\logs} log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Capturing status output" cd $binaryPath if($j) { .\bat\status.bat --bindDN "$rootDN" --bindPasswordFile $bindPasswordParam --trustAll | Out-File -Encoding ASCII $o\support-data\status.out } if($w) { $bindPasswordParam = $w .\bat\status.bat --bindDN "$rootDN" --bindPassword $bindPasswordParam --trustAll | Out-File -Encoding ASCII $o\support-data\status.out } if($bindPasswordParam -eq $null) { .\bat\status.bat --bindDN "$rootDN" --bindPassword $bindPassword --trustAll | Out-File -Encoding ASCII $o\support-data\status.out } #cd $instancePath log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Creating a zip archive" $Source = "$o\support-data" $destination = "$o\opendj-support-data-$(get-date -f yyyyMMdd-HHmmssffff).zip" If(Test-path $destination) {Remove-item $destination} Add-Type -assembly "system.io.compression.filesystem" [io.compression.zipfile]::CreateFromDirectory($Source, $destination) log "$(get-date -f "yyyy-MM-dd HH:mm:ss") INFO * Removing temp files - $o\support-data" FinalTask Write-Host "" Write-Host "The following archive has been created : opendj-support-data-$(get-date -f yyyyMMdd-HHmmssffff).zip (attach this to the ticket)"