common.ps1
### Includes: #. $PSScriptRoot\files.ps1 ### Variables: # ... $script:config = $null #$env:MMH_CONFIG_PATH ### Functions: function Get-ValidFileName { param ( [Parameter(Mandatory = $true)] [string]$Filename, [string]$Replacement = "_" ) [IO.Path]::GetinvalidFileNameChars() | % { $Filename = $Filename.Replace($_, $Replacement) } $Filename = $Filename -replace ('{0}+' -f ([regex]::Escape($Replacement))), $Replacement return $Filename } function Get-MD5Hash { [OutputType([string])] param ( [Parameter(Mandatory = $true)] [string]$String ) $md5_csp = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider $utf8 = New-Object -TypeName System.Text.UTF8Encoding return [string](([System.BitConverter]::ToString($md5_csp.ComputeHash($utf8.GetBytes($String)))) -replace "-") } ### Раскрыть значения "{env:ENV_VAR}" function Expand-String { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$String ) Write-Verbose "Expand-String: String: '$String'" if (!$String) { return $String } ### Example: '{env:TEST_ENV2}:{env:TEST_ENV3}' -> 'aaaTEST_ENV2 value:TEST_ENV3 valuebbb' $result = [system.Text.StringBuilder]::new($String) $matches = @(Select-String -InputObject $String -Pattern '\{([^}]+)\}' -AllMatches | select -ExpandProperty matches) foreach ($m in $matches) { [string]$var = $m.Groups[1].Value if ($var.StartsWith('env:')) { $env_var = $var.Substring('env:'.Length) $value = [System.Environment]::GetEnvironmentVariable($env_var) if ($value) { $result.Replace($m.Groups[0].Value, $value) >$null } } else { Write-Warning "Cannot expand var '$var': unknown syntax" } } ### WARNING: Can be injections: # $result = Invoke-Expression "`"$($String)`"" # if ($Secret.StartsWith('$env:')) { # $env_var = $Secret.Substring('$env:'.Length) # $result = [System.Environment]::GetEnvironmentVariable($env_var) # } # # if (!$result) { # throw "Cannot expand secret '$Secret'" # } return $result.ToString() } ### Рекурсивно раскрыть значения "{env:ENV_VAR}" в конфиге function Expand-ConfigValues { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [hashtable]$Node ) process { $keys = @($Node.Keys | % { $_ }) $keys | % { $value = $node[$_] if (($value -is [string]) -and ("$value".Contains('{'))) { $node[$_] = Expand-String $value } elseif ($value -is [hashtable]) { $node[$_] = Expand-ConfigValues -Node $value } } $node } } function Get-Config { [CmdletBinding()] param ( $Path = $env:MMH_CONFIG_PATH ) Write-Verbose "Get-Config: begin" if (!$script:config) { if (!(Get-Module 'powershell-yaml' -ListAvailable)) { Install-Module 'powershell-yaml' -Force -ErrorAction 'Stop' -SkipPublisherCheck } # Import-Module 'powershell-yaml' -ErrorAction 'Stop' -DisableNameChecking Write-Verbose "Get-Config: read config '$Path'" $Path = (Resolve-Path $Path).Path Import-Module powershell-yaml -ea Stop $script:config = ConvertFrom-Yaml -Yaml (gc $Path -raw) -ea Stop | Expand-ConfigValues } else { Write-Verbose "Get-Config: config already read: '$Path'" } return $script:config } |