newVmId === null) { throw new RuntimeException('Rebuild password: newVmId is null'); } $vcenter = VCenterModel::find($ctx->vcenterId); if (!$vcenter) { throw new RuntimeException("Rebuild password: vCenter #{$ctx->vcenterId} not found"); } // Prefer a customer-supplied credential when one was provided. $newPassword = null; $log = $reinstallLogId ? ReinstallLog::find($reinstallLogId) : null; if ($log && $log->password_supplied_by_customer && $log->password) { try { $newPassword = SignRSA::DecryptFunc($log->password); } catch (\Throwable $e) { $newPassword = null; } } if (!is_string($newPassword) || $newPassword === '') { $newPassword = $this->generatePassword(16); } $output = $this->ssh->changePassword( $ctx->newVmId, $newPassword, $ctx->osFamily, (string) $vcenter->host, (string) $vcenter->user, SignRSA::DecryptFunc($vcenter->password), ); if (!str_contains(strtoupper(trim($output)), 'SUCCESS')) { throw new RuntimeException( "Rebuild password: changePassword script failed — " . trim($output), ); } $encrypted = SignRSA::EncryptFunc($newPassword); ModuleVmware::where('id', $ctx->moduleVmwareId)->update([ 'password' => $encrypted, 'plain_password' => $newPassword, ]); if ($log) { $log->update([ 'password' => $encrypted, 'plain_password' => $newPassword, ]); } Log::info('VmRebuildPasswordService: password rotated', [ 'module_vmware_id' => $ctx->moduleVmwareId, 'new_vm_id' => $ctx->newVmId, 'reinstall_log_id' => $log?->id, ]); return $newPassword; } private function generatePassword(int $length): string { $sets = [ 'ABCDEFGHJKLMNPQRSTUVWXYZ', 'abcdefghjkmnpqrstuvwxyz', '23456789', '!@#$*', ]; $password = ''; $allChars = implode('', $sets); foreach ($sets as $set) { $password .= $set[random_int(0, strlen($set) - 1)]; } for ($i = count($sets); $i < $length; $i++) { $password .= $allChars[random_int(0, strlen($allChars) - 1)]; } $chars = str_split($password); for ($i = count($chars) - 1; $i > 0; $i--) { $j = random_int(0, $i); [$chars[$i], $chars[$j]] = [$chars[$j], $chars[$i]]; } return implode('', $chars); } }