WordPress is the most popular content management system (CMS) in the world. Individuals and businesses of all sizes use WordPress to build websites, run blogs, and sell products online. If you are seeking the most secure and scalable enterprise deployment of WordPress for your organization’s web site(s), consider deploying WordPress running as an Azure App service web app behind Azure App gateway.
This 35-step reference model checklist can guide you to achieve these technical goals:
- WordPress hosted in Azure as a Web App with integrated Azure Database for MySQL flexible servers
- Production and Staging sites
- Web site and database backups automatically enabled
- Network isolation of the app service and the database so that neither has direct Internet exposure
- Protection of web sites and database by Microsoft Defender for Cloud
- Optional automatic scale-up (to more powerful instances) and scale-out (to additional instances)
- Reverse-proxy (website publishing) by Azure App gateway with Web Application Firewall (WAF) protection
- Optional automatic scale-out of the WAF gateway components
- Diagnostics logging of both web app and WAF gateway to Azure Log Analytics (and optionally Microsoft Sentinel)
- Dashboarding of WAF gateway activities (Azure workbook)
- Enabling and tuning the automatic blocking features of WAF gateway in Prevention mode
This demonstration publishes a web site “www.johnjoyner.net” using an Azure sponsorship subscription provided to me by Microsoft. That URL is not normally active (I only use “blog.johnjoyner.net”). After publishing this guide, the Azure resources seen in this article will be deleted.
While this guide is an end-to-end protocol to achieve the technical goals, it is not exhaustive, does not include references, and should not be considered authoritative as the only way or even the best way. But it worked for me, and I wanted to share a condensed, highly actionable checklist to the community.
Reference model checklist
- Deploy from the Azure Marketplace WordPress on App Service by Microsoft.
- Hosting plan: Standard (PremiumV2 App Service, Burstable MySQL database)
- Auto-scale: Disabled with instance count: 1, Availability zone: 1 (only)
- All Add-ons are deselected (no Azure Email Service, Azure CDN, or Azure Front Door)
- Azure Blog Storage is not enabled.
- A new Virtual Network is allowed to be created (default).
- Staging Environment is enabled to add a staging slot.
- Optionally enable Application Insights for the web app and select your Log Analytics workspace for Create a new resource (recommended).
- App service backups happen automatically every hour. Azure Database for MySQL flexible server takes full backups once daily. Optionally modify these automatic backups if you need a different backup schedule
- Log into WordPress on the Production URL: wwwjohnjoyner.azurewebsites.net and customize the home page with the “Production” label.
- Log into WordPress on the Staging URL: wwwjohnjoyner-staging.azurewebsites.net and customize the home page with the “Staging” label.
- Verify production website is reached over the Internet at URL https://wwwjohnjoyner.azurewebsites.net and the staging website at https://wwwjohnjoyner-staging.azurewebsites.net.
- Swap deployment slots in the Web app and verify the Staging website is now the Production website.
- Swap deployment slots in the Web app again and verify the Production website is again the Production website and the Staging website is working properly at the staging URL.
- Upload a wildcard public certificate at Web App -> Certificates -> Bring your own certificates (.pfx) to both the production and the staging slots (do this twice, once for each slot):
8. Add the custom domain (production) www.johnjoyner.net to the production slot of the Web App:
9. Add the custom domain (staging) staging.johnjoyner.net to the staging slot of the Web App:
10. Create a Public IP (PIP) to be used by the App gateway:
11. Make public DNS entries for the www and staging hostnames in the public DNS hosting service, both pointing to the App gateway PIP:
12. Create an Application gateway of the Standard V2 Tier with desired settings including a new virtual network.
13. Create Application gateway Listeners:
14. Create Backend pools:
15. Create custom Health probes:
16. Create Backend settings:
17. Create Rules:
18. Test Backend health (Backend settings -> Backend health):
19. Test access to production and staging web sites over the Internet.
20. Test swapping production with staging web sites over the Internet and back.
21. Assign Microsoft.Web service as a Service Endpoint on the AppGatewaySubnet:
22. Modify the Access Restriction of the App Services Networking to both the Production and the Staging deployment slots as follows:
-
- Public network access enabled from select virtual networks and IP addresses
- Unmatched rule action to Deny
- Add a Service Endpoint Rule that specifies the AppGatewaySubnet
23. Attempt to browse to the URL of the App service (not the URL associated with the App Gateway) and confirm you get an Error 403 – Forbidden. Repeat the test to the URL of the Staging URL of the App service.
Note: Default deployment of WordPress on Azure App service leverages an automatically created private DNS zone and virtual network subnet delegation for use only with MySQL Flexible Server, so the database is never directly exposed to the Internet.
24. Enable Diagnostic setting of the App Service to your Log Analytics workspace:
25. Enable Diagnostic setting of the Application Gateway to your Log Analytics workspace with the Azure diagnostics destination table:
26. Make sure Defender for Cloud workload protection is enabled for App Service and for Open-source relational databases:
27. Upgrade Application gateway from Standard V2 to WAF V2, creating a new WAF Firewall Policy with Bot Protection (Detection only mode is created by default, blocking will not start automatically):
28. Update to the latest OWASP and Bot Manager Rule Sets in the Application Gateway WAF policy -> Managed rules -> Managed Rulesets -> Assign:
29. Deploy the Azure Monitor Workbook for WAF from GitHub, pointing it to the same Azure Log Analytics workspace as the Diagnostic log setting of the App service: (https://github.com/Azure/Azure-Network-Security/blob/master/Azure%20WAF/Workbook%20-%20WAF%20Monitor%20Workbook/README.md)
30. Customize the workbook with your subscription, workspace, WAF Type Application Gateway, and your WAF gateway and push the Save (floppy disk) button:
Note: If running Microsoft Sentinel, also install the Azure Web Application Firewall solution from Content management -> Content hub.
31. Review the workbook after some hours or days of operation to see what requests might be blocked by the WAF gateway in Protection mode (by default, OWASP requests labeled as Matched with an anomaly score of 5 or higher and Bot Manager rules set to Block trigger a block action in Prevention mode):
32. If legitimate business requests are found in Matched status, either add Custom rules to the Application Gateway WAF policy to Allow traffic, or add exclusions to the Managed Rules:
33. When satisfied no business-critical traffic is going to be dropped, switch the Application Gateway WAF policy from Detection to Prevention mode:
34. Tune the blocking feature for the built-in Bot Manager and OWASP rule sets as follows:
- Bot Manager protection by default only blocks “BadBots”, however you can change the default behavior to block (or allow) one or more Bot scenarios by selecting a Bot Manager Rule Set rule and clicking the Change action button:
- OWASP protection by default only blocks requests with an anomaly score of 5 or higher, however you can change the default behavior to block (or allow) one or more OWASP scenarios by selecting an OWASP rule and clicking the Change action button:
35. Congratulations! Your WordPress web site with support for Production and Staging slots has been securely published behind Azure WAF Gateway. Bulletproof!
#MVPBuzz #WordPress #AzureAppService #AzureAppGateway #WAFGateway #AzureWAFGateway #AzureWebApp #OWASP #cloudsecurity