diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 069cde9..43a73d9 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -41,4 +41,13 @@ jobs: TWITTER_CONSUMER_API_SECRET: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} - + bsky-post: + needs: publish-to-gallery + runs-on: ubuntu-latest + steps: + - uses: zentered/bluesky-post-action@v0.0.1 + with: + post: "[New Release] ${{ github.event.repository.name }} ${{ github.event.release.tag_name }}! Check out what's new! ${{ github.event.release.html_url }} #Microsoft #Azure #AsBuiltReport #PowerShell" + env: + BSKY_IDENTIFIER: ${{ secrets.BSKY_IDENTIFIER }} + BSKY_PASSWORD: ${{ secrets.BSKY_PASSWORD }} diff --git a/AsBuiltReport.Microsoft.Azure.json b/AsBuiltReport.Microsoft.Azure.json index 68ada06..6c29e2f 100644 --- a/AsBuiltReport.Microsoft.Azure.json +++ b/AsBuiltReport.Microsoft.Azure.json @@ -19,6 +19,7 @@ "_comment_": "0 = Disabled, 1 = Enabled / Summary, 2 = Detailed, 3 = Comprehensive", "AvailabilitySet": 1, "Bastion": 1, + "DnsPrivateResolver": 1, "ExpressRoute": 1, "Firewall": 1, "IpGroup": 1, @@ -33,6 +34,8 @@ "RouteTable": 1, "SiteRecovery": 1, "StorageAccount": 1, + "Subscription": 1, + "Tenant": 0, "VirtualNetwork": 1, "VirtualMachine": 1 }, diff --git a/AsBuiltReport.Microsoft.Azure.psd1 b/AsBuiltReport.Microsoft.Azure.psd1 index c3aff43..70153c9 100644 --- a/AsBuiltReport.Microsoft.Azure.psd1 +++ b/AsBuiltReport.Microsoft.Azure.psd1 @@ -12,7 +12,7 @@ RootModule = 'AsBuiltReport.Microsoft.Azure.psm1' # Version number of this module. -ModuleVersion = '0.1.7' +ModuleVersion = '0.1.8' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/CHANGELOG.md b/CHANGELOG.md index fa7fc41..87ce9cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # :arrows_clockwise: Microsoft Azure As Built Report Changelog +## [[0.1.8](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Azure/releases/tag/v0.1.8)] - 2024-11-13 + +### Added +* Add support for DNS private resolver +* Add Tenant and Subscription InfoLevels to toggle on/off + +### Changed +* Update GitHub release workflow to add post to Bluesky social platform + ## [[0.1.7](https://github.com/AsBuiltReport/AsBuiltReport.Microsoft.Azure/releases/tag/v0.1.7)] - 2024-10-13 ### Added diff --git a/README.md b/README.md index ec06526..d794d39 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ The Microsoft Azure As Built Report currently supports reporting for the followi * Key Vaults * Load Balancers * Policies +* Private DNS Resolvers * Route Tables * Storage Accounts * Subscriptions @@ -90,8 +91,13 @@ Open a PowerShell terminal window and install each of the required modules. :warning: Microsoft Az 12.0.0 or higher is required. Please ensure older Az modules have been uninstalled. ```powershell -install-module Az -MinimumVersion 12.0.0 -install-module AsBuiltReport.Microsoft.Azure +# Install +install-module Az -Repository PSGallery -MinimumVersion 12.0.0 -Force +install-module AsBuiltReport.Microsoft.Azure -Repository PSGallery -Force + +# Update +update-module Az -Force +update-module AsBuiltReport.Microsoft.Azure -Force ``` ### GitHub @@ -112,6 +118,9 @@ _Note: You are not limited to installing the module to those example paths, you The Microsoft Azure As Built Report utilises a JSON file to allow configuration of report information, options, detail and healthchecks. +> [!IMPORTANT] +> Please rememeber to generate a new report JSON configuration file after each module update to ensure the report functions correctly. + A Microsoft Azure report configuration file can be generated by executing the following command; ```powershell New-AsBuiltReportConfig -Report Microsoft.Azure -FolderPath -Filename @@ -185,6 +194,7 @@ The table below outlines the default and maximum **InfoLevel** settings for each |-----------------------|:---------------:|:---------------:| | AvailabilitySet | 1 | 1 | | Bastion | 1 | 2 | +| DnsPrivateResolver | 1 | 2 | | ExpressRoute | 1 | 2 | | Firewall | 1 | 3 | | IpGroup | 1 | 2 | @@ -197,6 +207,8 @@ The table below outlines the default and maximum **InfoLevel** settings for each | RouteTable | 1 | 2 | | SiteRecovery | 1 | 1 | | StorageAccount | 1 | 2 | +| Subscription | 1 | 1 | +| Tenant | 1 | 1 | | VirtualNetwork | 1 | 2 | | VirtualMachine | 1 | 2 | diff --git a/Src/Private/Get-AbrAzDnsPrivateResolver.ps1 b/Src/Private/Get-AbrAzDnsPrivateResolver.ps1 new file mode 100644 index 0000000..f981942 --- /dev/null +++ b/Src/Private/Get-AbrAzDnsPrivateResolver.ps1 @@ -0,0 +1,150 @@ +function Get-AbrAzDnsPrivateResolver { + <# + .SYNOPSIS + Used by As Built Report to retrieve Azure DNS Private Resolver information + .DESCRIPTION + + .NOTES + Version: 0.1.0 + Author: Tim Carman + Twitter: @tpcarman + Github: tpcarman + .EXAMPLE + + .LINK + + #> + [CmdletBinding()] + param ( + ) + + begin { + Write-PScriboMessage "DnsPrivateResolver InfoLevel set at $($InfoLevel.DnsPrivateResolver)." + } + + process { + Try { + if ($InfoLevel.DnsPrivateResolver -gt 0) { + $AzDnsPrivateResolvers = Get-AzDnsResolver | Sort-Object Name + if ($AzDnsPrivateResolvers) { + Write-PscriboMessage "Collecting Azure DNS Private Resolver information." + Section -Style Heading4 'DNS Private Resolver' { + if ($Options.ShowSectionInfo) { + Paragraph "Azure Private DNS Resolver is a service that securely resolves DNS queries for private resources in Azure VNets, enabling seamless communication between on-premises and cloud environments without exposing traffic to the public internet. It centralises DNS management and supports hybrid cloud architectures." + } + $AzDnsPrivateResolverInfo = @() + foreach ($AzDnsPrivateResolver in $AzDnsPrivateResolvers) { + $AzResourceGroup = Get-AzResource -ResourceType $AzDnsPrivateResolver.Type + $AzDnsResolverInboundEndpoint = Get-AzDnsResolverInboundEndpoint -DnsResolverName $AzDnsPrivateResolver.Name -ResourceGroupName $AzResourceGroup.ResourceGroupName + $AzDnsResolverOutboundEndpoint = Get-AzDnsResolverOutboundEndpoint -DnsResolverName $AzDnsPrivateResolver.Name -ResourceGroupName $AzResourceGroup.ResourceGroupName + $InObj = [Ordered]@{ + 'Name' = $AzDnsPrivateResolver.Name + 'Resource Group' = $AzResourceGroup.ResourceGroupName + 'Location' = $AzLocationLookup."$($AzDnsPrivateResolver.Location)" + 'Subscription' = "$($AzSubscriptionLookup.(($AzDnsPrivateResolver.Id).split('/')[2]))" + 'Inbound Endpoints' = $AzDnsResolverInboundEndpoint.Count + 'Outbound Endpoints' = $AzDnsResolverOutboundEndpoint.Count + 'Virtual Network' = ($AzDnsPrivateResolver.VirtualNetworkId).split('/')[-1] + 'Resource Guid' = $AzDnsPrivateResolver.ResourceGuid + 'Creation Time' = get-date $AzDnsPrivateResolver.SystemDataCreatedAt.ToLocalTime() -format G + 'Last Modified' = get-date $AzDnsPrivateResolver.SystemDataLastModifiedAt.ToLocalTime() -format G + 'Current State' = $AzDnsPrivateResolver.State + 'Provisioning State' = $AzDnsPrivateResolver.ProvisioningState + } + + if ($Options.ShowTags) { + $InObj['Tags'] = if ([string]::IsNullOrEmpty($AzResourceGroup.Tags)) { + 'None' + } else { + ($AzResourceGroup.Tags.GetEnumerator() | ForEach-Object {"$($_.Key):`t$($_.Value)"}) -join [Environment]::NewLine + } + } + + $AzDnsPrivateResolverInfo += [PSCustomObject]$InObj + } + + if ($InfoLevel.DnsPrivateResolver -ge 2) { + Paragraph "The following sections detail the configuration of the DNS private resolver(s) within the $($AzSubscription.Name) subscription." + foreach ($AzDnsPrivateResolver in $AzDnsPrivateResolverInfo) { + Section -Style NOTOCHeading5 -ExcludeFromTOC "$($AzDnsPrivateResolver.Name)" { + $TableParams = @{ + Name = "Private DNS Resolver - $($AzDnsPrivateResolver.Name)" + List = $true + ColumnWidths = 40, 60 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $AzDnsPrivateResolver | Table @TableParams + + # Inbound Endpoints + if ($AzDnsResolverInboundEndpoint) { + Section -Style NOTOCHeading6 -ExcludeFromTOC 'Inbound Endpoints' { + $InboundEndpointInfo = @() + $InObj = [Ordered]@{ + 'Endpoint Name' = $AzDnsResolverInboundEndpoint.Name + 'IP Address' = $AzDnsResolverInboundEndpoint.IPConfiguration.PrivateIPAddress + 'IP Allocation' = $AzDnsResolverInboundEndpoint.IPConfiguration.PrivateIPAllocationMethod + } + $InboundEndpointInfo += [PSCustomObject]$InObj + + $TableParams = @{ + Name = "Inbound Endpoints - $($AzDnsPrivateResolver.Name)" + List = $false + ColumnWidths = 40, 30, 30 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $InboundEndpointInfo | Table @TableParams + } + } + + # Outbound Endpoints + if ($AzDnsResolverOutboundEndpoint) { + Section -Style NOTOCHeading6 -ExcludeFromTOC 'Outbound Endpoints' { + $OutboundEndpointInfo = @() + $InObj = [Ordered]@{ + 'Endpoint Name' = $AzDnsResolverOutboundEndpoint.Name + 'IP Address' = $AzDnsResolverOutboundEndpoint.IPConfiguration.PrivateIPAddress + 'IP Allocation' = $AzDnsResolverOutboundEndpoint.IPConfiguration.PrivateIPAllocationMethod + } + $OutboundEndpointInfo += [PSCustomObject]$InObj + + $TableParams = @{ + Name = "Outbound Endpoints - $($AzDnsPrivateResolver.Name)" + List = $false + ColumnWidths = 40, 30, 30 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $OutboundEndpointInfo | Table @TableParams + } + } + } + } + } else { + Paragraph "The following table summarises the configuration of the DNS private resolver(s) within the $($AzSubscription.Name) subscription." + BlankLine + $TableParams = @{ + Name = "DNS Private Resolver - $($AzSubscription.Name)" + List = $false + Columns = 'Name', 'Resource Group', 'Location', 'Subscription' + ColumnWidths = 25, 25, 25, 25 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $AzDnsPrivateResolverInfo | Table @TableParams + } + } + } + } + } Catch { + Write-PScriboMessage -IsWarning $($_.Exception.Message) + } + } + + end {} +} \ No newline at end of file diff --git a/Src/Private/Get-AbrAzSubscription.ps1 b/Src/Private/Get-AbrAzSubscription.ps1 index 30c2870..4c7cd45 100644 --- a/Src/Private/Get-AbrAzSubscription.ps1 +++ b/Src/Private/Get-AbrAzSubscription.ps1 @@ -19,12 +19,13 @@ function Get-AbrAzSubscription { ) begin { - Write-PscriboMessage "Collecting Azure Subscription information." + Write-PScriboMessage "Subscription InfoLevel set at $($InfoLevel.Subscription)." } process { Try { - if ($AzSubscriptions) { + if (($InfoLevel.Subscription -gt 0) -and ($AzSubscriptions)) { + Write-PscriboMessage "Collecting Azure Subscription information." if ($Options.ShowSectionInfo) { Paragraph "An Azure subscription is a logical container used to provision resources in Azure. It holds the details of all your resources like virtual machines (VMs), databases, and more. When you create an Azure resource like a VM, you must identify the subscription it belongs to." BlankLine diff --git a/Src/Private/Get-AbrAzTenant.ps1 b/Src/Private/Get-AbrAzTenant.ps1 index 2c0077c..a07297e 100644 --- a/Src/Private/Get-AbrAzTenant.ps1 +++ b/Src/Private/Get-AbrAzTenant.ps1 @@ -5,7 +5,7 @@ function Get-AbrAzTenant { .DESCRIPTION .NOTES - Version: 0.1.1 + Version: 0.1.2 Author: Tim Carman Twitter: @tpcarman Github: tpcarman @@ -19,29 +19,33 @@ function Get-AbrAzTenant { ) begin { - Write-PscriboMessage "Collecting Azure Tenant information." + Write-PScriboMessage "Tenant InfoLevel set at $($InfoLevel.Tenant)." + } process { Try { - $AzTenantInfo = [PSCustomObject]@{ - 'Tenant Name' = $AzTenant.Name - 'Tenant ID' = $AzTenant.TenantId - 'Tenant Type' = $AzTenant.TenantType - 'Country ' = (Get-CountryName $AzTenant.CountryCode) - 'Domains' = $AzTenant.Domains -join ', ' - 'Default Domain' = $AzTenant.DefaultDomain - } + if ($InfoLevel.Tenant -gt 0) { + Write-PscriboMessage "Collecting Azure Tenant information." + $AzTenantInfo = [PSCustomObject]@{ + 'Tenant Name' = $AzTenant.Name + 'Tenant ID' = $AzTenant.TenantId + 'Tenant Type' = $AzTenant.TenantType + 'Country ' = (Get-CountryName $AzTenant.CountryCode) + 'Domains' = $AzTenant.Domains -join ', ' + 'Default Domain' = $AzTenant.DefaultDomain + } - $TableParams = @{ - Name = "Tenant - $($AzTenant.Name)" - List = $true - ColumnWidths = 40, 60 - } - if ($Report.ShowTableCaptions) { - $TableParams['Caption'] = "- $($TableParams.Name)" + $TableParams = @{ + Name = "Tenant - $($AzTenant.Name)" + List = $true + ColumnWidths = 40, 60 + } + if ($Report.ShowTableCaptions) { + $TableParams['Caption'] = "- $($TableParams.Name)" + } + $AzTenantInfo | Table @TableParams } - $AzTenantInfo | Table @TableParams } Catch { Write-PScriboMessage -IsWarning $($_.Exception.Message) } diff --git a/Src/Public/Invoke-AsBuiltReport.Microsoft.Azure.ps1 b/Src/Public/Invoke-AsBuiltReport.Microsoft.Azure.ps1 index c87a89c..0a4e99a 100644 --- a/Src/Public/Invoke-AsBuiltReport.Microsoft.Azure.ps1 +++ b/Src/Public/Invoke-AsBuiltReport.Microsoft.Azure.ps1 @@ -95,6 +95,7 @@ function Invoke-AsBuiltReport.Microsoft.Azure { $AzContext = Set-AzContext -Subscription $AzSubscription.Id -Tenant $TenantId Get-AbrAzAvailabilitySet Get-AbrAzBastion + Get-AbrAzDnsPrivateResolver Get-AbrAzExpressRouteCircuit Get-AbrAzFirewall Get-AbrAzIpGroup