Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

De base, WCF fournit toute l’infrastructure pour monter des solutions de services multiprotocoles. On peut fournir et consommer des services sur des carneaux divers et variés. Avant .net 4, fournir un même service pour deux Binding différents imposait une configuration très verbeuse (peut-être un peu trop). Après .net 4, et l’introduction des configurations à défaut, la configuration est devenue beaucoup plus facile.

Pour rappel: la configuration à défaut consiste à introduire des nœuds de configuration WCF (binding, beavior,.. etc…) sans propriété name ou alors avec la propriété name=””.

Seul petit hic, tous les développeurs n’ont pas forcément saisi que la pierre angulaire de tout cela résidait dans le mapping des protocoles. Sans ce mapping, WCF ne peut pas savoir que vous voulez utiliser tel ou tel type de Binding.

Avant toute configuration, si vous souhaitez utiliser les configurations à défaut il faut donc fixer le Binding utiliser pour chaque protocole.

La MSDN nous donne un exemple simple de configuration (https://msdn.microsoft.com/en-us/library/ee816881(v=vs.110).aspx)

<protocolMapping>
   <add scheme="http" binding="basicHttpBinding"/>
   <add scheme="net.tcp" binding="netTcpBinding"/>
   <add scheme="net.pipe" binding="netNamedPipeBinding"/>
   <add scheme="net.msmq" binding="netMsmqBinding"/>
</protocolMapping>

 

Cet exemple est simple, et s’utile pour les cas les plus faciles. Dans la pratique, dès que l’on veut mixer http et https, les choses sont un peu plus complexes.

Par exemple, la configuration suivante n’est pas possible :

<protocolMapping>
   <clear/>
   <!-- Binding utilisé par le HTTPS -->
   <add scheme="https" binding="webHttpBinding"/>
   <!-- Binding utilisé par le HTTP -->
   <add scheme="http" binding="webHttpBinding"/>
</protocolMapping>

 

Pourquoi?

La réponse se trouve dans les configurations des Binding. On ne peut pas avoir un deux configurations de Binding à défaut pour un même type de Binding. Ceci est tout à fait normal, comment le system peut savoir quelle configuration utiliser, si aucune n’a de nom? Dans ce genre de situation, j’ai souvent vu des développeurs choisir d’utiliser un type de Binding pour HTTP et un autre type pour HTTPS ou alors coder leur propre type de Binding.

Heureusement, WCF est bien plus simple qu’il n’y parait, et il suffit de donner un nom à ses différentes configurations. Les noms peuvent ensuite être affectés comme bindingConfiguration de chaque protocole.

Ce qui donne au final ceci :

<system.serviceModel>
  <protocolMapping>
    <clear/>
    <add scheme="https" binding="webHttpBinding" bindingConfiguration="httpsConfiguration"/>
    <add scheme="http" binding="webHttpBinding" bindingConfiguration="httpConfiguration"/>
  </protocolMapping>
    
  <bindings>
    <webHttpBinding>
      <clear/>
      <binding name="httpsConfiguration">
        <security mode="Transport"/>
      </binding>
      <binding name="httpConfiguration">
        <security mode="None"/>
      </binding>
    </webHttpBinding>
  </bindings>
    
  <behaviors>
    <serviceBehaviors>
      <clear/>
      <behavior>
        <!-- Suppression de meta-->
        <serviceMetadata httpsGetEnabled="false" httpGetEnabled="false"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <clear/>
      <behavior>
        <!-- Configuration REST -->
        <webHttp defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

 

Facile non?

Souvent, on me dit que WCF est compliqué à utiliser, à configurer, et qu’il faut toujours du code custom pour que cela marche. Connaissant bien la plateforme, j’aime que l’on me présente un cas concret quand on a ce genre de propos. À force de décortique ces cas, je me suis rendu compte que ce qui clochait le plus souvent était la configuration. Les possibilités de WCF étant parfois mal comprises, les développeurs configurent mal leurs services ou compensent avec du code personnel. Dans la plupart des cas, ce code ne fait que reproduire la configuration WCF en dure. Dans d’autres cas, ce code introduit des beahaviors ou des binding qui existent déjà.

La base de tout cela reste donc la connaissance de la configuration WCF. Entre celle-ci et IIS, les développeurs ont parfois du mal (voir mon précédent article sur IIS). Pour éviter tout écueil, je conseille de partir d’une configuration de base clean. Son objectif est de s’assurer que l’on n’hérite pas d’une autre configuration (via la topologie de IIS, et des applications qui seront en production sur le serveur).

On doit donc faire systématiques un clear des éléments de configuration suivant :

  • protocolMapping
  • serviceBehaviors
  • endpointBehaviors

Ce qui donne comme configuration de base ceci :

<system.serviceModel>
  <protocolMapping>
    <clear/>
  </protocolMapping>    
  <behaviors>
    <serviceBehaviors>
      <clear/>
    </serviceBehaviors>
    <endpointBehaviors>
      <clear/>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

 

Si par exemple on reprend une configuration à la mode comme un REST, on a donc au final ceci :

<system.serviceModel>
  <protocolMapping>
    <clear/>
    <!-- Binding utilisé par le HTTPS -->
    <add scheme="https" binding="webHttpBinding"/>
  </protocolMapping>
    
  <bindings>
    <webHttpBinding>
      <clear/>
      <binding>
        <!-- Ajout du SSL -->
        <security mode="Transport"/>
      </binding>
    </webHttpBinding>
  </bindings>
    
  <behaviors>
    <serviceBehaviors>
      <clear/>
      <behavior>
        <!-- Suppression de meta-->
        <serviceMetadata httpsGetEnabled="false"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <clear/>
      <behavior>
        <!-- Configuration REST -->
        <webHttp defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

Cela fera déjà quelques années que l'on se pose des questions sur l'avenir de l'AppFabric. L'AppFabric n'avait presque pas évolué entre ses versions 1.0 et 1.1. Il y a quelques mois, l'AppFabric 1.1 était annoncée comme compatible avec Windows 2012 R2. Mais aucune nouvelle version n'était publiée.

Depuis le 3 avril dernier, la situation est enfin claire : fin de support le 2 avril 2016 ( Microsoft AppFabric 1.1 for Windows Server Ends Support 4/2/2016 ).

Workflow Foundation et WCF vont souffrir de la disparition de ce produit qui leur apportait dans de facilités. Comme le dit si bien l'équipe AppFrabric sur son blog, il a y des solutions de remplacement possibles pour le Cache, le Hosting. Pour le monitoring et la gestion des services, il faudra monter ses propres solutions. Ayant déjà monté ce type de solution pour des projets personnels, je ne me fais pas de soucis, on peut y arriver sans monter une usine à gaz.

Étrangement, c'est au sujet des solutions de cache que je tiens à mettre en garde les utilisateurs d'AppFabric (ou d'autres produits). Avec les temps, je me suis rendu compte que l'AppFabric n'était pas toujours utilisée à bon escient. Son service de cache avait pour vocation première de fournir un cache distribué entre les serveurs IIS d'une ferme. Avec un seul serveur, le cache était souvent contre performant.

 

Demain, si vous devez choisir une nouvelle solution de cache, regardez de plus près votre besoin :

 

Cache partagé : Vous devez charger des objets et fournir un cache de ceux-ci qui soit synchro pour tous vos IIS

Redis est prometteur. Cependant sa dernière version n'est pas encore supportée par Windows Server, et toutes les fonctionnalités n'y sont pas encore (mais ça va venir).

Les puristes seront tentés d'utiliser la version Linux. Attention, à ne pas être dans la contreperformance. Le cache n'étant plus disponible localement sur votre serveur IIS, il devra passer par le réseau. Il faudrait mieux vérifier que le jeu en vaut bien la chandelle avant de se lancer. Pour les futurs projet .net Core, il est peut-être un peu trop tôt pour se faire un avis.

 

Cache applicatif non partagé : Vous devez charger des objets uniquement pour le serveur local

La simple classe Cache de System.Web.Caching peut certainement faire l'affaire.

https://msdn.microsoft.com/fr-fr/library/6hbbsfk6(v=vs.100).aspx

 

Cache de pages web dynamique : Vous devez mettre en cache des pages ASP .net

Que vous soyez sur du WebForm ou sur du MVC, ASP .net a tout l'outillage pour répondre à votre besoin (sans rien ajouter). De plus, rien ne vous empêche d'utiliser les bonnes vielles entêtes http et metas pour demander à vos clients d'utiliser le cache de leurs navigateurs.

https://msdn.microsoft.com/fr-fr/library/06bh14hk(v=vs.100).aspx

https://technet.microsoft.com/en-us/library/dd239248(WS.10).aspx

 

Cache de pages web ou contenu statique : Vous devez mettre en cache des pages HTML, des fichiers ou des images

IIS étant votre ami, il dispose déjà de tout ce dont il faut pour gérer un cache des contenus qu'il sert (statique comme dynamique). Cela se trouve ici :

https://technet.microsoft.com/en-us/library/cc732475(v=ws.10).aspx

Ce poste est destiné à couper court à une rumeur qui a la peau dure: WCF ne serait pas en mesure d’utiliser SSL et api REST en même temps???

Ceci est totalement faux. WCF peut faire du REST sur du SSL.

Pour y arriver, il suffit de mettre en place sa configuration REST habituelle. La seule partie qui change se trouve au niveau du transport du Binding qui devient sécurisé.

Exemple:

<system.serviceModel>
  <protocolMapping>
    <clear/>
    <!-- Binding utilisé par le HTTPS -->
    <add scheme="https" binding="webHttpBinding"/>
  </protocolMapping>
    
  <bindings>
    <webHttpBinding>
      <binding>
        <!-- Ajout du SSL -->
        <security mode="Transport"/>
      </binding>
    </webHttpBinding>
  </bindings>
    
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <!-- Suppression des meta-->
        <serviceMetadata httpsGetEnabled="false"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior>
        <!-- Configuration REST -->
        <webHttp defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json"/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

De base, la politique de validation utilisée dans .net fait bien son travail. Elle nous prémunit de toute mauvaise utilisation d'un certificat (objet non valide, certificat d'une autorité non reconnue … etc…)

Dans certains cas, vous pouvez vouloir ajouter des règles ou en supprimer. Pour arriver à vos fins, il suffit de modifier la propriété ServerCertificateValidationCallback de l'objet ServicePointManager. Cette propriété attend une fonction aux multiples arguments, qui doit retourner un Boolean à True quand on accepte un certificat. Les arguments nous permettent de savoir quel certificat est à valider ainsi que son contenu.

Ceci est utilisable avec toute technologie .net qui exploite un certificat : WCF, ASMX, Workflow foundation… etc.

Par exemple, si on veut accepter tout type de certificat comme les certificats auto signés, on peut utiliser le code suivant.

// Faire confiance au certificat quoi qu'il arrive et d'où qu'il vienne !!! 
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => 
{
    return true;
};

Note : Code tellement moche et dangereux, qu'il ne faut pas utiliser en production ;)

Plus d'informations sont disponibles via la MSDN https://msdn.microsoft.com/fr-fr/library/vstudio/system.net.security.remotecertificatevalidationcallback(v=vs.100).aspx

Pour la publication en production, il est conseillé de passer toutes les options un peu trop bavardes de WCF à False. Personnellement, j'aurai tendance à être plus radical. Je supprime donc les behaviors liés aux métas et au debug. Dans le cas où j'utilise les fonctionnalités de configuration par défaut de WCF 4, je peux donc profiter du fichier web.config de Release pour supprimer toutes les configurations indésirables en une seule opération :

Mon fichier Web.Release.config a donc la forme suivante :

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> 
   <system.web>
      <compilation xdt:Transform="RemoveAttributes(debug)" /> 
   </system.web> 
   <system.serviceModel> 
      <behaviors> 
         <serviceBehaviors> 
            <behavior> 
               <serviceMetadata xdt:Transform="Remove" /> 
               <serviceDebug xdt:Transform="Remove" /> 
            </behavior> 
         </serviceBehaviors> 
      </behaviors> 
   </system.serviceModel> 
</configuration> 

 

Pour la recette, je veux avoir le détail des erreurs, mon fichier Web.Release.config a donc la forme suivante :

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> 
   <system.web>
      <compilation xdt:Transform="RemoveAttributes(debug)" /> 
   </system.web> 
   <system.serviceModel> 
      <behaviors> 
         <serviceBehaviors> 
            <behavior> 
               <serviceMetadata xdt:Transform="Remove" /> 
               <serviceDebug ptionDetailInFaults="true" /> 
            </behavior> 
         </serviceBehaviors> 
      </behaviors> 
   </system.serviceModel> 
</configuration>

Faire un site web, c'est bien. Le déployer, c'est mieux…

Malheureusement, trop peu de développeurs font attention au déploiement. Ce qui fait qu'ils ne sont pas habitués à diagnostiquer une installation ratée ou à identifier une topologie dangereuse. Via ce court article, je me propose de faire un rappel sur la gestion des fichiers de configuration.

On oublie bien vite, qu'une application web ne dépend pas que d'un seul fichier de configuration.

 

Configuration dans l'application

Les fichiers web.config font partie intégrante de votre application. Vous pouvez en avoir plusieurs. En général, on a un fichier principal et des fichiers secondaires que l'on dépose dans les répertoires où l'on souhaite ajouter ou retirer des paramètres (typiquement, la gestion de droits sur un dossier).

Exemple type :

Chaque dossier a son fichier web.config. Les fichiers dans Admin et Services ajoutent ou retirent des paramètres et héritent des paramètres définis dans le fichier de configuration à la racine de la configuration. Cette partie étant fournie avec votre code, en général, il n'y a pas de problèmes.

 

Configuration liée au serveur IIS

La configuration IIS est stockée dans le fichier applicationHost.config que l'on peut trouver ici : «  %windir%\system32\inetsrv\config\ ». Celle-ci peut avoir un impact direct sur votre applicatif. Malheureusement, elle diffère d'un OS à l'autre.

Si vous utilisez un OS client (Vista, Windows 7, Windows 8, Windows 10), la configuration sera peut-être différente de l'OS serveur que vous utiliserez en production (2008, 2008R2, 2012, 2012R2). Par prudence, il vaut donc mieux faire ses recettes sur un vrai serveur que sur un poste client.

À noter que :

  • certains paramètres fixés peuvent être verrouillés pour vous interdire de les modifier dans vos fichiers web.config. Il est donc bon de connaitre ces verrous (Certains verrous peuvent sauter si on vide les collections via <clear/> et qu'on les repeuple à la main dans son fichier web.config avec des <add>)
  • certains paramètres verrouillés sur un OS client, ne le sont pas sur un OS serveur (ex : authentification anonyme déverrouillée sur 2008R2 et verrouillée sur Windows 7)
  • certains paramètres n'existent pas dans IIS Express, il est donc bon d'utiliser un IIS complet pour développeur.

     

Configuration liée au pool

Le choix du pool a un impact direct sur la configuration. Il y a trois notions à retenir :

1. Pour chaque plateforme x64, x86, il y a un fichier de configuration

Par défaut, notre pool fonctionne en 64 bits. Si on l'autorise à fonctionner en 32, il ne fera plus que du 32 bits.

  • Le fichier de configuration 64bits se trouve dans le dossier « %windir%\Microsoft.NET\Framework64 ».
  • Le fichier de configuration 32bits se trouve dans le dossier « %windir%\Microsoft.NET\Framework ».

     

2. Pour chaque CLR .net, il y a un fichier de configuration

Dans chaque dossier lié à une plateforme, il y a un dossier par CLR déployée. Dans ce dossier se trouve un dossier « config » contenant les configurations.

Exemple pour un pool 64 bits et une CLR4 (c'est le cas par défaut sur les serveurs récents)

%windir%\Microsoft.NET\Framework64\v4.0.30319\Config

 

3. La gestion du pipeline intégré ou non, a un impact sur les sections utilisables dans vos fichiers de configuration

Avant II7, la notion de pipeline intégré n'existait pas. Il s'agit d'une évolution de IIS qui nous permet d'utiliser nos applications dans un pipeline full .net (au revoir ISAPI) et d'utiliser nos modules .net pour des éléments qui n'étaient pas couverts (exemple : contenu statique).

Avec cette option, un certain nombre de configurations sont déportées dans la section system.webServer. Si vous utiliser httpModules, httpHandler, dans vos fichiers de configurations, ils ne seront pas pris en comptes. Il faudra les remplacer par leurs équivalents dans system.webServer.

Ex : https://msdn.microsoft.com/fr-fr/library/bb763179(v=vs.100).aspx

 

Imbrication d'applications

Un site peut contenir plusieurs applications. Les applications héritent de la configuration de l'application qui est à leur racine. Cette situation est extrêmement courante. Par exemple, TFS utilise ce type d'implantation pour fonctionner.

Exemple :

Certaines sections de la configuration de l'application racine peuvent ne pas être compatibles avec les applications App1 et App2. Si vous avez pour responsabilité de gérer App1 ou App2, il faudra dans la mesure du possible connaitre la configuration se trouvant à la racine du site.

Si ce n'est pas possible, il faut être prudent et utiliser autant que possible <clear/> et <remove/> dans vos collections de paramètres. En supprimant systématiquement les paramètres dont vous n'avez pas besoin, vous vous prémunissez de leurs éventuels effets de bords.

 

Imbrication d'applications et de pools

Avec l'imbrication d'applications, on peut aussi se retrouver à imbriquer des pools. On peut donc imbriquer des CLR, et des plateformes 32/64 bits différentes !…

Courage fuyons !

Cette situation est à éviter autant que possible, car on peut conjuguer une multitude de configurations qui ne sont peut-être pas compatibles (exemple : sections qui n'existent pas en .net 2 car elles proviennent de .net 4).

Si vous n'avez pas le choix, et que vous devez effectuer ce genre de déploiement, il faudra utiliser des sections <location>. En utilisant <location> dans le fichier de configuration à la racine du site (et non pas de vos propres applications), vous pourrez créer des zones d'exceptions et ainsi ne pas propager la configuration du site racine aux applications imbriquées.

 

Bons déploiements ;)

Dernièrement, j'ai été confronté à un problème embarrassant : Je ne pouvais plus redimensionner le disque système de l'un de mes serveurs Core.

Il était aussi impossible de défragmenter les données et le Trim ne faisait rien  L . La recherche d'erreur ne trouvait rien.

En cherchant à savoir si je n'avais pas des fichiers trop fragmenté, je suis tombé sur un fichier de log qui était découpé en quelques millions de fragments… Il s'agissait du log de DISM.

Après clean up de DISM, tout est redevenu normal ;)

Moralité : même sur un SSD, surveiller la fragmentation ne peut pas faire de mal. Cela peut même permettre de trouver des problèmes.

N'étant pas un professionnel et l'orthographe, j'ai toujours pris l'habitude de localiser mes applications. J'ai très vite trouvé mon intérêt dans le fait d'avoir un seul endroit où trouver tous les textes à corriger.

Cela m'a aussi forcé à ne rien mettre en dure dans le code et à toujours en extraire ce qui était localisable. Ceci m'a évité nombre d'erreurs. Vous comprendrez donc que je m'énerve quand je tombe sur un programme qui me parle dans ma langue et qui me prose de répondre dans une autre :

Je crois que la capture parle d'elle-même. Je me suis bien énervé sur le « O » de oui, avant de taper le « Y » de yes.

Amis développeurs, s'il vous plait retenez cet exemple comme étant une erreur à ne pas reproduire.

Si au passage, vous pouviez faire attention à l'encodage des textes, ce serait top ;)

Merci

 

PS : En plus c'était pour désinstaller un produit…. Arg !!!!

Vous cherchez les mises à jour pour Test Professional, mais vous ne les trouvez pas ? C'est normal, il n'y en a pas. Ou du moins, il n'y a pas de package de mise à jour propre à ce produit. Celui-ci dépendant de Visual Studio, il faut utiliser l'iso des updates de Visual Studio. Ceci métra à jour vos clients TFS, comme les compléments Office.

Capture de l'Update 3

En faisant le ménage dans mes captures d'écran, je suis tombé sur cette petite perle qui m'avait fait sourire : c'est une boite de dialogue qui s'affiche après la création d'un projet d'équipe via le site web de Visual Studio Online.

 

 

Bonne année et bon code pour 2015.

Je vous souhaite un bon Visual Studio 2015 tout neuf et tous les beaux produits qui vont avec !

Aujourd'hui, je m'attaque à un fleau bien connu du monde TFS : l'utilisation d'une édition SQL Enterprise qui empêche de migrer son TFS vers une édition inférieure (type Standard ou Express).

Tout administrateur TFS, le sait, la solution est simple. Il suffit de supprimer les features Enterprise activées sur les bases de données à migrer. En soit, rien de compliquer. Par contre quand il faut l'appliquer à une un gros volume de collections... cela devient vite rébarbatif.

Pour faciliter la chose, j'ai réalisé un script SQL bien pratique :

-- Déclarations
declare 
 @DataBase sysname

-- Crusor pour aller chercher les bases de données
declare databases_cursor cursor for
select db.name
from sys.databases as db
where db.name like 'tfs_%';

open databases_cursor

-- Passer à la base suivante
fetch next from databases_cursor into @DataBase

while @@FETCH_STATUS=0
begin
    -- Changement de propriétaire
	exec('exec [' + @DataBase + '].dbo.prc_EnablePrefixCompression @online = 0, @disable = 1');

	-- Passer à la base suivante
	fetch next from databases_cursor into @DataBase
end

close databases_cursor
deallocate databases_cursor

 

Note, en plus d'empêcher la migration, si l'édition SQL Server est inapproprié, car induisant des features superflues, on peut contacté un usage de la RAM plus important que ce qu’il devrait être.

Exemple constaté : TFS 2013, SQL 2012, une trentaine de collections, 2 CPU, 4 Gb RAM. Après suppression de la compression, le serveur utilise 11% de RAM en moins et les performances pour les utilsaiteurs sont restées identiques.

Voilà, bonnes migrations ;)

Mauvaise surprise pour les utilisateurs de Windows Technical preview sur Windows To Go : Les upgrades de builds ne sont pas possibles.

J'ai testé avec les toutes les builds disponibles à ce jour, et aucune ne permet l'upgrade.

Voici le message obtenu :

Note : Windows Update reste fonctionnel.

Grand fan de Windows To Go, je me suis lancé dans la préparation d'un disque externe avec Windows 10. Dans un élan de folie, j'ai voulu tenter l'opération à partir de mon Windows 8.1 Enterprise.

Bonne surprise, ça marche. Cela fait maintenant une semaine que j'utilise la Technical Preview Enterprise à partir d'un support Windows To Go.

Le déploiement a suivi les étapes classiques d'une installation Windows To Go à partir d'un PC Windows 8.1.

Il faut ouvrir son panneau de configuration. Utiliser le raccourci Windows To Go.

 

On sélectionne sa clé USB ou son disque externe.

 

On ajoute le chemin vers le disque (ici, j'ai monté l'iso sur F:\)

 

On fait suivant (hors mis si on veut tester BitLocker)

 

Et c'est parti

 

Ensuite il faut patienter

 

La dernière boite de dialogue propose de rebooter. On peut la fermer sans apporter de modification a sa machine et utiliser le disque.

 

Testé et approuvé ;)

Aujourd'hui, je vous propose un petit tour d'horizon des possibilités offertes par IIS et .net pour personnaliser ses pages d'erreurs.

Première chose à assimiler, il ne faut pas confondre les pages d'erreurs de nos applications .net et les pages d'erreur IIS :

  • La première catégorie sert principalement à afficher les erreurs internes à nos applications (exceptions diverses)
  • La seconde catégorie contient toutes les erreurs clients et applicatifs IIS qui peuvent être utilisée par des applications autres qu'ASP .net (erreurs 400-500 type : page introuvable, site indisponible, accès refusé …)

La première catégorie d'erreur se gère assez facilement via la section customErros du fichier web.config. Il n'y a pas grand-chose à dire. Vous pouvez gérer les erreurs dans vos applications web, et choisir sur quel client on veut ou non afficher les erreurs en détail. Dans certains cas, vous risquez d'être en grosse galère, car les pages d'erreur IIS peuvent prendre le dessus sur vos pages d'erreurs ASP.net. Un développeur .net doit donc avoir connaissance des possibilités offertes par la personnalisation des pages d'erreur IIS.

La seconde est bien plus intéressante car elle offre des possibilités de personnalisations aux hébergeurs et administrateurs système. Ceci de manière uniforme quelle que soit la technologie utilisée. Certes les pages ainsi personnalisées sont en général statiques (pour éviter de donner trop d'informations aux utilisateurs finaux), mais au moins elles sont chartes aux couleurs de la société.

Pour ceux qui n'auraient jamais fait attention, voici une capture du panneau IIS qui met en avant les deux zones de configurations :

 

Pour présenter correctement la chose, j'ai choisi d'utiliser le plan suivant :

  1. Activité les erreurs personnalisées IIS
  2. Scope de la configuration des pages d'erreurs
  3. Possibilité 1 : Modification de la configuration machine et Structure du dossier des pages d'erreurs
  4. Possibilité 2 : Embarquer les pages dans son site
  5. Possibilité 3 : Hébergement sur un serveur dédié

Ma volonté étant de vulgariser les pages d'erreurs IIS pour les développeurs .net, j'omettrai volontairement un certain nombre de détails. Je n'aborderai donc pas des notions comme :

  • Les pages détaillées
  • Les redirections/réécritures de pages
  • La possibilité absolument diabolique d'empêcher les développeurs de personnaliser les pages d'erreurs (c'est méchant ça !)

Attaquons donc dans le vif !

 

1. Activité les erreurs personnalisées IIS

En soit, l'activation des pages personnalisées n'a rien de bien compliquer. Sur un poste client, il suffit d'aller dans le panneau de configuration t d'ajouter une fonctionnalité Windows.

Ici sur un Windows 8.1 en français : « Erreurs http » 

 

Sur un serveur, il faut ajouter une fonctionnalité au rôle IIS. Ici sur un Windows 2012 R2 qui a déjà cette fonctionnalité activé : « Erreurs HTTP (Installé) » 

Aucun reboot n'est utile.

 

2. Scope de la configuration des pages d'erreurs

La configuration des pages d'erreurs étant enregistrée dans un fichier *.config section system.webServer (nœud httpErrors). Voici ce à quoi ressemble la configuration par défaut :

Il est possible de la modifier à différents endroits :

  • applicationHost.config
  • web.config

Bien entendu, machine.config ne fait pas parti des possibilités envisageables. Imaginez une page d'erreur qui change en fonction de la CLR ou de la plateforme ciblée (32 ou 64bits). Ce serait un cauchemar !

 

En fonction de l'endroit où l'on configure la section system.webServer, il est donc possible de personnaliser les erreurs pour :

  • Tous les sites d'un même serveur (applicationHost.config)
  • Un site (web.config)
  • Une application (web.config)
  • Un répertoire virtuel ou non (web.config)

La configuration peut donc être très souple. Via la console IIS, on dispose même d'une interface très pratique. Celle-ci permet de changer une page d'erreur existante et d'ajouter/supprimer des erreurs.

 

Le formulaire de configuration d'une erreur reste simple, à condition de comprendre les trois possibilités de personnalisation offertes par IIS.

 

3. Possibilité 1 : Modification de la configuration machine et Structure du dossier des pages d'erreurs

La première possibilité offerte consiste dans l'usage de pages statiques stockées sur le serveur. Il s'agit de la configuration par défaut de IIS. Les fichiers sont stockés dans le répertoire « %SystemDrive%\inetpub\custerr\ » (donc bien souvent dans C:\ inetpub\custerr\).

Si vous le souhaitez, vous pouvez choisir d'utiliser des pages qui diffèrent en fonction de la langue de l'utilisateur (pages localisées). Pour cela, il suffit de créer un répertoire par langue. Exemple : ici le français (fr-FR)

 

Lors de la saisie, si la case «Essayer de retourner le fichier d'erreur dans le langage client » est cochée, le bouton définir est disponible. Il permet d'accéder au formulaire suivant :

Dans le cas où cette case n'est pas cochée, vous ne pourrez pas avoir de pages d'erreurs localisées. Il faudra donc donner le lien complet vers la page d'erreur.

Voici par exemple, la configuration obtenue en personnalisant uniquement deux pages (401 localisée et 403 non localisée)

Notes :

  • errorMode doit être défini sur Custom pour que votre configuration soit prise en compte
  • On peut utiliser un noeaud <clear/> si on veut supprimer les autres pages.

 

4. Possibilité 2 : Embarquer les pages dans son site

Il s'agit là de l'approche préférée des développeurs. Les pages font partie du site. On peut en profiter pour avoir une page dont le contenu change dynamiquement (exemple erreur 403 du fichier de configuration suivant).

 

5. Possibilité 3 : Hébergement sur un serveur dédié

Cette approche est très pratique dans le cas d'une ferme IIS. Les fichiers n'ont pas besoin d'être répliqués sur l'ensemble des serveurs de la ferme. Cette approche comme la précédente permet d'avoir une page dont le contenu change dynamiquement (exemple erreur 403 du fichier de configuration suivant).

 

Voilà, j'espère que cet article vous donnera envie de considérer cette possibilité de personnalisation de IIS.

Aujourd'hui je suis toujours surpris pas la complexité mise en place pour sécurisées des informations (bases de données, partages de fichiers, FTP…). Pour une même application, il y a les développeurs qui vont stocker 50 comptes qui ne sont utilisés que par l'application (ou le groupe d'applications qu'ils gèrent). Pour ne pas distribuer les mots de passe sur les serveurs, ou les pc clients, on se retrouve souvent avec trois solutions qui parfois se complètent:

  • Le stockage de logins, mots de passe cryptés (dans l'application ou le fichier de configuration).
  • L'utilisation d'un API tiers de sécurité pour stocker logins et mots de passe (parfois avec un mot de passe ou token d'accès qui lui n'est pas sécurisé)
  • L'impersonation pour que le processus s'exécute avec des droits d'un autre utilisateur.

Il y a peut-être d'autres solutions que je n'ai pas croisées.

Dans tous les cas, on finira systématiquement avec un problème : « il y aura toujours un mot de passe qu'une personne devra conserver », ou « une personne qui aura accès à l'information sans restriction ».

Exemples absurdes, car l'utilisateur aura accès quoi qu'il soit décidé :

  • Ne pas vouloir donner accès à un site SharePoint alors que l'utilisateur est administrateur de la collection contenant le site.
  • Ne pas vouloir donner accès à un partage alors que l'utilisateur gère aussi le compte qui sert au backup de ce dossier (donc un compte qui lui aura accès quoi qu'il arrive)
  • … etc ….

Chacun a connu dans sa carrière l'une de ses situations absurdes. Je sais d'expérience qu'il y a des personnes qui préfèrent ne pas expliquer la situation : « c'est sécure ! ». Personnellement, j'ai toujours bataillé pour que la situation soit claire. Il n'y a pas de sécurité dans l'opacité.

La solution simple :

1. L'humain :

Ne pas prendre un responsable de votre société, car dans la plupart des cas, ils ne sont pas formés à la sécurité et risquent de compromettre l'information.

Exemple typique de ce type d'utilisateur :

  • Téléphone sans verrouillage d'accès posé sur une table.
  • PC laissé session ouverte lors de la pause pipi.
  • Lien vers les mots de passe sur le bureau Windows.
  • … etc…

Mettre en avant une personne « administrateur système » ou un « administrateur applicatif ». Cette personne a l'accès complet à l'outil et la sécurité fait partie de son métier. S'il faut conserver un mot de passe, c'est lui qui doit le faire.

 

2.  Le technique simple

La quasi-totalité des applicatifs peut utiliser une authentification Windows (aussi appelée authentification intégrée sur certaines applications comme SQL Server). Ce qui permet aussi la centraliser la gestion des comptes dans l'Active Directory. Notre administrateur aillant accès à l'AD, il pourra immédiatement couper un compte si besoin. Ceci est très pratique dans le cas d'applications compromises, ou changer le mot de passe rapidement.

A partir du moment où l'on utilise ce mode d'authentification, il n'est plus utile de stocker des chaines de connexion avec mot de passe dans l'applicatif ou le fichier de configuration. Ni même de stocker un mot de passe. Le ou les processus lancés se feront avec les droits de l'utilisateur qui a lancé le processus.

Pour chaque type d'application, il y a une solution simple qui s'appuie sur un compte Windows:

  • Application Windows classique : Le compte d'ouverture de session est utilisé
  • Site Web : Le compte du pool IIS est utilisé.
  • Planificateur de tâche : On peut déterminer un compte lors de la mise en place
  • Service Windows : On peut déterminer un compte lors de la mise en place
  • SharePoint : On a une liste de compte géré.

Note : On peut faire encore plus simple si l'on n'a pas besoin d'accéder aux ressources d'autres machines. On peut utiliser un compte système (ou un compte intégré à IIS par exemple)

 

3. Le technique un peu plus évolué

Si l'authentification Windows n'est pas disponible et qu'il faut sécuriser des données, on stocke les données cryptées dans un fichier de configuration. Mais avant de crypter les données, il faut commencer par extraire les clés machines qui serviront au cryptage.

Sans ces clés, votre fichier ne pourra pas être déployé hors de la machine qui a servi au cryptage. Ceci est très important pour une ferme IIS, ou pour un plan de reprise d'activité (PRA). Il s'agit là d'une erreur qui est malheureusement trop courante.

Il y a une documentation très claire que l'on peut trouver ici : http://msdn.microsoft.com/en-us/library/ff650304.aspx

Cette page date un peu, mais son contenu reste valable. Vous y trouverez le nécessaire pour sécuriser vos fichiers de configuration de manière fiable et portable.

 

Voilà. Vu que sécurité rime avec simplicité, j'espère que ces petites vous seront utiles et vous faciliterons la tâche.

Après avoir lu avec beaucoup d'attention l'annonce de S. Somasegar, j'ai été surpris de ne pas trouver de lien direct vers l'ISO de Visual Studio 2015.

Ce matin, une recherche sur Bing ou Google ne donnait pas grand-chose. Ce soir la donne a un peu changé et on peut enfin trouver facilement le lien vers la preview ici :

http://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs

Petit avertissement pour les plus distraits : c'est le second lien qu'il faut utiliser pour obtenir l'ISO complète. Le premier pointe vers l'installer web.

Bons tests ;)

Un petit bug existe sur le package Oracle Database Client (12.1.0.2.0) for Microsoft Windows (32-bit) qui se trouve sur la page de téléchargement suivante : http://www.oracle.com/technetwork/database/enterprise-edition/downloads/database12c-win64-download-2297732.html

Le fichier oranfsodm12.dll est manquant, ce qui empêche l'utilisation de SQL*Loader.

En recherchant dans la documentation, on découvre qu'il s'agit d'une version modifiée de la librairie oraodm.

https://docs.oracle.com/database/121/NTDBI/postcfg.htm

 

En copiant oraodm12.dll et en la renommant oranfsodm12.dll on obtient une dll de remplacement utilisable sans NFS. On peut donc l'utiliser sur un poste client, mais on ne profitera pas de fonctionnalités du client direct NFS documenté ici (en version 11) :

http://www.oracle.com/technetwork/articles/directnfsclient-11gr1-twp-129785.pdf

 

Si la solution est acceptable dans un environnement, de développement, sur un environnement de production, il sera préférable de se procurer la DLL présente dans le package DataBase. Seul hic, ce package n'existe pas en 32 bits L

 

Derrière ce titre étrange se cachent quelques conseils sur l'utilisation de dépendance externes à vos projets. Que ce soit dans le cadre d'une maintenance, de la migration d'une application ou tout simplement dans l'évolution d'une application, des dépendances mal gérées peuvent faire capoter votre projet.

1. Lister ses dépendances

Il n'y a rien de pire qu'un projet dont on ne connait pas les dépendances. Savoir quelles dépendances on a, s'est déjà connaitre une partie de ce que l'on a besoin pour faire fonctionner son application. Dans certains cas, si vous connaissez les dépendances, vous pouvez même anticiper certains problèmes.

Si l'on ne connait pas ses dépendances, il est possible que l'on ne puisse pas déployer l'application.

Dans le cadre d'une migration, c'est une étape primordiale. Cette liste vous permettra de savoir quelles dépendances pourront être conservées, mises à jour, ou devront être supprimés. Si trop de dépendances n'existent pas sur la plateforme cible, il est possible que cela change complètement la philosophie de votre projet de migration en le transformant en projet de réécriture complète (pas de chance).

2. Ne garder que des dépendances utiles

Cette remarque vous fait sourire ? Si oui, avez-vous déjà listé les dépendances utilisées par le Template d'application web de Visual Studio ? Êtes-vous certain d'avoir besoin de toutes celles-ci pour votre projet ?

Il y a trop de projets qui incluent des dépendances pour effectuer des opérations déjà possibles avec les Frameworks. Exemple : sur un projet .net on peut déjà faire de la compression ou du cryptage sans utiliser de dépendances supplémentaires (et ça n'est pas très compliqué).

Parfois, il y a de dépendances que l'on garde par habitue. Il faut être vigilant avec celles-ci et régulièrement se tenir informé sur les évolutions de son Framework pour vérifier que celles-ci ne sont pas devenues inutiles. Exemple : avec le passage de Windows 8.0 à 8.1, j'ai supprimé plus de la moitié de mes dépendances, car j'ai presque trouvé tout ce dont j'avais besoin dans WinRT et les évolutions de Xaml.

3. Bien choisir ses dépendances

On a vite fait de lancer une recherche sur CodePlex, Nuget…etc… pour aller chercher des dépendances censées nous simplifier la vie. Certain préfèrerons acheter des composants aux près de fournisseurs bien connus comme DevExpress, Telerik… etc…

Quelle que soit la source des dépendances, il faut s'assurer de :

  • La viabilité de la source : un projet maintenu par un seul développeur très actif peut être parfaitement viable. Mais qu'en est-il d'un projet dont il n'y a toujours eu qu'une version ?
  • La fraicheur de la dépendance : un produit qui n'a pas été mis à jour depuis longtemps est un produit qui est peut-être mort. Il n'a donc pas d'avenir. Un bon indicateur pour identifier un projet mort, c'est de vérifier qu'il utilise un Framework récent. Exemple : une dépendance qui cible .net 2 en 2014… c'est risqué.
  • La maintenance corrective et évolutive : Un produit acheté doit toujours l'être avec ses mises à jour. Cela vous permettra de profiter des correctifs de celui-ci. Ce surcout doit être considéré avant tout achat pour éviter des débordements sur votre budget. J'ai déjà vu des projets en galère, car les bugs induits par les dépendances ne peuvent être résolus.
  • Regarder les breacking change : toujours vérifier si une dépendance est habituée à induire des breackin change suite à ses mises à jour. S'il y en a beaucoup, vous aurez beaucoup de travail à fournir lors des mises à jour.

4. Les dépendances ont des dépendances

On l'oublie souvent, mais une dépendance peut induire l'utilisation d'autres dépendances. Rien de pire que le message disant : «  la dépendance X où l'une de ses dépendances ne peut être résolue…. ».

À ce titre, vous devez appliquer les mêmes précautions sur celles-ci que sur vos dépendances directes. Il faut aussi être très prudent sur le fait qu'une dépendance n'aille pas à contrario des contraintes qui vous sont imposées. Exemple : Dépendance indirecte qui dépend de .net 4.5 alors que vous ciblez .net 4.0.

5. Garder un œil sur ses dépendances

Comme votre application, les dépendances évoluent. Ceci peut être pour votre plus grand bonheur. Mais ceci peut aussi être un véritable casse-tête à gérer.

Les problèmes pouvant être anticipés si on suit l'actualité de ses dépendances :

  • Breaking changes
  • Classes/Méthodes obsolètes
  • Classes/Méthodes abandonnées
  • Classes/Méthodes remplacées par d'autres
  • Ajout/suppression de dépendances indirectes
  • Abandon du projet par l'éditeur
  • .. etc…

Outre le fait de suivre ses informations, il faut aussi mettre à jour régulièrement ses dépendances. Ceci permet de réduire le travail à fournir. Si on espace les mises à jour de plusieurs mois ou années, on s'expose à de grands risques. Exemple : perte de temps, delta trop important entre deux versions et donc situation difficilement gérable.

6. Garder ses dépendances au chaud

Il faut toujours stocker les dépendances et/ou les fichiers qui ont servi à leur déploiement. Que ce soit sur un TFS, un SharePoint ou un simple partage. Ces fichiers vous seront indispensables pour remonter un environnement. Que ce soit un environnement de développement ou de production.

Même si aujourd'hui des dispositifs types Nuget sont devenus fréquents, j'ai toujours pris l'habitude de conserver les fichiers téléchargés par ceux-ci. Qui sait, la source sera peut-être coupée un jour.

Stocker, c'est bien, mais il faut aussi penser à noter clairement la plateforme cible. Il n'y a rien de pire que d'avoir deux DLL avec le même nom, le même numéro de version et ne plus savoir laquelle est destinée au 32 bits ou au 64 bits.

 

Il est fort probable que j'oublie une ou deux petites choses, mais l'essentiel est là.

Et vous, auriez-vous d'autres conseils à donner sur la gestion des dépendances ?

Plus de Messages Page suivante »


Les 10 derniers blogs postés

- [ #SharePoint 2016 ] frappe à nos portes ! (1/2) par Le blog de Patrick [MVP Office 365] le 04-19-2015, 23:21

- Lync devient Skype Entreprise par Le petit blog de Pierre / Pierre's little blog le 04-18-2015, 22:47

- [WCF] Prendre la main sur les protocoles par Blog de Jérémy Jeanson le 04-18-2015, 12:57

- yOS Tour Geneva - Retour des sessions par Blog Technique de Romelard Fabrice le 04-16-2015, 11:54

- YOS Genève 2015 : gestion des gros fichiers et plus … par The Mit's Blog le 04-13-2015, 11:56

- YOS Genève 2015 : App et bonnes pratiques par The Mit's Blog le 04-13-2015, 10:55

- [YOS Genève 2015] : Et si on adoptait enfin nos espaces collaboratifs par The Mit's Blog le 04-13-2015, 09:48

- [WCF] Les bases d’une configuration clean par Blog de Jérémy Jeanson le 04-11-2015, 11:48

- Dernière partie de cache cache avec l’AppFabric le 2/04/2016 par Blog de Jérémy Jeanson le 04-08-2015, 23:01

- [WCF] Binding REST et SSL, c’est possible par Blog de Jérémy Jeanson le 04-04-2015, 09:19