Azure / Azure-Network-Security

Resources for improving Customer Experience with Azure Network Security
MIT License
783 stars 303 forks source link

Get-DanglingDnsRecords uses a Resource Graph query that is partially wrong and incomplete #394

Open eeertel opened 1 week ago

eeertel commented 1 week ago

Describe the bug The Azure Resource Graph query used in Get-DanglingDnsRecords.ps1 (at line 822: $interestedResourcesQuery = ...) has the following shortcomings:

Please compare the original query used in the script to the query below.

Reproduce Steps to reproduce the behavior:

  1. create a DNS records for one of the missed services above and it will be reported as dangling
  2. apimanagement endpoints are not recognized correctly
  3. afdverify and cdnverify subdomains are reported as dangling

Expected behavior All Azure resources that provide an "fqdn" should be handled by the Azure Resource Graph query

Screenshots See query below

Environment- if applicable n.a.

Desktop (please complete the following information if applicable): n.a. - Azure Resource Graph query can be executed in the browser

Logs- if applicable n.a.

Additional context Please see below the query that we are currently using in our custom script.

resources
    | where subscriptionId matches regex '(?i)'
    | where type in (
    'microsoft.network/frontdoors',
    'microsoft.storage/storageaccounts',
    'microsoft.cdn/profiles/endpoints',
    'microsoft.cdn/profiles/afdendpoints',
    'microsoft.network/publicipaddresses',
    'microsoft.containerinstance/containergroups',
    'microsoft.apimanagement/service',
    'microsoft.web/sites',
    'microsoft.web/sites/slots',
    'microsoft.classiccompute/domainnames',
    'microsoft.classicstorage/storageaccounts',
    'microsoft.containerregistry/registries',
    'microsoft.app/containerapps',
    'microsoft.web/staticsites',
    "microsoft.network/trafficmanagerprofiles"    
    )
    | extend dnsEndpoint = case
    (
       type =~ 'microsoft.network/frontdoors', pack_array(properties.cName, strcat("afdverify.",properties.cName)),
       type =~ 'microsoft.cdn/profiles/endpoints', pack_array(properties.hostName, strcat("cdnverify.",properties.hostName)),
       type =~ 'microsoft.storage/storageaccounts', iff(properties['primaryEndpoints']['blob'] matches regex '(?i)(http|https)://',
                pack_array(parse_url(tostring(properties['primaryEndpoints']['blob'])).Host), pack_array(tostring(properties['primaryEndpoints']['blob']))),
       type =~ 'microsoft.cdn/profiles/afdendpoints', pack_array(properties.hostName),
       type =~ 'microsoft.network/publicipaddresses', pack_array(properties.dnsSettings.fqdn),
       type =~ 'microsoft.network/trafficmanagerprofiles', pack_array(properties.dnsConfig.fqdn),
       type =~ 'microsoft.containerinstance/containergroups', pack_array(properties.ipAddress.fqdn),
       type =~ 'microsoft.apimanagement/service',            pack_array(
            parse_url(tostring(properties.gatewayRegionalUrl)).Host,
            parse_url(tostring(properties.developerPortalUrl)).Host,
            parse_url(tostring(properties.managementApiUrl)).Host,
            parse_url(tostring(properties.portalUrl)).Host,
            parse_url(tostring(properties.scmUrl)).Host,
            parse_url(tostring(properties.gatewayUrl)).Host),
       type =~ 'microsoft.web/sites', pack_array(properties.defaultHostName),
       type =~ 'microsoft.web/sites/slots', pack_array(properties.defaultHostName),
       type =~ 'microsoft.classiccompute/domainnames',pack_array(properties.hostName),
       type =~ 'microsoft.app/containerapps',pack_array(properties.configuration.ingress.fqdn),
       type =~ 'microsoft.containerregistry/registries',array_concat(properties.dataEndpointHostNames, pack_array(properties.loginServer)),
       type =~ 'microsoft.web/staticsites', pack_array(properties.defaultHostname),       
       pack_array('')
    )
    | mv-expand (dnsEndpoint)
    | extend dnsEndpoint = tostring(dnsEndpoint)
    | where isnotempty(dnsEndpoint)
    | extend resourceProvider = case
    (
        dnsEndpoint endswith 'azure-api.net', 'azure-api.net',
        dnsEndpoint endswith 'azurecontainer.io', 'azurecontainer.io',
        dnsEndpoint endswith 'azurecr.io', 'azurecr.io',
        dnsEndpoint endswith 'azureedge.net', 'azureedge.net',
        dnsEndpoint endswith 'azurefd.net', 'azurefd.net',
        dnsEndpoint endswith 'azurewebsites.net', 'azurewebsites.net',
        dnsEndpoint endswith 'blob.core.windows.net', 'blob.core.windows.net',
        dnsEndpoint endswith 'cloudapp.azure.com', 'cloudapp.azure.com',
        dnsEndpoint endswith 'cloudapp.net', 'cloudapp.net',
        dnsEndpoint endswith 'trafficmanager.net', 'trafficmanager.net',
        dnsEndpoint endswith 'azurecontainerapps.io', 'azurecontainerapps.io',
        dnsEndpoint endswith 'azurestaticapps.net', 'azurestaticapps.net',
        ''
    )
    | project id, tenantId, subscriptionId, type, resourceGroup, name, dnsEndpoint, properties, resourceProvider
    | order by dnsEndpoint asc, name asc, id asc
    | order by ['type'] asc
github-actions[bot] commented 1 week ago

Message that will be displayed on users' first issue