wks_automationHelper.psm1



function get-ahCurrentAutomationInfo {
    [cmdletbinding()]

    $ServicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
    
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $ServicePrincipalConnection.TenantId `
        -ApplicationId $ServicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint  | Write-Verbose 

    Select-AzureRmSubscription -SubscriptionId $ServicePrincipalConnection.SubscriptionID  | Write-Verbose 

    $automationAccounts = @(Get-AzureRmAutomationAccount)
    write-verbose "$($automationAccounts.count) AutomationAccounts found"
    
    $found = $false
    foreach ($Automation in $automationAccounts)
    {
        $Job = Get-AzureRmAutomationJob -ResourceGroupName $Automation.ResourceGroupName `
            -AutomationAccountName $Automation.AutomationAccountName -Id $PSPrivateMetadata.JobId.Guid `
            -ErrorAction SilentlyContinue
        if (!([string]::IsNullOrEmpty($Job)))
        {
            if ($PSPrivateMetadata.JobId -eq $Job.JobId.Guid) {
                $AutomationInformation = @{}
                $AutomationInformation.Add("Location",$Automation.Location)
                $AutomationInformation.Add("ResourceGroupName",$Job.ResourceGroupName)
                $AutomationInformation.Add("AutomationAccountName",$Job.AutomationAccountName)
                $AutomationInformation.Add("RunbookName",$Job.RunbookName)
                $AutomationInformation.Add("JobId",$Job.JobId.Guid)
                $AutomationInformation.Add("SubscriptionId",$ServicePrincipalConnection.SubscriptionID)
                $AutomationInformation
                $found = $true
                break;
            }
        }
    }
    if ($found -ne $true) { throw [Exception] "Automation Account information not found" }
}

function import-ahVariables {
    [cmdletbinding(DefaultParameterSetName = 'withAzureAutomationVariables')]
    param(
        [Parameter(Mandatory=$true, ParameterSetName='withProvidedVariables')]
        [Parameter(Mandatory=$true, ParameterSetName='withAzureAutomationVariables')]
        [object[]]$variableSets,
        [Parameter(Mandatory=$true, ParameterSetName='withProvidedVariables')]
        [PSCustomObject]$variables,
        [Parameter(Mandatory=$false, ParameterSetName='withProvidedVariables')]
        [Parameter(Mandatory=$false, ParameterSetName='withAzureAutomationVariables')]
        [ValidateSet('global','local','script')]
        [string]$scope='script'
    )

    Write-Verbose "Calling cmd-let 'load-ahVariables' with parameterSet '$($PSCmdlet.ParameterSetName)'"

    if ($PSCmdlet.ParameterSetName -eq 'withAzureAutomationVariables') {
        if($PSPrivateMetadata.JobId) {
            write-verbose 'Running in Azure Automation'
            # Finding VariableSet matching with provided config file content
            $vset = $null

            $aaInfo = get-ahCurrentAutomationInfo -verbose
            
            foreach ($vs in $variableSets) {
                Write-verbose "Testing variableSet $($vs.name)"
                $matchingVSet = $true
                foreach ($var in $vs.variableSet) {
                    try {
                        (Get-AzureRMAutomationVariable -Name $($var.name) -ResourceGroupName $aaInfo.ResourceGroupName -AutomationAccountName $aaInfo.AutomationAccountName) |out-null
                        Write-verbose "- Validated attribute $($var.id) = $($var.name)"
                        $matchingVSet = $true
                    } catch {
                        $matchingVSet = $false
                        Write-Verbose "- Missing variable in Automation Accunt : $($var.name)"
                        Write-verbose $_.exception.message
                    }
                }
                if ($matchingVSet) { $vset = $vs; break }
                
            }
            if ($null -eq $vset) { 
                throw [System.ArgumentException]::new("No variableSet matching the attributes provided")
            }
            Write-Verbose "Using variableSet '$($vset.name)'"
            
            # Load Variables according to detected variableSet
            foreach ($var in $vset.variableSet) {
                try {
                    new-variable -name $var.id -value ((Get-AzureRMAutomationVariable -Name $($var.name) -ResourceGroupName $aaInfo.ResourceGroupName -AutomationAccountName $aaInfo.AutomationAccountName)).value -scope $scope -Force
                    Write-verbose "Loaded $($var.name) : $($var.id) = $(get-variable -name $var.id -ValueOnly)"
                    
                } catch {
                    throw "Failed creating variable '$($var.name)'"
                }
            }
        }
        else {
            throw "Reading Azure Automation variables is not supported outside an Azure Automation Runbook"
        }
    } else {
        # Finding VariableSet matching with provided config file content
        $vset = $null
        
        foreach ($vs in $variableSets) {
            Write-verbose "Testing variableSet $($vs.name)"
            $matchingVSet = $true
            foreach ($var in $vs.variableSet) {
                if (Invoke-Expression "`$variables.name -notcontains '$($var.name)'") {
                    Write-Verbose "- Missing attribute $($var.name)"    
                    $matchingVSet = $false
                } else {
                    Write-verbose "- Validated attribute $($var.id) = $($var.name)"
                }
            }
            if ($matchingVSet) { $vset = $vs; break }
            
        }
        if ($null -eq $vset) { 
            throw [System.ArgumentException]::new("No variableSet matching the attributes provided")
        }
        Write-Verbose "Using variableSet '$($vset.name)'"
        
        # Load Variables according to detected variableSet
        foreach ($var in $variables) {
            if ($null -ne $var.value) {
                $v = $vset.variableSet |? {$_.name -eq $var.name}
                if ($null -eq $v) { write-warning "Variable $($var.name) is not recognized as member of this variableSet. Thus the variable was not created"}
                else {
                    
                    new-variable -name $v.id -value "$($var.value)" -scope $scope -Force
                    Write-verbose "Loaded $($var.name) : $($v.id) = $(get-variable -name $v.id -ValueOnly)"
                }
            } else {
                write-error "Failed loading variable '$($var.name)'"
            }
        }
    }   
}

function get-ahSecretFromAzVault {
    [cmdletbinding()]
    param (
        [Parameter(Mandatory=$true)][string]$vaultName,
        [Parameter(Mandatory=$true)][string]$vaultKeyName
    )
    Write-verbose "Retrieving Secret from vault '$vaultName' with key '$vaultKeyName'"
    
    # Name of the Azure Run As connection
    $ConnectionName = 'AzureRunAsConnection'
    try
    {
        if($PSPrivateMetadata.JobId) {
            write-verbose 'Running in Azure Automation'
            
            # Get the connection properties
            $ServicePrincipalConnection = Get-AutomationConnection -Name $ConnectionName      
        
            $null = Connect-AzAccount `
                -ServicePrincipal `
                -TenantId $ServicePrincipalConnection.TenantId `
                -ApplicationId $ServicePrincipalConnection.ApplicationId `
                -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint 
        } else {
            write-verbose 'Running outside Azure Automation'
            $null = Connect-AzAccount -ea stop
            
        }
    }
    catch 
    {
        if (!$ServicePrincipalConnection)
        {
            # You forgot to turn on 'Create Azure Run As account'
            $ErrorMessage = "Connection $ConnectionName not found: $($_.exception.message)"
            throw $ErrorMessage
        }
        else
        {
            # Something else went wrong
            #Write-Error -Message $_.Exception.Message
            throw $_.Exception
        }
    }
    ########################################################
    try {
        $secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $vaultKeyName -ea stop
        $secretValueText = '';
        $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret.SecretValue)
        try {
            $secretValueText = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
        } finally {
            [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
        }
        $secretValueText
    } catch {
        Throw "Failed Querying KeyVault Secret: $($_.exception.message)"
    }
}