Azure App Service Security & Best Practices
Today we'll be taking a look at Azure App Services and some of their features from a security standpoint. Azure App Services allow you to quickly build, deploy, and scale web apps and APIs using .NET, Node.js, Java, Python, or PHP running in Windows or Linux, or as a containerized application.
Security built into Azure App Services
Azure App Services contain a number of built-in security features listed in Microsoft's documentation:
- The platform components of App Service, including Azure VMs, storage, network connections, web frameworks, management, and integration features are actively secured and hardened. App Service goes through vigorous compliance checks on a continuous basis.
- App resources are secured from other customer's resources.
- VM instances and runtime software are regularly updated.
- Communication of secrets between your app and other Azure resources stay within Azure and do not cross any network boundaries.
- Secrets are encrypted.
- All communications over app service connectivity features are encrypted.
- Connections with remote management tools are encrypted.
- 24-hour threat management protects the infrastructure and platform against malware, DDoS, man in the middle, and other threats.
By the nature of Azure App Service as a Platform as a Service (PaaS), these features are provided to you by Microsoft as long as you maintain an active subscription. However, the responsibility of cloud security is still shared between YOU and the cloud provider. Many of the security recommendations we will be covering are not enabled by default when creating a new Azure App Service. Senserva helps you secure your Azure App Services by reviewing your Azure environment and finding where compliance and security issues lie before they end up being a problem.
Deploying Containerized Applications
Containerized applications are lightweight, standalone executable packages that contain everything needed to run. This includes the code, runtime, system tools, libraries, and settings.
Containerized applications have a number of inherent security benefits: they isolate applications as standalone entities, have integrated security capabilities, and they provide a fast mechanism for patching security vulnerabilities because they can be easily and quickly replaced.
In spite of these security benefits, they also have unique properties that make them vulnerable to threats. Container images are often derived from other containers, called base images. These images must originate from trusted sources, hosted on reputable registries, and be validated for security. Strong cloud security practices within your organization (including user access control) and identifying modified container images that break policies or documented best practices (known as container misconfigurations) will reduce the likelihood and impact of potential compromises.
App Service Best Practices
Azure App Services have a number of different settings and configuration options that can improve the security of your App Service. A primary recommendation is to use the latest versions of supported platforms, programming languages, protocols, and frameworks.
In the Networking tab of the Settings section on your Azure App Service, access restrictions can be applied for inbound network traffic such as static IP restrictions to prevent access to your App Service from unintended clients.
All pricing tiers except for the isolated pricing tier run on shared network infrastructure in Azure App Service. The isolated tier provides complete network isolation by running apps inside a dedicated App Service Environment.
It is recommended to use secure connections when accessing on-premise resources, such as hybrid connections or virtual network integrations which can also be configured in the Networking section of your Azure App Service. Virtual network integration is configured by default when using App Service Environments, but must be manually configured when using tiers other than the isolated tier. Limit exposure to inbound network traffic using network security groups for restricting network access and limiting the number of exposed endpoints.
Identity and Access Management (IAM)
IAM can be managed under the Access control (IAM) section of your App Service. General recommendations are to disable anonymous access, require authentication, protect backend resources with authenticated access, and require client certificate authentication.
It is recommended not to use local authentication methods for Azure data plane access (such as a local username and password). Instead, Azure AD Authentication should be enabled - this feature is not enabled by default.
An Azure Active Directory managed identity provides access for your application to other Azure resources, such as Azure Key Vault, and should be enabled instead of using service principals whenever possible. Under the Identity tab of the Settings section, system-assigned identities and user-assigned identities can be added. Identities are managed by Azure, and do not require provisioning or rotating secrets.
Previously mentioned, Azure Key Vault allows you to store secrets, keys, and certificates such as access tokens, API keys, and TLS certificates. Azure Key Vault should be utilized in conjunction with managed identities, allowing you to avoid hard-coded credentials in source code or configuration files which can result in exposure of secrets.
Conditional Access provides access restriction for resources based on conditions that you define, and should be utilized for securing your cloud resources. Conditional access is commonly used for blocking risky sign-in behavior, requiring organization-managed devices to access applications and organizational resources, and blocking or granting access from specific locations.
Several methods can be utilized for the protection of data, including methods for network communications such as:
- Redirect HTTP to HTTPS
- Encrypt communication to Azure resources
- Require the latest TLS version possible
- Use FTPS over FTP
For client application secrets (such as database credentials, API tokens, or private keys), DO NOT store these in your code or configuration files. It is very easy to unintentionally upload these to public repositories hosted on GitHub, Azure DevOps, etc. As previously mentioned in IAM, you should use an Azure Key Vault for secret management. If the key vault is accessed with a managed identity, your app can securely access the secret(s) it needs.
In the Configuration tab in Settings, you can define environment variables under the application settings and connection strings sections. These are encrypted and exposed as environment variables for access by your application at runtime. Environment variables are decrypted only before being injected into your application's process memory when the application starts.
When serving static content, ensure that only the intended files and folders are included in the deployment, and verify that hidden folders are not included.
Monitor your application using Microsoft Defender for App Service which is natively integrated into Azure App Service. The Monitoring section in your app's configuration page provides tools for setting up alerts, metrics, and logging. Diagnostics and health checks are also included for troubleshooting the application. Use the Senserva product that we have developed to help with this.
Other Security, Configuration, and Best Practice Recommendations
Colocation in the same region is best for solutions requiring multiple interconnected resources, such as a web application and database. This reduces latency in communication between resources.
Digital security certificates can be used to secure custom DNS names in Azure App Service. Transport Layer Security (TLS) certificates help secure internet connections by encrypting data sent between the web browser, websites visited, and servers.
Certificate pinning limits your application to a list of acceptable Certificate Authorities, public keys, thumbprints, etc. Applications should never have a hard dependency to the default *.azurewebsites.net TLS certificate because this certificate can be rotated at any time. Certificate pinned applications will break in the event that Azure App Service rotates the default wildcard TLS certificate.
App Service Resource Consumption
For memory consumption, Azure App Service includes an auto-healing feature which can take custom actions triggered by a memory threshold. Actions can include email notifications, investigations via memory dump, on-the-spot mitigation by recycling worker processes, etc.
For CPU consumption or repeated CPU spikes, consider scaling up or scaling out the App Service plan. If the application is stateful (actions are performed with the context of previous transactions), scaling up is the only option. If the application is stateless (no stored knowledge of or reference to past transactions), scaling out provides more flexibility.
For reference, scaling up means adding further resources such as CPU cores and/or memory to increase the computing capacity. Scaling out means adding additional servers to spread the workload between more machines.
When socket resources are exhausted, follow the recommendations in the library documentation referenced by the applications in your App Service Plan to ensure they are configured or accessed in your code for efficient reuse of outbound connections. A common reason for exhausting outbound TCP connections is client libraries which are not implemented to reuse TCP connections, or when HTTP keep alive is not used.
When dealing with Node.js and outgoing HTTP requests, HTTP keep alive is important. HTTP responses should always be handled even if the handler performs no actions. Incorrect response handling can prevent sockets from being properly released and recycled.
App Service Backup Failure
The two most common reasons for backup failure are invalid storage settings and invalid database configurations. These typically happen when changes to storage or database resources are made, such as an update to access credentials. Review and update the storage and/or database configurations to resolve this type of failure.
IoT Devices Connecting to App Services
IoT devices commonly use certificate pinning, which as mentioned earlier, can create unforeseen downtime when certificates are rotated. You should use a custom domain with custom TLS certificates for certificate pinning.
Relying on a single endpoint for all of your devices is not recommended. Hosting applications in two different regions for failover traffic in the event of a regional failure will prevent downtime. Identical custom domains can be applied to different applications within App Service as long as they are hosted in different regions. Load balancers can also be used in front of web apps to ensure high availability.
Deployment slots can reduce downtime and minimize risk during application updates. Setting up an entirely separate staging environment (a live application with its own host name) from the default production slot allows you to validate application changes before swapping application content and configurations with the production environment.
Deploying to a staging slot first provides an opportunity for all instances to warm up before being swapped into production, provides a valuable opportunity for testing, and eliminates downtime.
The slot with the previously staged application will then contain your previously deployed production application which provides an opportunity to immediately roll-back to the last known good configuration of your application if changes are not as expected.
By leveraging Azure App Service's security capabilities along with the best practices we've outlined here, you and your organization can focus on building cloud-based applications without compromising on security. At Senserva, we prioritize your security in all of our work and products. Please reach out on our contact page and ask for Kyle or TJ, or call +1-651-728-6108 if you have any questions or would like to demo our solution and discuss your needs. We hope to talk with you soon!