bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Linter warns about hardcoded URLs within Azure Firewall Rules

Open cloudchristoph opened this issue 4 years ago • 13 comments

Bicep version Bicep CLI version 0.4.63 (7ebed03284) Extension v0.4.63

Describe the bug The Linter warns me not to use hardcoded URLs, but environment variables (https://aka.ms/bicep/linter/no-hardcoded-env-urls). However, these URLs are part of Azure Firewall rules and should not be covered by the Linter at all I think.

From my point of view, the resource type Microsoft.Network/firewallPolicies/ruleCollectionGroups is affected.

For NetworkRules, the following parameter should be ignored by the Linter:

  • destinationFqdns

For ApplicationRules the following parameters:

  • targetFqdns
  • targetUrls

To Reproduce Steps to reproduce the behavior:

Use this template in a fresh Bicep file, it shows all the warnings:

param location string = resourceGroup().location
param dnsServers array

resource FirewallPolicy 'Microsoft.Network/firewallPolicies@2020-11-01' = {
    name: 'fw-prod-hub-${location}-firewallpolicy'
    location: location
    properties: {
        sku: {
            tier: 'Standard'
        }
        threatIntelMode: 'Alert'
        dnsSettings: {
            enableProxy: true
            servers: dnsServers
        }
        snat: {
            privateRanges: [
                'IANAPrivateRanges'
                '4.3.2.1/24'
            ]
        }
    }
}

resource NetworkRules 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2020-08-01' = {
    parent: FirewallPolicy
    name: 'NetworkRules'
    dependsOn: [
        FirewallPolicy
    ]
    properties: {
        priority: 200
        ruleCollections: [
            {
                ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
                action: {
                    type: 'Allow'
                }
                name: 'bar'
                priority: 200
                rules: [
                    {
                        ruleType: 'NetworkRule'
                        name: 'foo'
                        ipProtocols: [
                            'TCP'
                        ]
                        sourceAddresses: [
                            '1.2.3.4'
                        ]
                        destinationFqdns: [
                            'kms.core.windows.net'
                            'somevault.vault.azure.net'
                        ]
                        destinationPorts: [
                            '1688'
                            '443'
                        ]
                    }
                ]
            }
        ]
    }
}

resource ApplicationRules 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2020-08-01' = {
    parent: FirewallPolicy
    name: 'ApplicationRules'
    dependsOn: [
        FirewallPolicy
        NetworkRules
    ]
    properties: {
        priority: 300
        ruleCollections: [
            {
                ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
                action: {
                    type: 'Allow'
                }
                name: 'bar'
                priority: 100
                rules: [
                    {
                        ruleType: 'ApplicationRule'
                        name: 'foo'
                        protocols: [
                            {
                                protocolType: 'Https'
                                port: 443
                            }
                        ]
                        targetFqdns: [
                            'prod.msocdn.com'
                            'management.azure.com'
                            'device.login.microsoftonline.com'
                            'login.microsoftonline.com'
                            'graph.windows.net'
                        ]
                        destinationAddresses: [
                            '1.2.3.4/24'
                        ]
                    }
                ]
            }
        ]
    }
}


cloudchristoph avatar Jun 07 '21 10:06 cloudchristoph

@cloudchristoph - have you tried using variables and the environment() function for these values?

e.g.

var kms = 'kms.${environment().suffixes.storage}'
var keyVault = 'somevault.${environment().suffixes.keyvaultDns}'
var resourceManager =  environment().resourceManager
var graphAudience = environment().graphAudience

MarcusFelling avatar Jun 07 '21 15:06 MarcusFelling

I can do that, of course.

However, this does not meet the goal for a Firewall Rule Set (at least not for my customers, unfortunately). There are exactly defined URLs approved for whitelisting.

I really think that the Linter should ignore these parameters (targetFqdns, destinationFqdns, targetUrls) regarding the "hardcoded URLs" rule.

Don't you think @MarcusFelling?

cloudchristoph avatar Jun 07 '21 15:06 cloudchristoph

@cloudchristoph - Does using bicepconfig.json meet your needs? You can modify the list of URL's by specifying disallowedhosts.

MarcusFelling avatar Jun 07 '21 16:06 MarcusFelling

I agree with @cloudchristoph here, we need a way to exclude firewall policies from the linter. Adding all targetFqdns, destinationFqdns, targetUrls from all firewall rules will be a real pain. It would be nice if we could ignore specific resource types like Microsoft.Network/firewallPolicies/ruleCollectionGroups in bicepconfig.json.

StefanIvemo avatar Jun 07 '21 19:06 StefanIvemo

@bmoore-msft - curious to get your take on this one. I believe this is a TTK rule as well, so wondering how we handle it there.

alex-frankel avatar Jun 09 '21 01:06 alex-frankel

I think the rule is correct, those are cloud specific URIs and would not work in other clouds (which is one purpose for the rule). @MarcusFelling has the correct solution. If the Cx never needs to be concerned about the rule (will never use another cloud) just disable the rule.

bmoore-msft avatar Jun 09 '21 22:06 bmoore-msft

According to the documentation on the environment() function, it returns the URI with https:// prepended to the value. Is that not the case? That would not work in the Firewall Rules since there are separate properties for the targetFQDN, protocolType and port number. https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-deployment?tabs=json#example-1

cchapin-ms avatar Jul 23 '21 17:07 cchapin-ms

I think you can still concat/replace as needed...

bmoore-msft avatar Jul 29 '21 20:07 bmoore-msft

By the way, for anyone wondering about the data returned by the environment() function - a quick way to test this is to deploy the following Bicep file:

output env object = environment()

You can use the following script to execute it and dump the result:

az deployment group create -g <your_resource_group> --template-file main.bicep --query properties.outputs.env.value

anthony-c-martin avatar Jul 29 '21 21:07 anthony-c-martin

or if you're really lazy:

https://management.azure.com/metadata/endpoints?api-version=2019-05-01

bmoore-msft avatar Jul 29 '21 23:07 bmoore-msft

@cloudchristoph would adding the ability to override linter rules in-line help with your scenario? https://github.com/Azure/bicep/issues/3354

MarcusFelling avatar Aug 23 '21 18:08 MarcusFelling

It could, I guess. Actually, I don't want to override these rules in principle. They make sense in most places. It is just problematic when they are applied to such parameters. But I think we'll be fine for now if we use the option to disable the rule.

cloudchristoph avatar Aug 24 '21 09:08 cloudchristoph

This is indeed quite clumsy but you can achieve this by replacing the https:// and trailing / by doing the following.

        name: 'microsoft-authentication'
        ruleType: 'ApplicationRule'
        targetFqdns: [
         '${replace(replace(environment().authentication.loginEndpoint, 'https://', ''), '/', '')}'
        ]

joni-nieminen avatar Oct 17 '24 06:10 joni-nieminen