Azure DSC Configuration Issue - azure

Basically I am just trying a very basic thing of accessing the VM details using Azure DSC.
I have done the following
Added a new Credential(which holds the username and password) and Variable(which holds the subscriptionId) under Shared Resources of my
automation account
Have implemented the following DSC code for retrieving the VM details: I am able to complie this file in the portal it generates
the .MOF file as well. But when I try to apply this to a node in the
portal I get the following error:
PowerShell DSC resource
MSFT_ScriptResource failed to execute Set-TargetResource
functionality with error message: The term
'Get-AutomationPSCredential' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path
is correct and try again
Please note that the code written inside the SetScript executes successfully in a runbook!!!!!!
Configuration VMAzureDSCTasks
{
param
(
[Parameter()]
[System.String]
$NodeName = "rajeshserver",
[Parameter()]
[System.String]
$ResourceGroupName = "rajeshresourcegroup",
[Parameter()]
[System.String]
$VMSize = "Standard_D2s_v3",
[Parameter()]
[System.String]
$CredentialAssetName = "cred"
)
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
Node $NodeName
{
Script resizevm
{
SetScript = {
# Credentials and Subscription ID declaration
$Cred = Get-AutomationPSCredential -Name $using:CredentialAssetName
$null = Add-AzureRmAccount -Credential $Cred -ErrorAction Stop
$SubId = Get-AutomationVariable -Name 'SubscriptionId'
$null = Set-AzureRmContext -SubscriptionId $SubId -ErrorAction Stop
try {
$vm = Get-AzureRmVm -ResourceGroupName $using:ResourceGroupName -VMName $using:NodeName -ErrorAction Stop
} catch {
throw "Virtual Machine not found!!!!!!"
exit
}
# Output current VM Size
$currentVMSize = $vm.HardwareProfile.vmSize
Write-Verbose -Message "`nFound the specified Virtual Machine: $using:NodeName"
Write-Verbose -Message "Current size: $using:currentVMSize"
}
TestScript = {
return $false
}
GetScript = {
}
}
}
}

Command Get-AutomationPSCredential works in Azure Automation.
For DSC, pass credentials using Get-Credential.
Add parameter
[Parameter()]
[pscredential]
$Credential
And replace Get-AutomationPSCredential with Get-Credential -Credential $Credential.

Related

Not able to access Azure FileShare Storage container from Azure Automation Runbook

I've the following Azure Automation Runbook script which goal is to take an dump/export from a REST API call which must run from a target device which is able to reach the REST API device. So Azure Automation runbook is targeting a "proxy server" then from this we're taking the REST API backup.
The approach has been working exception the fact we're able not to copy this backup file from the target server once 'cm.vm.run_command' presents output size limitation and is truncating the backup. The workaround we found for this was copying the backup file from the 'target/proxy server' directly into a Storage Account Fileshare which is mounted on the target/proxy server. My problem now is when running from Azure Automation it's not able to access the drive mounted by other user and/or is not able to mount the device or access it directly like below errors messages. Does anybody have any alternative for this ? I was able to check the runbook is having connectivity on the storage account ports 443/445 from t. That was one of the possible reasons described here https://learn.microsoft.com/en-us/azure/storage/files/storage-troubleshoot-windows-file-connection-problems
Below the commands and errors I'm receiving and the whole script used.
Copy-item -Path C:\Devicebackup.txt -Destination \\storage_account_name.file.core.windows.net\configdatafileshare\Orchestration
net use w: \\storage_account_name.file.core.windows.net\configdatafileshare\Orchestration `'/yBapkthow==`' /user:Azure\storage_account_name
Copy-item : The network path was not found
At C:\Packages\Plugins\Microsoft.CPlat.Core.RunCommandWindows\1.1.5\Downloads\s
cript9.ps1:15 char:1
+ Copy-item -Path C:\Devicebackup.txt -Destination \\storage_account_name. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Comma
nds.CopyItemCommand
The option /DL2D2QKD1OU2ZKEOJVRK4LGPIRTJKAJBZ+EDKNHWVYYEJDDYSL9CPB5T8F/9VWQBMBWC37B1NJS4YBAPKTHOW== is unknown.
The syntax of this command is:
NET USE
[devicename | *] [\\computername\sharename[\volume] [password | *]]
[/USER:[domainname\]username]
[/USER:[dotted domain name\]username]
[/USER:[username#dotted domain name]
[/SMARTCARD]
[/SAVECRED]
[[/DELETE] | [/PERSISTENT:{YES | NO}]]
NET USE {devicename | *} [password | *] /HOME
NET USE [/PERSISTENT:{YES | NO}]
Param (
[Parameter(Mandatory=$false)][string] $rgName
,[Parameter(Mandatory=$false)][string] $ProxyServerName
)
function CreatePSCommandFile {
Param(
[parameter(Mandatory=$true)][String[]]$DeviceName,
[parameter(Mandatory=$true)][String[]]$DeviceIP,
[parameter(Mandatory=$true)][String[]]$ApiToken
)
$remoteCommand =
#"
add-type #`"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
`"#
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri 'www.mydownload.com' -UseBasicParsing -Headers #{ Authorization="Bearer $($ApiToken)" } | Out-file C:\Devicebackup.txt
net use w: \\storage_account_name.file.core.windows.net\configdatafileshare\Orchestration `'/STORAGE_KEY+EDknHWvyyeJDDYsL9cPB5T8F/9VwqBmbwc37B1NJS4yBapkthow==`' /user:Azure\storage_account_name
Copy-item -Path C:\Devicebackup.txt -Destination \\storage_account_name.file.core.windows.net\configdatafileshare\Orchestration
"#
Set-Content -Path .\InvokeCommand.ps1 -Value $remoteCommand
}
$connectionName = "AzureRunAsConnection"
try {
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
Write-Host "Logging in to Azure..."
$connectionResult = Connect-AzAccount `
-ServicePrincipal `
-Tenant $servicePrincipalConnection.TenantID `
-ApplicationId $servicePrincipalConnection.ApplicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
function Backup-Device {
Param (
[Parameter(Mandatory=$false)][string] $DeviceName
,[Parameter(Mandatory=$false)][string] $DeviceIP
,[Parameter(Mandatory=$false)][string] $ApiToken
)
# Execute Backup on Fortigate Rest API
CreatePSCommandFile -DeviceName $DeviceName -DeviceIP $DeviceIP -ApiToken $ApiToken
$Output = Invoke-AzVMRunCommand -ResourceGroupName $rgName -VMName $ProxyServerName -CommandId 'RunPowerShellScript' -Scriptpath ".\InvokeCommand.ps1" -Parameter #{'api_url' = "10.29.255.212"; 'api_token' = "0p6h1rmspjf37kp80bc6ny88jw"}
($Output).Value.Message
}
Backup-Device -DeviceName "DeviceName" -DeviceIP '10.29.255.212' -ApiToken 'Api_Token'
Sharing the solution which was presented by a blessed colleague :)
Using New-SmbMapping we were able to mount the Storage Account File Share from Azure Automation PS script successfully.
if (!(Test-Path `$MapDrive)) {
New-SmbMapping -LocalPath `$MapDrive -RemotePath `$RemotePath -UserName `$UserName -Password `$Key
}
Copy-Item .\Devicebackup.txt `$MapDrive

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Check if Azure VM name exists before deploying arm template

I am trying to use Azure powershell to get VM name (Eg: demovm01, where the VM name is demovm and the suffix is 01.
I want to get the output and automatically append a new suffix of 02 if 01 already exists.
Sample script to get vm name:
$getvm = Get-AzVM -Name "$vmname" -ResourceGroupName "eodemofunction" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
}
else {
Write-Output "VM exists."
return $true
}
I want to be able to inject this new vm name to an arm deploy to deploy
This should do it. Will increment until no VM is found and use a simple -replace to inject to your json file. Will also return all thr VM values that are already present in Azure
$i=1
$vmname_base = "vmserver"
$VMexists = #()
do {
#invert int value to double digit string
$int = $i.tostring('00')
$getvm = Get-AzVM -Name "$vmname_base$int" -ResourceGroupName "eodemofunction" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
Write-Output "VM created name is $vmname_base$int"
#Set condition to end do while loop
VMcreated = "true"
#commands to inject to json here. I always find replace method the easiest
$JSON = Get-Content azuredeploy.parameters.json
$JSON = $JSON -replace ("Servername","$vmname_base$int")
$JSON | Out-File azuredeploy.parameters.json -Force
}
else {
Write-Output "VMexists."
# Add existing VM to array
$VMexists += "$vmname_base$int"
# Increment version, ie. 01 to 02 to 03 etc
$i++
}
} while ($VMcreated -ne "true")
return $VMexists
Your command could be like below, the $newvmname is that you want.
$vmname = "demovm01"
$getvm = Get-AzVM -Name "$vmname" -ResourceGroupName "<group name>" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
}
else {
Write-Output "VM exists."
if($getvm.Name -like '*01'){
$newvmname = $vmname.TrimEnd('01')+"02"
}
Write-Output $newvmname
return $true
}

Azure webhook get VM status

I'm trying to do a runbook/webhook that return a status of machine. What I finally notices is that
Get-AzureRmVM
is only returning 2 resource groups. Where
Get-AzureRmResource
Does return many more but not all of them again!
I'm sure about my Resource Group Name but still it says resource group 'groupName' could not be found. when I try to run with specific name
Get-AzureRmVM -ResourceGroupName groupName
While my other start and stop runbook works just fine, so i'm confused I can't see the difference between the groups.
PS: I'm using Azure Run As Connection
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
if ($WebhookData) {
$vms = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
Write-Output "Authenticating to Azure with service principal and certificate"
$ConnectionAssetName = "AzureRunAsConnection"
Write-Output "Get connection asset: $ConnectionAssetName"
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
throw "Could not retrieve connection asset: $ConnectionAssetName. Check that this asset exists in the Automation account."
}
Write-Output "Authenticating to Azure with service principal."
Add-AzureRmAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint | Write-Output
# Start each virtual machine
foreach ($vm in $vms)
{
$vmName = $vm.Name
Write-Output "Checking $vmName"
$vmstatus = Get-AzureRmVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroup -Status# | Select-Object -ExpandProperty StatusesText | ConvertFrom-Json
#select code index and convert to $vmpowerstate
$vmPowerState = $vmstatus#[1].Code
#Write-Output "Resource Group: $vmResourceGroupName", ("VM Name: " + $VM.Name), "Status: $VMStatusDetail" `n
Write-Output ("VM Name: " + $vmName), "Status: $vmPowerState" `n
}
}
else {
write-Error "This is webhook only."
}
Because your resource groups are in the different subscriptions.
As #et3rnal mentioned,
I have 2 subscriptions and Get-AzureRmVM returning 2 vms only because the rest are classics. The automation account I created this runbook at is the other one and I can see that in the overview? its the same one I use to start/stop machines in the other subscription!
Update:
If you want to get the PowerState of the VM, you could try the command below, in your case, just put it in the loop, the $PowerState is the PowerState.
$status = Get-AzureRmVM -Name <VM Name> -ResourceGroupName <Resource Group Name> -Status
$PowerState = ($status.Statuses | Where-Object {$_.Code -like "PowerState/*"}).DisplayStatus
Update2:
1.For the classic VM, we need to use azure ASM powershell module command, you could try Get-AzureVM, may be the Example 3: Display a table of virtual machine statuses in that link will help.
2.Another option is to migrate the classic VM(ASM) to ARM, then use the ARM command Get-AzureRmVM.
References:
Platform-supported migration of IaaS resources from classic to Azure Resource Manager
Migrate IaaS resources from classic to Azure Resource Manager by using Azure PowerShell

Unable to create storage account thru azure automation runbook

I am trying hands on on azure automation runbook, below is the small script i am using to create a storage account.
Param
(
[Parameter(Mandatory=$true)]
[String]
$AzureResourceGroup,
[Parameter(Mandatory=$true)]
[String]
$StorageAC,
[Parameter(Mandatory=$true)]
[String]
$Loc,
[Parameter(Mandatory=$true)]
[String]
$sku
)
$CredentialAssetName = "AutomationAccount";
$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
if(!$Cred) {
Throw "Could not find an Automation Credential Asset named
'${CredentialAssetName}'. Make sure you have created one in this Automation
Account."
}
Add-AzureRmAccount -Credential $Cred
Add-AzureAccount -Credential $Cred
$storeac = Get-AzureRmStorageAccount -ResourceGroupName $AzureResourceGroup
if ($storeac.StorageAccountName -eq "testdd" ){
write-output " AC found !";
} else {
New-AzureRmStorageAccount -ResourceGroupName $AzureResourceGroup -Name
$StorageAC -Location $Loc -SkuName $sku
}
However, when ever i run it after publishing, the job is completed with an error
(New-AzureRmStorageAccount : A parameter cannot be found that matches parameter name 'SkuName')
Can someone tell me what am i doing wrong ??
To resolve the error :
New-AzureRmStorageAccount : A parameter cannot be found that matches parameter name 'SkuName'
Please update the Azure modules in you automation account and by clicking : "Update Azure Modules" under Automation Accounts => Modules and retry the runbook
Update Azure Modules

Resources