#Save-AzureRmContext
Explore tagged Tumblr posts
prashantjayaram · 7 years ago
Text
Select-AzureRmProfile : The term 'Select-AzureRmProfile' is not recognized as the name of a cmdlet, function, script file, or operable program
Select-AzureRmProfile : The term ‘Select-AzureRmProfile’ is not recognized as the name of a cmdlet, function, script file, or operable program
Tumblr media
I got a chance to work with PowerShell automation script to automate the login process. In the script, the profile is loaded using the Select-AzureRmProfile. If you try to log in using Select-AzureRmProfile you most likely encounter the following error message.
Error Message:
Select-AzureRmProfile : The term ‘Select-AzureRmProfile’ is not recognized as the name of a cmdlet, function, script file,…
View On WordPress
0 notes
ibarrau · 6 years ago
Text
[AzureScript][T1:E3] Login Automático
¡Hola de nuevo! si te perdiste la primera parte, te dejo un link donde vemos el porque usar Azure desde linea de comando, y la forma de instalarlo.
T1:E1 - Introducción
T1:E2 - Usos Básicos
En esta ocasión les voy a comentar algo que deje pendiente al final del post anterior, y es como loguear a Azure sin la interacción del usuario. Esto es importante porque si tenemos procesos automatizados, dado que nuestros scripts deberían poder autenticarse en Azure sin la necesidad de que haya alguien ingresando manualmente las contraseñas. Hay varias formas de hacer esto, les voy a comentar 2 que son las que considero más prácticas: 
Logueo mediante contexto de Azure
Logueo mediante Service Principal
Logueo mediante contexto de Azure.
En este caso, lo que se hace es almacenar un token de autenticacion de Azure en un archivo json. Luego al comienzo de cada script podemos cargar ese archivo json y eso automáticamente nos autenticará contra Azure. Es muy práctico de implementar, pero tiene una desventaja importante: el token vence luego de 30 días. Aun así, nos puede salvar de apuros hasta que tengamos una solución mas robusta.
Lo primero que debemos hacer para almacenar este token, es abrir Powershell y loguear de modo manual como ya hemos visto en episodios anteriores:
Login-AzureRmAccount
Luego, debemos elegir donde se almacenará y como se llamará este archivo json que contendrá el token, puede ser cualquier carpeta y cualquier nombre. Como ya hemos hecho antes, almacenamos la ruta en una variable y luego llamamos al cmdlet correspondiente:
 $ruta = "C:/Ruta/Al/Archivo/AzureAuth.json"  Save-AzureRmContext -Path $ruta
De este modo, habremos generado un archivo json que contiene un token para autenticarnos sin interacción del usuario en Azure. Ahora para que nuestros scripts sean 100% autónomos, podemos reemplazar la parte de Login-AzureRmAccount por esto:
$ruta = "C:/Ruta/Al/Archivo/AzureAuth.json" Import-AzureRmContext -Path $ruta
¡Así de sencillo! Al ejecutar esto ya estaremos autenticados. La gran contra que tiene este método, como ya comente, es que el token expira luego de un mes y hay que regenerarlo. Esto implica que alguien debe loguear manualmente y guardar el contexto nuevamente para que sea válido el token.
Logueo mediante Service Principal 
Para evitar tener problemas con el contexto y su token, lo recomendable es usar este método. Un service principal es un usuario de servicio, que nos permitirá administrar recursos de Azure para los cuales tenga permisos asignados. Este método lleva unos pasos extra, pero nos da la opción de programar scripts que no tienen fecha de caducidad, y ademas es más seguro porque al loguear solo tendremos permisos para administrar algunos recursos sobre los que tenga permiso el service principal, y no sobre todos los que disponga un usuario en particular como en el caso del contexto. Para loguear con un service principal, el primer paso es tener uno. Para crear uno, tenemos la opción de hacerlo mediante el portal o mediante Powershell con el cmdlet New-AzureRmADServicePrincipal. Como es algo que haremos solo una vez, explicaré como hacerlo en el portal de modo gráfico. Para esto, dentro del portal vamos a la opción Azure Active Directory en la parte izquierda de la pantalla. Una vez ahí, elegimos App Registrations, y luego en el símbolo +, que dice New Registration. 
Tumblr media
Al momento de crear un service principal solo debemos asignarle un nombre, procura que sea un nombre que describa su función, o a que recursos tendrá acceso. Luego de ponerle un nombre damos click en Register. Luego de crearlo, ya podremos asignarle permisos a nuestro service principal a los recursos que queremos que pueda administrar desde Access Control (IAM) en el correspondiente recurso, como si se tratara de un usuario más. Después de darle los permisos correspondientes, tomaremos nota de algunos valores que necesitaremos al momento de autenticarnos en nuestro script, estos valores son: TenantId, ApplicationId, y SecretId. 
A continuación, te explico como obtener cada uno:
ApplicationId: lo podemos obtener dentro de Azure Active Directory -> App Registration -> Selecciona el service principal creado. Nos mostrará algunos códigos, pero el que nos interesa en este caso es este "Application (client) ID".
SecretId: en la misma ventana de donde sacamos el ApplicationId, podemos ver a la izquierda "Certificates & secrets", clickeamos ahí. Después vamos a "New Client Secret", asignamos un nombre a nuestro secret, y damos click en "Add". Esto generará un nuevo secreto, ¡asegúrate de guardarlo bien! Una vez que cierres esta ventana no podrás volver a obtenerlo!!
TenantId: este es más sencillo, lo obtenemos de Azure Active Directory -> Properties -> Directory Id.
Entonces, ahora ya tenemos nuestro service principal creado, con sus permisos y tenemos los datos que necesitamos para autenticarnos en nuestro script. ¡Manos a la obra! Como hemos hecho con anterioridad, almacenaremos en variables y luego las llamaremos. El código es un poco más largo esta vez, pero no mucho:
$ServPpalSecret = "ServicePrincipalSecret" $ServPpalAppId = "ServicePrincipalAppId" $TenantId = "DirectoryId"$secpasswd = ConvertTo-SecureString $ServPpalSecret -AsPlainText -Force $creds = New-Object System.Management.Automation.PSCredential ($ServPpalAppId, $secpasswd)Login-AzureRmAccount -Credential $creds -ServicePrincipal -TenantId $TenantId
¡Listo! Al ejecutar éstas lineas nuestro script estará logueado con este service principal de forma 100% autónoma! Ahora si podremos usar nuestros scripts como runbooks en Azure Automation, o almacenarlos como .ps1 y llamarlos desde el programador de tareas de Windows (o cron desde Linux, si usamos Powershell Core), sin preocuparnos por fechas de caducidad de tokens, con la tranquilidad de que no requerirán ninguna interacción por parte del usuario.
Espero que les haya gustado, ¡¡no se pierdan el próximo episodio!!  :)
Escrito por Martín Zurita.
0 notes
stefanstranger · 7 years ago
Text
Running ACS-Engine in Docker container
This sprint I've been busy with the implementation of running Kubernetes in Azure.
What is Kubernetes?
Kubernetes is an open-source platform designed to automate deploying, scaling, and operating application containers. With Kubernetes, you are able to quickly and efficiently respond to customer demand:
Deploy your applications quickly and predictably.
Scale your applications on the fly.
Roll out new features seamlessly.
Limit hardware usage to required resources only.
Kubernetes on Azure
Azure Container Service (ACS) allows you to quickly deploy a production ready Kubernetes cluster. ACS for Kubernetes makes it simple to create, configure, and manage a cluster of virtual machines that are preconfigured to run containerized applications.
Remark:
Azure Container Service (AKS) is being updated to add new deployment options, enhanced management capabilities, and cost benefit to Kubernetes on Azure. Visit the AKS documentation to start working with these preview features.
What is the difference between ACS and AKS?
ACS is our current Azure Container Service, which is the unmanaged version compaired to the managed version of Azure Container Service (AKS).
By using AKS, you can take advantage of the enterprise-grade features of Azure, while still maintaining application portability through Kubernetes and the Docker image format.
Managed Kubernetes in Azure AKS reduces the complexity and operational overhead of managing a Kubernetes cluster by offloading much of that responsibility to Azure. As a hosted Kubernetes service, Azure handles critical tasks like health monitoring and maintenance for you. In addition, you pay only for the agent nodes within your clusters, not for the masters. As a managed Kubernetes service, AKS provides:
Automated Kubernetes version upgrades and patching
Easy cluster scaling
Self-healing hosted control plane (masters)
Cost savings - pay only for running agent pool nodes
With Azure handling the management of the nodes in your AKS cluster, you no longer need to perform many tasks manually, like cluster upgrades. Because Azure handles these critical maintenance tasks for you, AKS does not provide direct access (such as with SSH) to the cluster.
Deployment options AKS
You can deploy AKS via the following options:
Azure CLI
Azure Portal (search the Marketplace for Azure Container Service)
ACS-Engine
ACS-Engine
Because we needed more control over the Azure Resource Manager templates, we used the open source acs-engine project to build our own custom Kubernetes cluster and deploy it via PowerShell.
The Azure Container Service Engine (acs-engine) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DC/OS, Kubernetes, Swarm Mode, or Swarm orchestrators. The input to the tool is a cluster definition. The cluster definition is very similar to (in many cases the same as) the ARM template syntax used to deploy a Microsoft Azure Container Service cluster.
And now we are getting close to the title of this blog post.
The default installation option for the ACS-Engine is the following: Download the latest version of acs-engine for here. Download acs-engine for your operating system. Extract the binary and copy it to your $PATH.
But my collegue Alessandro Vozza created a Docker file and Image for the ASC-Engine. Which makes it so easy to use the ACS-Engine tool.
Running ASC-Engine in Docker for Windows
To get the ASC-Engine running in Docker for Windows you need to do the following:
Install Docker for Windows
Configure a Shared Drive in Docker for Windows.
Pull Docker image ams0/acs-engine-light-autobuild from Docker Hub
Create a ACS-Engine Cluster Definition file
Run the ASC-Engine Docker instance and generate ARM (Azure Resource Manager) templates from Cluster definition input.
Deploy Kubernetes Cluster to Azure via PowerShell or Azure CLI.
Step 1. Install Docker for Windows
Just follow the steps described here to install Docker for Windows.
Step 2. Configure a Shared Drive in Docker for Windows
Because we are going to create and edit the ACS-Engine Cluster definition on our Windows machine we need to make sure we can access this file from within the Docker Engine on Windows.
Open the setting of the Docker for Windows Client and configure the Shared Drive.
Step 3. Pull Docker image ams0/acs-engine-light-autobuild from Docker Hub
Open your favorite shell (PowerShell Core?) and type the following:
docker pull ams0/acs-engine-light-autobuild
You can verify the Docker image download by running the following command:
docker images
Step 4. Create a ACS-Engine Cluster Definition file
Open your favorite editor (VSCode) and create a Cluster Definition file and store that file on the Docker Shared Drive.
You can find some examples of Cluster Definition files on the Github page.
For more detailed configuration of your Cluster Definition have a look at the Cluster Definition documentation on Github.
Empty example of a kubernetes.json Cluster Definition file:
{ "apiVersion": "vlabs", "properties": { "orchestratorProfile": { "orchestratorType": "Kubernetes" }, "masterProfile": { "count": 1, "dnsPrefix": "", "vmSize": "Standard_D2_v2" }, "agentPoolProfiles": [ { "name": "agentpool1", "count": 3, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet" } ], "linuxProfile": { "adminUsername": "azureuser", "ssh": { "publicKeys": [ { "keyData": "" } ] } }, "servicePrincipalProfile": { "clientId": "", "secret": "" } } }
Step 5. Run the ASC-Engine Docker instance and generate ARM (Azure Resource Manager) templates from Cluster definition input
Go back to the shell where you have docker running.
Start Docker Container asc-engine with attached drive where kubernetes.json file is stored. Output is stored in c:\temp\_output folder
docker run -it --rm -v c:/Temp:/acs -w /acs ams0/acs-engine-light-autobuild:latest /acs-engine generate kubernetes.json
You should now see all kinds of files being created in the output folder of the ACS-Engine.
Step 6. Deploy Kubernetes Cluster to Azure via PowerShell or Azure CLI.
The final step is to deploy the ARM Templates created in the output folder from step 5.
If you use PowerShell you can do the following:
#region Variables $ResourceGroupName = '[configure resource group name for Kubernetes Cluster]' $Location = '[configure Azure Location]' #endregion #region Connect to Azure Add-AzureRmAccount #Select Azure Subscription $subscription = (Get-AzureRmSubscription | Out-GridView ` -Title 'Select an Azure Subscription ...' ` -PassThru) Set-AzureRmContext -SubscriptionId $subscription.Id -TenantId $subscription.TenantID #endregion #region create Resource Group to test Azure Template Functions If (!(Get-AzureRMResourceGroup -name $ResourceGroupName -Location $Location -ErrorAction SilentlyContinue)) { New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location } #endregion #region variables $ARMTemplateFile = 'C:\Temp\_output\dts\azuredeploy.json' $ParameterFile = 'C:\Temp\_output\dtc\azuredeploy.parameters.json' #endregion #region Test ARM Template Test-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName ` -TemplateFile $ARMTemplateFile ` -TemplateParameterFile $ParameterFile ` -OutVariable testarmtemplate #endregion #region Deploy ARM Template with local Parameter file $result = (New-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName ` -TemplateFile $ARMTemplateFile ` -TemplateParameterFile $ParameterFile -Verbose -DeploymentDebugLogLevel All) $result #endregion
Hope you found this blog post interesting.
References:
What is Kubernetes?
Introduction to Azure Container Service for Kubernetes
Introducing AKS (managed Kubernetes) and Azure Container Registry improvements
ACS-Engine on Github
ACS-Engine Download bits
A multi-container Dockerfile for acs-engine
Get started with Docker for Windows
Deploy Kubernetes cluster for Linux containers
from Stefan Stranger's Weblog – Manage your IT Infrastructure http://ift.tt/2qrHcjL via IFTTT
0 notes
stefanstranger · 8 years ago
Text
Using Azure Custom Script Extension to execute scripts on Azure VMs
With Azure Custom Script Extension you can download and execute scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration / management task. Scripts can be downloaded from Azure storage or GitHub, or provided to the Azure portal at extension run time.
In this blog post I'm going to explain how you can use the Azure Custom Script Extension to execute a PowerShell script multiple times on an Azure Windows VM from an Azure Automation Runbook.
Why use the Azure Custom Script Extension?
There are multiple ways to execute a PowerShell script on a Windows Virtual machine in Azure.
PowerShell Remoting
Desired State Configuration script resource
Custom Script Extension
Let's go through each of them.
Ad 1. PowerShell Remoting
The advantages are:
PowerShell Remoting does not need an extra agent or extension installation on VM
With PowerShell Remoting you are able to run a script against multiple VMs a the same time.
PowerShell Remoting also allows an interactive session (not really a use-case for calling a script from an Azure Automation Runbook)
Proven technology. PowerShell Remoting is already available since PowerShell v 2.0.
PowerShell Remoting can be used for running PowerShell scripts and Workflows.
The disadvantages are:
Powershell remoting (WinRM) endpoint is not default configured for ARM Virtual Machines. Extra configuration steps are needed:
WinRM listener on VM needs to be configured.
Firewall port for incoming traffice needs to be opened.
Network Security Group Rule to allow inbound requests needs to be added.
VM needs to have a Public IP Address to remote into the VM.
Credential with permissions on the Azure VM for PowerShell Remoting needed before you can remote into the Azure VM.
Ad 2. Desired State Configuration script resource
The advantages are:
DSC agent is built into windows (there is no agent to install)
DSC agent uses the ‘pull’ model (no ports need to be opened on the Azure VM)
DSC script resource can be rerun at regular intervals by DSC agent.
Success/fail can be monitored via the Azure portal or Azure PowerShell.
The disadvantages are:
DSC script resource only supports native PowerShell scripts. (PowerShell workflow and graphical runbooks cannot be used with DSC)
DSC does not return output streams in the way a Runbook would. (DSC reports success/fail with few (if any) script execution details to Azure).
Ad 3. Custom Script Extension
The advantages are:
No local or domain credential needed to login to Azure VM.
VM does not need to have a Public IP address to be able to remotely connect to VM, like PowerShell Remoting needs.
Simple to implement, not many pre-requisites needed.
The disadvantages are:
The Custom Script Extension needs to be enabled for each VM you want to run your (PowerShell) script on.
The VM needs to have internet access to access the script location Azure storage or GitHub.
Relatively slow. (some PowerShell cmdlets like the Set-AzureRmVMCustomScriptExtension could be blocking the call until it finishes)
Because using the Custom Script Extension was the easiest and fastest way to have a PowerShell Script running on an Azure VM I choose for this option.
In this blog post I'm going to describe how to use the Custom Script Extension for the following scenario.
Scenario:
Trigger Windows Update using the PSWindowsUpdate PowerShell Module from Azure Automation on a Windows Virtual Machine in Azure.
The following high-level steps need to be executed to implement above scenario:
Install PSWindowsUpdate PowerShell Module on the Azure Windows VM.
Create PowerShell script (Install-WindowsUpdate.ps1) to use Get-WUInstall from the PSWindowsUpdate PowerShell Module to get list of available updates, next download and install it.
Store Install-WindowsUpdate.ps1 in Azure Blob Storage Container.
Create an Azure Runbook that updates the Custom Script Extension on a scheduled interval.
Step 1. Install PSWindowsUpdate PowerShell Module on the Azure Windows VM
Connect to Azure Windows VM and install the PSWindowsUpdate Module using the following PowerShell code from an elevated PowerShell prompt:
Install-Module -name PSWindowsUpdate -Scope AllUsers
Remark:
You can also have the Custom Script Extension (PowerShell) script download and install the PSWindowsUpdate PowerShell Module.
Step 2. Create PowerShell script (Install-WindowsUpdate.ps1)
We want to install all Windows Updates which can be achieved with the following command from the PSWindowsUpdate module.
Get-WUInstall -WindowsUpdate -AcceptAll -AutoReboot -Confirm:$FALSE
This command will get list of available updates, next download and install it from Windows Update Server as source. Does not ask for confirmation updates, installs all available updates, does not ask for reboot if needed and does not prompt for confirmation.
Store the Install-WindowsUpdate.ps1 script on your local machine (example: c:\temp\Install-WindowsUpdate.ps1) before uploading the script to the Storage Container.
Step 3. Store Install-WindowsUpdate.ps1 in Azure Blob storage
We first need to create an Azure Blob Storage Container to store the Install-WindowsUpdate.ps1 script.
Use the following script to create a new Storage Account with a Blob Container.
#region variables $Location = 'westeurope' $ResourceGroupName = 'scriptextensiondemo-rg' $StorageAccountName = 'scriptextensiondemosa' $ContainerName = 'script' $FileName = 'Install-WindowsUpdate.ps1' $ScriptToUpload = 'c:\temp\{0}' -f $FileName $Tag = @{'Environment'='Demo'} #endregion #Login to Azure Add-AzureRmAccount #Select Azure Subscription $subscription = (Get-AzureRmSubscription | Out-GridView ` -Title 'Select an Azure Subscription ...' ` -PassThru) Set-AzureRmContext -SubscriptionId $subscription.Id -TenantId $subscription.TenantID Select-AzureRmSubscription -SubscriptionName $($subscription.Name) #endregion #region Create new Resource Group New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location -Tag $Tag #endregion #region Create a new storage account. New-AzureRmStorageAccount -Name $StorageAccountName -ResourceGroupName $ResourceGroupName -SkuName Standard_LRS -Location $Location -Kind BlobStorage -AccessTier Cool -Tag $Tag #endregion #region Create a Script Container Set-AzureRmCurrentStorageAccount -Name $StorageAccountName -ResourceGroupName $ResourceGroupName New-AzureStorageContainer -Name $ContainerName -Permission Blob #endregion #region upload script extension script to container Set-AzureStorageBlobContent -Container $ContainerName -File $ScriptToUpload #endregion
Step 4. Create an Azure Runbook that updates the Custom Script Extension on a scheduled interval
The final step in this scenario is to create an Azure Runbook which updates the Custom Script Extension.
To update (re-run) an already configured Custom Script Extension we need to use the ForceRerun parameter of the Set-AzureRmVMCustomScriptExtension cmdlet.
Example:
#region rerun script extension Set-AzureRmVMCustomScriptExtension -ResourceGroupName $ResourceGroupName ` -VMName $VMName ` -StorageAccountName $StorageAcccountName ` -ContainerName $ContainerName ` -FileName $FileName ` -Run $FileName ` -Name $ScriptExtensionName ` -Location $Location ` -ForceRerun $(New-Guid).Guid #endregion
Although the Set-AzureRmVMCustomScriptExtension cmdlet can configure and rerun Custom Script extensions it has one small drawback and that is that it is blocking the call until it finishes the script on the Azure VM. For scripts that don't take a while to finish this is not a problem but for the Windows Update installation Get-WUInstall cmdlet this can take quite some time to finish.
That's why I choose to use the Azure REST API directly instead of using the Set-AzureRmVMCustomScriptExtension cmdlet in the Azure Automation Runbook. This will save us Runbook running costs.
Change the Install-WindowsUpdate.ps1 to the following version:
try { #Verify if PowerShellGet module is installed. If not install if (!(Get-Module -Name PowerShellGet)) { Invoke-WebRequest 'http://ift.tt/2veBzpU' -OutFile $($env:temp +'\PackageManagement_x64.msi') Start-Process $($env:temp +'\PackageManagement_x64.msi') -ArgumentList "/qn" -Wait } #Verify if PSWindowsUpdate PowerShell Module is installed. If not install. if (!(Get-Module -Name PSWindowsUpdate -List)){ Install-Module -Name PSWindowsUpdate -Scope AllUsers -Confirm:$false -Force } Get-WUInstall -WindowsUpdate -AcceptAll -AutoReboot -Confirm:$FALSE -ErrorAction stop } catch { Write-Output "Oops. Something failed" }
Now we can create a new Azure Automation Runbook. Check the Azure Automation documentation for getting started with Azure Automation.
Remark:
If you are using the Set-AzureRmVMCustomScriptExtension cmdlet in your Runbook make sure you have installed the latest AzureRM.Compute PowerShell module in Azure Automation, because this Runbook needs the Set-AzureRmVMCustomScriptExtension cmdlet with the ForceReRun parameter! You can update the AzureRM PowerShell modules in your Azure Automation Account using the Update Azure Modules button.
You can now create a new WindowsUpdatePS Runbook with the following code in your Azure Automation Account.
This Runbook shows the usage of the Set-AzureRmVMCustomScriptExtension cmdlet which has the drawback that it is blocking the call until it finishes the script on the Azure VM. And that's why you see the timeout message error for the Runbook.
# --------------------------------------------------- # Script: WindowsUpdatePS.ps1 # Tags: Blog, WindowsUpdate # Runbook name: WindowsUpdatePS # Version: 0.1 # Author: Stefan Stranger # Date: 21-07-2017 11:28:52 # Description: This runbooks triggers Windows Update using WindowsUpdate PowerShell Module. # Comments: # Changes: # Disclaimer: # This example is provided "AS IS" with no warranty expressed or implied. Run at your own risk. # **Always test in your lab first** Do this at your own risk!! # The author will not be held responsible for any damage you incur when making these changes! # --------------------------------------------------- $VerbosePreference = 'Continue' #remove when publishing runbook #region variables $Location = 'westeurope' $ResourceGroupName = 'scriptextensiondemo-rg' $StorageAcccountName = 'scriptextensiondemosa' $ContainerName = 'script' $FileName = 'Install-WindowsUpdate.ps1' $ScriptToUpload = 'c:\temp\{0}' -f $FileName $Tag = @{'Environment'='Demo'} $VMName = 'scriptdemovm-01' $ScriptExtensionName = 'WindowsUpdate' #endregion #region Connection to Azure write-verbose "Connecting to Azure" $connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName "Logging in to Azure..." Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else{ Write-Error -Message $_.Exception.Message throw $_.Exception } } #endregion #region update Windows Update Custom Script Extension try { Write-Verbose 'Updating Custom Script Extension' Set-AzureRmVMCustomScriptExtension -ResourceGroupName $ResourceGroupName ` -VMName $VMName ` -StorageAccountName $StorageAcccountName ` -ContainerName $ContainerName ` -FileName $FileName ` -Run $FileName ` -Name $ScriptExtensionName ` -Location $Location ` -ForceRerun $(New-Guid).Guid } Catch { Write-Error -Message $_.Exception.Message throw $_.Exception } #endregion
To avoid the time out message we can change the Runbook to use the Azure ARM REST API directly.
For more information about using the Azure ARM REST API check the following blog posts:
Using the Azure ARM REST API – Get Access Token
Using the Azure ARM REST API – Get Subscription Information
Using the Azure ARM REST API – End to end Example Part 1
Using the Azure ARM REST API – End to end Example Part 2
The following Runbook uses the Azure ARM REST API directly to configure and update the Custom Script Extension of an Azure VM.
# --------------------------------------------------- # Script: WindowsUpdatePS.ps1 # Tags: Blog, WindowsUpdate # Runbook name: WindowsUpdatePS # Version: 0.2 # Author: Stefan Stranger # Date: 30-07-2017 11:28:52 # Description: This runbook triggers Windows Update using WindowsUpdate PowerShell Module using the Azure REST API. # The ARM REST API is being used due to fact that the Set-AzureRmVMCustomScriptExtension cmd blocks the call until # the Custom Script Extension is being executed. Which can take quite some time to finish. # Comments: Make sure the Script is available via anonymous access. # Changes: # Disclaimer: # This example is provided "AS IS" with no warranty expressed or implied. Run at your own risk. # **Always test in your lab first** Do this at your own risk!! # The author will not be held responsible for any damage you incur when making these changes! # --------------------------------------------------- [CmdletBinding()] [OutputType([string])] Param ( # VM Name [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] $VMName ) $VerbosePreference = 'Continue' #remove when publishing runbook #region Runbook variables Write-Verbose -Message 'Retrieving hardcoded Runbook Variables' $Resourcegroupname = 'scriptextensiondemo-rg' $ExtensionName = 'WindowsUpdate' $APIVersion = '2017-03-30' $ScriptExtensionUrl = 'https://[enteryourvaluehere].blob.core.windows.net/script/Install-WindowsUpdate.ps1' #endregion #region Connection to Azure Write-Verbose -Message 'Connecting to Azure' $connectionName = 'AzureRunAsConnection' try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName 'Logging in to Azure...' Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else { Write-Error -Message $_.Exception.Message throw $_.Exception } } #endregion #region Get AccessToken Write-Verbose 'Get Access Token' $currentAzureContext = Get-AzureRmContext $azureRmProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile $profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azureRmProfile) $token = $profileClient.AcquireAccessToken($currentAzureContext.Subscription.TenantId) #endregion #region Get extension info Write-Verbose -Message 'Get extension info' $Uri = 'http://ift.tt/2veD6w4}' -f $($currentAzureContext.Subscription), $Resourcegroupname, $VMName, $ExtensionName, $APIVersion $params = @{ ContentType = 'application/x-www-form-urlencoded' Headers = @{ 'authorization' = "Bearer $($token.AccessToken)" } Method = 'Get' URI = $Uri } $ExtensionInfo = Invoke-RestMethod @params -ErrorAction SilentlyContinue if (!($ExtensionInfo)) { Write-Verbose 'No Custom Script Extension Configured. Please do an initial script configuration first' #region configure custom script extension $Uri = 'http://ift.tt/2veD6w4}' -f $($currentAzureContext.Subscription), $Resourcegroupname, $VMName, $ExtensionName, '2017-03-30' $body = @" { "location": "westeurope", "properties": { "publisher": "Microsoft.Compute", "type": "CustomScriptExtension", "typeHandlerVersion": "1.4", "autoUpgradeMinorVersion": true, "forceUpdateTag": "InitialConfig", "settings": { "fileUris" : ["$ScriptExtensionUrl"], "commandToExecute": "powershell -ExecutionPolicy Unrestricted -file Install-WindowsUpdate.ps1" } } } "@ $params = @{ ContentType = 'application/json' Headers = @{ 'authorization' = "Bearer $($token.AccessToken)" } Method = 'PUT' URI = $Uri Body = $body } $InitialConfig = Invoke-RestMethod @params $InitialConfig exit #endregion } #endregion #region Get Extension message info Write-Verbose 'Get Extension message info' $Uri = 'http://ift.tt/2tQAOzP}' -f $($currentAzureContext.Subscription), $Resourcegroupname, $VMName, $ExtensionName, $APIVersion $params = @{ ContentType = 'application/x-www-form-urlencoded' Headers = @{ 'authorization' = "Bearer $($token.AccessToken)" } Method = 'Get' URI = $Uri } $StatusInfo = Invoke-RestMethod @params #$StatusInfo [regex]::Replace($($StatusInfo.properties.instanceView.SubStatuses[0].Message), '\\n', "`n") #endregion #region Update Script Extension try { Write-Verbose 'Update Script Extension' $Uri = 'http://ift.tt/2veD6w4}' -f $($currentAzureContext.Subscription), $Resourcegroupname, $VMName, $ExtensionName, '2017-03-30' $body = @" { "location": "westeurope", "properties": { "publisher": "Microsoft.Compute", "type": "CustomScriptExtension", "typeHandlerVersion": "1.4", "autoUpgradeMinorVersion": true, "forceUpdateTag": "$(New-Guid)", "settings": { "fileUris" : ["$ScriptExtensionUrl"], "commandToExecute": "powershell -ExecutionPolicy Unrestricted -file Install-WindowsUpdate.ps1" } } } "@ $params = @{ ContentType = 'application/json' Headers = @{ 'authorization' = "Bearer $($token.AccessToken)" } Method = 'PUT' URI = $Uri Body = $body } $Updating = Invoke-RestMethod @params $Updating } catch { Write-Error -Message $_.Exception.Message throw $_.Exception } #endregion
When you test the Runbook from the AzureAutomationAuthoringToolkit PowerShell Module you will see the following output.
The initial Get Extension Info retrieve fails due to the fact that there is no Custom Script Extension configured yet for the VM.
You can verify if the Custom Script Extension is configured via the Azure Portal.
Now we just have to wait for the Custom Script Extension PowerShell Script to finish. This can take quite some time if a larger number of Windows Updates have to be installed on the VM.
You can retrieve the status of the Custom Script Extension with the following PowerShell commands:
Get-AzureRmVMDiagnosticsExtension -ResourceGroupName $ResourceGroupName -VMName $VMName -Name $ScriptExtensionName -Status
Is our case you can see the script is still running on the VM.
When the Custom Script Extension is finished you see something like this.
With the following code you can prettify the output.
#region get script extension status $output = Get-AzureRmVMDiagnosticsExtension -ResourceGroupName $ResourceGroupName -VMName $VMName -Name $ScriptExtensionName -Status #-Debug $text = $output.SubStatuses[0].Message [regex]::Replace($text, "\\n", "`n") #endregion
Or you can go to the portal and check the status for the extension.
A final check to see if all the Windows Updates have been installed can be executed but verifying with the Get-WUHistory cmdlet on the VM itself which Windows Updates have been installed.
You can now schedule the Runbook to have Windows Updates regularly been run on the Azure VM.
References:
Custom Script Extension for Windows
Remoting into Azure ARM Virtual Machines - Configuration and Management
DSC Script Resource
PSWindowsUpdate PowerShell Module
Using Azure PowerShell with Azure Storage
Azure Automation Documentation
Using the Azure ARM REST API – Get Access Token
Using the Azure ARM REST API – Get Subscription Information
Using the Azure ARM REST API – End to end Example Part 1
Using the Azure ARM REST API – End to end Example Part 2
PowerShell Azure Automation Authoring Toolkit
from Stefan Stranger's Weblog – Manage your IT Infrastructure http://ift.tt/2tQlN12 via IFTTT
0 notes