如何安全地读取PowerShell.PSD1文件

如何安全地读取PowerShell.PSD1文件,powershell,Powershell,PowerShell模块清单文件格式(.psd1)本质上是一个哈希表文本,需要某些键。这非常适合于PowerShell脚本的配置文件。我最终要做的是读取一个.psd1文件,该文件包含一组特定于脚本的键 例如(MyScriptConfig.psd1): 对于这些信息,我没有理由不能使用XML、INI、JSON或任何东西,但我更希望它使用与PowerShell模块清单相同的基本数据格式 显然,最简单的方法是读取文本并将其传递给Invoke Expression,后者将返回哈希表,但随后它将调用文件中

PowerShell模块清单文件格式(.psd1)本质上是一个哈希表文本,需要某些键。这非常适合于PowerShell脚本的配置文件。我最终要做的是读取一个.psd1文件,该文件包含一组特定于脚本的键

例如(MyScriptConfig.psd1):

对于这些信息,我没有理由不能使用XML、INI、JSON或任何东西,但我更希望它使用与PowerShell模块清单相同的基本数据格式

显然,最简单的方法是读取文本并将其传递给
Invoke Expression
,后者将返回哈希表,但随后它将调用文件中的任何内容,这很容易出错,并且可能不安全

我想我想起了一个cmdlet,它使用PowerShell cmdlet的“安全”子集读取此数据,但我想到的是
ConvertFrom-StringData
data
节,它们都不允许我读取包含哈希表文字的任意文件


PowerShell中有内置的东西可以让我这样做吗?如果没有内置内容,那么我可能会选择JSON或Key=Value,使用
ConvertFrom StringData

模块清单专门设计为仅使用PSH的一个受限子集,但是在该模式下没有直接的方法来处理内容(并获取所有数据)。但是,您可以使用
testmodulemanifest
2验证清单,然后才评估文件的内容


1至少在第二版中的PowerShell涵盖范围内


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
属性实现调用内部帮助程序,该帮助程序在受限语言上下文中评估文件的内容,其中仅允许以下cmdlet:

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

Powershell版本5添加了用于安全解析PSD1文件的Cmdlet

在版本5之前,至少有三种解决方案:

  • Cmdlet。虽然用于处理语言文件,但将读取任何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
    
  • 也可以使用一种方法来处理在线数据(在线排序有点达不到目的)

  • 第三个是第一个

  • # 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