Keyops-Azure.psm1

$ErrorActionPreference = 'Stop'

<#
.SYNOPSIS
    Regstering vaults for Azure Secret
.DESCRIPTION
    If vault is exist, then it's returns from cmdlet without exception throw
.OUTPUTS
    Vault that has been registered or existing
.EXAMPLE
    Regsirer-AzureVault
.EXAMPLE
    Register-AzureVault -Name My-Azure-Vault
#>

Function Register-AzureVault
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Name
    )

    $vaultObj = Get-AzureVault -Name $Name
    if($null -eq $vaultObj){
        $vaultObj = Register-SecretVault `
            -Name $Name `
            -ModuleName Microsoft.PowerShell.SecretStore `
            -PassThru `
            -Verbose:$false
    }
    
    return [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$vaultObj
}

<#
.SYNOPSIS
    Unregister Azure vault
.DESCRIPTION
    Unregisters the Azure vault that is passed as a pipeline argument.
.EXAMPLE
    Register-AzureVault -Name My-Azure-Vault | Unregister-AzureVault
.EXAMPLE
Register-AzureVault -Name My-Azure-Vault | Unregister-AzureVault
#>

Function Unregister-AzureVault
{
    [CmdletBinding(DefaultParameterSetName='ByVault')]
    param(
        [Parameter(Mandatory, ValueFromPipeline, ParameterSetName='ByVault')]
        [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$Vault
    ) 
    
    Unregister-SecretVault -Name $Vault.Name
}

<#
.SYNOPSIS
    Returns vaults of Azure Secret
.DESCRIPTION
    Azure vault are secret vault that are managed by the Microsoft.PowerShell.SecretStore module.
.EXAMPLE
    Get-AzureVault
.EXAMPLE
    Get-AzureVault -Name My-Azure-Vault
#>

Function Get-AzureVault
{
    [CmdletBinding(DefaultParameterSetName='parameterless')]
    param(
        [Parameter(Mandatory, ParameterSetName='ByName')]
        [string]$Name
    )  

    switch ($PSCmdlet.ParameterSetName) {
        'parameterless' {
            $vaultObj = Get-SecretVault -Verbose:$false `
                | Where-Object -Property ModuleName -eq 'Microsoft.PowerShell.SecretStore'
        }
        'ByName' {
            $vaultObj = Get-SecretVault -Verbose:$false `
                | Where-Object -Property ModuleName -eq 'Microsoft.PowerShell.SecretStore' `
                | Where-Object -Property Name -eq $Name
        }
    }

    return $vaultObj
}

<#
.SYNOPSIS
    Returns secrets from vault
.DESCRIPTION
    Return secrets from vault, but not receive it
.EXAMPLE
    Get-AzureVault | Get-AzureSecret
.EXAMPLE
    Get-AzureVault | Get-AzureSecret my-azure-secret
#>

Function Get-AzureSecret
{
    [CmdletBinding(DefaultParameterSetName='ByVaultOnly')]
    param(

        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ParameterSetName='ByVaultOnly')]
        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ParameterSetName='ByVaultAndSecretName')]
        [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$Vault,

        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ParameterSetName='ByVaultAndSecretName', Position = 0)]
        [string]$Name
    )

    Write-Verbose "Parameter `'Vault`' has property values:"
    $Vault | Format-List | Out-String | Write-Verbose

    switch($PSCmdlet.ParameterSetName)
    {
        'ByVaultOnly'
        {
            [Microsoft.PowerShell.SecretManagement.SecretInformation[]]$secretInfoObjArray = `
                Get-SecretInfo -Vault $Vault.Name -Verbose:$false 
        }
        'ByVaultAndSecretName'
        {
            Write-Verbose "Parameter `'Name`' has value `'$Name`'"

            [Microsoft.PowerShell.SecretManagement.SecretInformation[]]$secretInfoObjArray = 
                `Get-SecretInfo -Vault $Vault.Name -Name $Name -Verbose:$false
        }
    }   

    $vaultName = $Vault.Name
    if(0 -lt $secretInfoObjArray.Count)
    {
        Write-Verbose "This objects was found in vault `'$vaultName`'."
        $secretInfoObjArray | Format-List | Out-String | Write-Verbose
    }
    else{
        Write-Verbose "Objects in vault `'$vaultName`' not found."
    }

    return [Microsoft.PowerShell.SecretManagement.SecretInformation[]]$secretInfoObjArray
}

<#
.SYNOPSIS
    Receive secret from vault
.DESCRIPTION
    Receive secret from vault.
.EXAMPLE
    Get-AzureVault | Receive-AzureSecret 'my-azure-secret'
.EXAMPLE
    Get-AzureVault | Get-Secret 'my-azure-secret' | Receive-AzureSecret
#>

Function Receive-AzureSecret
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline, ParameterSetName ='BySecret')]
        [Microsoft.PowerShell.SecretManagement.SecretInformation]$Secret,
        [Parameter(Mandatory, ValueFromPipeline, ParameterSetName ='ByVaultAndSecretName')]
        [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$Vault,
        [Parameter(Mandatory, ParameterSetName ='ByVaultAndSecretName',Position = 1)]
        [string]$secretName 
    )

    switch ($PSCmdlet.ParameterSetName) {
        'BySecret' {  
            $cred = New-Object Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo `
                ($Secret.VaultName, $Secret.Name) -Verbose:$false
        }
        'ByVaultAndSecretName' {
            $cred = New-Object Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo `
                ($Vault.Name, $secretName) -Verbose:$false          
        }
    }

    return [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo]$cred
}

<#
.SYNOPSIS
    Create and set secret into vault
.DESCRIPTION
    Create and set secret into vault
.EXAMPLE
    Get-AzureVault | Set-AzureSecret -PATName 'my-azure-secret' -PAT 'patlongvalue'
#>

Function Set-AzureSecret
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$Vault,
        [Parameter(Mandatory)][string]$PatName,
        [Parameter(Mandatory)][string]$Pat
    )

    $credentialObj = New-Object System.Management.Automation.PSCredential($PatName, ($Pat | ConvertTo-SecureString -AsPlainText -Force))

    $secretObj = Set-Secret `
        -Vault $Vault.Name `
        -Name  $credentialObj.GetNetworkCredential().username `
        -Secret $credentialObj 

    return [Microsoft.PowerShell.SecretManagement.SecretVaultInfo]$Vault
}

<#
.SYNOPSIS
    Remove secret from azure vault
.DESCRIPTION
    Remove secret from azure vault
.EXAMPLE
    Get-AzureVault | Get-AzureSecret 'my-azure-secret' | Remove-Secret
#>

Function Remove-AzureSecret
{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
        [Microsoft.PowerShell.SecretManagement.SecretInformation]$Secret
    )

    BEGIN{}
    PROCESS{
        Remove-Secret -Vault $Secret.VaultName -Name $Secret.Name
    }
    END{

    }
}

<#
.SYNOPSIS
    Register Azure Artifact repository
.DESCRIPTION
    Register Azure Artifact repository
.EXAMPLE
    Register-AzureVault -Name Azure-Vault `
        | Set-AzureSecret -PatName azure-pat -PAT '<MY_AZURE_PAT_VALUE>' `
        | Get-AzureSecret -Name 'azure-pat' `
        | Receive-AzureSecret `
        | Register-AzureRepository -Organization <OrgName> -Project <ProjectName> -Feed <FeedName>
#>

Function Register-AzureRepository
{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
        [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo]$CredentialInfo,
        [Parameter(Mandatory=$true)][string]$Organization,
        [Parameter(Mandatory=$true)][string]$Project,
        [Parameter(Mandatory=$true)][string]$Feed
    )

    $repoObj = Register-PSResourceRepository `
        -Name $Feed `
        -Uri "https://pkgs.dev.azure.com/${Organization}/${Project}/_packaging/${Feed}/nuget/v3/index.json"  `
        -Trusted `
        -CredentialInfo $CredentialInfo `
        -ApiVersion v3

    return $repoObj
}

<#
.SYNOPSIS
    Unregister Azure Artifact repository
.DESCRIPTION
    Unregister Azure Artifact repository
.EXAMPLE
    Get-AzureRepository -Name <repoName> | Unregister-AzureRepository
#>

Function Unregister-AzureRepository{
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSRepositoryInfo]$repo)
    
    if($true -eq (IsAzureRepository($repo))){
        Unregister-PSResourceRepository -Name $repo.Name
    }
} 

Function IsAzureRepository
{
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSRepositoryInfo]$Repo) 
        
    if('https://pkgs.dev.azure.com' -eq ($Repo.Uri.ToString().ToLower().Trim().Substring(0,26))){
        return $true
    }
    else{
        return $false
    }
}

<#
.SYNOPSIS
    Returns Azure Artifacts repositories
.DESCRIPTION
    Returns only Azure Artifacts repositories. Other repositories will be skipped
.EXAMPLE
    Get-AzureRepository
.EXAMPLE
    Get-AzureRepository -Name <repoName>
#>

Function Get-AzureRepository
{
    [CmdletBinding(DefaultParameterSetName='parameterless')]
    param(
        [Parameter(ParameterSetName='ByName')]
        [string]$Name
    )

    switch ($PSCmdlet.ParameterSetName) {
        'ByName' {  
            return Get-PSResourceRepository `
                | Where-Object -FilterScript{$true -eq (IsAzureRepository($_)) -and $true -eq ($_.Name -eq $Name)}
        }
        'parameterless' {
            return Get-PSResourceRepository `
                | Where-Object -FilterScript{$true -eq (IsAzureRepository($_))}
        }
    }
}

<#
.SYNOPSIS
    Set properties of Azure Artifacts repository
.DESCRIPTION
    Set properties of Azure Artifacts repository
.EXAMPLE
    Get-AzureRepository | Set-AzureRepository ... parameters
#>

Function Set-AzureRepository
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSRepositoryInfo]$repo,
        [string]$Uri,
        [switch]$Trusted = $false,
        [int]$Priority,
        [ApiVersion]$ApiVersion,
        [PSCredentialInfo]$CredentialInfo
    )

    Get-AzureRepository `
        | Where-Object -Property Name -eq $repo.Name `
        | Set-PSResourceRepository -Uri $Uri -Trusted $Trusted -Priority $Priority `
            -ApiVersion $ApiVersion -CredentialInfo $CredentialInfo
}