Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs-mslearn/toolkit/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ The following section lists features and enhancements that are currently in deve

- **Fixed**
- Corrected stale and incorrect descriptions for `BilledCost`, `EffectiveCost`, `BillingCurrency`, `BillingProfileId`, `BillingProfileName`, `CommitmentDiscountQuantity`, `ListUnitPrice`, `PricingQuantity`, `PricingUnitDescription`, and `TotalSavingsRunningTotal` to align with FOCUS 1.2 ([#2112](https://github.com/microsoft/finops-toolkit/pull/2112)).

### [Optimization engine](optimization-engine/overview.md) updates

- **Fixed**
- Removed call to Azure Classic administrators endpoint (deprecated on May 1, 2026) from Azure RBAC assignments exports ([#2142](https://github.com/microsoft/finops-toolkit/issues/2142)).

-->

<br><a name="latest"></a>
Expand Down
6 changes: 3 additions & 3 deletions src/optimization-engine/azuredeploy-nested.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ var runbooks = [
}
{
name: rbacExportsRunbookName
version: '1.1.1.0'
version: '1.1.2.0'
description: 'Exports RBAC assignments to Blob Storage using ARM and Microsoft Entra'
type: 'PowerShell'
scriptUri: uri(templateLocation, 'runbooks/data-collection/${rbacExportsRunbookName}.ps1')
Expand Down Expand Up @@ -1054,14 +1054,14 @@ var runbooks = [
}
{
name: reservationsPriceExportsRunbookName
version: '1.0.2.0'
version: '1.0.3.0'
description: 'Exports Reservations Prices to Blob Storage using the Retail Prices API'
type: 'PowerShell'
scriptUri: uri(templateLocation, 'runbooks/data-collection/${reservationsPriceExportsRunbookName}.ps1')
Comment thread
helderpinto marked this conversation as resolved.
}
{
name: priceSheetExportsRunbookName
version: '1.1.2.0'
version: '1.1.3.0'
description: 'Exports Price Sheet to Blob Storage using the EA or MCA APIs'
type: 'PowerShell'
scriptUri: uri(templateLocation, 'runbooks/data-collection/${priceSheetExportsRunbookName}.ps1')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,16 @@ if (-not([string]::IsNullOrEmpty($externalCredentialName)))

"Logging in to Azure with $authenticationOption..."

switch ($authenticationOption) {
"UserAssignedManagedIdentity" {
switch ($authenticationOption)
{
"UserAssignedManagedIdentity"
{
Connect-AzAccount -Identity -EnvironmentName $cloudEnvironment -AccountId $uamiClientID
break
}
Default { #ManagedIdentity
Default
{
#ManagedIdentity
Connect-AzAccount -Identity -EnvironmentName $cloudEnvironment
break
}
Expand All @@ -86,7 +90,7 @@ if (-not([string]::IsNullOrEmpty($externalCredentialName)))
}

$tenantId = (Get-AzContext).Tenant.Id
$datetime = (get-date).ToUniversalTime()
$datetime = (Get-Date).ToUniversalTime()
$timestamp = $datetime.ToString("yyyy-MM-ddTHH:mm:00.000Z")

$subscriptions = Get-AzSubscription | Where-Object { $_.State -eq "Enabled" }
Expand All @@ -95,44 +99,30 @@ $roleAssignments = @()

"Iterating through all reachable subscriptions..."

foreach ($subscription in $subscriptions) {
foreach ($subscription in $subscriptions)
{

Select-AzSubscription -SubscriptionId $subscription.Id -TenantId $tenantId | Out-Null

$assignments = Get-AzRoleAssignment -IncludeClassicAdministrators -ErrorAction Continue
$assignments = Get-AzRoleAssignment -ErrorAction Continue
"Found $($assignments.Count) assignments for $($subscription.Name) subscription..."

foreach ($assignment in $assignments) {
if ($null -eq $assignment.ObjectId -and $assignment.Scope.Contains($subscription.Id))
foreach ($assignment in $assignments)
{
$duplicateRoleAssignment = $roleAssignments | Where-Object { $_.PrincipalId -eq $assignment.ObjectId -and $_.Scope -eq $assignment.Scope -and $_.RoleDefinition -eq $assignment.RoleDefinitionName }
if (-not($duplicateRoleAssignment))
{
$assignmentEntry = New-Object PSObject -Property @{
Timestamp = $timestamp
TenantGuid = $tenantId
Cloud = $cloudEnvironment
Model = "AzureClassic"
PrincipalId = $assignment.SignInName
Scope = $assignment.Scope
RoleDefinition = $assignment.RoleDefinitionName
Timestamp = $timestamp
TenantGuid = $tenantId
Cloud = $cloudEnvironment
Model = "AzureRM"
PrincipalId = $assignment.ObjectId
Scope = $assignment.Scope
RoleDefinition = $assignment.RoleDefinitionName
}
$roleAssignments += $assignmentEntry
}
else
{
$duplicateRoleAssignment = $roleAssignments | Where-Object { $_.PrincipalId -eq $assignment.ObjectId -and $_.Scope -eq $assignment.Scope -and $_.RoleDefinition -eq $assignment.RoleDefinitionName}
if (-not($duplicateRoleAssignment))
{
$assignmentEntry = New-Object PSObject -Property @{
Timestamp = $timestamp
TenantGuid = $tenantId
Cloud = $cloudEnvironment
Model = "AzureRM"
PrincipalId = $assignment.ObjectId
Scope = $assignment.Scope
RoleDefinition = $assignment.RoleDefinitionName
}
$roleAssignments += $assignmentEntry
}
}
}
}

Expand All @@ -148,7 +138,7 @@ $rbacObjectsJson | Export-Csv -NoTypeInformation -Path $csvExportPath
"Export to $csvExportPath"

$csvBlobName = $csvExportPath
$csvProperties = @{"ContentType" = "text/csv"};
$csvProperties = @{"ContentType" = "text/csv" }

Set-AzStorageBlobContent -File $csvExportPath -Container $storageAccountSinkContainer -Properties $csvProperties -Blob $csvBlobName -Context $saCtx -Force

Expand All @@ -171,27 +161,32 @@ $roleAssignments = @()

#workaround for https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/888
$localPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::UserProfile)
if (-not(get-item "$localPath\.graph\" -ErrorAction SilentlyContinue))
if (-not(Get-Item "$localPath\.graph\" -ErrorAction SilentlyContinue))
{
New-Item -Type Directory "$localPath\.graph"
}

Import-Module Microsoft.Graph.Identity.DirectoryManagement

switch ($cloudEnvironment) {
"AzureUSGovernment" {
switch ($cloudEnvironment)
{
"AzureUSGovernment"
{
$graphEnvironment = "USGov"
break
}
"AzureChinaCloud" {
"AzureChinaCloud"
{
$graphEnvironment = "China"
break
}
"AzureGermanCloud" {
"AzureGermanCloud"
{
$graphEnvironment = "Germany"
break
}
Default {
Default
{
$graphEnvironment = "Global"
}
}
Expand All @@ -205,12 +200,16 @@ else
{
"Logging in to Microsoft Graph with $authenticationOption..."

switch ($authenticationOption) {
"UserAssignedManagedIdentity" {
switch ($authenticationOption)
{
"UserAssignedManagedIdentity"
{
Connect-MgGraph -Identity -ClientId $uamiClientID -Environment $graphEnvironment -NoWelcome
break
}
Default { #ManagedIdentity
Default
{
#ManagedIdentity
Connect-MgGraph -Identity -Environment $graphEnvironment -NoWelcome
break
}
Expand All @@ -219,20 +218,20 @@ else

$domainName = (Get-MgDomain | Where-Object { $_.IsVerified -and $_.IsDefault } | Select-Object -First 1).Id

$roles = Get-MgDirectoryRole -ExpandProperty Members -Property DisplayName,Members
$roles = Get-MgDirectoryRole -ExpandProperty Members -Property DisplayName, Members
foreach ($role in $roles)
{
$roleMembers = $role.Members | Where-Object { -not($_.DeletedDateTime) }
foreach ($roleMember in $roleMembers)
{
$assignmentEntry = New-Object PSObject -Property @{
Timestamp = $timestamp
TenantGuid = $tenantId
Cloud = $cloudEnvironment
Model = "AzureAD"
PrincipalId = $roleMember.Id
Scope = $domainName
RoleDefinition = $role.DisplayName
Timestamp = $timestamp
TenantGuid = $tenantId
Cloud = $cloudEnvironment
Model = "AzureAD"
PrincipalId = $roleMember.Id
Scope = $domainName
RoleDefinition = $role.DisplayName
}
$roleAssignments += $assignmentEntry
}
Expand All @@ -250,7 +249,7 @@ $rbacObjectsJson | Export-Csv -NoTypeInformation -Path $csvExportPath
"Export to $csvExportPath"

$csvBlobName = $csvExportPath
$csvProperties = @{"ContentType" = "text/csv"};
$csvProperties = @{"ContentType" = "text/csv" }

Set-AzStorageBlobContent -File $csvExportPath -Container $storageAccountSinkContainer -Properties $csvProperties -Blob $csvBlobName -Context $saCtx -Force

Expand Down
6 changes: 3 additions & 3 deletions src/optimization-engine/upgrade-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@
{
"runbook": {
"name": "runbooks/data-collection/Export-RBACAssignmentsToBlobStorage.ps1",
"version": "1.1.1.0"
"version": "1.1.2.0"
},
"container": "rbacexports",
"requiredVariables": [
Expand Down Expand Up @@ -689,7 +689,7 @@
{
"runbook": {
"name": "runbooks/data-collection/Export-PriceSheetToBlobStorage.ps1",
"version": "1.1.2.0"
"version": "1.1.3.0"
},
Comment thread
helderpinto marked this conversation as resolved.
"container": "pricesheetexports",
"requiredVariables": [
Expand All @@ -704,7 +704,7 @@
{
"runbook": {
"name": "runbooks/data-collection/Export-ReservationsPriceToBlobStorage.ps1",
"version": "1.0.2.0"
"version": "1.0.3.0"
},
"container": "reservationspriceexports",
"requiredVariables": [
Expand Down