Hi there 👋

Welcome to my blog where I document my journey with Azure, PowerShell, automation, and security.

Migrating from VMware to Azure using Azure Files

When using a tool such as Disk2VHD, you need a storage location—and sometimes plenty of it—to export the virtual machine (VM). But what if no local storage is available, and no USB can be connected, such as with a VMware hosting provider? In that case, you can export the VHD directly to an Azure File Share and then copy it to Azure Blob Storage. Note: Dynamically expanding disks are not supported in this process—you must use a fixed-size disk. ...

August 18, 2025 · 2 min · 362 words · Benedikt Gabriel Egilsson

GSPRO Control box

esp32 code to create GSPRO Control box {: width=“350” height=“200” } {: width=“350” height=“200” } // Benedikt Gabriel Egilsson - bensiegils.com // 1= 5 - Camera to ball // 2= KEY_M_CTRL - Muligan // 3= T - Scorecard display // 4= P - See the pin // 5= O - Flyover of the hole // 6= . - shadow quality // 7= B - Hide - Make objects in your line of sight invisible // 8= Z - Hide or show the 3D gras // 9= KEY_UP_ARROW // 10= KEY_DOWN_ARROW // 11= KEY_LEFT_ARROW // 12= KEY_RIGHT_ARROW #define USE_NIMBLE #include <BleKeyboard.h> BleKeyboard bleKeyboard("GSPRO BOX"); #define NUM_KEYS 12 struct Key { int pin; uint8_t code; bool state; bool isCtrl; // New field to indicate if Ctrl needs to be held }; Key keys[NUM_KEYS] = { {16, '5', false, false}, {17, 'm', false, true}, // 'm' with Ctrl modifier {18, 't', false, false}, {19, 'p', false, false}, {21, 'o', false, false}, {22, '.', false, false}, {32, 'b', false, false}, {33, 'z', false, false}, {27, KEY_UP_ARROW, false, false}, {14, KEY_DOWN_ARROW, false, false}, {12, KEY_LEFT_ARROW, false, false}, {13, KEY_RIGHT_ARROW, false, false} }; bool connectNotificationSent = false; void setup() { Serial.begin(115200); Serial.println("Code running..."); // Set pin modes for (int i = 0; i < NUM_KEYS; i++) { pinMode(keys[i].pin, INPUT_PULLUP); } // Initialize BLE keyboard bleKeyboard.begin(); } void loop() { if (bleKeyboard.isConnected()) { if (!connectNotificationSent) { Serial.println("BLE connected..."); connectNotificationSent = true; } for (int i = 0; i < NUM_KEYS; i++) { handleButton(i); } } else { if (connectNotificationSent) { Serial.println("BLE disconnected..."); connectNotificationSent = false; } } delay(10); // Small delay to stabilize readings } void handleButton(int keyIndex) { bool currentState = !digitalRead(keys[keyIndex].pin); // Read the button state (active low) if (currentState != keys[keyIndex].state) { keys[keyIndex].state = currentState; if (currentState) { if (keys[keyIndex].isCtrl) { // Check if Ctrl modifier is needed bleKeyboard.press(KEY_LEFT_CTRL); } bleKeyboard.press(keys[keyIndex].code); Serial.print("Key pressed: "); } else { bleKeyboard.release(keys[keyIndex].code); if (keys[keyIndex].isCtrl) { // Check if Ctrl modifier is needed bleKeyboard.release(KEY_LEFT_CTRL); } Serial.print("Key released: "); } Serial.println(keys[keyIndex].code); } }

June 23, 2024 · 2 min · 333 words · Benedikt Gabriel Egilsson

Arc - Diskspace Monitoring - Teams)

Upon successfully installing Azure Arc on your Server and activating Insights, you open the door to a powerful monitoring capability. One essential aspect is overseeing disk space usage on your server, ensuring optimal performance and preventing potential issues. This example provides a step-by-step guide on how to set up disk space monitoring and receive instant notifications via Microsoft Teams when space is running low. Furthermore, this versatile approach can be extended to send email alerts, providing an additional layer of flexibility in how you manage critical resource thresholds. This comprehensive monitoring strategy empowers you with the tools to proactively maintain your server’s health and responsiveness, bolstering the reliability of your operations. ...

October 15, 2023 · 3 min · 603 words · Benedikt Gabriel Egilsson

Azure Arc - (Azure Cli - ssh - rdp)

If you have deployed Azure Arc, you have the option to utilize Windows Admin Center for Windows Machines. Additionally, you can enable the OpenSSH Extension on Windows Server, granting the capability to establish SSH tunnels to the localhost or other machines that support RDP/SSH connections. {: .normal-image} To begin the process, please follow these steps: Ensure that you have the Azure CLI installed on your local computer. If it is not already installed, open PowerShell and execute the command: winget install -e –id Microsoft.AzureCLI. ...

October 8, 2023 · 2 min · 218 words · Benedikt Gabriel Egilsson

hyper-v-tool

My tool to create vm’s in my lab https://github.com/Lubenz007/hyper-v-tool Utilizing a standalone Hyper-V server and generating VMs from a golden image might be considered an older approach, but it’s one I personally prefer. Over the years, I’ve diligently maintained a tool for crafting VMs on my Hyper-V host within the lab environment. I employ SSH to connect to the Hyper-V host and initiate the VM creation process. This tool provides a streamlined menu system that automatically configures the VM, allowing me to promptly begin using it. ...

September 30, 2023 · 1 min · 149 words · Benedikt Gabriel Egilsson

Get Azure Defender for Cloud score Via API

How to build a report of Azure Defender for Cloud score Via API, and export it to CSV. Why do we need this? share it with your ?, and show them the progress of your security posture. Need to create service principal with the following permissions: Read RBAC on each subscription. {: .prompt-info } #set the variables $ClientID = '' $ClientSecret = '' $tenant_Id = '' # your subscription Ids $subscription_Ids = '' # Create the body of the request. $Body = @{ Grant_Type = "client_credentials" Resource = "https://management.azure.com/" client_id = $clientId client_secret = $clientSecret } $ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoft.com/$tenant_Id/oauth2/token?api-version=1.0" -Method POST -Body $Body $Headers = @{ 'Content-Type' = "application/json" 'Authorization' = "Bearer $($ConnectGraph.access_token)" } # Force TLS 1.2. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 #function to get graph data with pagination function Get-GraphData { param ( [parameter(Mandatory)] [string]$AccessToken, [parameter(Mandatory)] [string]$Uri ) $Headers = @{ 'Authorization' = "Bearer $AccessToken" } do { $Results = Invoke-RestMethod -Uri $Uri -Headers $Headers -ErrorAction Stop $QueryResults += $Results.value $Uri = $Results.'@odata.nextLink' } while ($Uri) return $QueryResults } # Get the data foreach ($subscription_Id in $subscription_Ids) { $uri1 = "https://management.azure.com/subscriptions/$subscription_Id/providers/Microsoft.Security/secureScores?api-version=2020-01-01" [array]$secureScores = Get-GraphData -AccessToken $ConnectGraph.access_token -Uri $uri1 $uri2 = "https://management.azure.com/subscriptions/$subscription_Id/providers/Microsoft.Security/secureScores/ascScore/securescorecontrols?api-version=2020-01-01" [array]$ascScores = Get-GraphData -AccessToken $ConnectGraph.access_token -Uri $uri2 $uri3 = "https://management.azure.com/subscriptions/$subscription_Id/providers/Microsoft.Security/secureScoreControlDefinitions?api-version=2020-01-01" [array]$secureScoreControlDefinitions = Get-GraphData -AccessToken $ConnectGraph.access_token -Uri $uri3 $uri4 = "https://management.azure.com/subscriptions/$subscription_Id/providers/Microsoft.Security/assessments?api-version=2020-01-01" [array]$assessments = Get-GraphData -AccessToken $ConnectGraph.access_token -Uri $uri4 $uri5 = "https://management.azure.com/subscriptions/$subscription_Id/providers/Microsoft.Security/secureScores/ascScore/securescorecontrols?api-version=2020-01-01&expand=definition" [array]$securescorecontrols = Get-GraphData -AccessToken $ConnectGraph.access_token -Uri $uri5 } # Create the report $ReportLineScore = [PSCustomObject][Ordered]@{ MaxScore = $secureScores.Properties.score.max Current = $secureScores.Properties.score.current percentage = $secureScores.Properties.score.percentage * 100 } $SPData = [System.Collections.Generic.List[Object]]::new() ForEach ($ascScore in $ascScores) { $SPLine = [PSCustomObject][Ordered]@{ Name = $ascScore.properties.displayName Healthy = $ascScore.properties.healthyResourceCount UnHealthy = $ascScore.properties.unhealthyResourceCount NotApplicable = $ascScore.properties.notApplicableResourceCount weight = $ascScore.properties.weight maxScore = $ascScore.properties.score.max currentScore = $ascScore.properties.score.current percentage = $ascScore.properties.score.percentage * 100 } $SPData.Add($SPLine) } $SPData1 = [System.Collections.Generic.List[Object]]::new() foreach ($secureScoreControlDefinition in $secureScoreControlDefinitions) { $SPLine1 = [PSCustomObject][Ordered]@{ Name = $secureScoreControlDefinition.properties.displayName MaxScore = $secureScoreControlDefinition.properties.maxScore } $SPData1.Add($SPLine1) } $SPData2 = [System.Collections.Generic.List[Object]]::new() foreach ($assessment in $assessments) { $SPLine2 = [PSCustomObject][Ordered]@{ Name = $assessment.properties.displayName Status = $assessment.properties.status.description Code = $assessment.properties.status.code Cause = $assessment.properties.status.cause Details = $assessment.properties.resourceDetails.Id } $SPData2.Add($SPLine2) } $SPData3 = [System.Collections.Generic.List[Object]]::new() foreach ($securescorecontrol in $securescorecontrols) { $SPLine3 = [PSCustomObject][Ordered]@{ Name = $securescorecontrol.properties.displayName HealthyCount = $securescorecontrol.properties.healthyResourceCount UnHealthyCount = $securescorecontrol.properties.unhealthyResourceCount NotApplicableCount = $securescorecontrol.properties.notApplicableResourceCount } $SPData3.Add($SPLine3) } $ReportLineScore | Export-Csv -Path "c:\temp\ReportLineScore.csv" -NoTypeInformation -Encoding UTF8 $SPData | Export-Csv -Path "c:\temp\SPData.csv" -NoTypeInformation -Encoding UTF8 $SPData1 | Export-Csv -Path "c:\temp\SPData1.csv" -NoTypeInformation -Encoding UTF8 $SPData2 | Export-Csv -Path "c:\temp\SPData2.csv" -NoTypeInformation -Encoding UTF8 $SPData3 | Export-Csv -Path "c:\temp\SPData3.csv" -NoTypeInformation -Encoding UTF8 MaxScore Current percentage 31 24 77,42 Name MaxScore Protect applications against DDoS attacks 2 Enable MFA 10 Encrypt data in transit 4 Restrict unauthorized network access 4 Implement security best practices 0 Apply adaptive application control 3 Enable auditing and logging 1 Enable encryption at rest 4 Enable endpoint protection 2 Apply system updates 6 Manage access and permissions 4 Remediate security configurations 4 Secure management ports 8 Remediate vulnerabilities 6 Enable enhanced security features 0

May 28, 2023 · 3 min · 481 words · Benedikt Gabriel Egilsson

Monitor Azure Usage for a subscription

Why do we need to monitor Azure usage? Well, if you have a subscription with a spending limit, you need to keep track of your usage. If you go over the spending limit, your resources will be disabled. And you will need to pay for the overage. My concern is that some one gets a hold of my subscription, and start to use it. And I will get a big bill at the end of the month. {: .prompt-info } ...

May 13, 2023 · 3 min · 468 words · Benedikt Gabriel Egilsson

Monitor Azure usage with github actions

This will not work for Azure Plan subscriptions. ((400) Subscription scope usage is not supported for current api version. Please use api version after 2019-10-01) {: .prompt-info } Need to keep track of your Azure usage? here is a way to use github actions to keep track of your usage. And send you a Teams message if you are over a certain amount. We will need to enable webhook in Teams and add the webhook to the script, and create a Service Principal with access to the subscription you want to monitor. {: .prompt-tip } ...

May 13, 2023 · 2 min · 391 words · Benedikt Gabriel Egilsson

Three great tools for Azure

Always in need for some tools to help make great things. Azure Quick Review Azure Quick Review (azqr) goal is to produce a high level assessment of an Azure Subscription or Resource Group providing the following information for each Azure Service. Azure Visualizer PowerShell module to automatically generate Azure resource topology diagrams by just typing a PowerShell cmdlet and passing the name of one or more Azure Resource Group(s). Azure Cost CLI simple command line tool to get the cost of your Azure subscription. ...

May 10, 2023 · 1 min · 84 words · Benedikt Gabriel Egilsson

Azure Cost CLI

Azure-Cost-CLI is a new tool to get cost information from Azure. Link{: .btn } What are the benefits of this tool?, Simple, you can get cost information from Azure without having to log in to the portal. ? Send teams messages with cost information. ? Send emails with cost information. ? Azure Cost Overview Accumulated cost for subscription id `0692777c-ed93-4a6a-85c7-144c24xxxx` from **1.5.2023** to **9.5.2023** Totals Period Amount Today 0,90 EUR Yesterday 2,21 EUR Last 7 days 17,26 EUR Last 30 days 19,40 EUR gantt title Accumulated cost dateFormat X axisFormat %s section 01 maí EUR 2,14 :0, 214 section 02 maí EUR 4,24 :0, 424 section 03 maí EUR 6,37 :0, 637 section 04 maí EUR 8,51 :0, 851 section 05 maí EUR 11,00 :0, 1100 section 06 maí EUR 13,61 :0, 1361 section 07 maí EUR 16,29 :0, 1629 section 08 maí EUR 18,50 :0, 1850 section 09 maí EUR 19,40 :0, 1940 section 10 maí EUR 21,36 : done, 0, 2136 section 11 maí EUR 23,33 : done, 0, 2333 section 12 maí EUR 25,52 : done, 0, 2552 section 13 maí EUR 27,71 : done, 0, 2771 section 14 maí EUR 30,04 : done, 0, 3004 section 15 maí EUR 32,19 : done, 0, 3219 section 16 maí EUR 34,08 : done, 0, 3408 section 17 maí EUR 35,99 : done, 0, 3599 section 18 maí EUR 37,91 : done, 0, 3791 section 19 maí EUR 40,04 : done, 0, 4004 section 20 maí EUR 42,18 : done, 0, 4218 section 21 maí EUR 44,46 : done, 0, 4446 section 22 maí EUR 46,54 : done, 0, 4654 section 23 maí EUR 48,39 : done, 0, 4839 section 24 maí EUR 50,24 : done, 0, 5024 section 25 maí EUR 52,10 : done, 0, 5210 section 26 maí EUR 54,18 : done, 0, 5418 section 27 maí EUR 56,26 : done, 0, 5626 section 28 maí EUR 58,48 : done, 0, 5848 section 29 maí EUR 60,51 : done, 0, 6051 section 30 maí EUR 62,30 : done, 0, 6230 section 31 maí EUR 64,10 : done, 0, 6410 By Service Name Service Amount Backup 21,92 EUR Security Center 9,88 EUR Azure App Service 2,52 EUR Virtual Network 1,40 EUR Log Analytics 1,21 EUR Sentinel 1,00 EUR Azure DNS 0,52 EUR Storage 0,31 EUR Advanced Threat Protection 0,04 EUR Others 0,00 EUR pie title Cost by service "Backup" : 21.92 "Security Center" : 9.88 "Azure App Service" : 2.52 "Virtual Network" : 1.40 "Log Analytics" : 1.21 "Sentinel" : 1.00 "Azure DNS" : 0.52 "Storage" : 0.31 "Advanced Threat Protection" : 0.04 "Others" : 0.00 By Location Location Amount EU West 8,23 EUR Unassigned 4,96 EUR US West 4,07 EUR EU North 1,88 EUR Unknown 0,26 EUR pie title Cost by location "EU West" : 8.23 "Unassigned" : 4.96 "US West" : 4.07 "EU North" : 1.88 "Unknown" : 0.26 By Resource Group Resource Group Amount bensa 6,80 EUR microsoft.security 4,96 EUR backuptest 4,07 EUR alitis 2,22 EUR test2 1,35 EUR pie title Cost by resource group "bensa" : 6.80 "microsoft.security" : 4.96 "backuptest" : 4.07 "alitis" : 2.22 "test2" : 1.35 Generated at 2023-05-09 23:33:20 ...

May 3, 2023 · 3 min · 529 words · Benedikt Gabriel Egilsson