Как безопасно читать файлы PowerShell.PSD1

Формат файла манифеста модуля PowerShell (.psd1) - это, по существу, литерал Hashtable с определенными ключами. Это идеально подходит для файла конфигурации для PowerShell script. В конечном итоге я хочу прочитать файл .psd1, содержащий набор ключей, специфичных для script.

Например (MyScriptConfig.psd1):

@{
    FTPHost = "ftp.blah.com"
    FTPUserName = "blah"
    FTPPassword = "blah"
}

Нет причин, по которым я не могу использовать XML, INI, JSON или что-то еще для этой информации, но я предпочел бы использовать тот же базовый формат данных, что и модуль PowerShell.

Очевидно, что проще всего прочитать текст и передать его в Invoke-Expression, который вернет Hashtable, но затем он будет вызывать все, что в файле, которое подвержено ошибкам и потенциально опасно.

Я думал, что вспомнил командлет для чтения этих данных с помощью "безопасного" подмножества командлетов PowerShell, но я думал о разделах ConvertFrom-StringData и DATA, ни один из которых не позволяет мне читать произвольный файл, содержащий литерал Hashtable.

Есть ли что-то встроенное в PowerShell, которое позволяет мне это делать? Если ничего не встроено, то я, вероятно, поеду по маршруту JSON или Key = Value с ConvertFrom-StringData.

Ответ 1

Версия Powershell 5 добавила Cmdlet Import-PowershellDataFile для безопасного анализа файлов PSD1.

До версии 5 было по крайней мере три решения:

  • Командлет Import-LocalizedData. Который, хотя и предназначенный или обрабатывающий языковые файлы, будет читать любой файл в формате PSD1.

    # Create a test PSD1 file
    @'
        @{
            a1 = 'a1'
            a2 = 2
            a3 = @{
              b1 = 'b1'
            }
        }
    '@ | Set-Content -Path .path\example.psd1
    
    # Read the file
    Import-LocalizedData -BaseDirectory .\path -FileName example.psd1 -BindingVariable Data
    
    # Use the data
    $Data.a1
    $Data.a3.b1
    
  • Также можно обрабатывать потоковые данные с помощью раздела данных (в некотором роде поражения целей).

    # Safely parse data
    $Data2 = DATA {
        @{
            a1 = 'a1'
            a2 = 2
            a3 = @{
              b1 = 'b1'
            }
        }
    }
    
    # Use the data
    $Data2.a1
    $Data2.a3.b1
    
  • Третий - это атрибут преобразования параметра PowerShell DSC, упомянутый @Jakub Berezanski.

Ответ 2

PowerShell DSC определяет атрибут преобразования параметров, используемый для поддержки передачи пути к файлу .psd1 в качестве значения параметра ConfigurationData при вызове конфигурации. Этот атрибут является общедоступным и может использоваться в пользовательской функции, например:

function Parse-Psd1
{
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformation()]
        [hashtable] $data
    )
    return $data
}
Parse-Psd1 C:\MyData.psd1

Реализация атрибута вызывает внутренний помощник, который оценивает содержимое файла в контексте ограниченного языка, где разрешены только следующие командлеты:

Import-LocalizedData
ConvertFrom-StringData
Write-Host
Out-Host
Join-Path

Ответ 3

Модульные манифесты специально разработаны для использования только ограниченного подмножества PSH, однако нет прямого 1 прямого способа обработки содержимого (и получения всех данных) в этом режиме. Однако вы можете проверить манифест с помощью Test-ModuleManifest 2 и только затем оценить содержимое файла.


1 По крайней мере, насколько PowerShell In Action 2nd Ed охватывает его.

2 К сожалению, онлайн-копия книги использует изображения для исходного кода (чтобы разрешить аннотации), поэтому здесь не могу копировать.