<# .SYNOPSIS Altera a senha de um usuário de forma sincronizada em dois ambientes Active Directory (Cliente e Exchange). .DESCRIPTION Versão 1.0. Este script é um componente crítico da "Plataforma Unificada de Trabalho Digital". Ele primeiro valida a senha antiga do usuário e, se bem-sucedido, aplica a nova senha em ambos os Domain Controllers. O script foi projetado para tratar falhas parciais (ex: sucesso no primeiro AD, falha no segundo) gerando logs específicos para alertar sobre a dessincronização. .NOTES Autor: Gemini (Especialista NGINX & Automação) Data: 15 de outubro de 2025 Versão: 1.0 Contexto: Módulo "Alteração de Senha (Self-Service)" do Portal de Autoatendimento. #> function Set-UnifiedADUserPassword { [CmdletBinding()] param( # --- Parâmetros de Conexão e Autenticação (Obrigatórios) --- [Parameter(Mandatory = $true, HelpMessage = "IP ou FQDN do Domain Controller principal (cliente).")] [string]$ClientADServer, [Parameter(Mandatory = $true, HelpMessage = "Credencial (usuário e senha) da conta de serviço para autenticar no AD do cliente.")] [pscredential]$ClientADCredential, [Parameter(Mandatory = $true, HelpMessage = "IP ou FQDN do Domain Controller do ambiente Exchange.")] [string]$ExchangeADServer, [Parameter(Mandatory = $true, HelpMessage = "Credencial (usuário e senha) da conta de serviço para autenticar no AD do Exchange.")] [pscredential]$ExchangeADCredential, # --- Parâmetros do Usuário (Obrigatórios) --- [Parameter(Mandatory = $true, HelpMessage = "O nome de logon do usuário (SamAccountName) cuja senha será alterada.")] [string]$SamAccountName, [Parameter(Mandatory = $true, HelpMessage = "A senha ANTIGA do usuário. Deve ser um objeto SecureString.")] [System.Security.SecureString]$OldPassword, [Parameter(Mandatory = $true, HelpMessage = "A NOVA senha do usuário. Deve ser um objeto SecureString.")] [System.Security.SecureString]$NewPassword, # --- Parâmetros de Logging --- [Parameter(Mandatory = $false)] [string]$LogFilePath = ".\Set-UnifiedADUserPassword-Log-$(Get-Date -Format 'yyyy-MM-dd').txt" ) # --- LÓGICA PRINCIPAL --- # Dependência da função Write-Log (deve estar no mesmo escopo ou módulo) if (-not (Get-Command Write-Log -ErrorAction SilentlyContinue)) { Write-Host "[ERRO FATAL] A função auxiliar 'Write-Log' não foi encontrada. O script não pode continuar." -ForegroundColor Red return } try { Import-Module ActiveDirectory -ErrorAction Stop } catch { Write-Log -Level 'ERROR' -Message "Falha ao importar o módulo ActiveDirectory. Verifique se as Ferramentas de Administração de Servidor Remoto (RSAT) estão instaladas." return } Write-Log -Level 'INFO' -Message "Iniciando tentativa de alteração de senha para '$SamAccountName'." $clientADSuccess = $false # --- Bloco 1: Alteração no Active Directory do Cliente --- # O cmdlet Set-ADAccountPassword valida a senha antiga e define a nova em uma única operação. try { Write-Host " Tentando alterar a senha no AD do Cliente..." Set-ADAccountPassword -Identity $SamAccountName -OldPassword $OldPassword -NewPassword $NewPassword -Server $ClientADServer -Credential $ClientADCredential -ErrorAction Stop $clientADSuccess = $true Write-Log -Level 'INFO' -Message "SUCESSO: Senha para '$SamAccountName' alterada no AD do Cliente." -TargetADServer $ClientADServer Write-Host " [OK] Senha alterada com sucesso no AD do Cliente." -ForegroundColor Green } catch { # A falha aqui geralmente significa "senha antiga incorreta" ou "política de complexidade não atendida". $errorMessage = "FALHA ao alterar a senha de '$SamAccountName' no AD do Cliente. Erro: $($_.Exception.Message -replace "`r`n"," ")" Write-Log -Level 'ERROR' -Message $errorMessage -TargetADServer $ClientADServer Write-Host " [ERRO] Falha ao alterar senha no AD do Cliente. Verifique a senha antiga e as políticas de complexidade." -ForegroundColor Red # Não continuamos se o primeiro passo falhar. return } # --- Bloco 2: Alteração no Active Directory do Exchange --- # Este bloco só executa se o primeiro foi bem-sucedido. if ($clientADSuccess) { try { Write-Host " Tentando alterar a senha no AD do Exchange para manter a sincronia..." # Repetimos a operação no segundo AD Set-ADAccountPassword -Identity $SamAccountName -OldPassword $OldPassword -NewPassword $NewPassword -Server $ExchangeADServer -Credential $ExchangeADCredential -ErrorAction Stop Write-Log -Level 'INFO' -Message "SUCESSO: Senha para '$SamAccountName' alterada no AD do Exchange." -TargetADServer $ExchangeADServer Write-Host " [OK] Senha alterada com sucesso no AD do Exchange." -ForegroundColor Green Write-Log -Level 'INFO' -Message "SINCRONIZAÇÃO COMPLETA: A senha de '$SamAccountName' foi alterada com sucesso em ambos os ambientes." } catch { # ESTE É O CENÁRIO CRÍTICO DE DESSINCRONIZAÇÃO $errorMessage = "FALHA DE SINCRONIZAÇÃO: A senha de '$SamAccountName' FOI ALTERADA no AD do Cliente, mas FALHOU no AD do Exchange. AÇÃO MANUAL PODE SER NECESSÁRIA. Erro: $($_.Exception.Message -replace "`r`n"," ")" Write-Log -Level 'ERROR' -Message $errorMessage -TargetADServer $ExchangeADServer Write-Host " [ERRO CRÍTICO] Falha ao sincronizar a senha no AD do Exchange. A senha foi alterada apenas no primeiro ambiente!" -ForegroundColor Red } } Write-Host "Processo de alteração de senha concluído." } # --- FUNÇÃO AUXILIAR DE LOG (Exemplo, assumindo que já existe no seu ambiente) --- # Coloque aqui a sua função Write-Log ou carregue-a de outro arquivo .ps1 # Exemplo mínimo para o script funcionar de forma autônoma: function Write-Log { param( [Parameter(Mandatory=$true)] [string]$Message, [Parameter(Mandatory=$true)] [ValidateSet('INFO', 'WARN', 'ERROR')] [string]$Level, [Parameter(Mandatory=$false)] [string]$TargetADServer ) $LogFilePath = ".\Set-UnifiedADUserPassword-Log-$(Get-Date -Format 'yyyy-MM-dd').txt" $logEntry = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - [$Level] - $Message" $logEntry | Out-File -FilePath $LogFilePath -Append }