azureautomation / runbooks

Sample Automation runbooks
MIT License
157 stars 129 forks source link

Update-AzureModule doesn't actually support sovereign clouds #34

Open dcrreynolds opened 6 years ago

dcrreynolds commented 6 years ago

Hard coded Azure URIs at lines 82, 88, and 115 prevent this from working in non-AzureCloud instances

ryanrclark commented 6 years ago

Same problem here. I'm in the government azure cloud and I get this error: The remote server returned an error: (404) Not Found. (The remote server returned an error: (404) Not Found.)

CHDAFNI-MSFT commented 6 years ago

+1 on this The AzureCloud URIs are incorrect as well.

To resolve this for all environments, the variable should be populated from the 'Get-AzureRMEnvironment' or 'Get-AzEnvironment' cmdlets

ryanrclark commented 6 years ago

I actually got this script working in the Gov't cloud by changing the URLs in the script. There's a good document that shows you the URIs for everything having to do with public cloud and its sovereign cloud equivalents; I posted the links below. Compare my below code to the original script to see what changed. Forgive me if I shouldn't paste code directly. I'm not up on my github etiquette. I also must warn readers that updating to the latest modules in the specific sovereign cloud i'm using (Government) actually caused me massive headaches with Azure automation. the updater put the latest AzureRM.Network module in my Automation modules. Which then killed my runbooks becuase of module incompatibility of some sort. Anyway, i had to manually install an older powershell module. Proceed with caution.

https://docs.microsoft.com/en-us/azure/azure-government/documentation-government-developer-guide

https://docs.microsoft.com/en-us/azure/azure-government/documentation-government-services-monitoringandmanagement

<# .SYNOPSIS This Azure Automation runbook imports the latest version of the Azure modules from the PowerShell Gallery.

.DESCRIPTION This Azure Automation runbook imports the latest version of the Azure modules from the PowerShell Gallery. It requires that this runbook be run from the automation service and that the RunAs account is enabled on the automation account. You could put this runbook on a schedule so that it updates the modules each month or call through a webhook as needed.

.PARAMETER AutomationResourceGroup Required. The name of the Azure Resource Group containing the Automation account.

.PARAMETER AutomationAccountName Required. The name of the Automation account.

.PARAMETER ModuleVersionOverrides Optional. A PowerShell HashTable or a JSON dictionary which contains module version overrides. Please be careful of version incompatibility between modules when overriding module versions.

.PARAMETER AzureEnvironment Optional. The name of the target Azure environment (one of the values returned by 'Get-AzureRmEnvironment | select Name').

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount -ModuleVersionOverrides @{'Azure'="4.0.2"; 'Azure.Storage'="3.0.2"; 'AzureRM.Profile'="3.0.1"; 'AzureRM.Automation'="3.0.1"; 'AzureRM.Compute'="3.0.1"; 'AzureRM.Resources' = "4.0.1"; 'AzureRM.Sql' = "3.0.1"; 'AzureRM.Storage'="3.0.2"} -AzureEnvironment 'AzureCloud'

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount -ModuleVersionOverrides '{"Azure" : "4.0.2", "AzureRM.Sql" : "3.0.1", "AzureRM.Automation" : "3.0.1", "Azure.Storage" : "3.0.2", "AzureRM.Resources" : "4.0.1", "AzureRM.Storage" : "3.0.2", "AzureRM.Compute" : "3.0.1", "AzureRM.Profile" : "3.0.1"}'

.NOTES AUTHOR: Automation Team LASTEDIT: Sep 26th, 2018

>

Param ( [Parameter(Mandatory=$True)] [String] $AutomationResourceGroup,

[Parameter(Mandatory=$True)]
[String] $AutomationAccount,

[Parameter(Mandatory=$False)]
[object] $ModuleVersionOverrides,

[Parameter(Mandatory=$False)]
[String] $AzureEnvironment = 'AzureCloud'
)

$versionOverrides = ""

Try to parse module version overrides

if ($ModuleVersionOverrides) { if ($ModuleVersionOverrides.GetType() -eq [HashTable]) { $versionOverrides = ConvertTo-Json $ModuleVersionOverrides } elseif ($ModuleVersionOverrides.GetType() -eq [String]) {

Verify that the ModuleVersionOverrides can be deserialized

    try{
        $temp = ConvertFrom-Json $ModuleVersionOverrides -ErrorAction Stop
    }
    catch [System.ArgumentException] {
        $ex = $_ 
        # rethrow intended
        throw "The value of the parameter ModuleVersionOverrides is not a valid JSON string: ", $ex
    }
    $versionOverrides = $ModuleVersionOverrides
} else {
    $ex = [System.ArgumentException]::new("The value of the parameter ModuleVersionOverrides should be a PowerShell HashTable or a JSON string")
    throw $ex
}

}

try {

Azure management uri

$ResourceAppIdURI = "https://management.core.usgovcloudapi.net/"

# Path to modules in automation container
$ModulePath = "C:\Modules"

# Login uri for Azure AD
$LoginURI = "https://login.microsoftonline.us/"

# Find AzureRM.Profile module and load the Azure AD client library
$PathToProfileModule = Get-ChildItem (Join-Path $ModulePath AzureRM.Profile) -Recurse
Add-Type -Path (Join-Path $PathToProfileModule "Microsoft.IdentityModel.Clients.ActiveDirectory.dll")

# Get RunAsConnection
$RunAsConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
$Certifcate = Get-AutomationCertificate -Name "AzureRunAsCertificate"
$SubscriptionId = $RunAsConnection.SubscriptionId

# Set up authentication using service principal client certificate
$Authority = $LoginURI + $RunAsConnection.TenantId
$AuthContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $Authority
$ClientCertificate = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate" -ArgumentList $RunAsConnection.ApplicationId, $Certifcate
$AuthResult = $AuthContext.AcquireToken($ResourceAppIdURI, $ClientCertificate)

# Set up header with authorization token
$AuthToken = $AuthResult.CreateAuthorizationHeader()
$RequestHeader = @{
  "Content-Type" = "application/json";
  "Authorization" = "$AuthToken"
}

# Create a runbook job
$JobId = [GUID]::NewGuid().ToString()
$URI =  "https://management.usgovcloudapi.net/subscriptions/$SubscriptionId/"`
     +"resourceGroups/$($AutomationResourceGroup)/providers/Microsoft.Automation/"`
     +"automationAccounts/$AutomationAccount/jobs/$($JobId)?api-version=2015-10-31"

# Runbook and parameters
if($versionOverrides){
    $Body = @"
        {
           "properties":{
           "runbook":{
               "name":"Update-AutomationAzureModulesForAccount"
           },
           "parameters":{
                "AzureEnvironment":"$AzureEnvironment",
                "ResourceGroupName":"$AutomationResourceGroup",
                "AutomationAccountName":"$AutomationAccount",
                "ModuleVersionOverrides":"$versionOverrides"
           }
          }
       }

"@ } else { $Body = @" { "properties":{ "runbook":{ "name":"Update-AutomationAzureModulesForAccount" }, "parameters":{ "AzureEnvironment":"$AzureEnvironment", "ResourceGroupName":"$AutomationResourceGroup", "AutomationAccountName":"$AutomationAccount" } } } "@ }

# Start runbook job
Invoke-RestMethod -Uri $URI -Method Put -body $body -Headers $requestHeader        

} catch { throw $_.Exception }

CHDAFNI-MSFT commented 6 years ago

I made an edit and pull request which should pull the environment values for any of the cloud environment


(internal only) If I helped you, please take this 1-minute survey – https://aka.ms/chdafni-feedback

Chase Dafnis

Sr. Premier Field Engineer US Public Sector Microsoft Corporation

Office: 646.225.4724 Chase.Dafnis@microsoft.commailto:Chase.Dafnis@microsoft.com

[Twitter]https://twitter.com/Microsoft [Facebook] https://www.facebook.com/Microsoft [Linkedin] https://www.linkedin.com/company/microsoft [Youtube] https://www.youtube.com/user/Microsoft

[Microsoft Logo]

If you have any feedback about my work, please let either myself or my manager Arthur Dahl know at adahl@microsoft.commailto:adahl@microsoft.com

From: ryanrclark notifications@github.com Sent: Tuesday, November 6, 2018 10:09 PM To: azureautomation/runbooks runbooks@noreply.github.com Cc: Chase Dafnis Chase.Dafnis@microsoft.com; Manual manual@noreply.github.com Subject: Re: [azureautomation/runbooks] Update-AzureModule doesn't actually support sovereign clouds (#34)

I actually got this script working in the Gov't cloud by changing the URLs in the script. There's a good document that shows you the public cloud and its sovereign cloud equivalents; I posted the links below. Compare my below code to the original script to see what changed.

https://docs.microsoft.com/en-us/azure/azure-government/documentation-government-developer-guidehttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-government%2Fdocumentation-government-developer-guide&data=02%7C01%7CChase.Dafnis%40microsoft.com%7C395cf070aa924670e78408d6445e5a5f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636771569373204038&sdata=%2Fl5458d%2FxoeimeAcd6SFzOrhPrLCfuKSxvCDPUUQv9I%3D&reserved=0

https://docs.microsoft.com/en-us/azure/azure-government/documentation-government-services-monitoringandmanagementhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-government%2Fdocumentation-government-services-monitoringandmanagement&data=02%7C01%7CChase.Dafnis%40microsoft.com%7C395cf070aa924670e78408d6445e5a5f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636771569373214042&sdata=WWacrLnCNH3CJrHk4%2F4YFLGk4nEgeh%2BdNQRIAnSMZQU%3D&reserved=0

<# .SYNOPSIS This Azure Automation runbook imports the latest version of the Azure modules from the PowerShell Gallery.

.DESCRIPTION This Azure Automation runbook imports the latest version of the Azure modules from the PowerShell Gallery. It requires that this runbook be run from the automation service and that the RunAs account is enabled on the automation account. You could put this runbook on a schedule so that it updates the modules each month or call through a webhook as needed.

.PARAMETER AutomationResourceGroup Required. The name of the Azure Resource Group containing the Automation account.

.PARAMETER AutomationAccountName Required. The name of the Automation account.

.PARAMETER ModuleVersionOverrides Optional. A PowerShell HashTable or a JSON dictionary which contains module version overrides. Please be careful of version incompatibility between modules when overriding module versions.

.PARAMETER AzureEnvironment Optional. The name of the target Azure environment (one of the values returned by 'Get-AzureRmEnvironment | select Name').

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount -ModuleVersionOverrides @{'Azure'="4.0.2"; 'Azure.Storage'="3.0.2"; 'AzureRM.Profile'="3.0.1"; 'AzureRM.Automation'="3.0.1"; 'AzureRM.Compute'="3.0.1"; 'AzureRM.Resources' = "4.0.1"; 'AzureRM.Sql' = "3.0.1"; 'AzureRM.Storage'="3.0.2"} -AzureEnvironment 'AzureCloud'

.EXAMPLE Update-AzureModule -AutomationResourceGroup contoso -AutomationAccountName contosoaccount -ModuleVersionOverrides '{"Azure" : "4.0.2", "AzureRM.Sql" : "3.0.1", "AzureRM.Automation" : "3.0.1", "Azure.Storage" : "3.0.2", "AzureRM.Resources" : "4.0.1", "AzureRM.Storage" : "3.0.2", "AzureRM.Compute" : "3.0.1", "AzureRM.Profile" : "3.0.1"}'

.NOTES AUTHOR: Automation Team LASTEDIT: Sep 26th, 2018

>

Param ( [Parameter(Mandatory=$True)] [String] $AutomationResourceGroup,

[Parameter(Mandatory=$True)]

[String] $AutomationAccount,

[Parameter(Mandatory=$False)]

[object] $ModuleVersionOverrides,

[Parameter(Mandatory=$False)]

[String] $AzureEnvironment = 'AzureCloud'

)

$versionOverrides = ""

Try to parse module version overrides

if ($ModuleVersionOverrides) { if ($ModuleVersionOverrides.GetType() -eq [HashTable]) { $versionOverrides = ConvertTo-Json $ModuleVersionOverrides } elseif ($ModuleVersionOverrides.GetType() -eq [String]) {

Verify that the ModuleVersionOverrides can be deserialized

try{ $temp = ConvertFrom-Json $ModuleVersionOverrides -ErrorAction Stop } catch [System.ArgumentException] { $ex = $_

rethrow intended

throw "The value of the parameter ModuleVersionOverrides is not a valid JSON string: ", $ex } $versionOverrides = $ModuleVersionOverrides } else { $ex = [System.ArgumentException]::new("The value of the parameter ModuleVersionOverrides should be a PowerShell HashTable or a JSON string") throw $ex } }

try {

Azure management uri

$ResourceAppIdURI = "https://management.core.usgovcloudapi.net/https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmanagement.core.usgovcloudapi.net%2F&data=02%7C01%7CChase.Dafnis%40microsoft.com%7C395cf070aa924670e78408d6445e5a5f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636771569373214042&sdata=D29R4AU5QMsDbTWZfK74pdfrbGyI%2FfiBSgIMK5TWTZ4%3D&reserved=0"

Path to modules in automation container

$ModulePath = "C:\Modules"

Login uri for Azure AD

$LoginURI = "https://login.microsoftonline.us/"

Find AzureRM.Profile module and load the Azure AD client library

$PathToProfileModule = Get-ChildItem (Join-Path $ModulePath AzureRM.Profile) -Recurse

Add-Type -Path (Join-Path $PathToProfileModule "Microsoft.IdentityModel.Clients.ActiveDirectory.dll")

Get RunAsConnection

$RunAsConnection = Get-AutomationConnection -Name "AzureRunAsConnection"

$Certifcate = Get-AutomationCertificate -Name "AzureRunAsCertificate"

$SubscriptionId = $RunAsConnection.SubscriptionId

Set up authentication using service principal client certificate

$Authority = $LoginURI + $RunAsConnection.TenantId

$AuthContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $Authority

$ClientCertificate = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate" -ArgumentList $RunAsConnection.ApplicationId, $Certifcate

$AuthResult = $AuthContext.AcquireToken($ResourceAppIdURI, $ClientCertificate)

Set up header with authorization token

$AuthToken = $AuthResult.CreateAuthorizationHeader()

$RequestHeader = @{

"Content-Type" = "application/json";

"Authorization" = "$AuthToken"

}

Create a runbook job

$JobId = [GUID]::NewGuid().ToString()

$URI = "https://management.usgovcloudapi.net/subscriptions/$SubscriptionId/"`

 +"resourceGroups/$($AutomationResourceGroup)/providers/Microsoft.Automation/"`

 +"automationAccounts/$AutomationAccount/jobs/$($JobId)?api-version=2015-10-31"

Runbook and parameters

if($versionOverrides){

$Body = @"

    {

       "properties":{

       "runbook":{

           "name":"Update-AutomationAzureModulesForAccount"

       },

       "parameters":{

            "AzureEnvironment":"$AzureEnvironment",

            "ResourceGroupName":"$AutomationResourceGroup",

            "AutomationAccountName":"$AutomationAccount",

            "ModuleVersionOverrides":"$versionOverrides"

       }

      }

   }

"@ } else { $Body = @" { "properties":{ "runbook":{ "name":"Update-AutomationAzureModulesForAccount" }, "parameters":{ "AzureEnvironment":"$AzureEnvironment", "ResourceGroupName":"$AutomationResourceGroup", "AutomationAccountName":"$AutomationAccount" } } } "@ }

Start runbook job

Invoke-RestMethod -Uri $URI -Method Put -body $body -Headers $requestHeader

} catch { throw $_.Exception }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fazureautomation%2Frunbooks%2Fissues%2F34%23issuecomment-436489160&data=02%7C01%7CChase.Dafnis%40microsoft.com%7C395cf070aa924670e78408d6445e5a5f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636771569373224052&sdata=u1KANpUQbAZe6kJRB%2BnvvcCjgjwZtcy7znwbaoWKNzg%3D&reserved=0, or mute the threadhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAa_7mdhLZWN-7qPLdSEuuIGq8nfciAerks5usk7GgaJpZM4XzbsV&data=02%7C01%7CChase.Dafnis%40microsoft.com%7C395cf070aa924670e78408d6445e5a5f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636771569373224052&sdata=FHsmTPGZQpmz6SMeOy53EU1JplaU2f2Vi8kkp8%2FuGwI%3D&reserved=0.

alongafni commented 6 years ago

@CHDAFNI-MSFT exactly what I wanted to submit for PR