Providers/AD/Private/Export-ADTestPasswordDocumentation.ps1

function Export-ADTestPasswordDocumentation {
    <#
    .SYNOPSIS
        Exports password documentation to a timestamped file for service accounts

    .DESCRIPTION
        Creates a secure password documentation file with timestamped filename containing
        service account names and their generated passwords. This is used for secure
        password distribution and documentation purposes.

    .PARAMETER PasswordData
        Array of objects containing password information to export.
        Each object should have: ServiceAccountName, Password, CreatedDate

    .PARAMETER OutputDirectory
        Directory where the password file should be created. Defaults to current location.

    .PARAMETER FilePrefix
        Prefix for the password file name. Defaults to "ServiceAccountPW"

    .PARAMETER ExcludeWarnings
        Include security warnings in the exported file

    .EXAMPLE
        $passwordData = @(
            @{ ServiceAccountName = 'svc-app1'; Password = 'SecurePass123!'; CreatedDate = Get-Date }
            @{ ServiceAccountName = 'svc-db1'; Password = 'AnotherPass456@'; CreatedDate = Get-Date }
        )
        Export-ADTestPasswordDocumentation -PasswordData $passwordData

        Exports passwords to a timestamped file in the current directory

    .EXAMPLE
        Export-ADTestPasswordDocumentation -PasswordData $passwordExports -OutputDirectory "C:\SecureLocation" -FilePrefix "Prod-ServiceAccounts"

        Exports passwords to a custom location with custom filename prefix

    .OUTPUTS
        String containing the full path to the created password file

    .NOTES
        Author: Jeffrey Stuhr
        Version: 1.0.0
        Last Updated: 2025-08-03
        
        SECURITY CONSIDERATIONS:
        - Password files should be stored securely and deleted after distribution
        - File permissions should be restricted to authorized personnel only
        - Consider using encrypted storage or secure file transfer methods
    #>


    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [array]$PasswordData,
        
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$OutputDirectory = (Get-Location).Path,
        
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$FilePrefix = "ServiceAccountPW",
        
        [Parameter()]
        [switch]$ExcludeWarnings
    )

    begin {
        $correlationId = [System.Guid]::NewGuid()
        Write-Verbose "Starting Export-ADTestPasswordDocumentation - CorrelationId: $correlationId"
        
        # Validate output directory
        if (-not (Test-Path $OutputDirectory)) {
            try {
                New-Item -Path $OutputDirectory -ItemType Directory -Force | Out-Null
                Write-Verbose "Created output directory: $OutputDirectory"
            }
            catch {
                throw "Failed to create output directory '$OutputDirectory': $($_.Exception.Message)"
            }
        }
    }

    process {
        try {
            # Create timestamped filename
            $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
            $fileName = "$FilePrefix-$timestamp.txt"
            $filePath = Join-Path $OutputDirectory $fileName
            
            Write-Verbose "Creating password documentation file: $filePath"
            
            # Build export content
            $exportContent = @()
            
            # Add header with metadata
            $exportContent += "# $FilePrefix Password Documentation"
            $exportContent += "# Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
            $exportContent += "# Total Accounts: $($PasswordData.Count)"
            $exportContent += "# Correlation ID: $correlationId"
            
            if (-not $ExcludeWarnings) {
                $exportContent += ""
                $exportContent += "# =========================================="
                $exportContent += "# SECURITY WARNING"
                $exportContent += "# =========================================="
                $exportContent += "# This file contains sensitive password information"
                $exportContent += "# - Store securely with restricted access permissions"
                $exportContent += "# - Delete after passwords are distributed/changed"
                $exportContent += "# - Do not transmit via unsecured channels"
                $exportContent += "# - Log access and distribution for audit purposes"
                $exportContent += "# =========================================="
            }
            
            $exportContent += ""
            $exportContent += "# Password Information"
            $exportContent += "# Format: Account | Password | Created Date"
            $exportContent += ""
            
            # Process each password entry
            foreach ($entry in $PasswordData) {
                # Validate required properties
                if (-not $entry.ServiceAccountName) {
                    Write-Warning "Skipping entry with missing ServiceAccountName"
                    continue
                }
                if (-not $entry.Password) {
                    Write-Warning "Skipping entry with missing Password for account: $($entry.ServiceAccountName)"
                    continue
                }
                
                # Set default created date if not provided
                $createdDate = if ($entry.CreatedDate) { 
                    $entry.CreatedDate 
                } else { 
                    Get-Date 
                }
                
                # Add account information
                $exportContent += "Account: $($entry.ServiceAccountName)"
                $exportContent += "Password: $($entry.Password)"
                $exportContent += "Created: $($createdDate.ToString('yyyy-MM-dd HH:mm:ss'))"
                
                # Add additional properties if available
                if ($entry.Description) {
                    $exportContent += "Description: $($entry.Description)"
                }
                if ($entry.Department) {
                    $exportContent += "Department: $($entry.Department)"
                }
                if ($entry.ExpirationDate) {
                    $exportContent += "Expires: $($entry.ExpirationDate.ToString('yyyy-MM-dd HH:mm:ss'))"
                }
                
                $exportContent += ""  # Blank line between entries
            }
            
            # Write content to file
            try {
                $exportContent | Out-File -FilePath $filePath -Encoding UTF8 -ErrorAction Stop
                Write-Verbose "Password documentation written to: $filePath"
                
                # Set restrictive file permissions (Windows)
                if ($IsWindows -or $PSVersionTable.PSVersion.Major -lt 6) {
                    try {
                        # Remove inheritance and set restricted permissions
                        $acl = Get-Acl $filePath
                        $acl.SetAccessRuleProtection($true, $false)  # Disable inheritance, don't copy existing
                        
                        # Add only current user and administrators
                        $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
                        $adminGroup = "BUILTIN\Administrators"
                        
                        $accessRule1 = New-Object System.Security.AccessControl.FileSystemAccessRule($currentUser, "FullControl", "Allow")
                        $accessRule2 = New-Object System.Security.AccessControl.FileSystemAccessRule($adminGroup, "FullControl", "Allow")
                        
                        $acl.RemoveAccessRuleAll((New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "FullControl", "Allow")))
                        $acl.RemoveAccessRuleAll((New-Object System.Security.AccessControl.FileSystemAccessRule("Users", "ReadAndExecute", "Allow")))
                        
                        $acl.SetAccessRule($accessRule1)
                        $acl.SetAccessRule($accessRule2)
                        
                        Set-Acl -Path $filePath -AclObject $acl
                        Write-Verbose "Restrictive file permissions applied to: $filePath"
                    }
                    catch {
                        Write-Warning "Failed to set restrictive permissions on password file: $($_.Exception.Message)"
                    }
                }
                
                # Return the file path
                return $filePath
                
            }
            catch {
                throw "Failed to write password documentation file '$filePath': $($_.Exception.Message)"
            }
            
        }
        catch {
            Write-Error "Failed to export password documentation: $($_.Exception.Message)" -ErrorAction Stop
        }
    }

    end {
        Write-Verbose "Completed Export-ADTestPasswordDocumentation - CorrelationId: $correlationId"
    }
}