Mother.psm1
##region Variables Set-Variable -Name "DefaultSMFXSubID" ` -Value "" ` -Option AllScope Set-Variable -Name "DefaultSMFXTenantID" ` -Value "" ` -Option AllScope Set-Variable -Name "TMSKeyVault" ` -Value $null ` -Option AllScope Set-Variable -Name "TMSStorage" ` -Value $null ` -Option AllScope Set-Variable -Name "TMSTable" ` -Value $null ` -Scope Global -Visibility Public #endregion <# TODO: * serch all keyvaults #> Function Test-TooManyKeyVault() { <# .SYNOPSIS Verify if a key vault by name exists .DESCRIPTION Given the name of a Key Vault, returns a binary response ($true/$false) as to whether it exists .PARAMETER Name The name of a Key Vault resource in the current Azure subscription. .EXAMPLE PS> Test-TooManyKeyVault -Name "MyVault" Returns true if there is at least one Key Vault named MyVault in the current subscription, or false if none were found. .LINK Get-TooManyKeyVault Get-AzKeyVault #> param([string]$Name) If (Get-TooManyKeyVault -Name $Name) { return $true } else { return $false } } Function Install-TooManySecret { <# .SYNOPSIS Create Azure resources for storage .DESCRIPTION Makes calls to Azure Resource Manager to create a new key vault in the current Azure subscription #> [Cmdletbinding()] param( [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('VaultName')] #The name of the Key Vault to use in Azure [string]$KeyVault, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('RG')] #Name of the Resource Group to store resources in [string]$ResourceGroupName, [parameter(ValueFromPipelineByPropertyName=$true)] #Name of the storage account to keep the table for metadata in [string]$StorageAccountName, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('StorageAccountResourceGroup')] #Resource group where storage account is kept [string]$StorageAccountRG, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('TableName','TMSTable')] #Table within the storage account to store metadata [string]$Table, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('Region','AzureRegion')] #Azure region to store Azure resources in [string]$Location, #return the created object(s) [switch]$PassThru ) Process { ForEach ($ParamName in @('KeyVault','ResourceGroupName','StorageAccountName','StorageAccountRG','Table','Location')) { If ([string]((Get-Variable -name $ParamName -ErrorAction Ignore).Value) -eq '') { write-Debug "Setting [$ParamName] to [$(Get-TooManySetting -name $ParamName)]" Set-Variable -Name $ParamName -Value (Get-TooManySetting -name $ParamName) } } If ($KeyVault -eq '') { $KeyVault="TMSVault{0:00000}" -f (Get-Random -Minimum 0 -Maximum 100000) } If ($ResourceGroupName -eq '') { $ResourceGroupName="TMS-rg" } If ($StorageAccountName -eq '') { $StorageAccountName= ("{0}{1:0000000}" -f $KeyVault,(Get-Random -Minimum 0 -Maximum 10000000)).ToLower() } If ($StorageAccountRG -eq '') { $StorageAccountRG=$ResourceGroupName } If ($Table -eq '') { $Table=$KeyVault } If ($Location -eq '') { $Location = 'westus' } New-TooManyTable -Name $Table -StorageAccountName $StorageAccountName -ResourceGroupName $StorageAccountRG -Location $Location -PassThru:$PassThru New-TooManyKeyVault -Name $KeyVault -ResourceGroupName $ResourceGroupName -Location $Location -PassThru:$PassThru } } Function Add-UserToAccessKeyVault { param( [Microsoft.Azure.Commands.KeyVault.Models.PSKeyVault]$KeyVault, [string]$UserPrincipalName = ((Get-AzContext).Account.Id), [switch]$AllPermissions ) $Permissions = @('Get','List','Set') If ($AllPermissions) { $Permissions += @('Delete','Backup','Restore','Recover','Purge') } Write-Debug "Adding [$UserPrincipalName to [$($KeyVault.VaultName)] with [$($Permissions -join ';')] permissions" Set-AzKeyVaultAccessPolicy -InputObject $KeyVault -UserPrincipalName $UserPrincipalName -PermissionsToSecrets $Permissions } Function New-TooManyKeyVault() { <# .SYNOPSIS Create a new key vault .DESCRIPTION Makes calls to Azure Resource Manager to create a new key vault in the current Azure subscription .PARAMETER Name Name to give this Key Vault #> [Cmdletbinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias('KeyVault')] [string]$Name, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('RG')] [string]$ResourceGroupName, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('Region','AzureRegion')] [string]$Location, #return the created object(s) [switch]$PassThru ) Process { If (-not $TMSSettings) { Import-TooManySetting } If (Test-TooManyAzure -SwitchContext) { $KeyVault = Get-AzKeyVault -VaultName $Name -ResourceGroupName $ResourceGroupName -ErrorAction Ignore If (-not $KeyVault) { try { $RG = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Stop } catch { If (-not $RG) { $RG = New-AzResourceGroup -Name $ResourceGroupName -Location $Location } } $KeyVault = New-AzKeyVault -Name $Name -ResourceGroupName $RG.ResourceGroupName -Location $Location Add-UserToAccessKeyVault -KeyVault $KeyVault -AllPermissions } If ($KeyVault) { Set-TooManySetting -Name "KeyVault" -Value $KeyVault.VaultName Set-TooManySetting -Name "ResourceGroupName" -Value $KeyVault.ResourceGroupName Set-TooManySetting -Name "Location" -Value $KeyVault.Location If ($PassThru) { return $KeyVault } } } } } Function New-TooManyTable() { <# .SYNOPSIS Create a table for metadata .DESCRIPTION Makes calls to Azure Resource Manager to create a new table in a storage account in the current Azure subscription .PARAMETER Name Name to give this Key Vault #> [Cmdletbinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [Alias('TableName','Table')] [string]$Name, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('RG')] [string]$ResourceGroupName, [parameter(ValueFromPipelineByPropertyName=$true)] [string]$StorageAccountName, [parameter(ValueFromPipelineByPropertyName=$true)] [Alias('Region','AzureRegion')] [string]$Location, #return the created object(s) [switch]$PassThru ) Process { If (-not $TMSSettings) { Import-TooManySetting } If (Test-TooManyAzure -SwitchContext) { try { Write-Debug "Looking for [$ResourceGroupName]" $ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Stop } catch { $ResourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location } try { $StorageAccount = Get-AzStorageAccount -Name $StorageAccountName -ResourceGroupName $ResourceGroup.ResourceGroupName -ErrorAction Stop } catch { If (-not $Location) { $Location = $ResourceGroup.Location } $StorageAccount = New-AzStorageAccount -Name $StorageAccountName -ResourceGroupName $ResourceGroup.ResourceGroupName ` -Location $Location -SkuName Standard_LRS -Kind StorageV2 -AccessTier Hot } ForEach ($TableName in @($Name,"TMSSettings")) { try { $Table = Get-AzStorageTable -Name $TableName -Context $StorageAccount.Context -ErrorAction Stop } catch { $Table = New-AzStorageTable -Name $TableName -Context $StorageAccount.Context } } Set-TooManySetting -Name "Table" -Value $Table.Name Set-TooManySetting -Name "StorageAccountRG" -Value $StorageAccount.ResourceGroupName Set-TooManySetting -Name "StorageAccountName" -Value $StorageAccount.StorageAccountName Set-TooManySetting -Name "Location" -Value $Location if ($PassThru) { return $Table } } } } Function Get-TooManyKeyVault() { <# .SYNOPSIS Retrieve an Azure Key Vault .DESCRIPTION Find the first key vault in the current subscription with the give name. .PARAMETER Name Name given to the Key Vault .EXAMPLE PS> $MyVaut = Get-TooManyKeyVault -Name "MyVault" #> param([string]$Name, [switch]$Refresh) if (-not $Refresh -and (($TMSKeyVault -and (-not $name -or ($TMSKeyVault.Name -eq $name))))) { $TMSKeyVault } else { If (Test-TooManyAzure) { If ($TMSKeyVault -and (($TMSKeyVault.VaultName -eq $Name) -xor (-not $Name))) { Write-Debug "Using existing vault [$($TMSKeyVault.VaultName)]..." $KeyVault = $TMSKeyVault } elseif (-not $Name -and (Test-TooManySetting -Name "KeyVault")) { $Name = Get-TooManySetting -Name "KeyVault" $KeyVault = Get-AzKeyVault -VaultName $Name } If (-not $KeyVault) { $KeyVault = Get-AzKeyVault | Where-Object { $_.VaultName -match $Name } | Select-Object -First 1 Set-TooManySetting -Name "KeyVault" -Value $KeyVault.VaultName Write-Debug "Got new vault [$($KeyVault.VaultName)]..." } If (-not $TMSKeyVault) { $TMSKeyVault = $KeyVault } $KeyVault } } } Function Select-TooManyKeyVault() { <# .SYNOPSIS Sets the default key vault to be used by the module. .DESCRIPTION Find the first key vault in the current subscription with the give name. .PARAMETER Name Name given to the Key Vault .EXAMPLE PS> $MyVaut = Select-TooManyKeyVault -Name "MyVault" .LINK Get-AzKeyVault #> [Alias('Select-KeyVault')] param([parameter(ParameterSetName="ByString",Mandatory=$true,Position=1)][string]$Name, [parameter(ParameterSetName="ByObject",Mandatory=$true,Position=1)][Microsoft.Azure.Commands.KeyVault.Models.PSKeyVaultIdentityItem]$KeyVault ) If ($KeyVault) { $TMSKeyVault = $KeyVault } elseif (Test-TooManyAzure) { If ($TMSKeyVault -and (($TMSKeyVault.VaultName -eq $Name) -xor (-not $Name))) { Write-Debug "Using existing vault [$($TMSKeyVault.VaultName)]..." } else { $KeyVault = Get-AzKeyVault | Where-Object { $_.VaultName -match $Name } | Select-Object -First 1 $TMSKeyVault = $KeyVault Write-Debug "Got new vault [$($TMSKeyVault.VaultName)]..." } } Set-TooManySetting -Name "KeyVault" -Value $TMSKeyVault.VaultName Return $TMSKeyVault } Function Select-TooManyTable() { <# .SYNOPSIS Sets the default table to be used by the module. .DESCRIPTION Find the first table in the current subscription with the give name. .EXAMPLE PS> $MyTable = Select-TooManyKeyVault -Name "MyVault" .LINK Get-AzKeyVault #> param( #Name given to the Table [parameter(ParameterSetName="ByString",Position=1)][string]$Name, #Azure table object to use [parameter(ParameterSetName="ByObject",Mandatory=$true,Position=1)][Microsoft.Azure.Cosmos.Table.CloudTable]$Table, #Azure Storage Account object containing the table [Microsoft.Azure.Commands.Management.Storage.Models.PSStorageAccount]$StorageAccount ) If ($Table) { $TMSTable = $Table } elseif (Test-TooManyAzure) { If ($TMSTable -and (($TMSTable.Name -eq $Name) -xor (-not $Name))) { Write-Debug "Using existing table [$($TMSTable.Name)]..." } else { If ($StorageAccount) { $TMSStorage = $StorageAccount } elseif ($TMSStorage) { } elseif (Test-TooManySetting -Name "StorageAccountName") { $TMSStorage = Get-AzStorageAccount -ResourceGroupName (Get-TooManySetting -Name "StorageAccountRG") ` -Name (Get-TooManySetting -Name "StorageAccountName") } else { $TMSStorage = Get-AzStorageAccount | Where-Object{ $_.StorageAccountName -match "tmsmeta" } } If ($TMSStorage) { Set-TooManySetting -Name "StorageAccountRG" -Value $TMSStorage.ResourceGroupName Set-TooManySetting -Name "StorageAccountName" -Value $TMSStorage.StorageAccountName If (-not $Name) { $Name = Get-TooManySetting -Name KeyVault } write-Debug "TMSStorage: $($TMSStorage.StorageAccountName) - $($TMSStorage.Context.Gettype())" write-Debug "Name: $Name - $($Name.GetType())" $Table = (Get-AzStorageTable -Name $Name -Context $TMSStorage.Context).CloudTable If ($Table) { Set-Variable -Name "TMSTable" -Value $Table -Scope Global -Visibility Private Write-Debug "Using found table [$($TMSTable.Name)]" } } Write-Debug "Got new table [$($TMSTable.Name)]..." } } If ($TMSTable) { Set-TooManySetting -Name "Table" -Value $TMSTable.Name Return $TMSTable } } Function Test-TooManyTable() { <# .SYNOPSIS Check to see if table for TMS is available .OUTPUTS boolean #> param() If ($TMSTable) { $true } elseif (Select-TooManyTable) { $true } else { $false } } Function Connect-TooManySecret { <# .SYNOPSIS Connect to Azure and use existing context if available. .LINK Register-TooManySecret Connect-AzAccount Set-AzContext #> [Cmdletbinding()] param( #Causes the switch to the appropriate context without prompting user. [switch]$Force) $TenantID = Get-TooManySetting -Name "TenantID" $SubID = Get-TooManySetting -Name "SubscriptionID" $Context = Get-AzContext If ($Context.Tenant.Id -ne $TenantID -or $Context.Subscription.Id -ne $SubID) { $PossibleConext = Get-AzContext -ListAvailable | Where-Object { $_.Tenant.Id -eq $TenantID } If ($PossibleConext) { If (-not $Force) { Do { $Response = Read-Host "Existing subscription [$($Context.Subscription.Id)] does not match previous [$SubID]. Switch context? [Y/n]" If ($Response -eq '') { $Response = 'Y' } } Until ($Response -match "\A(Y(es)?)|(N(o)?)\Z") } If ($Force -or $Response -match '\A(Y(es)?)\Z') { $ExactContext = $PossibleConext | Where-Object { $_.Subscription.Id -eq $SubID} | Select-Object -First 1 If ($ExactContext) { $Context = $ExactContext | Set-AzContext } else { $PossibleConext | Select-Object -First 1 | Set-AzContext | Out-Null $Context = Set-AzContext -Subscription $SubID } } } else { $Context = Connect-AzAccount -Subscription $SubID -Tenant $TenantID } } } Function Test-TooManyAzure() { <# .SYNOPSIS Return if connected to Azure .DESCRIPTION Looks to see if there is a current conext with Azure. If not, attempt to connect using DefaultTooManyTenantID & DefaultTooManySubID, and prompt for authentication. .PARAMETER DoNotConnect If flagged, cmdlet will NOT attempt to login if no current context .EXAMPLE PS> If (Test-TooManyAzure) { Write-Host "connected!" } else { Write-Host "No Connection to Azure" } .LINK Connect-TooManySecret #> param( #If flagged, cmdlet will NOT attempt to login if no current context [switch]$DoNotConnect, #Prompt the user for connection if needed [switch]$Prompt, #Switch context if existing context is not intended AzureAD/Sub [switch]$SwitchContext) $Result = $False $context = Get-AzContext If ($Context) { $Result = $true } elseif (-not $DoNotConnect) { $TenantID = Get-TooManySetting -Name "TenantID" $SubID = Get-TooManySetting -Name "SubscriptionID" $context = Connect-AzAccount -Tenant $TenantID -Subscription $SubID #-Tenant $DefaultTooManyTenantID -Subscription $DefaultTooManySubID } If ($Prompt -or $SwitchContext) { Connect-TooManySecret -Force:($SwitchContext -or -not $Prompt) } If ($context) { Set-TooManySetting -Name "TenantID" -Value $Context.Tenant.ToString() Set-TooManySetting -Name "SubscriptionID" -Value $Context.Subscription.ToString() $Result = $true } return $Result } Function Register-TooManySecret() { <# .DESCRIPTION Sets the local settings for the Azure key vault and storage account to use by default as well as the subscription and Azure AD tenant. .ExAMPLE PS> Register-TooManySecret -VaultName TMSVault -ResourceGroupName TMS-rg -TableName TMSMeta -StorageAccountName mycompsa2314 ` -StorageAccountRG Storage-rg -AADTenantID 12345678-abcd-4321-fedc-123456789012 -SubscriptionID 87654321-1234-dcba-4321-cba987654321 This will set it so you will you use the key vault TMSVault in the TMS-rg resource group in the subscription 87654321-1234-dcba-4321-cba987654321 under Azure AD 12345678-abcd-4321-fedc-123456789012. Also, all metadata will be stored in the table TMSMeta within the storage account mycompsa2314 within the Storage-rg resource group of that subscription. .LINK Connect-TooManySecret #> [Alias('Register-TooManySecrets')] param([parameter(ValueFromPipelineByPropertyName=$true)][string]$VaultName, [parameter(ValueFromPipelineByPropertyName=$true)][string]$TableName, [parameter(ValueFromPipelineByPropertyName=$true)][string]$ResourceGroupName, [parameter(ValueFromPipelineByPropertyName=$true)][string]$Location, [parameter(ValueFromPipelineByPropertyName=$true)][string]$StorageAccountName, [parameter(ValueFromPipelineByPropertyName=$true)][string]$StorageAccountRG = $ResourceGroupName, [parameter(ValueFromPipelineByPropertyName=$true)][string]$AADTenantID = $DefaultTooManyTenantID, [parameter(ValueFromPipelineByPropertyName=$true)][string]$SubscriptionID = $DefaultTooManySubID) Import-TooManySetting If ($VaultName) { Set-TooManySetting -Name "KeyVault" -Value $VaultName } If ($TableName) { Set-TooManySetting -Name "Table" -Value $TableName } If ($ResourceGroupName) { Set-TooManySetting -Name "ResourceGroupName" -Value $ResourceGroupName } If ($Location) { Set-TooManySetting -Name "Location" -Value $Location } If ($StorageAccountName) { Set-TooManySetting -Name "StorageAccountName" -Value $StorageAccountName } If ($StorageAccountRG) { Set-TooManySetting -Name "StorageAccountRG" -Value $StorageAccountRG } If ($AADTenantID) { Set-TooManySetting -Name "TenantID" -Value $AADTenantID } If ($SubscriptionID) { Set-TooManySetting -Name "SubscriptionID" -Value $SubscriptionID } } |