Enhance configuration data validation and add new utility functions
- Added validation for empty values in Assert-ConfigurationDataParameter. - Introduced Assert-ConfigurationDataSecretReference for secret reference validation. - Implemented Test-ConfigurationDataExpressionParentheses to validate expression syntax. - Added Test-ConfigurationDataMissingReferenceError to check for missing parameter or variable definitions. - Updated Invoke-ConfigurationDataExpression to handle new validation logic. - Revised Readme.md to reflect changes in secret reference handling.
This commit is contained in:
@@ -42,6 +42,10 @@ function Assert-ConfigurationDataParameter {
|
||||
return
|
||||
}
|
||||
|
||||
if((Test-ConfigurationDataValueIsEmpty -Value $Value) -and (-not $Required)){
|
||||
return
|
||||
}
|
||||
|
||||
Assert-ConfigurationDataParameterType -Name $Name -Definition $Definition -Value $Value
|
||||
Assert-ConfigurationDataParameterAllowedValue -Name $Name -Definition $Definition -Value $Value
|
||||
|
||||
|
||||
@@ -48,11 +48,15 @@ function Assert-ConfigurationDataParameterType {
|
||||
if(($Value -isnot [string]) -and ($Value -isnot [System.Security.SecureString]) -and (-not (Test-ConfigurationDataMap -Value $Value))){
|
||||
throw "Parameter [$Name] expects type [secureString], but received [$($Value.GetType().Name)]."
|
||||
}
|
||||
|
||||
Assert-ConfigurationDataSecretReference -Name $Name -TypeName "securestring" -Value $Value
|
||||
}
|
||||
"credential" {
|
||||
if(($Value -isnot [System.Management.Automation.PSCredential]) -and (-not (Test-ConfigurationDataMap -Value $Value))){
|
||||
throw "Parameter [$Name] expects type [credential], but received [$($Value.GetType().Name)]."
|
||||
}
|
||||
|
||||
Assert-ConfigurationDataSecretReference -Name $Name -TypeName "credential" -Value $Value
|
||||
}
|
||||
default {
|
||||
throw "Parameter [$Name] uses unsupported type [$TypeName]."
|
||||
|
||||
45
Private/Assert-ConfigurationDataSecretReference.ps1
Normal file
45
Private/Assert-ConfigurationDataSecretReference.ps1
Normal file
@@ -0,0 +1,45 @@
|
||||
function Assert-ConfigurationDataSecretReference {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Name,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet("credential", "securestring")]
|
||||
[string]
|
||||
$TypeName,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
$Value
|
||||
)
|
||||
|
||||
if(-not (Test-ConfigurationDataMap -Value $Value)){
|
||||
return
|
||||
}
|
||||
|
||||
if(-not (Test-ConfigurationDataMapContainsKey -Map $Value -Key "Provider")){
|
||||
throw "Parameter [$Name] uses type [$TypeName] and a secret reference, but [Provider] is not defined."
|
||||
}
|
||||
|
||||
if(-not (Test-ConfigurationDataMapContainsKey -Map $Value -Key "Name")){
|
||||
throw "Parameter [$Name] uses type [$TypeName] and a secret reference, but [Name] is not defined."
|
||||
}
|
||||
|
||||
$Provider = [string](Get-ConfigurationDataMapValue -Map $Value -Key "Provider")
|
||||
if([string]::IsNullOrWhiteSpace($Provider)){
|
||||
throw "Parameter [$Name] secret reference [Provider] must not be empty."
|
||||
}
|
||||
|
||||
$SecretName = [string](Get-ConfigurationDataMapValue -Map $Value -Key "Name")
|
||||
if([string]::IsNullOrWhiteSpace($SecretName)){
|
||||
throw "Parameter [$Name] secret reference [Name] must not be empty."
|
||||
}
|
||||
|
||||
switch($Provider.ToLowerInvariant()){
|
||||
"keepass" { return }
|
||||
default {
|
||||
throw "Parameter [$Name] uses unsupported secret provider [$Provider]."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,40 @@ function Invoke-ConfigurationDataExpression {
|
||||
return [bool]::Parse($Expression)
|
||||
}
|
||||
|
||||
if(-not (Test-ConfigurationDataExpressionParentheses -Expression $Expression)){
|
||||
throw "Invalid configuration data expression [$Expression]."
|
||||
}
|
||||
|
||||
if($Expression -notmatch "^([A-Za-z][A-Za-z0-9]*)\((.*)\)$"){
|
||||
throw "Invalid configuration data expression [$Expression]."
|
||||
}
|
||||
|
||||
$FunctionName = $Matches[1]
|
||||
$ArgumentText = $Matches[2]
|
||||
|
||||
if($FunctionName -ieq "coalesce"){
|
||||
$RawArguments = @(Split-ConfigurationDataExpressionArguments -ArgumentText $ArgumentText)
|
||||
Assert-ConfigurationDataExpressionMinimumArgumentCount -Name $FunctionName -Arguments $RawArguments -Count 1
|
||||
|
||||
foreach($Argument in $RawArguments){
|
||||
try {
|
||||
$Value = Invoke-ConfigurationDataExpressionArgument -Argument $Argument -Context $Context
|
||||
if(-not (Test-ConfigurationDataValueIsEmpty -Value $Value)){
|
||||
return $Value
|
||||
}
|
||||
}
|
||||
catch {
|
||||
if(Test-ConfigurationDataMissingReferenceError -ErrorRecord $_){
|
||||
continue
|
||||
}
|
||||
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
$Arguments = @()
|
||||
foreach($Argument in @(Split-ConfigurationDataExpressionArguments -ArgumentText $ArgumentText)){
|
||||
$Arguments += ,(Invoke-ConfigurationDataExpressionArgument -Argument $Argument -Context $Context)
|
||||
|
||||
39
Private/Test-ConfigurationDataExpressionParentheses.ps1
Normal file
39
Private/Test-ConfigurationDataExpressionParentheses.ps1
Normal file
@@ -0,0 +1,39 @@
|
||||
function Test-ConfigurationDataExpressionParentheses {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[AllowNull()]
|
||||
[string]
|
||||
$Expression
|
||||
)
|
||||
|
||||
if([string]::IsNullOrWhiteSpace($Expression)){
|
||||
return $true
|
||||
}
|
||||
|
||||
$Depth = 0
|
||||
$InString = $false
|
||||
|
||||
for($Index = 0; $Index -lt $Expression.Length; $Index++){
|
||||
$Character = $Expression[$Index]
|
||||
|
||||
if($Character -eq "'"){
|
||||
$InString = -not $InString
|
||||
continue
|
||||
}
|
||||
|
||||
if($InString){
|
||||
continue
|
||||
}
|
||||
|
||||
if($Character -eq "("){
|
||||
$Depth++
|
||||
}elseif($Character -eq ")"){
|
||||
$Depth--
|
||||
if($Depth -lt 0){
|
||||
return $false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $Depth -eq 0 -and -not $InString
|
||||
}
|
||||
11
Private/Test-ConfigurationDataMissingReferenceError.ps1
Normal file
11
Private/Test-ConfigurationDataMissingReferenceError.ps1
Normal file
@@ -0,0 +1,11 @@
|
||||
function Test-ConfigurationDataMissingReferenceError {
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[System.Management.Automation.ErrorRecord]
|
||||
$ErrorRecord
|
||||
)
|
||||
|
||||
$Message = $ErrorRecord.Exception.Message
|
||||
return $Message -match "^(Parameter|Variable) \[.+\] is not defined\.$"
|
||||
}
|
||||
16
Readme.md
16
Readme.md
@@ -103,7 +103,9 @@ FarmPassphrase = @{
|
||||
Required = $true
|
||||
Sensitive = $true
|
||||
Value = @{
|
||||
SecretName = 'SharePointFarmPassphrase'
|
||||
Provider = 'KeePass'
|
||||
Vault = 'BGW'
|
||||
Name = 'SharePoint/FarmPassphrase'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +114,21 @@ SetupCredential = @{
|
||||
Required = $true
|
||||
Sensitive = $true
|
||||
Value = @{
|
||||
CredentialName = 'SharePointSetup'
|
||||
Provider = 'KeePass'
|
||||
Vault = 'BGW'
|
||||
Name = 'SharePoint/SetupAccount'
|
||||
UserName = 'BGW\SVC_SHP_SETUP'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Secret references are validated by `Resolve-DSCConfigurationData`, but they are resolved by `Resolve-DSCConfigurationSecrets` before the normal data resolve step:
|
||||
|
||||
```powershell
|
||||
$withSecrets = Resolve-DSCConfigurationSecrets -ConfigurationData $merged
|
||||
$resolved = Resolve-DSCConfigurationData -ConfigurationData $withSecrets
|
||||
```
|
||||
|
||||
Array values can be restricted item by item:
|
||||
|
||||
```powershell
|
||||
|
||||
Reference in New Issue
Block a user