Skip to main content

188 posts tagged with "Azure"

View All Tags

Azure Resource Graph Explorer and the PowerShell Azure Resource Graph

· 7 min read

Every now and again you come across something that you pay little attention to until you actually spend the time to sit down, work through and try to break stuff! The Azure Resource Graph was that for me!

The idea was to create an export of Azure Recommendations, directly from the Azure Advisor into PowerShell, Microsoft Azure has this functionality out of the box with a few tools:

Azure Graph Resource Explorer

The Azure Graph Resource Explorer is built into the Azure Portal, it can be found by going to https://portal.azure.com/#blade/HubsExtension/ArgQueryBlade or by logging into the Azure Portal and typing in 'Resource Graph' and select Explorer.

Azure Resource Graph

The Azure Resource Graph Explorer, allows you to explore the Microsoft Azure Resource Graph, using inbuilt Sample Queries and the Kusto Query language.

The Powershell queries mentioned in the section below, started by clicking on the 'microsoft.advisor/recommendations' field and selecting Run Query.

advisorresources
| where type == "microsoft.advisor/recommendations"

Azure Resource Graph Explorer

I then clicked on the 'See Details' on the right-hand side to see all the details that were being brought in, in each object or row. Example below:

{
"recommendationTypeId": "7262dc51-c168-41b5-b99b-b5b98f8fe50a",
"extendedProperties": {
"assessmentKey": "7262dc51-c168-41b5-b99b-b5b98f8fe50a",
"score": "0"
},
"resourceMetadata": {
"resourceId": "/subscriptions/0673a0bd-0c9b-483f-9aee-c44795ae739f",
"singular": null,
"plural": null,
"action": null,
"source": "/subscriptions/0673a0bd-0c9b-483f-9aee-c44795ae739f/providers/Microsoft.Security/assessments/7262dc51-c168-41b5-b99b-b5b98f8fe50a"
},
"shortDescription": {
"solution": "Subscriptions should have a contact email address for security issues",
"problem": "Subscriptions should have a contact email address for security issues"
},
"suppressionIds": null,
"impactedField": "Microsoft.Subscriptions/subscriptions",
"impactedValue": "0673a0bd-0c9b-483f-9aee-c44795ae739f",
"lastUpdated": "2021-04-08T13:15:54.2870000Z",
"category": "Security",
"metadata": null,
"impact": "Low"
}

And no, that isn't my real Subscription ID etc, I've replaced the field with randomly generated GUIDs.

We can see that there is a good amount of actionable data here such as:

  • This is a Security Category recommendation
  • It is Low Impact
  • The problem is that the Azure subscription should have a contact email address to be used for Security alerts and it does not have one set up (Oops!)

So we need to turn it into something a bit more useable, I know that the Azure Advisor has the following categories:

  • Cost
  • HighAvailability
  • OperationalExcellence
  • Performance
  • Security

The same syntax can be used for any of these categories, for my example, we will continue with Security, Looking at the Details (or Example above) we can see that Category is simply listed on its own at the top level, inside the 'microsoft.advisor/recommendations' field, so we now need to add another pipe to the query:

| where properties['category'] == 'Security'

This will now only select the 'Security' category. However as you can see below, it's hardly something you can action on or read.

Azure Resource Graph - Category 'Security'

The next step is to look into making it a bit more readable because we know this is a Kusto Language, its time to hit the Microsoft Docs page and read up about the 'Project Operator' - https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/projectoperator. Project = "Select the columns to include, rename or drop, and insert new computed columns." That sounds like what we want.

If we take a gander back at the 'Full Details' (or Example above) there are 3 fields I am looking at that would add the most value to a report or digest for the security posture of my Azure ecosystem:

  • Solution
  • impactedField
  • impactedValue

We now need to add our final pipe to remove everything we don't want and add the properties that make the most sense to use, because we are using multiple properties we will do it separated by commas. It's worth noting that unlike the 'Security' property above (and the impactedField, impactedValue), which was a top-level property, the Solution property is a sub-properties of 'shortDescription', so we have to select the shortdescription property and then expand out to the extended solution property like below:

| project properties.shortDescription.solution

That now gives us a list of the security alerts on the subscription, but without a heading that makes sense:

Azure Resource Graph

To add a header called: Recommendation, we need to do the following

| project Recommendation=tostring(properties.shortDescription.solution)

Now we are ready to add the impactedField and impactedValue.

The final query should look like this:

advisorresources
| where type == 'microsoft.advisor/recommendations'
| where properties['category'] == 'Security'
| project Recommendation=tostring(properties.shortDescription.solution), ImpactedType=tostring(properties.impactedField), ImpactedResources=tostring(properties.impactedValue )

and the Azure Resource Graph Explorer should display something like this:

Azure Resource Graph

Protip, on the Azure Resource Graph Explorer page, click on 'Get Started', underneath the Query window to view Example Queries, such as Listing all Public IP addresses or even getting the Security Center Recommendations. They are really good to use as a base and see how they work.

Azure Graph PowerShell

Using the Azure Resource Graph Explorer is a good way to create the Kusto queries you want, which you can then run the queries in PowerShell and turn them into PowerShell objects, which opens up a few possibilities for things like:

  • Automated Reporting on Cost, Security etc
  • Proactive remediation actions.

First things first you need to install the Az.ResourceGraph module, then you can use the Search-AzGraph to run the queries that you created above. I am going to rely on the gist below to give you a few examples.

Azure Resource Graph

AzGraph.ps1

<#
.SYNOPSIS
Installs the Az.ResourceGraph Module and has example queries
.NOTES
Version: 1.0
Author: Luke Murray (Luke.Geek.NZ)
Website: https://luke.geek.nz/azure-resource-graph-explorer-and-the-powershell-azure-resource-graph
Creation Date: 09.04.21
Change History:
09.04.21 - Intital script development

#>

# Install the Resource Graph module from PowerShell Gallery
Install-Module -Name Az.ResourceGraph -Scope CurrentUser

# Imports the Resource Graph module into the PowerShell session
Import-Module -Name Az.ResourceGraph

#Connects to Microsoft Azure
Connect-AzAccount

#Grabs the acount of all recommendations under each Category that the Azure Advisor Has

Search-AzGraph -Query "advisorresources | summarize Count=count() by Category=tostring(properties.category) | where Category!='' | sort by Category asc"

#Following on from the Blog post, this is the query we created to list all Security recommendations, their resource type and what resources were impacted

Search-AzGraph -Query "advisorresources
| where type == 'microsoft.advisor/recommendations'
| where properties['category'] == 'Security'
| project Recommendation=tostring(properties.shortDescription.solution), ImpactedType=tostring(properties.impactedField), ImpactedResources=tostring(properties.impactedValue )"

#List of Performance recommendations

Search-AzGraph -Query "advisorresources | where type == 'microsoft.advisor/recommendations' and properties.category == 'Performance' | project Solution=tostring(properties.shortDescription.solution) | summarize Count=count() by Solution | sort by Count"

#List of Cost recommendations

Search-AzGraph -Query "advisorresources | where type == 'microsoft.advisor/recommendations' and properties.category == 'Cost' | summarize Resources = dcount(tostring(properties.resourceMetadata.resourceId)), Savings = sum(todouble(properties.extendedProperties.savingsAmount)) by Solution = tostring(properties.shortDescription.solution), Currency = tostring(properties.extendedProperties.savingsCurrency) | project Solution, Resources, Savings = bin(Savings, 0.01), Currency | order by Savings desc"

Keep up to date with Azure changes using PowerShell

· 3 min read

Keeping up with what is happening with changes and previews in Microsoft Azure is difficult, change happens all the time - and being able to stay informed on what is happening with the Azure ecosystem is half the battle, whether it is a new feature or security fix.

Microsoft publishes the latest updates on Azure Products and features to their Azure Updates blog: https://azure.microsoft.com/en-us/updates/

So you can browse the website each week, or... monitor the RSS feeds. Sometimes this isn't enough, you may want to do something with this information such as:

  • Create Alerts or Notifications to specific teams who may work with Azure SQL, or Azure Automation and not care about any other product.
  • Not have to go to the website to keep up-to-date with what is happening, maybe your happy with it popping up in your PowerShell session each time you open it.
  • Publish the information to Microsoft Teams channels to keep people informed.

I have created a basic PowerShell function, that will retrieve the latest updates from the Microsoft Azure Updates RSS Feed and turn it into a PowerShell object you can actually use to keep informed.

The Script - Get-AzureBlogUpdates

The script is hosted on my Github repository. Feel free to clone/recommend improvements or fork, I can add parameter sets instead of relying on the PowerShell methods listed in the examples section - if you find this script useful:

Get-AzureBlogUpdates.ps1

function Get-AzureBlogUpdates {
<#
.SYNOPSIS
Retrieves the latest Updates of Azure, from the Azure Blog RSS feed.
.DESCRIPTION
Retrieves the latest Updates of Azure, from the Azure Blog RSS feed.
.NOTES
Version: 1.0
Author: Luke Murray (Luke.Geek.NZ)
Website: https://luke.geek.nz/keep-up-to-date-with-latest-changes-on-azure-using-powershell
Creation Date: 03.04.21
Purpose/Change:
03.04.21 - Intital script development
.EXAMPLE
Get-AzureBlogUpdate

#>
#Retrieving RSS Feed Content - as XML, then converting into PSObject
$xml = [xml](Invoke-WebRequest -Uri 'https://azurecomcdn.azureedge.net/en-us/updates/feed/').content
$Array = @()
foreach ($y in $xml.rss.channel.selectnodes('//item'))
{
$PSObject = New-Object -TypeName PSObject
$Date = [datetime]$y.pubdate
$PSObject | Add-Member NoteProperty 'Title' $y.title
$PSObject | Add-Member NoteProperty 'Date' $Date
$PSObject | Add-Member NoteProperty 'Category' $y.category
$PSObject | Add-Member NoteProperty 'Description' $y.content.InnerText
$PSObject | Add-Member NoteProperty 'Link' $y.link


$Array += $PSObject
}
#Some article had multiple categories, to make it easier for reporting, joined the categories together and got rid of duplicates.

$results = @()
ForEach ($item in $Array) {
$Category = Foreach ($title in $item.Title)
{
$results += [pscustomobject]@{
'Title' = $item.Title
'Category' = $item.Category -join ',' | Select-Object -Unique
'Published Date' = $item.Date
'Description' = $item.Description
'Link' = $item.Link
}
}
}
$results
}

Examples

#Runs the actual Function:
Get-AzureBlogUpdates

Get-AzureBlogUpdates

#EXAMPLE - Gets Azure Blog Updates, that have been published in the last 7 days.
$PublishedIntheLastDays = (Get-Date).AddDays(-7)
Get-AzureBlogUpdates | Where-Object 'Published Date' -GT $PublishedIntheLastDays

Get-AzureBlogUpdates

#EXAMPLE - Gets all Azure Blog Updates, and displays it as a Table, organised by Category
Get-AzureBlogUpdates | Sort-Object Category -Descending | Format-Table

Get-AzureBlogUpdates

#EXAMPLE -Gets the latest 10 Azure Blog Articles
Get-AzureBlogUpdates | Select -Last 10

Get-AzureBlogUpdates - Select Last 10 Articles

#EXAMPLE - Gets the Azure Blog Update articles, where the title has Automation in it.
Get-AzureBlogUpdates | Where-Object Title -match 'Automation'

Get-AzureBlogUpdates - Title matches Automation

Transfer Ownership of an Azure Subscription

· 4 min read

Imagine you want to transfer Azure resources to another person or company? This could be because something may have been created in an external third-party subscription, to begin with, or you have created a product using Azure resources that you have just sold to the highest bidder!

Before you start rolling in that money bin of cash, you need to be able to give that person the Azure resources. The best way to do this is to transfer ownership of an Azure subscription.

It may be best to create a new Azure subscription, and then transfer (using the Move Resources in the Azure Resource Group) the resources to that new subscription. That way it is clean, then the recipient can just migrate the resources to their own Production subscription later, etc as they see fit.

Just a heads up IF you are selling services you have created in Microsoft Azure, whether freelance or professionally make sure you have spent time working on Azure governance to make sure you have a proper Azure Landing Zone stood up for standardization and naming conventions in place if you are a transferring a resource that has a Global Scope (ie these are usually Public-facing, the last thing you want is to transfer the resources to someone else and find out that you can't reuse the same unique name.

Please read this carefully, there are certain limitations when transferring Subscription Ownership - especially across to another tenancy that you need to be aware of, these limitations are the Type of Subscription it is and the type of resources, encryption status, etc.Transfer an Azure subscription to a different Azure AD directory In some cases, you may need to look at alternative ways, such as redeploying or recreating the resources in the other subscription/tenancy manually - via redirecting an Azure DevOps deployment or manual backup export and import.

Transfer a Subscription

Once you are ready to transfer a subscription, you can do the rest, simply through the Azure Portal:

  1. In the Azure Portal, navigate to Subscriptions
  2. Click on the Subscription you want to migrate
  3. Click on Transfer billing ownership
  4. Type in the Recipient's email address, in the email address field
  5. If you are moving the Azure subscription to another Azure AD tenancy (in this article, I am assuming we are), select the 'Move Subscription Tenant toggle: Yes Transfer Billing Ownership
  6. Click on Send Transfer Request, acknowledge the prompt and click Yes
  7. This will send an email to the recipient with a link to transfer the Azure subscription and all the resources. Transfer Billing Ownership

Note: The Transfer Request is not permanent, the recipient has only a few weeks to accept the transfer before you will need to it again, you can see the expires date in the screenshot above.

Note: Something to be aware of, only the user in the new account who accepted the transfer request will have access to manage the resources, they will need to add the necessary groups and rights on their end.

Cancel an Azure Subscription Transfer

If the recipient hasn't accepted the transfer, you can revoke or cancel the transfer request. To do this, do the following:

  1. In the Azure Portal, navigate to Subscriptions
  2. Click on the Subscription you want to migrate
  3. Click on Transfer billing ownership
  4. You will now get a Window indicating the Transfer Request is pending
  5. Click on Cancel the Transfer Request (bottom of the Blade) Transfer Billing Ownership
  6. Accept the prompt to cancel the transfer request.

Note: You can now click on the Transfer billing ownership, to confirm the request was canceled and if needed, open a new request. Just a heads up as well, that canceling the transfer, will also email the recipient.

Microsoft Entra ID Recommendations

· 8 min read

Microsoft Entra ID is the foundation, which Microsoft 365 is built-on.

In the words of Microsoft:

Microsoft Entra ID (Azure AD) is Microsoft’s cloud-based identity and access management service, which helps your employees sign in and access resources in:

  • External resources, such as Microsoft 365, the Azure portal, and thousands of other SaaS applications.
  • Internal resources, such as apps on your corporate network and intranet, along with any cloud apps developed by your own organization.

Microsoft Entra ID (AAD) is simply not set and forget, especially given the fact that AAD services are constantly evolving in terms of features and improved security.

Below is a table of some Microsoft Entra ID and best practice recommendations.

Please keep in mind that like any recommendations, do not blindly follow them, make sure to determine the impact on your users on enabling some of this functionality, there may also be recommendations that you will not be able to apply, do to business constraints.

RecommendationWhy Consider ThisProbabilityImpactEffort
Change break glass accounts passwords every 90 daysEmergency access accounts are highly privileged, and they are not assigned to specific individuals. Emergency access accounts are limited to emergency or "break glass"' scenarios where normal administrative accounts can't be used. We recommend that you maintain a goal of restricting emergency account use to only the times when it is absolutely necessary.HighHighLow
Review possible stale Guest (B2B) accountsGuest accounts do not exist by default and pose a potential data exposure vulnerability if left unused. Guest accounts should only be used with a defined business need and closely monitored to ensure accounts are valid/legitimate.HighModerateLow
Remove invited guests who have not accepted inviteRemove invited guests who have not accepted invite as it helps control the scope of identity and access management as it pertains to provisioning users in Azure AD. In addition, removing stale invites and user from Azure AD is part of the recommended routine account maintenance.HighLowLow
Enable Windows Hello for Business PIN Reset ServiceThe Microsoft PIN reset services enables you to help users recover who have forgotten their PIN. Using Group Policy, Microsoft Intune or a compatible MDM, you can configure Windows 10 devices to securely use the Microsoft PIN reset service that enables users to reset their forgotten PIN through settings or above the lock screen without requiring re-enrollment.Low to ModerateModerateLow
Ensure security compliance notification mail is setManaging security and compliance is a partnership. You are responsible for protecting your data, identities, and devices, while Microsoft vigorously protects Office 365 services. You can use Office 365 and Enterprise Mobility + Security (EMS) together to help you achieve the appropriate level of protection for your organization.Low to ModerateModerateLow
Add owner to legacy Service PrincipalLegacy service principals without a defined owner create a challenge for management and accountability.Low to ModerateModerateLow
Add owner to applicationAssigning an application owner provides an opportunity for delegation and establishes accountability for management of the resource.Low to ModerateModerateLow
Add owner to cloud-only groupsAssigning a group owner provides an opportunity for delegation and establishes accountability for management of the resource.Low to ModerateModerateLow
Require that users can create security groups is set to noThe creation and management of security groups should be restricted to administrators only to limit proliferation of this security principal. The default setting is to prevent users from creating security groups in the Azure portal and it is recommended to maintain this configuration unless required by a defined business need.Low to ModerateModerateLow
Delete empty cloud-only groupsCloud-only groups that contain no members and are not associated with Azure applications should be deleted as they serve no purpose.Low to ModerateLowLow
Review Dynamic Groups with membershipRuleProcessingState not turned onSometimes you may want to stop the processing of a dynamic group, like when you’re importing a large number of new users or reorganizing your group architecture. To do that, use the MembershipRuleProcessingState parameter to switch processing on and off.Low to ModerateLowLow
Review and consider federating all domainsWhen a domain is federated with Azure AD, several properties are set on the domain in Azure. One important one is IssuerUri. This property is a URI that is used by Azure AD to identify the domain that the token is associated with.Low to ModerateLowLow
Review applications with credentials about to expire or are expiredApplications with expired credentials will prevent its use and should be updated before expiration to avoid an outage. If the application's service principal already has newer credentials remove the no longer valid credentials.ModerateHighLow
Review applications granted with risky OAUTH2 permissionsDepending on the scope of permissions, it can pose a risk to the confidentiality, integrity, or availability of the organization's data. Periodic review of application permission grants can help identity over-privileged applications and establish access controls that align with the principle of least privilege.ModerateHighLow
Configure user passwords to never expireRequesting users to regularly change passwords will lead to weak password practices like patterns or sequential words and numbers.ModerateModerateLow
Review Service Principals using password based credentialsProtect and manage your confidential app credentials for web apps, web APIs and daemon apps. Use certificate credentials, not password credentials (client secrets).ModerateModerateLow
Review Azure AD Guest (B2B) accountsGuest accounts do not exist by default and pose a potential data exposure vulnerability if left unused. Guest accounts should only be used with a defined business need and closely monitored to ensure accounts are valid/legitimate.ModerateModerateLow
Review applications consented by adminsReview applications granted consent by admins to ensure this global configuration is desired, which results in authorization for applications to data for all users in the Azure AD tenant.ModerateModerateLow
Review applications consented by one userReview applications granted consent by a single users to ensure the configuration is desired, which results in authorization for applications to data for individual users as compared to admin consent which is global for the tenant.ModerateModerateLow
Review domain password policies that do not match defaults.Only passwords for user accounts that are not synchronized through directory synchronization can be configured for password policies. By default users do not have a password policy defined.ModerateModerateLow
Specify the usage location property for usersSome Microsoft services aren't available in all locations because of local laws and regulations. Before you can assign a license to a user, you must specify the Usage location property for the user.ModerateModerateLow
Require that users can consent to apps accessing company data on their behalf is set to noAllowing users to provide consent for third-party applications risks exfiltration of personally identifiable information (PII) such as email and phone number, as it's associated with the user's profile.HighHighModerate
Review group license errorsThese errors should be resolved and all users should be assigned expected licenses, for avoiding any loss of productivity.HighModerateModerate
Remove email / mailbox from directory role adminsTo help separate internet risks (phishing attacks, unintentional web browsing) from administrative privileges, create dedicated accounts for each user with administrative privileges with no mail enabled to make sure they do not inadvertently open emails or run programs associated with their admin accounts.ModerateHighModerate
Remove Skype address from directory role adminsTo help separate internet risks (phishing attacks, unintentional web browsing) from administrative privileges, create dedicated accounts for each user with administrative privileges with no Skype Enabled to make sure they do not inadvertently open emails or run programs associated with their admin accounts.ModerateHighModerate
Develop plan to migrate or remove legacy Service PrincipalsServicePrincipals with ServicePrincipalType of legacy are not associated with an application and should be migrated to an application to improve manageability.ModerateModerateModerate
Federated domains in Azure AD must have SupportsMFA enabled if ADFS MFA is usedWhen the configured conditional access policy requires multi-factor authentication, Azure AD defaults to using Azure MFA. If you use the federation service for MFA, you can configure Azure AD to redirect to the federation service when MFA is needed by setting -SupportsMFA to $true in PowerShell. This setting works for federated authentication services that support the MFA challenge request issued by Azure ADModerateModerateModerate
Verify all root level domainsEvery new Azure AD tenant comes with an initial domain name, domainname.onmicrosoft.com. You can't change or delete the initial domain name, but you can add your organization's names to the list. Adding custom domain names helps you to create user names that are familiar to your usersModerateModerateModerate
Review user objects no longer syncing with on-premisesUsers present in Windows Server AD and no longer syncing to Azure AD impacts users ability to use services provided by Azure AD (Password reset, access to O365 services and cloud based apps etc.) and it also poses administrative challenge in managing the account.ModerateModerateModerate

How to restrict users to specific boards in Azure DevOps

· One min read

Do you ever want to add external Microsoft Entra ID or other users to specific boards in a project, but not want to give them access to the entire Azure DevOps Project?

Using the steps below, we can restrict users to a specific board.

  1. Invite external users to DevOps org with Stakeholder access.
  2. In the project, create a new Team and do not add it to the existing security group to inherit permissions. Azure DevOps - Boards
  3. Add external users to created Team.
  4. Set permission for created Team properly. In this case, it’s to set View project-level information to Allow. Azure DevOps - Boards
  5. Create a new area path and set the permission for the created Team in Security Azure DevOps - Boards
  6. Assign the area path to the newly created Team.