Comment sécuriser vos applications PaaS dans Azure

Dans les principes généraux du Cloud, on trouve la stratégie « Go Fast ». La plateforme Azure nous autorise à apprendre rapidement. Le challenge étant d’apprendre assez rapidement de nos erreurs pour ne plus les reproduire. Problème, il ne faut pas penser que « Go-Fast » signifie « bâcler la sécurité de nos applications ».
En réalité, c’est le meilleur moyen de croiser le chemin de votre RSI/RSSI.
Dans de nombreux projets, je constate que les fonctionnalités PaaS (Plateforme en tant que Service) proposées par la plateforme Azure sont utilisées sans trop penser à l’aspect sécurité.
Oui, Microsoft assure la sécurité de ses composants PaaS, mais il nous revient quand même de les configurer convenablement. Bien souvent, lorsque l’on arrive devant le RSI/RSSI, le projet est retoqué alors que la plateforme Azure propose de répondre aux exigences sécurité.
Pour illustrer mon propos, prenons un exemple concret disponible sur le portail Azure. Une simple Web App + MySQL.
Pour ces deux composants PaaS, nous pouvons faire beaucoup afin d’améliorer la sécurité out of the box, et cela sans surcoût financier. Commençons donc par déployer ce socle applicatif dans la région Azure West Europe.
Très rapidement, les composants suivants sont mis en œuvre au sein d’un groupe de ressources nommé « DemoWebApp » :
- Une instance du service App Service Plan pour porter notre App Service,
- L’instance App Service,
- Une instance de base de données Azure Database for MySQL Server.
Pour tester la connectivité de notre instance de base de données MySQL, nous allons installer l’extension MyPHPAdmin au sein de notre App Service.
Pour valider que la connectivité avec notre base de données MySQL est opérationnelle, nous n’avons qu’à nous connecter à l’url : https://<nomwebapp>.scm.azurewebsites.net/phpMyAdmin/. Dans l’interface ci-dessous, on constate que nous sommes bien en mesure de voir quelques bases MySQL.
A ce stade, nous avons plusieurs problèmes à résoudre :
- La sécurité de notre instance Azure Database for MySQL,
- Sécuriser la communication entre deux services PaaS.
Problème n°1 : La sécurité de notre instance Azure Database for MySQL
Lorsqu’on regarde la configuration de la sécurité de la Azure Database for MySQL Server, on constate plusieurs choses :
- La case à cocher « Allow Access to Azure Services» est décochée,
- Une exception de firewall est configurée.
Le premier point ne me derrange pas car il ferme la porte à toutes les adresses IP publiques de la plateforme Azure, que celles-ci soient consommées dans notre souscription ou pour tout autre client.
Le second point est plus problématique car la règle est tellement large que cela décrit la totalité du plan d’adressage IPv4.
La première chose que nous allons devoir corriger concerne le fait de limiter l’exposition Internet de notre instance Azure Database for MySQL en :
- Réactivant la fonctionnalité « Allow access to Azure Services»,
- Supprimant la règle « AllowAll ».
Jusque-là, tout est plutôt simple. Du point de vue sécurité, il y a du mieux mais ce n’est pas encore parfait. A ce stade, toute adresse IPv4 publique de la plateforme Azure est autorisée à se connecter à notre instance Azure Database for MySQL Server.
Problème n°2 : Sécuriser la communication entre deux services PaaS
C’est là que réside le point de critique pour nos amis RSI/RSSI. Azure App Service est un service PaaS qui consomme des adresses IP publiques.
(Get-AzWebApp -ResourceGroupName DemoWebApp -Name labdemowebapp) | Select-Object Name, OutboundIpAddresses, PossibleOutboundIpAddresses |
C’est maintenant que ça se complique. D’un côté, nous avons App Service qui est un service PaaS qui consomme un pool d’adresses IP publiques et Azure Database for MySQL Server qui fait de même. Sur le papier, sécuriser les communications entre les deux pourrait sembler simple. Le problème, c’est que ce sont tous les deux des services PaaS pour lesquels Microsoft assure la responsabilité du maintien en condition opérationnelle. A ce titre, Microsoft s’engage à le maintenir à niveau en réalisant la maintenance des instances.
Lors de ces opérations de maintenance, de nouvelles instances techniques sont provisionnées, ce qui entraine un renouvellement des adresses publiques consommées. C’est à ce stade que les RSI/RSSI commencent à froncer les sourcils. De leur point de vue, il est presque impossible de sécuriser les communications entre les deux services.
Historiquement, Microsoft proposait deux solutions qui reposaient sur l’intégration entre App Service et le Virtual Network :
- Point-to-Site
- App Service Environment
Le premier scénario consistait à utiliser la fonctionnalité « Point-to-Site » d’une Azure Virtual Network Gateway, pour rendre notre App Service comme client VPN. Le scénario est intéressant mais techniquement, on va être limité par les performances de l’instance de la passerelle réseau Azure. Il est certes possible d’augmenter la taille de l’instance mais on paie cher cette performance.
Le second scénario repose sur le service App Service Environement (ASE) qui est une version dédiée et isolée de l’usine App Service mise à notre disposition. Microsoft met à notre disposition une instance dédiée d’App Service qui propose une intégration native au Virtual Network. L’approche est intéressante mais pour que cela soit rentable financièrement, il faudra déployer un maximum d’App Services sur une seule instance d’App Service Environment.
Ce n’est que très récemment que Microsoft a commencé à déployer une fonctionnalité (donc actuellement en preview) qui permet de connecter une instance App Service directement à un Virtual Network sans surcout. Pour configurer cette fonctionnalité nous allons mettre en œuvre une instance du service Virtual Network avec un seul subnet.
Au sein de ce Virtual Network, on va commencer par dédier notre subnet à l’usage d’App Service comme illustré ci-dessous. De cette manière, il ne sera pas possible d’associer la carte réseau d’une machine virtuelle, puis nous allons activer la fonctionnalité Virtual Network Endpoint pour le service « Microsoft.SQL ». Nous reviendrons sur ce point ultérieurement.
Côté App Service, la configuration de l’intégration au réseau se trouve dans la section « Networking ». Le bouton « Add VNet » correspond au scénario « Point-to-site ». Le bouton « Add VNet (preview) » correspond à la nouvelle expérience actuellement en preview.
Ne reste plus qu’à sélectionner l’instance du service Virtual Network que nous venons de configurer ainsi que le sous-réseau que nous avons dédié à App Service.
A ce stade, notre instance App Service est connectée à notre Virtual Network. Dans phpmyadmin, on voit tout de suite la différence puisque notre instance de Azure Database for MYSQL ne répond plus. Le firewall du service nous indique clairement que notre réseau n’est pas autorisé. A ce stade, le trafic réseau sortant de notre App Service tente bien de passer par le Virtual Network mais le trafic n’est pas autorisé dans l’instance Azure Database for MySQL.
La prochaine étape de la configuration se déroulera donc sur notre instance Azure Database for MYSQL, plus précisément dans le nœud « Connection Security » avec l’option « Add Existing Virtual Network ». Pour rappel, nous avons préalablement activé le support des Endpoint de type « Microsoft.SQL », cela inclut Azure SQL Database, Azure MYSQL Database, Azure MariaDB Database et Azure Postgres Database.
A noter que l’activation du service n’est réalisable que si nos permissions comprennent l’action « Join Service Endpoint Policy » sur le endpoint configuré au niveau du Virtual Network. Dans un environnement avec des rôles bien séparés, tout le monde ne pourra pas raccorder son instance d’Azure Database for MySQL.
Une fois l’opération finalisée, ne reste plus qu’à désactiver l’accès pour les adresses IP publiques Azure en configurant à « Off » la fonctionnalité « Allow access to Azure Services ».
Très rapidement, on va constater que l’accès à l’instance Azure Database for MYSQL est de nouveau opérationnelle.
Au moment de l’écriture de ce billet, la fonctionnalité d’intégration d’un App Service au sein d’un Virtual Network est encore en Preview. J’ai pu constater que le délai d’activation n’est pas encore immédiat. Dans ce cas, on constate que c’est toujours une des adresses IP publiques de notre App Service qui tente d’accéder à l’instance Azure Database for MySQL comme illustré ci-dessous :
Si votre RSI/RSSI n’est pas rassuré, il lui suffira d’activer les fonctionnalités de journalisation de votre Azure Database for MySQL. On pourra y constater un changement majeur puisque les accès seront réalisés en utilisant des adresses IP qui dépendent de votre sous-réseau au sein du Virtual Network.
Pour information, le service Virtual Network Endpoint est disponible pour les services Azure suivants :
- Azure Storage
- Azure SQL Database
- Azure SQL Data Warehouse
- Azure Database for PostgreSQL server
- Azure Database for MySQL server
- Azure Cosmos DB
- Azure Key Vault
- Azure Service Bus
- Azure Event Hubs
- Azure Data Lake Store Gen 1
Quelques liens intéressants :
Note : Ce n’est pas par ce que la connectivité réseau entre nos deux Services PaaS est maintenant privée qu’on peut se dispenser d’utiliser du TLS : SSL connectivity in Azure Database for MySQL. Ça fera toujours plaisir à votre RSSI.
Conclusion
La plateforme Azure évolue en permanence et beaucoup de nouvelles fonctionnalités sont proposées sans surcoût. Maintenant que la fonctionnalité Virtual Network Endpoint est disponible pour un grand nombre de services Azure, il devient intéressant de revoir nos applications déjà déployées pour améliorer leur sécurité.