Public/Find-AzureUtilsInsecureConfig.ps1

function Find-AzureUtilsInsecureConfig {
    <#
        .SYNOPSIS
            Finds resources with weak (insecure) configuration.

        .DESCRIPTION
            Uses Azure Resource Graph to surface common hardening gaps and explains
            each in a 'Finding' column. This is the configuration-weakness companion
            to Find-AzureUtilsPublicResource (which covers public exposure). Returns
            one object per finding (also a colored console table). Categories
            (all by default, narrow with -Type):

                StorageInsecureTransfer storage that allows non-HTTPS traffic
                StorageWeakTls storage with minimum TLS 1.0 / 1.1
                WebAppHttpsOnly web apps not enforcing HTTPS-only
                KeyVaultNoPurgeProtection key vaults with purge protection disabled

            These are heuristics; review before acting. A resource may appear more
            than once when several checks apply.

        .PARAMETER SubscriptionId
            One or more subscription IDs. Default: every enabled subscription.

        .PARAMETER ManagementGroupId
            One or more management groups to scan (requires Az.ResourceGraph).

        .PARAMETER Type
            Limit the checks to run. Defaults to all of them.

        .EXAMPLE
            Find-AzureUtilsInsecureConfig

        .EXAMPLE
            Find-AzureUtilsInsecureConfig -Type StorageWeakTls, StorageInsecureTransfer

        .OUTPUTS
            AzureUtils.InsecureConfig
    #>

    [CmdletBinding(DefaultParameterSetName = 'Subscriptions')]
    [OutputType('AzureUtils.InsecureConfig')]
    param(
        [Parameter(ParameterSetName = 'Subscriptions')]
        [string[]] $SubscriptionId,

        [Parameter(ParameterSetName = 'ManagementGroup', Mandatory)]
        [string[]] $ManagementGroupId,

        [ValidateSet('StorageInsecureTransfer', 'StorageWeakTls', 'WebAppHttpsOnly', 'KeyVaultNoPurgeProtection')]
        [string[]] $Type = @('StorageInsecureTransfer', 'StorageWeakTls', 'WebAppHttpsOnly', 'KeyVaultNoPurgeProtection')
    )

    $null = Assert-AzureUtilsContext

    $resolved = Resolve-AzureUtilsScope -SubscriptionId $SubscriptionId -ManagementGroupId $ManagementGroupId
    if ($resolved.Type -eq 'Subscription' -and -not $resolved.HasSubscriptions) {
        Write-Warning 'No accessible subscriptions in scope.'
        return
    }

    $query   = New-AzureUtilsInsecureConfigQuery -Type $Type
    $nameMap = $resolved.NameMap
    $scope   = $resolved.Scope
    Write-Verbose "Insecure-config query:`n$query"

    Invoke-AzureUtilsGraphQuery -Query $query @scope | ForEach-Object {
        $subId = [string]$_.subscriptionId
        [pscustomobject]@{
            PSTypeName       = 'AzureUtils.InsecureConfig'
            Name             = $_.name
            ResourceType     = $_.type
            ResourceGroup    = $_.resourceGroup
            Location         = $_.location
            SubscriptionName = if ($nameMap.ContainsKey($subId)) { $nameMap[$subId] } else { $subId }
            SubscriptionId   = $subId
            Finding          = $_.finding
            Tags             = ConvertTo-AzureUtilsHashtable -InputObject $_.tags
            ResourceId       = $_.id
        }
    }
}