Menu Notifications
Dismiss all

Runbooks

<#
.SYNOPSIS
    Script para start/stop de recursos com o schedule gerenciado via Tags
.DESCRIPTION
    O script não precisa de nenhum parâmetro, ele irá ler todo o ambiente no Azure em busca dos recursos com o schedule gerenciado via Tag

    Módulos necessários que não são padrão na Automation Account:
        Az.Accounts
        Az.Aks

    Os schedules necessários podem ser criados com o script abaixo, apenas substituindo o ID da Automation Account
        $AutomationAccountId = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1";
        $RunbookName = "ManagedSchedule";

        $TempID = $AutomationAccountId.Split("/");
        $SubscriptionId = $TempID[2];
        $ResourceGroupName = $TempID[4];
        $ResourceName = $TempID[-1];

        Select-AzSubscription -SubscriptionId $SubscriptionId;

        $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
        $TimeZoneId = $TimeZone.Id;
        $BrazilDateTime = [System.TimeZoneInfo]::ConvertTimeFromUtc([DateTime]::UtcNow, $TimeZone);
        $BrazilDateTime = $BrazilDateTime.AddHours(2);
        $Minutes = @("00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55");

        foreach ($Minute in $Minutes) {
            $StartTime = "$($BrazilDateTime.Hour):$($Minute)";
            New-AzAutomationSchedule -AutomationAccountName $ResourceName -Name "ManagedSchedule-$($Minute)" -StartTime $StartTime -HourInterval 1 -ResourceGroupName $ResourceGroupName -TimeZone $TimeZoneId;
            Register-AzAutomationScheduledRunbook -AutomationAccountName $ResourceName -RunbookName $RunbookName -ScheduleName "ManagedSchedule-$($Minute)" -ResourceGroupName $ResourceGroupName;
        }

.EXAMPLE
    PS C:\> ManagedSchedule.ps1

.NOTES
    Filename: ManagedSchedule.ps1
    Author: Caio Souza do Carmo
    Modified date: 2023-02-27
    Version 1.0 - Start e Stop de VMs e AKS
#>

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

function DesiredState() {
    param (
        [Parameter()]
        [String[]]$StartAt,

        [Parameter()]
        [String[]]$StopAt,

        [Parameter()]
        [String]$KeepStatus
    )
    $Weekday = (Get-Date).DayOfWeek.value__;
    $TimeFormat = "^([01]\d|2[0-3]):([0-5]\d)$";

    if ($KeepStatus -eq "On") {
        return "start";
    }
    if ($KeepStatus -eq "Off") {
        return "stop";
    }

    $StartTime = $StartAt[$Weekday];
    $StopTime = $StopAt[$Weekday];

    if ( ($StartTime -notmatch $TimeFormat) -or ($StopTime -notmatch $TimeFormat) ) {
        if ( ($StartTime -match $TimeFormat) -and ($StopTime -notmatch $TimeFormat) ) {
            $StopTime = "23:59";
        }
        else {
            $Index = $Weekday;
            $ExpectedState = "";
            for ($i = 0; $i -lt 6; $i++) {
                $Index--;
                if ($Index -eq -1) {
                    $Index = 6;
                }

                if ($StopAt[$Index] -match $TimeFormat) {
                    $ExpectedState = "stop";
                    break;
                }
                if ($StartAt[$Index] -match $TimeFormat) {
                    $ExpectedState = "start";
                    break;
                }
            }
            if ($ExpectedState -eq "start") {
                $StartTime = "00:00";
                if ($StopTime -notmatch $TimeFormat) {
                    $StopTime = "23:59";
                }
            }
            else {
                $StartTime = "23:59";
                if ($StopTime -notmatch $TimeFormat) {
                    $StopTime = "00:00";
                }
            }
        }
    }

    $Format = "HH:mm";
    $BrazilCulture = New-Object System.Globalization.CultureInfo("pt-BR");
    $StartDateTime = [DateTime]::ParseExact($StartTime, $Format, $BrazilCulture);
    $StopDateTime = [DateTime]::ParseExact($StopTime, $Format, $BrazilCulture);

    $BrazilTimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $BrazilDateTime = [System.TimeZoneInfo]::ConvertTimeFromUtc([DateTime]::UtcNow, $BrazilTimeZone);

    $StartDateTime = $BrazilDateTime.Date.Add($StartDateTime.TimeOfDay);
    $StopDateTime = $BrazilDateTime.Date.Add($StopDateTime.TimeOfDay);

    if ( ($StartDateTime -le $BrazilDateTime) -and ($StopDateTime -ge $BrazilDateTime) ) {
        return "start";
    }
    else {
        return "stop";
    }
}

function StartStopVM() {
    param (
        [Parameter()]
        [String]$ResourceId,

        [Parameter()]
        [String]$Action
    )

    $TempID = $ResourceId.Split("/");
    #$SubscriptionId = $TempID[2];
    $ResourceGroupName = $TempID[4];
    $ResourceName = $TempID[-1];

    if ($Action -eq "start") {
        Start-AzVM  -ResourceGroupName $ResourceGroupName `
                    -Name $ResourceName `
                    -NoWait;
    }
    elseif ($Action -eq "stop") {
        Stop-AzVM  -ResourceGroupName $ResourceGroupName `
                    -Name $ResourceName `
                    -Force `
                    -NoWait;
    }
}

function StartStopAKS() {
    param (
        [Parameter()]
        [String]$ResourceId,

        [Parameter()]
        [String]$Action
    )

    $TempID = $ResourceId.Split("/");
    #$SubscriptionId = $TempID[2];
    $ResourceGroupName = $TempID[4];
    $ResourceName = $TempID[-1];

    if ($Action -eq "start") {
        Start-AzAksCluster  -ResourceGroupName $ResourceGroupName `
                            -Name $ResourceName `
                            -NoWait `
                            -WarningAction SilentlyContinue;
    }
    elseif ($Action -eq "stop") {
        Stop-AzAksCluster  -ResourceGroupName $ResourceGroupName `
                            -Name $ResourceName `
                            -NoWait `
                            -WarningAction SilentlyContinue;
    }
}

Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected -WarningAction SilentlyContinue;
if ($AccountNotConnected) {
    Write-Host ("[$(GetDate)] Falha ao conectar ao Azure");
    Write-Host $AccountNotConnected;
}

$ResourceTypes = @("Microsoft.Compute/virtualMachines", "Microsoft.ContainerService/managedClusters");

$SubscriptionList = (Get-AzSubscription);
foreach ($Subscription in $SubscriptionList) {
    Write-Host ("[$(GetDate)] Selecionando assinatura $($Subscription.Id)");
    $SelectedSubscription = (Select-AzSubscription -SubscriptionId $Subscription.Id);
    Write-Host ("[$(GetDate)] Assinatura `"$($SelectedSubscription.Subscription.Name)`" selecionada");

    Write-Host ("[$(GetDate)] Listando recursos com o schedule gerenciado");
    $ResourceList = (Get-AzResource -Tag @{ managedSchedule = 'Yes' });
    Write-Host ("[$(GetDate)] $($ResourceList.Count) recursos encontrados com o schedule gerenciado");

    foreach ($Resource in $ResourceList) {
        if ($ResourceTypes -icontains $Resource.Type) {
            $TagsTable = $Resource.TagsTable;
            $Tags = $Resource.Tags;
            $ResourceId = $Resource.Id;

            $TempID = $ResourceId.Split("/");
            $ResourceGroupName = $TempID[4];
            $ResourceName = $TempID[-1];

            $KeepStatus = "";
            if ($TagsTable.Contains("keepStatus")) {
                $KeepStatus = $Tags["keepStatus"];
            }

            $Action = DesiredState -StartAt $Tags["startAt"].Split("|") -StopAt $Tags["stopAt"].Split("|") -KeepStatus $KeepStatus;
            if ($Resource.Type -ieq "Microsoft.Compute/virtualMachines") {
                $CurrentStatus = ((Get-AzVM -Name $ResourceName -ResourceGroupName $ResourceGroupName -Status).Statuses.code[1]).Split("/")[1];
                if ( ($CurrentStatus -ieq "running") -and ($Action -eq "start") ) {
                    Write-Host ("[$(GetDate)] VM `"$($ResourceName)`" já está com o estado esperado: $($CurrentStatus)");
                }
                elseif ( ($CurrentStatus -ieq "running") -and ($Action -eq "stop") ) {
                    Write-Host ("[$(GetDate)] Parando VM `"$($ResourceName)`"");
                    StartStopVM -ResourceId $ResourceId -Action "stop";
                }
                elseif ( ($CurrentStatus -ine "running") -and ($Action -eq "start") ) {
                    Write-Host ("[$(GetDate)] Ligando VM `"$($ResourceName)`"");
                    StartStopVM -ResourceId $ResourceId -Action "start";
                }
                elseif ( ($CurrentStatus -ine "running") -and ($Action -eq "stop") ) {
                    Write-Host ("[$(GetDate)] VM `"$($ResourceName)`" já está com o estado esperado: $($CurrentStatus)");
                }
                else {
                    Write-Host ("[$(GetDate)] Erro. VM: `"$($ResourceName)`". Estado: $($CurrentStatus). Action: $($Action)");
                }
            }
            elseif ($Resource.Type -ieq "Microsoft.ContainerService/managedClusters") {
                $CurrentStatus = ((Get-AzAKSCluster -Name $ResourceName -ResourceGroupName $ResourceGroupName -WarningAction SilentlyContinue).PowerState.Code);
                if ( ($CurrentStatus -ieq "Running") -and ($Action -eq "start") ) {
                    Write-Host ("[$(GetDate)] AKS `"$($ResourceName)`" já está com o estado esperado: $($CurrentStatus)");
                }
                elseif ( ($CurrentStatus -ieq "Running") -and ($Action -eq "stop") ) {
                    Write-Host ("[$(GetDate)] Parando AKS `"$($ResourceName)`"");
                    StartStopAKS -ResourceId $ResourceId -Action "stop";
                }
                elseif ( ($CurrentStatus -ine "Running") -and ($Action -eq "start") ) {
                    Write-Host ("[$(GetDate)] Ligando AKS `"$($ResourceName)`"");
                    StartStopAKS -ResourceId $ResourceId -Action "start";
                }
                elseif ( ($CurrentStatus -ine "Running") -and ($Action -eq "stop") ) {
                    Write-Host ("[$(GetDate)] AKS `"$($ResourceName)`" já está com o estado esperado: $($CurrentStatus)");
                }
                else {
                    Write-Host ("[$(GetDate)] Erro. AKS: `"$($ResourceName)`". Estado: $($CurrentStatus). Action: $($Action)");
                }
            }
        }
    }
}

<#
.SYNOPSIS
    Script para start/stop de VM
.DESCRIPTION
    O script recebe como parâmetros a Assinatura (ID ou nome), Grupo de Recursos, nome da VM e ação (Start ou Stop) e executa conforme o especificado

    Para iniciar, é necessário ter instalado o módulo Az
        Install-Module -Name Az
    
    É necessário estar conectado à conta do Azure em que a(s) sua(s) Assinatura(s) existe(m)
    Se executado no Cloud Shell, os comandos abaixo não são necessários
        Para conectar, utilize o comando abaixo:
        Connect-AzAccount 

        Caso você possua mais de um diretório na mesma conta, pode ser especificado o TenantID em que as Assinaturas escolhidas existem
        Connect-AzAccount -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        Caso a página de login não abra automaticamente, pode ser utilizado o comando abaixo para gerar um código que deve ser inserido na URL "https://microsoft.com/devicelogin" para possibilitar o login
            Connect-AzAccount -UseDeviceAuthentication
    
.PARAMETER Subscription
    Id ou Nome da Assinatura quem contém o recurso
.PARAMETER ResourceGroupName
    Grupo de Recursos que contém o recurso
.PARAMETER VMName
    Nome do recurso
.PARAMETER StartStop
    Ação desejada (Start ou Stop)
.PARAMETER ConnectionType
    Tipo de conexão que será utilizada na Automation Account (Managed Identity ou Run As Account)

.EXAMPLE
    PS C:\> Start_Stop_VMs.ps1 `
            -Subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx `
            -ResourceGroupName grupo `
            -VMName vm001 `
            -StartStop start `
            -ConnectionType Identity

    Com os parâmetros acima, o script irá executar a ação de start na VM "vm001" do Grupo de Recursos "grupo" da Assinatura "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" utilizando a managed identity da Automation Account

.NOTES
    Filename: Start_Stop_VMs.ps1
    Author: Caio Souza do Carmo
    Modified date: 2022-08-11
    Version 1.0 - Start e Stop do VM
    Version 1.1 - Autenticação
#>

param(
    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Subscription")]
    [String]$Subscription,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Resource Group Name")]
    [String]$ResourceGroupName,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the VM Name")]
    [String]$VMName,

    [Parameter(Mandatory = $true, HelpMessage = "Start or Stop?")]
    [ValidateSet("start", "stop", IgnoreCase = $true)]
    [String]$StartStop,

    [Parameter(Mandatory = $true, HelpMessage = "Connection Type")]
    [ValidateSet("Identity", "RunAs", "Local", IgnoreCase = $true)]
    [String]$ConnectionType
)

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

if (@("Identity", "RunAs") -contains $ConnectionType) {
    Import-Module Az;
    if ($ConnectionType -eq "Identity") {
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected;
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    elseif ($ConnectionType -eq "RunAs") {
        Write-Host ("[$(GetDate)] Obtendo conexão da Automation Account") -ForegroundColor Yellow;
        $ServicePrincipalConnection = (Get-AutomationConnection -Name "AzureRunAsConnection");
    
        $AzAccountParams = @{
            "ServicePrincipal"      = $True
            "Tenant"                = $ServicePrincipalConnection.TenantID
            "ApplicationId"         = $ServicePrincipalConnection.ApplicationID
            "CertificateThumbprint" = $ServicePrincipalConnection.CertificateThumbprint
            "ErrorAction"           = "Stop"
            "ErrorVariable"         = "AccountNotConnected"
        }
        Write-Host ("[$(GetDate)] Tenant Id: $($ServicePrincipalConnection.TenantID)") -ForegroundColor Cyan;
    
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        (Connect-AzAccount @AzAccountParams);
    
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    else {
        Exit;
    }
}

Write-Host ("[$(GetDate)] Selecionando assinatura $($Subscription)") -ForegroundColor Yellow;
if ($VMSubscription -match '^[a-zA-Z0-9]{8}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{12}$') {
    Select-AzSubscription -SubscriptionId $Subscription;
}
else {
    Select-AzSubscription -SubscriptionName $Subscription;
}

if ($startStop.ToLower() -eq "start") {
    Write-Host ("[$(GetDate)] Iniciando VM $($VMName)") -ForegroundColor Yellow;
    Start-AzVM  -ResourceGroupName $ResourceGroupName `
                -Name $VMName `
                -NoWait;
}
elseif ($startStop.ToLower() -eq "stop") {
    Write-Host ("[$(GetDate)] Parando VM $($VMName)") -ForegroundColor Yellow;
    Stop-AzVM  -ResourceGroupName $ResourceGroupName `
                -Name $VMName `
                -NoWait;
}

<#
.SYNOPSIS
    Script para start/stop de Azure Database for MariaDB server

.DESCRIPTION
    O script recebe como parâmetro as informações do server, junto com a ação desejada (start ou stop) e realiza a ação solicitada

    Atualmente (2022-06-02) o script funciona realizando uma chamada na API do Azure, pois ainda não há o comando equivalente no módulo do Powershell
    O comando existe no CLI, no entanto não pode ser utilizado em Automation Accounts
        https://docs.microsoft.com/en-us/cli/azure/mariadb/server?view=azure-cli-latest#az-mariadb-server-stop 

    Para iniciar, é necessário ter instalado o módulo Az
        Install-Module -Name Az
    
    É necessário estar conectado à conta do Azure em que a(s) sua(s) Assinatura(s) existe(m)
    Se executado no Cloud Shell, os comandos abaixo não são necessários
        Para conectar, utilize o comando abaixo:
        Connect-AzAccount 

        Caso você possua mais de um diretório na mesma conta, pode ser especificado o TenantID em que as Assinaturas escolhidas existem
        Connect-AzAccount -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        Caso a página de login não abra automaticamente, pode ser utilizado o comando abaixo para gerar um código que deve ser inserido na URL "https://microsoft.com/devicelogin" para possibilitar o login
            Connect-AzAccount -UseDeviceAuthentication
    
.PARAMETER SubscriptionID
    O ID da Assinaturas contendo o recurso
.PARAMETER ResourceGroupName
    O nome do Grupo de Recursos contendo o recurso
.PARAMETER MariaDBName
    O nome do recurso
.PARAMETER StartStop
    Ação à ser realizada (start ou stop)
.PARAMETER ConnectionType
    Tipo de conexão que será utilizada na Automation Account (Managed Identity ou Run As Account)

.EXAMPLE
    PS C:\> Start_Stop_MariaDB.ps1 `
    -SubscriptionID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx `
    -ResourceGroupName xxxxxxxx `
    -MariaDBName "exemplo" `
    -StartStop "stop" `
    -ConnectionType Identity

    No exemplo acima, o MariaDB "exemplo" da Assinatura xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx do Grupo de Recursos xxxxxxxx será parado utilizando a managed identity da Automation Account

.NOTES
    Filename: Start_Stop_MariaDB.ps1
    Author: Caio Souza do Carmo
    Modified date: 2022-06-02
    Version 1.0 - Start/Stop de MariaDB
#>

param(
    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Subscription id")]
    [String]$SubscriptionID,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Resource Group Name")]
    [String]$ResourceGroupName,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the MariaDB Name")]
    [String]$MariaDBName,

    [Parameter(Mandatory = $true, HelpMessage = "Start or Stop?")]
    [ValidateSet("start", "stop", IgnoreCase = $true)]
    [String]$StartStop,

    [Parameter(Mandatory = $true, HelpMessage = "Connection Type")]
    [ValidateSet("Identity", "RunAs", "Local", IgnoreCase = $true)]
    [String]$ConnectionType
)

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

function GetAccessToken() {
    $AzContext = (Get-AzContext);
    $AzProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile;
    $ProfileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($AzProfile);
    $Token = $ProfileClient.AcquireAccessToken($AzContext.Subscription.TenantId);
    return $Token;
}

if (@("Identity", "RunAs") -contains $ConnectionType) {
    Import-Module Az;
    if ($ConnectionType -eq "Identity") {
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected;
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    elseif ($ConnectionType -eq "RunAs") {
        Write-Host ("[$(GetDate)] Obtendo conexão da Automation Account") -ForegroundColor Yellow;
        $ServicePrincipalConnection = (Get-AutomationConnection -Name "AzureRunAsConnection");
    
        $AzAccountParams = @{
            "ServicePrincipal"      = $True
            "Tenant"                = $ServicePrincipalConnection.TenantID
            "ApplicationId"         = $ServicePrincipalConnection.ApplicationID
            "CertificateThumbprint" = $ServicePrincipalConnection.CertificateThumbprint
            "ErrorAction"           = "Stop"
            "ErrorVariable"         = "AccountNotConnected"
        }
        Write-Host ("[$(GetDate)] Tenant Id: $($ServicePrincipalConnection.TenantID)") -ForegroundColor Cyan;
    
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        (Connect-AzAccount @AzAccountParams);
    
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    else {
        Exit;
    }
}

$InformationPreference = "SilentlyContinue";


Write-Host ("[$(GetDate)] Obtendo token") -ForegroundColor Yellow;
$Token = GetAccessToken;
$AccessToken = $Token.AccessToken;
$authHeader = @{
    'Content-Type'  = 'application/json'
    'Authorization' = 'Bearer ' + $AccessToken
}
Write-Host ("[$(GetDate)] $($AccessToken.Length)") -ForegroundColor Green;

$StartStop = $StartStop.ToLower();

Write-Host ("[$(GetDate)] Resumo da solicitação: ") -ForegroundColor Cyan;
Write-Host ("[$(GetDate)] ID do recurso: `"/subscriptions/$($SubscriptionID)/resourceGroups/$($ResourceGroupName)/providers/Microsoft.DBforMariaDB/servers/$($MariaDBName)`"") -ForegroundColor Cyan;
Write-Host ("[$(GetDate)] Ação: $($StartStop)") -ForegroundColor Cyan;

$restUri = "https://management.azure.com/subscriptions/$($SubscriptionID)/resourceGroups/$($ResourceGroupName)/providers/Microsoft.DBforMariaDB/servers/$($MariaDBName)/$($StartStop)?api-version=2020-01-01-privatepreview";
    
Invoke-RestMethod -Uri $restUri -Method Post -Headers $authHeader;

<#
.SYNOPSIS
    Script para start/stop de AKS
.DESCRIPTION
    O script recebe como parâmetros a Assinatura (ID ou nome), Grupo de Recursos, nome do AKS e ação (Start ou Stop) e executa conforme o especificado

    Para iniciar, é necessário ter instalado o módulo Az
        Install-Module -Name Az
    
    É necessário estar conectado à conta do Azure em que a(s) sua(s) Assinatura(s) existe(m)
    Se executado no Cloud Shell, os comandos abaixo não são necessários
        Para conectar, utilize o comando abaixo:
        Connect-AzAccount 

        Caso você possua mais de um diretório na mesma conta, pode ser especificado o TenantID em que as Assinaturas escolhidas existem
        Connect-AzAccount -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        Caso a página de login não abra automaticamente, pode ser utilizado o comando abaixo para gerar um código que deve ser inserido na URL "https://microsoft.com/devicelogin" para possibilitar o login
            Connect-AzAccount -UseDeviceAuthentication
    
.PARAMETER Subscription
    Id ou Nome da Assinatura quem contém o recurso
.PARAMETER ResourceGroupName
    Grupo de Recursos que contém o recurso
.PARAMETER AKSName
    Nome do recurso
.PARAMETER StartStop
    Ação desejada (Start ou Stop)
.PARAMETER ConnectionType
    Tipo de conexão que será utilizada na Automation Account (Managed Identity ou Run As Account)

.EXAMPLE
    PS C:\> Start_Stop_AKS.ps1 `
            -Subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx `
            -ResourceGroupName grupo `
            -AKSName kubernetes `
            -StartStop start `
            -ConnectionType Identity

    Com os parâmetros acima, o script irá executar a ação de start no AKS "kubernetes" do Grupo de Recursos "grupo" da Assinatura "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" utilizando a managed identity da Automation Account

.NOTES
    Filename: Start_Stop_AKS.ps1
    Author: Caio Souza do Carmo
    Modified date: 2022-06-20
    Version 1.0 - Start e Stop do AKS
    Version 1.1 - Input aceitando tanto ID quanto nome da Assinatura
#>

param(
    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Subscription id")]
    [String]$Subscription,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Resource Group Name")]
    [String]$ResourceGroupName,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the AKS Name")]
    [String]$AKSName,

    [Parameter(Mandatory = $true, HelpMessage = "Start or Stop?")]
    [ValidateSet("start", "stop", IgnoreCase = $true)]
    [String]$StartStop,

    [Parameter(Mandatory = $true, HelpMessage = "Connection Type")]
    [ValidateSet("Identity", "RunAs", "Local", IgnoreCase = $true)]
    [String]$ConnectionType
)

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

if (@("Identity", "RunAs") -contains $ConnectionType) {
    Import-Module Az;
    if ($ConnectionType -eq "Identity") {
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected;
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    elseif ($ConnectionType -eq "RunAs") {
        Write-Host ("[$(GetDate)] Obtendo conexão da Automation Account") -ForegroundColor Yellow;
        $ServicePrincipalConnection = (Get-AutomationConnection -Name "AzureRunAsConnection");
    
        $AzAccountParams = @{
            "ServicePrincipal"      = $True
            "Tenant"                = $ServicePrincipalConnection.TenantID
            "ApplicationId"         = $ServicePrincipalConnection.ApplicationID
            "CertificateThumbprint" = $ServicePrincipalConnection.CertificateThumbprint
            "ErrorAction"           = "Stop"
            "ErrorVariable"         = "AccountNotConnected"
        }
        Write-Host ("[$(GetDate)] Tenant Id: $($ServicePrincipalConnection.TenantID)") -ForegroundColor Cyan;
    
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        (Connect-AzAccount @AzAccountParams);
    
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    else {
        Exit;
    }
}

Write-Host ("[$(GetDate)] Selecionando assinatura $($Subscription)") -ForegroundColor Yellow;
if ($VMSubscription -match '^[a-zA-Z0-9]{8}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{12}$') {
    Select-AzSubscription -SubscriptionId $Subscription;
}
else {
    Select-AzSubscription -SubscriptionName $Subscription;
}

if ($StartStop.ToLower() -eq "start") {
    Write-Host ("[$(GetDate)] Iniciando AKS $($AKSName)") -ForegroundColor Yellow;
    Start-AzAksCluster  -ResourceGroupName $ResourceGroupName `
                        -Name $AKSName `
                        -NoWait `
                        -WarningAction SilentlyContinue;
}
elseif ($StartStop.ToLower() -eq "stop") {
    Write-Host ("[$(GetDate)] Parando AKS $($AKSName)") -ForegroundColor Yellow;
    Stop-AzAksCluster  -ResourceGroupName $ResourceGroupName `
                        -Name $AKSName `
                        -NoWait `
                        -WarningAction SilentlyContinue;
}

<#
.SYNOPSIS
    Script para start/stop de Application Gateway
.DESCRIPTION
    O script recebe como parâmetros a Assinatura (ID ou nome), Grupo de Recursos, nome do Application Gateway e ação (Start ou Stop) e executa conforme o especificado

    Para iniciar, é necessário ter instalado o módulo Az
        Install-Module -Name Az
    
    É necessário estar conectado à conta do Azure em que a(s) sua(s) Assinatura(s) existe(m)
    Se executado no Cloud Shell, os comandos abaixo não são necessários
        Para conectar, utilize o comando abaixo:
        Connect-AzAccount 

        Caso você possua mais de um diretório na mesma conta, pode ser especificado o TenantID em que as Assinaturas escolhidas existem
        Connect-AzAccount -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        Caso a página de login não abra automaticamente, pode ser utilizado o comando abaixo para gerar um código que deve ser inserido na URL "https://microsoft.com/devicelogin" para possibilitar o login
            Connect-AzAccount -UseDeviceAuthentication
    
.PARAMETER Subscription
    Id ou Nome da Assinatura quem contém o recurso
.PARAMETER ResourceGroupName
    Grupo de Recursos que contém o recurso
.PARAMETER ApplicationGatewayName
    Nome do recurso
.PARAMETER StartStop
    Ação desejada (Start ou Stop)
.PARAMETER ConnectionType
    Tipo de conexão que será utilizada na Automation Account (Managed Identity ou Run As Account)

.EXAMPLE
    PS C:\> Start_Stop_Application_Gateway.ps1 `
            -Subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx `
            -ResourceGroupName grupo `
            -ApplicationGatewayName appgw `
            -StartStop start

    Com os parâmetros acima, o script irá executar a ação de start no Application Gateway "appgw" do Grupo de Recursos "grupo" da Assinatura "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" utilizando a managed identity da Automation Account

.NOTES
    Filename: Start_Stop_Application_Gateway.ps1
    Author: Caio Souza do Carmo
    Modified date: 2022-07-15
    Version 1.0 - Start e Stop do Application Gateway
#>

param(
    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Subscription")]
    [String]$Subscription,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Resource Group Name")]
    [String]$ResourceGroupName,

    [Parameter(Mandatory = $true, HelpMessage = "Please specify the Application Gateway Name")]
    [String]$ApplicationGatewayName,

    [Parameter(Mandatory = $true, HelpMessage = "Start or Stop?")]
    [ValidateSet("start", "stop", IgnoreCase = $true)]
    [String]$StartStop,

    [Parameter(Mandatory = $true, HelpMessage = "Connection Type")]
    [ValidateSet("Identity", "RunAs", "Local", IgnoreCase = $true)]
    [String]$ConnectionType
)

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

if (@("Identity", "RunAs") -contains $ConnectionType) {
    Import-Module Az;
    if ($ConnectionType -eq "Identity") {
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected;
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    elseif ($ConnectionType -eq "RunAs") {
        Write-Host ("[$(GetDate)] Obtendo conexão da Automation Account") -ForegroundColor Yellow;
        $ServicePrincipalConnection = (Get-AutomationConnection -Name "AzureRunAsConnection");
    
        $AzAccountParams = @{
            "ServicePrincipal"      = $True
            "Tenant"                = $ServicePrincipalConnection.TenantID
            "ApplicationId"         = $ServicePrincipalConnection.ApplicationID
            "CertificateThumbprint" = $ServicePrincipalConnection.CertificateThumbprint
            "ErrorAction"           = "Stop"
            "ErrorVariable"         = "AccountNotConnected"
        }
        Write-Host ("[$(GetDate)] Tenant Id: $($ServicePrincipalConnection.TenantID)") -ForegroundColor Cyan;
    
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        (Connect-AzAccount @AzAccountParams);
    
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    else {
        Exit;
    }
}

Write-Host ("[$(GetDate)] Selecionando assinatura $($Subscription)") -ForegroundColor Yellow;
if ($Subscription -match '^[a-zA-Z0-9]{8}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{4}[-][a-zA-Z0-9]{12}$') {
    Select-AzSubscription -SubscriptionId $Subscription;
}
else {
    Select-AzSubscription -SubscriptionName $Subscription;
}

Write-Host ("[$(GetDate)] Obtendo informações do Application Gateway `"$($ApplicationGatewayName)`"") -ForegroundColor Yellow;
$AppGateway = (Get-AzApplicationGateway -Name $ApplicationGatewayName -ResourceGroupName $ResourceGroupName)

if ($StartStop.ToLower() -eq "start") {
    Write-Host ("[$(GetDate)] Iniciando Application Gateway $($ApplicationGatewayName)") -ForegroundColor Yellow;
    Start-AzApplicationGateway -ApplicationGateway $AppGateway;
}
elseif ($StartStop.ToLower() -eq "stop") {
    Write-Host ("[$(GetDate)] Parando Application Gateway $($ApplicationGatewayName)") -ForegroundColor Yellow;
    Stop-AzApplicationGateway -ApplicationGateway $AppGateway;
}

<#
.SYNOPSIS
    Script para remover fazer o expurgo de logs do Log Analytics workspace
.DESCRIPTION
    O script recebe como input o ID do Log Analytics workspace, as tabelas que serão expurgadas e a quantidade de dias de logs que será mantida

    Documentação da API: 
        https://docs.microsoft.com/en-us/rest/api/loganalytics/workspace-purge/purge
    
    O usuário ou serviço que executar esse script precisa da role "Data Purger" no recurso de destino, ter role de Contributor ou Owner não é o suficiente, é necessário essa role especifica, mais informações em:
        https://docs.microsoft.com/en-us/services-hub/health/purge_assessment_data_in_log_analytics

    Para iniciar, é necessário ter instalado o módulo Az
        Install-Module -Name Az
    
    É necessário estar conectado à conta do Azure em que a(s) sua(s) Assinatura(s) existe(m)
    Se executado no Cloud Shell, os comandos abaixo não são necessários
        Para conectar, utilize o comando abaixo:
        Connect-AzAccount 

        Caso você possua mais de um diretório na mesma conta, pode ser especificado o TenantID em que as Assinaturas escolhidas existem
        Connect-AzAccount -TenantId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        Caso a página de login não abra automaticamente, pode ser utilizado o comando abaixo para gerar um código que deve ser inserido na URL "https://microsoft.com/devicelogin" para possibilitar o login
            Connect-AzAccount -UseDeviceAuthentication

.PARAMETER ResourceId
    ID do Log Analytics workspace

.PARAMETER Tables
    Tabelas que serão expurgadas

.PARAMETER RetentionDays
    Dias de log que serão mantidos

.PARAMETER ConnectionType
    Tipo de conexão que será utilizada na Automation Account (Managed Identity ou Run As Account)

.EXAMPLE
    PS C:\> PurgeLogAnalytics.ps1`
    -ResourceId /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1`
    -Tables "Perf" `
    -RetentionDays 7 `
    -ConnectionType Identity

    No exemplo acima, serão removidos todos logs com data superior à 7 dias, da tabela "Perf" do Log Analytics "workspace1" utilizando a managed identity da Automation Account

.NOTES
    Filename: PurgeLogAnalytics.ps1
    Author: Caio Souza do Carmo
    Modified date: 2022-08-10
    Version 1.0 - Expurgar logs
#>

#Requires -Version 7
param(
    [Parameter(Mandatory = $true, HelpMessage = "Log Analytics workspace Id")]
    [String]$ResourceId,

    [Parameter(Mandatory = $true, HelpMessage = "Tables to purge")]
    [String[]]$Tables,

    [Parameter(Mandatory = $true, HelpMessage = "Days to retain")]
    [Int]$RetentionDays,

    [Parameter(Mandatory = $true, HelpMessage = "Connection Type")]
    [ValidateSet("Identity", "RunAs", "Local", IgnoreCase = $true)]
    [String]$ConnectionType
)

function GetDate() {
    $tDate = (Get-Date).ToUniversalTime();
    $TimeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("E. South America Standard Time");
    $tCurrentTime = [System.TimeZoneInfo]::ConvertTimeFromUtc($tDate, $TimeZone);
    
    $DateInfo = @{
        "UFormat" = "%Y-%m-%d %H:%M:%S"
        "Date"    = $tCurrentTime
    }

    return Get-Date @DateInfo;
}

function NormalizeDate {
    param (
        [Parameter()]
        $DateString,

        [Parameter()]
        [String]$InputDateFormat,

        [Parameter()]
        [String]$OutputDateFormat = "yyyy-MM-dd HH:mm:ss"
    )

    $NormalizedDate = "";

    if (($DateString).Length -gt 0) {
        $TempDate = [datetime]::parseexact($DateString, $InputDateFormat, [Globalization.CultureInfo]::CreateSpecificCulture('pt-BR'));
        $NormalizedDate = $TempDate.ToString($OutputDateFormat);
    }

    return $NormalizedDate;
}

function GetAccessToken() {
    $AzContext = (Get-AzContext);
    $AzProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile;
    $ProfileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($AzProfile);
    $Token = $ProfileClient.AcquireAccessToken($AzContext.Subscription.TenantId);
    return $Token;
}

function BuildUri() {
    param (
        [Parameter()]
        [String]$ResourceID,

        [Parameter()]
        [String]$URLQuery = "api-version=2020-08-01"
    )

    $RestUriBuilder = New-Object System.UriBuilder;
    $RestUriBuilder.Host = "management.azure.com";
    $RestUriBuilder.Path = ($ResourceID, "purge" -join '/');
    $RestUriBuilder.Port = 443;
    $RestUriBuilder.Scheme = 'https';
    $RestUriBuilder.Query = $URLQuery;
    return $RestUriBuilder.ToString();
}

if (@("Identity", "RunAs") -contains $ConnectionType) {
    Import-Module Az;
    if ($ConnectionType -eq "Identity") {
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        Connect-AzAccount -Identity -ErrorAction Stop -ErrorVariable AccountNotConnected;
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    elseif ($ConnectionType -eq "RunAs") {
        Write-Host ("[$(GetDate)] Obtendo conexão da Automation Account") -ForegroundColor Yellow;
        $ServicePrincipalConnection = (Get-AutomationConnection -Name "AzureRunAsConnection");
    
        $AzAccountParams = @{
            "ServicePrincipal"      = $True
            "Tenant"                = $ServicePrincipalConnection.TenantID
            "ApplicationId"         = $ServicePrincipalConnection.ApplicationID
            "CertificateThumbprint" = $ServicePrincipalConnection.CertificateThumbprint
            "ErrorAction"           = "Stop"
            "ErrorVariable"         = "AccountNotConnected"
        }
        Write-Host ("[$(GetDate)] Tenant Id: $($ServicePrincipalConnection.TenantID)") -ForegroundColor Cyan;
    
        Write-Host ("[$(GetDate)] Conectando ao Azure") -ForegroundColor Yellow;
        (Connect-AzAccount @AzAccountParams);
    
        if ($AccountNotConnected) {
            Write-Host ("[$(GetDate)] Falha ao conectar ao Azure") -ForegroundColor Red;
        }
        else {
            Write-Host ("[$(GetDate)] Conexão realizada com sucesso") -ForegroundColor Green;
        }
    }
    else {
        Exit;
    }
    $Tables = $Tables.Split("/");
}

$DateLimit = (Get-Date).AddDays(-$RetentionDays).ToString("yyyy-MM-ddTHH:mm:ss");
Write-Host ("[$(GetDate)] Logs anteriores à $($DateLimit) serão expurgados") -ForegroundColor Yellow;

Write-Host ("[$(GetDate)] Obtendo token de acesso") -ForegroundColor Yellow;
$Token = GetAccessToken;
$AccessToken = $Token.AccessToken;
Write-Host ("[$(GetDate)] O token irá expirar em: $(NormalizeDate -DateString $Token.ExpiresOn.LocalDateTime -InputDateFormat "MM/dd/yyyy HH:mm:ss" -OutputDateFormat "dd/MM/yyyy HH:mm:ss")") -ForegroundColor Green;

$AuthHeader = @{
    "Content-Type"  = "application/json"
    "Authorization" = "Bearer $($AccessToken)"
}

foreach ($Table in $Tables) {
    $PurgeUrl = (BuildUri -ResourceID $ResourceId);
    $Body = @{
        "table"   = $Table
        "filters" = @(
            @{
                "column"   = "TimeGenerated"
                "operator" = "<="
                "value"    = $DateLimit
            }
        )
    }
    $BodyJson = ($Body | ConvertTo-Json);
    Write-Host ("[$(GetDate)] Expurgando logs da tabela `"$($Table)`" ") -ForegroundColor Yellow;
    $Request = (Invoke-WebRequest -Uri $PurgeUrl -Method POST -Body $BodyJson -Headers $AuthHeader -ContentType "application/json");
    Write-Host ("[$(GetDate)] Status da requisição: $($Request.StatusCode) - $($Request.StatusDescription)") -ForegroundColor Cyan;
}