Tags: azure, ingress, application gateway, front door, web application firewall
Overview
Azure Web Application Firewall (WAF) provides centralized protection of your web applications from common exploits and vulnerabilities. Web applications are increasingly targeted by malicious attacks that exploit commonly known vulnerabilities. SQL injection and cross-site scripting are among the most common attacks.
WAF can be deployed with Azure Application Gateway and Azure Front Door service from Microsoft. WAF has features that are customized for each specific service.
Kublr provides full customization for integration Azure Front Door with WAF and Kuberntes NGNIX Ingress controller service.
Prerequisites
Ingress controller DNS record and SSL certificate
You will need to create DNS record for Ingress controller and provide a valid SSL certificate for this record. Please refer to Kublr documentation (https://docs.kublr.com/articles/tls-setup/) or Support portal article (https://support.kublr.com/support/solutions/articles/33000257554-let-s-enrypt-dns-solver-with-aws-route53-service)
To determine the health of ingress service for a given Front Door environment, each Front Door environment periodically sends a synthetic HTTP/HTTPS request to Kubernetes ingress controller. If you use HTTPS, your ingress
health probe host must have valid SSL Certificate (https://ccadb-public.secure.force.com/microsoft/IncludedCACertificateReportForMSFT).
You cannot use self-signed certificates when you are forwarding the traffic as HTTPS or HTTPS health probes or filling the cache for from origin for routing rules!
Certificate CN: For HTTPS connections, Front Door expects that your backend presents certificate from a valid CA with subject name(s) matching the backend hostname. You can disabling certificate subject name check for your Front Door.
Certificate CA: Only certificates from valid Certificate Authorities can be used at the backend with Front Door. Certificates from internal CAs or self-signed certificates aren't allowed. The certificate must have a complete certificate chain with leaf and intermediate certificates, and root CA must be part of the Microsoft Trusted CA List.
Ingress Controller LB DNS record: You will need to create A record in DNS for Kubernetes NGINX Ingress controller public LB IP address.
Workloads services DNS records: For each ingress hostname you will need to create CNAME records linked to Azure Front Door public DNS name (e.g. my-ingress-front-door.azurefd.net).
Azure WAF policy: You will need to create Web Application Firewall policy for FrontDoor in Azure console (https://docs.microsoft.com/en-us/azure/frontdoor/front-door-waf).
Kublr Cluster ARM Template extras
Azure FrontDoor Name: kublr-frontdoor
FrontDoor DNS: kublr-frontdoor-my-ingress-fqdn.azurefd.net
Kubernetes ingress public LB FQDN: ingress.kubernetes-ingress-domain.com
spec: locations: - name: azure1 azure: armTemplateResourcesExtra: - apiVersion: '2020-07-01' location: Global name: kublr-frontdoor type: Microsoft.Network/frontdoors properties: cName: {kublr-frontdoor-my-ingress-fqdn}.azurefd.net backendPoolsSettings: enforceCertificateNameCheck: Disabled backendPools: - name: ingress type: Microsoft.Network/Frontdoors/BackendPools properties: backends: - address: ingress.{kubernetes-ingress-domain.com} backendHostHeader: '' httpPort: 80 httpsPort: 443 priority: 1 weight: 50 healthProbeSettings: id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', resourceGroup().name, ''/providers/Microsoft.Network/Frontdoors/kublr-frontdoor/HealthProbeSettings/ingress'')]' loadBalancingSettings: id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', resourceGroup().name, ''/providers/Microsoft.Network/Frontdoors/kublr-frontdoor/LoadBalancingSettings/ingress-lb-0'')]' frontendEndpoints: - name: azurefd-net type: Microsoft.Network/Frontdoors/FrontendEndpoints properties: hostName: {kublr-frontdoor-my-ingress-fqdn}.azurefd.net sessionAffinityEnabledState: Enabled sessionAffinityTtlSeconds: 0 healthProbeSettings: - name: ingress type: Microsoft.Network/Frontdoors/HealthProbeSettings properties: healthProbeMethod: HEAD intervalInSeconds: 60 path: /healthz protocol: Https loadBalancingSettings: - name: ingress-lb-0 type: Microsoft.Network/Frontdoors/LoadBalancingSettings properties: additionalLatencyMilliseconds: 0 sampleSize: 4 successfulSamplesRequired: 2 routingRules: - name: ingress properties: acceptedProtocols: - Https - Http enabledState: Enabled frontendEndpoints: - id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', resourceGroup().name, ''/providers/Microsoft.Network/Frontdoors/kublr-frontdoor/FrontendEndpoints/azurefd-net'')]' patternsToMatch: - /* routeConfiguration: '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration' backendPool: id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', resourceGroup().name, ''/providers/Microsoft.Network/Frontdoors/kublr-frontdoor/backendPools/ingress'')]' forwardingProtocol: HttpsOnly type: Microsoft.Network/Frontdoors/RoutingRules tags: KubernetesCluster: Kublr-Cluster-Name
Workload service with WAF policy
Azure FrontDoor Name: kublr-frontdoor
Azure WAF policy for FrontDoor: MyWAFPolicy in waf-policy resource group
FrontDoor DNS: kublr-frontdoor-my-ingress-fqdn.azurefd.net
Workload FQDN: service.kubernetes-ingress-domain.com
You will need to create CNAME DNS record:
service.kubernetes-ingress-domain.com CNAME kublr-frontdoor-my-ingress-fqdn.azurefd.net
spec: locations: - name: azure1 azure: armTemplateResourcesExtra: - apiVersion: '2020-07-01' location: Global name: kublr-frontdoor type: Microsoft.Network/frontdoors properties: ... frontendEndpoints: ... - name: service type: Microsoft.Network/Frontdoors/FrontendEndpoints properties: hostName: service.kuberntes-ingress-domain.com sessionAffinityEnabledState: Enabled sessionAffinityTtlSeconds: 0 webApplicationFirewallPolicyLink: id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', ''waf-policy'', ''/providers/Microsoft.Network/frontdoorwebapplicationfirewallpolicies/MyWAFPolicy'')]' ... routingRules: - name: ingress properties: acceptedProtocols: - Https enabledState: Enabled frontendEndpoints: ... - id: '[concat(''/subscriptions/'', subscription().subscriptionId, ''/resourceGroups/'', resourceGroup().name, ''/providers/Microsoft.Network/Frontdoors/kublr-frontdoor/FrontendEndpoints/service'')]'
Workload enable SSL termination on FrontDoor
Azure FrontDoor Name: kublr-frontdoor
Workload FQDN: service.kubernetes-ingress-domain.com
spec: locations: - name: azure1 azure: armTemplateResourcesExtra: - apiVersion: '2020-07-01' type: Microsoft.Network/frontdoors/frontendEndpoints/customHttpsConfiguration name: kublr-frontdoor/{service}/default dependsOn: - '[resourceId(''Microsoft.Network/frontdoors'', ''kublr-frontdoor'')]' properties: certificateSource: FrontDoor frontDoorCertificateSourceParameters: certificateType: Dedicated minimumTlsVersion: 1.2 protocolType: ServerNameIndication tags: KubernetesCluster: My-Kubernetes-ClusterName
Customize Ingress service firewall rules
This can be done via chart parameters controller.service.annotations etc as shown below in Kublr cluster specification snippet:
spec: features: ingress: values: nginx-ingress: controller: service: annotations: service.beta.kubernetes.io/azure-allowed-service-tags: 'AzureFrontDoor.Backend' enableHttp: false