Q:

How to read PowerShell .PSD1 files safely

The PowerShell module manifest file format (.psd1) is essentially a Hashtable literal with certain keys expected. This is ideal for a configuration file for a PowerShell script. What I ultimately want to do is read a .psd1 file that contains a set of keys specific to the script.
For example (MyScriptConfig.psd1):
@{
    FTPHost = "ftp.blah.com"
    FTPUserName = "blah"
    FTPPassword = "blah"
}

There's no reason I can't use XML, INI, JSON or whatever for this information, but I'd rather it use the same basic data format as PowerShell's module manifests.
Obviously the easiest thing would be to read the text and pass it to Invoke-Expression which would return a Hashtable, but then it would invoke anything that's in the file, which is error prone and potentially unsafe.
I thought I recalled a cmdlet for reading this data using a "safe" subset of PowerShell cmdlets, but I was thinking of ConvertFrom-StringData and DATA sections, neither of which let me read an arbitrary file containing a Hashtable literal.
Is there something built into PowerShell that lets me do this? If there's nothing built in, then I would probably go the route of JSON or Key=Value with ConvertFrom-StringData.

A:

Powershell version 5 added the Cmdlet Import-PowershellDataFile for safely parsing PSD1 files.
Prior to version 5, there were at least three solutions:

The Cmdlet Import-LocalizedData. Which, though intended for processing language files, will read any PSD1 formatted file.
# 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

It is also possible to process in-line data with a Data Section (in-line sort of defeats the purpose).
# Safely parse data
$Data2 = DATA {
    @{
        a1 = 'a1'
        a2 = 2
        a3 = @{
          b1 = 'b1'
        }
    }
}

# Use the data
$Data2.a1
$Data2.a3.b1

The third being the PowerShell DSC parameter transformation attribute mentioned by @Jakub Berezanski.

A:

PowerShell DSC defines a parameter transformation attribute, used to support passing a path to a .psd1 file as the value of the ConfigurationData parameter when invoking a Configuration. This attribute is public and can be used in a custom function, such as:
function Parse-Psd1
{
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [Microsoft.PowerShell.DesiredStateConfiguration.ArgumentToConfigurationDataTransformation()]
        [hashtable] $data
    )
    return $data
}
Parse-Psd1 C:\MyData.psd1

The attribute implementation calls an internal helper that evaluates the contents of the file in a restricted language context, where only the following cmdlets are permitted:
Import-LocalizedData
ConvertFrom-StringData
Write-Host
Out-Host
Join-Path

