Translate

jeudi 20 décembre 2012

[TECH]: Utiliser l'objet COM+ Internet Explorer sur Windows Server 2012

Avec Exchange et Lync, il est souvent sympa de pouvoir générer des rapports divers et variés via un document HTML riche et bien formaté (au delà donc du simple usage des sorties formatées en HTML standard). Un exemple est un script que je fournis à mes clients et qui génère un rapport de santé d'un DAG et des composants d'infrastructure liés. Un exemple ci-dessous avec mon petit DAG Exchange 2013...


Le principe est de créer un objet COM Internet Explorer et de peupler un Document vide. Cela offre l'avantage de pouvoir utiliser les méthodes standards de l'objet comme getElementById() et d'aller modifier un style sur un code HTML généré en amont, par exemple ici le statut global qui passerait rouge en cas d'erreur. De plus, cela permet d'ouvrir une sorte de console IE en plain écran, de faire des rafraîchissements automatiques, ou même de sauvegarder le document complet au format HTML pour d'autres actions, type envoi par E-mail ou mise à disposition sur une racine IIS.

$IE = New-Object -comObject InternetExplorer.Application
$IE.Navigate2("about:blank")

A partir de là, la logique est d'attendre la fin du statut occupé de l'objet IE, puis de travailler avec l'attribut membre "Document", en utilisant les méthodes write() et writeln() afin de générer le code HTML.

Lorsque j'ai commencé à mettre à jour mon script de rapport de santé pour le rendre compatible Exchange 2013, je me suis retrouvé face à un problème de taille: mes serveurs Exchange 2013 étant installés sur un système d'exploitation Windows Server 2012, impossible d'utiliser les méthodes write() et writeln(). Elles existent toujours mais ne prennent aucun argument. Rien n'y faisait, impossible de générer le code.

Puis j'ai regardé le comportement sur un autre serveur Windows 2012, mis à jour lui depuis un Windows Server 2008 R2. Et là: les méthodes existent mais les arguments à passer sont dans un type bizarre issu du code en C/C++ de vieux bouts de code IE.

On a donc une différence fonctionnelle entre:

  • Windows Server 2008 R2
  • Windows Server 2012 avec des composants issus du système originel mis à jour
  • Windows Server 2012 installé en partant de rien
J'ai donc commencé à m'intéresser à l'objet "Document", comprendre voir quelle est la nature des différences. J'ai donc regardé le type sur les trois environnements:
$IE.Document.GetType().ToString()
et
$IE |fl Document

Et là ! J'ai enfin été mis sur une piste sérieuse: les objets sont de type de base "ComObject" (des objets COM+ donc). Sur les environnements où les méthodes on bien un prototype définissant des arguments, l'objet est de type "mshtml.HTMLDocumentClass". Sur l'environnement Windows Server 2012 installé en partant de rien, l'objet apparaît être d'un type "System.__ComObject" et donc chargé sans support des méthodes MSHTML.

Après quelques recherches, j'ai fini par trouver que cette classe est définie dans une "Primary Interop Assembly" nommée "Microsoft.mshtml" et définie dans la DLL "Microsoft.mshtml.dll". Une recherche rapide sur mes serveurs à permis de confirmer que cette assembly est bien installée sur les serveurs qui me fournissent un objet définissant les méthodes write() et writeln().

Le hic c'est que cette assembly n'est pas installée en standard/par défaut. Puisqu'il semblerait qu'IE sache l'utiliser lorsqu'elle est installée, je me suis dit qu'un chargement de l'assembly à la volée pourrait faire l'affaire.

Me voici donc à développer une fonction PowerShell pour le faire, appelée naturellement "Load-Assembly". Le code est disponible ici sous forme d'un script PowerShell: http://sdrv.ms/U6j7Wn.


J'ai ensuite copié la DLL de l'assembly depuis mon serveur Windows Server 2008 R2 vers l'emplacement réseau de mes scripts, dans un sous-répertoire "bin\PrimaryInteropAssemblies".

Avant la création de mon objet Internet Explorer, j'ai donc ajouté le code suivant:

if ( ("mshtml.HTMLDocumentClass" -as [Type]) -eq $null )
{
    $assembly = Load-Assembly -Path ".\bin\PrimaryInteropAssemblies\Microsoft.mshtml.dll"
    if ( $assembly -eq $null )
    {
        throw "Failed to load the MSHTML Primary Interoperability Assembly."
        return
    }
    Write-Verbose "PrimaryInteropAssembly MSHTML loaded: $($assembly.FullName)"
}


Et enfin, une fois mon assembly chargée, le type étant défini correctement, l'objet Document redevient un objet de la classe attendue, à savoir "mshtml.HTMLDocumentClass". Une fois l'assembly chargée, mes objets COM réagissent de la même manière sur mon serveur Windows 2012 qui ne fonctionnait pas auparavant.

Me reste maintenant un problème à élucider: les méthodes write() et writeln() se refusent à fonctionner correctement malgré l'objet chargé avec la bonne classe. Faute probablement ici au PowerShell v3 je pense, qui gère les types ou la conversion de type différemment. Le type attendu est un SAFEARRAY (cf la capture d'écran en PowerShell v2) qui est un type C/C++. Imaginez la galère en partant de PowerShell...

Et là miracle: en explorant l'objet Document, je me suis rendu compte qu'il existe des méthodes additionelles à celles disponibles en PowerShell v2... bizarre mais elles sont nommées IHTMLDocument2_xxx(), IHTMLDocument3_xxx(), IHTMLDocument4_xxx() et IHTMLDocument5_xxx(). Cela ressemble fort à des méthodes de compatibilité descendante !!!

J'essaye donc IHTMLDocument2_write() et IHTMLDocument2_writeln() avec succès !!!

Au final:
  • rajout d'un bout de code permettant de charger l'assembly,
  • utilisation des méthodes de compatibilité à la place des méthodes natives... dans mon cas j'ai codé une "surobjet" Document qui s'adapte et appelle la bonne méthode en fonction de la présence ou non de la méthode IHTMLDocument2_write().
Le bug avait été remonté via Connect, ici: http://connect.microsoft.com/PowerShell/feedback/details/764756/powershell-v3-internetexplorer-application-issue

mardi 11 décembre 2012

[INFO]: Nouveaux Rollups Exchange 2010 et Exchange 2007 disponibles

La DevTeam Exchange vient de publier les Rollups 5v2 Exchange 2010 SP2, Rollup 8 Exchange 2010 SP1 et Rollup 9 Exchange 2007 SP3.

Tous corrigent un bug de sécurité considérée Critique décrite dans le bulletin MS12-080.

N'oubliez pas de bien tester dans votre environnement de pré-production afin d'éviter des sueurs froides comme celles créées par le Rollup 5 Exchange 2010 SP2... :)

samedi 8 décembre 2012

[TUTORIEL]: Comment créer vous même un répartiteur de charge avec Ubuntu Server et HAProxy (v2)

En août dernier je m'étais finalement décidé à publier mon guide décrivant un approche pas-à-pas permettant de créer votre propre solution de répartition de charge basé sur HAProxy et stunnel.

Tout récemment, Willy Tarreau et l'équipe de développeurs contribuant aux évolutions du code d'HAProxy ont implémenté de nouvelles fonctionnalités en version 1.5-dev7 puis dev12, 13 et 14: à savoir (entre autres) le support de la terminaison SSL sur HAPproxy, ce qui permet naturellement des scénarios de SSL Offloading ou de SSL Bridging sans stunnel ou autre wrapper SSLJe rappelle que HAProxy est le composant clef des boîtiers Exceliance (http://www.exceliance.fr/), des solutions de répartition de charge très performances et peu onéreuses.

Voici donc le lien de téléchargement du guide v2, entièrement basé sur Ubuntu Server et HAProxy:


jeudi 22 novembre 2012

[TUTORIEL]: Exchange 2013 - Configurer l'accès Client et Kerberos (load-balancer ou DNS round-robin)

Depuis Exchange Server 2010 SP1, il est hautement recommandé d'activer Kerberos pour les accès clients. Cela se faisait au travers d'un ensemble de manipulations visant à créer un objet de sécurité dans l'Active Directory, puis de définir les Service Principal Names Kerberos sur cet objet.
Cet objet devait ensuite être défini sur la configuration des serveurs CAS comme le "Alternate Service Account", ce qui permettait alors au service "Microsoft Exchange Protected Service Host" de répondre en mode Negotiate à un challenge SPNEGO.

J'avais documenté le pas-à-pas dans un tutoriel Exchange 2010 SP1 >> ici << (à l'époque c'était sur la Beta du SP1 mais la procédure est toujours applicable).

Qu'en est-il d'Exchange Server 2013... ?

Plusieurs points:
  • Exchange 2013 n'utilise plus le Mapi/Rpc (pour les accès clients), seulement le Mapi sur Http (autrement dit, le Rpc/Http)
  • Exchange 2013 est configuré par défaut en mode Ntml, afin de conserver une compatibilité large et surtout parce que la configuration en Kerberos requiert des manipulations qui ne peuvent être faites automatiquement au moment du Setup
  • La haute disponibilité d'Exchange 2013 s'effectue uniquement au niveau du protocole HTTP, il n'y a par conséquent plus besoin de définir une VIP pour le Mapi/Rpc.
Ce que cela implique:
  • Au niveau de la haute-disponibilité: il devient possible de se passer de répartiteur de charge (load-balancer, HLB) et de ne faire que du DNS round-robin (DNS RR). Il s'agit avant tout d'une logique du client et donc ne fonctionnera pas dans 100% des cas (vous devrez avoir des clients dits "modernes") - il reste bien sûr (et je le recommande pour plein de raisons) la possibilité de faire de la répartition de charge classique, en mode 100% HTTP/HTTPS désormais. Cependant, point noir pour Exchange 2013 RTM: il n'y a pas de support du SSL Offloading. Pour l'avoir testé, cela ne fonctionne pas du tout et j'essayerai de vous faire un tutoriel sur le SSL Bridging, qui lui devrait (en théorie) fonctionner.
  • Au niveau de la configuration: il faudra configurer Outlook Anywhere et les Web Services afin de faire référence à un nom générique (load-balancé donc, ou en DNS RR). Cela permettra donc aux clients d'utiliser des URI liées à des points de connexion uniques, et non comme cela est le cas, directement liées au nom complet qualifié (Fqdn) de chaque serveur.

Première partie: configuration des Web Services

La configuration des Web Services est simple et presque identique à ce que l'on avait l'habitude de faire sur Exchange 2010, à savoir:
  • Définition d'une "InternalURL" pour les services suivants: OWA/ECP, Exchange Web Services, OAB, Exchange ActiveSync. La configuration du Web Service Autodiscover n'est désormais plus utile, mais il faudra conserver la partie de la configuration visant à changer le Service Connection Point HTTP pour la découverte automatique via l'Active Directory (pour rappel: en utilisant le cmdlet Set-ClientAccessServer). A cela viendra s'ajouter la configuration, maintenant O-BLI-GA-TOIRE d'Outlook Anywhere, activé par défaut et référençant le Fqdn de chaque serveur.
  • Optionnellement, définition des "ExternalURL", si vous souhaitez supporter des clients externes (pour du vrai Outlook Anywhere, dans le sens originel du terme... :)). Nous verrons cela dans un prochain article.
Pour l'exemple, nous allons donc configurer en premier lieu les URLs Internes et monter comment un client se connecte par défaut (il sera en Rpc/HTTP _et_ en Ntlm).
Le nom générique dans mon Lab sera "ex.w15-lab.com". J'ai ici deux serveurs (SV-E15-1 et SV-15-2) exécutant les rôles CAS et MBX, nous ne devrons configurer que la partie CAS. Pour l'exemple, je vais découper les actions en mode pas-à-pas et serveur par serveur.

Configuration des Web Services:
Regardons d'abord l'état de mon premier serveur pour le VDir Outlook Web App:
  • Get-OwaVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | fl *Url
Il est est de même pour les autres Web Services, nous allons donc les configurer individuellement (ici en Shell pour le premier):
  • Get-OwaVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | Set-OwaVirtualdirectory -InternalUrl "https://ex.w15-lab.com/owa"
  • Get-EcpVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | Set-EcpVirtualdirectory -InternalUrl "https://ex.w15-lab.com/ecp"
  • Get-WebServicesVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | Set-WebServicesVirtualDirectory -InternalUrl "https://ex.w15-lab.com/EWS/Exchange.asmx"
  • Get-OabVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | Set-OabVirtualDirectory -InternalUrl "https://ex.w15-lab.com/OAB"
  • Get-ActiveSyncVirtualDirectory -Server SV-E15-1 -ADPropertiesOnly | Set-ActiveSyncVirtualDirectory -InternalUrl "https://ex.w15-lab.com/Microsoft-Server-ActiveSync"
Note: Attention à la casse sur les "/répertoire". Il y a des scripts disponibles sur la blogosphère permettant de soit-disant les configurer "facilement". Historiquement il y a eu des soucis si la casse d'origine n'était pas respectée: typiquement en mode Proxy-CAS sur l'Exchange Control Panel où l'InternalURL était en autre chose que "/ecp" (en minuscules) et "cassait" le cookie msExchCanary. Mon conseil: écrivez votre propre script et respectez exactement la même casse que celle originellement trouvée sur l'InternalURL. Pour les ExternalURL, utilisez la même nomenclature que l'InternalURL.
Nous voyons ici que nous n'avons pas utilisé la Cmdlet Set-AutodiscoverVirtualDirectory, contrairement à ce que nous aurions fait dans Exchange 2010 et Exchange 2007. Cependant ces actions n'avaient que très peu d’intérêt  même dans les versions précédentes. Il semblerait donc que la directive dans Exchange 2013 est de ne même pas s'y attarder... :)
Par contre, nous devons absolument configurer le Service Connection Point de l'Autodiscover afin d'arriver sur notre URI générique. Cela ne peut se faire qu'en Shell. Notez que vous pouvez vous passer ce cette configuration si vous voulez disposer un certificat sur vos CAS ayant chaque Fqdn de chaque CAS dans le Subject Alternate Name. La meilleure méthode reste cela dit de définir une URI générique, comme pour tous les autres Web Services...

Nous y sommes presque ! Reste donc la partie Rpc/Http, autrement dit, Outlook Anywhere !

La grosse nouveauté ici est qu'il existe désormais un "InternalHostname" à Outlook Anywhere. Rappelez vous que pour Exchange 2007 et Exchange 2010, il n'était possible que de définir un  "ExternalHostName"... Vous l'aurez sans doute compris, le "InternalHostname" va être le point de connexion de vos clients et va complètement supprimer la notion de "Client Access Array" (NDLR: vous ne trouverez plus de Cmdlet New-ClientAccessArray, c'est donc normal :)).
Nous allons donc configurer l'InternalHostname afin qu'il pointe aussi sur notre nom générique. Cela s'effectue au travers de la Cmdlet Set-OutlookAnywhere:
  • Get-OutlookAnywhere -Server SV-E15-1 -ADPropertiesOnly | Set-OutlookAnywhere -InternalHostName "ex.w15-lab.com" -InternalClientsRequireSsl:$true
Vous pouvez vérifier la bonne application du changement en utilisant la Cmdlet Get-OutlookAnywhere:
  • Get-OutlookAnywhere -Server SV-E15-1 -ADPropertiesOnly | fl *Internal*
Dès lors, vous pouvez reproduire la même configuration pour vos autres serveurs CAS. Vous pouvez utiliser l'Exchange Administration Center (https://serveur.domaine.com/ecp en vous authentifiant avec un compte appartenant au(x) bon(s) Role Group(s)) et en allant dans les sections suivantes:
  • Servers ==> Virtual directories pour les Web Services classiques (OWA/ECP, EWS, EAS, OAB)
  • Servers ==> Servers ==> double-click puis section "Outlook Anywhere" pour la configuration du "InternalHostName" Outlook Anywhere.
Rappelez vous qu'il faudra quand même configurer l'AutodiscoverServiceInternalUri en Shell, l'EAC ne proposant pas la modification du champ.
Avant de tester la connexion avec un client Outlook, vous devrez attendre que les changements soient effectifs/commités dans la base IIS et la configuration Exchange de tous vos serveurs. Pour cela, cherchez dans l'eventlog Application une écriture au journal de l'évènement ID3025 de la source "MSExchange RPC Over HTTP Autoconfig".
En attendant que cela soit le cas, vous devez faire les actions suivantes:
  • Créer un certificat à base d'un modèle "Web Server" ou d'un dérivé, et l'assigner à IIS. Pour ma part j'utilise un certificat "Wildcard" généré par un script, et ayant le InternalHostName et optionnellement (nous y viendrons plus tard) le ExternalHostName dans l'attribut SAN. Mon certificat n'a pas les Fqd des serveurs CAS dans le SAN, c'est mon côté puriste même si je comprends que certains préfèrent les avoir.
  • Créer le ou les enregistrements DNS correspondant(s) au nom générique de connexion
    • Pour du DNS round-robin, créez 'n' enregistrement de type A ayant le même nom. Dans mon cas, cela fait 2 enregistrements DNS dans ma zone DNS "w15-lab.com"
    • Pour du load-balancing classique, il suffit de faire pointer l'enregistrement A sur la VIP créée à cet effet.
Faites ensuite un redémarrage d'IIS sur chacun des CAS (iisreset /noforce). Cette étape n'est normalement pas requise mais j'ai eu des comportements bizarres sur les URL retournées lors de l'Autodiscover.
Une fois toutes ces actions effectuées, vous pouvez démarrer votre client Outlook (testé avec Outlook 2010 ici).

Configuration Serveur Exchange et Exchange Rpc/HTTP Proxy
Etat des connexions:

On notera en particulier les points suivants:
  • Le nom du serveur Exchange (ou anciennement du CAS Array) n'a plus lieu d'être est est remplacé par un GUID (GUID@forest.com)
  • La configuration du Rpc/HTTP s'est fait automatiquement, comme pour les versions précédentes mais avec la subtilité d'avoir détecté une connectivité "interne" et donc une configuration du Rpc/HTTP Proxy faisant référence à l'InternalHostName configuré précédemment.
  • On remarquera aussi que les deux options visant à forcer l'utilisation du Rpc/HTTP sont forcées, et ceci sans configurer l'OutlookProvider EXPR.
  • On voit aussi clairement que la configuration par défaut se fait en Ntlm (auto-configuré ainsi) et en SSL (par défaut aussi).
Nous sommes maintenant connectés, passons donc à la seconde partie: le Kerberos !

Seconde partie: configuration du Kerberos


La configuration du Kerberos pour Exchange 2013 est dans la continuité d'Exchange 2010. Nous devons procéder ainsi:
  • Créer un objet pour l'Alternate Service Account
  • Lui assigner les Service Pincipal Names qui nous intéressent
  • Le configurer sur chaque serveur CAS
  • Reconfigurer le mode d'authentification
Création de l'Alternate Service Account:
J'utilise un objet de type "Computer", nommé ici EXCHANGE-MAIN$. La subtilité ici est qu'un compte d'ordinateur n'a pas de mot de passe positionné lorsqu'il est ajouté au domaine via la pré-création d'un objet. Puisqu'il n'y a pas à proprement parler de serveur à joindre au domaine, nous allons devoir positionner un mot de passe.
Pour ma part, j'utilise un script pour générer un mot de passe très long et très aléatoire puis un autre script pour faire une réinitialisation du mot de passe du compte ordinateur.

Lorsque l'objet est créé, il ne dispose d'aucun nom de service associé. Nous allons donc les créer à l'aide de la commande SETSPN.
  • setspn.exe -A HTTP/ex.w15-lab.com WFLAB\EXCHANGE-MAIN$
Assignation de l'Alternate Service Account:
Vous devrez procéder en mettant les Credentials de l'objet dans une variable, ici $ASA. L’assignation s'effectue au travers de la Cmdlet Set-ClientAccessServer, comme dans Exchange 2010:
  • $ASA = Get-Credential -Credential "WFLAB\EXCHANGE-MAIN$"
  • Set-ClientAccessServer -Identity SV-E15-1 -AlternateServiceAccountCredential $ASA
Répétez l'opération pour chaque serveur CAS partageant le même pool. Rappelez vous que l'Alternate Service Account ne peut être manipulé à distance (même en utilisant un Connect-ExchangeServer -Fqdn . Le plus simple est donc de se connecter en RDP à chaque serveur ou d'utiliser le script RollAlternateServiceAccountPassword.ps1 (qui - fait rigolo - affiche fièrement ne pas avoir été testé avec cette version d'Exchange :)).
Par exemple:
  • .\RollAlternateServiceAccountPassword.ps1 -CopyFrom SV-E15-1 -ToSpecificServers SV-E15-2
Reconfiguration du mode d'authentification
Comme nous l'avons vu précédemment, Outlook Anywhere est donc configuré par défaut en Ntlm. Nous devons donc reconfigurer chaque serveur CAS afin de bascule l'authentification en mode Negotiate afin de faire du Kerberos (avec fail-back en Ntlm potentiel). Nous le verrons plus tard, mais il existe d'autres modes d'authentification, comme le Nego2 mais qui n'est semble-t-il pas supporté sur Windows XP, même avec Outlook 2010. A terme, l'idée serait peut-être même de forcer le Kerberos, ce qui est totalement possible avec Exchange 2013 (à tester !).
Nous utiliserons la Cmdlet Set-OutlookAnywhere afin de reconfigurer l'authentification, l'Exchange Administration Center ne permettant que de modifier la méthode d'authentification externe (NDLR: Microsoft a encore pas mal de boulot pour finaliser l'EAC, trop léger à mon goût...).
  • Get-OutlookAnywhere -Server SV-E15-1 -ADPropertiesOnly | Set-OutlookAnywhere -InternalClientAuthenticationMethod Negotiate -IISAuthenticationMethods Negotiate,Ntlm
  • Get-OutlookAnywhere -Server SV-E15-2 -ADPropertiesOnly | Set-OutlookAnywhere -InternalClientAuthenticationMethod Negotiate -IISAuthenticationMethods Negotiate,Ntlm
Encore une fois, vous devrez surveiller l'eventlog Application afin de vérifier que la configuration Outlook Anywhere a bien été prise en compte et la configuration IIS alignée en conséquence (event ID 3025). Rappel: L'attente peut durer jusqu'à 15 minutes.
Vous pouvez aussi vérifier les Authentication Providers dans IIS sur l'application /Rpc et assurez-vous d'avoir (dans cet ordre: Negotiate et NTLM). Cette partie est normalement gérée par Exchange mais il semblerait que la synchronisation AD - Exchange - IIS ne fonctionne pas toujours très bien lors de modifications successives trop fréquentes... MEF !
Dès lors, vous pouvez redémarrer votre client Outlook. Celui-ci va se reconnecter en Ntlm puisque telle est la configuration actuellement en place coté client. L'avantage du mode Negotiate est donc de supporter une transition vers le Kerberos s'il est disponible, sans pour autant perturber le fonctionnement des clients déjà configurés.
Si vous ne voulez pas attendre une reconfiguration automatique de votre client (ce qui peut prendre jusqu'à 2 heures), effectuez une réparation de votre service Exchange, ce qui a pour effet de refaire appel au Web Service Autodiscover.
On voit bien d'ailleurs lorsque l'on fait un Test d'AutoConfiguration que l'on est configuré sur un autre mode d'authentification (ici, Nego2).
Et voici donc le résultat en se reconnectant et après une purge des tickets Kerberos (klist purge):

Promotion en Kerberos complet
Maintenant que nous avons vu comment configurer le mode Negotiate (le plus compatible), nous pouvons pousser l'exercice plus loin et forcer l'utilisation de Kerberos. N'appliquez pas cette procédure sur un environnement de production sans l'avoir testée dans un environnement de pré-production fonctionnellement similaire à la production.
La reconfiguration se fait de la même manière que précédemment, en utilisant la Cmdlet Set-OutlookAnywhere:
  • Get-OutlookAnywhere -Server SV-E15-1 -ADPropertiesOnly | Set-OutlookAnywhere -InternalClientAuthenticationMethod NegoEx -IISAuthenticationMethods Kerberos
  • Get-OutlookAnywhere -Server SV-E15-2 -ADPropertiesOnly | Set-OutlookAnywhere -InternalClientAuthenticationMethod NegoEx -IISAuthenticationMethods Kerberos
Note: vous pouvez utiliser "NegoEx" ou "Negotiate" pour l'InternalClientAuthenticationMethod.
D'un point de vue client, rien de change, on reste en Negotiate mais ce qui change est surtout côté serveur et des Authentication Providers, où l'on passe de "Negotiate" et "NTLM" à "Negotiate:Kerberos".

Notez que forcer le Kerberos sur cette partie d'IIS va impacter vos connexions externe, puisque un client hors Active Directory ne pourra utiliser Kerberos. Cela dépendra donc de la capacité de fournir une authentification externe en Negotiate et d'effectuer ou non de la délégation Kerberos via le Reverse Proxy, type ISA/TMG.

mardi 20 novembre 2012

[INFO]: Activer Kerberos pour Outlook Anywhere (clients internes)

Les avantages d'activer Kerberos avec Exchange 2010 ne fait plus de doute pour personne. C'est pleinement supporté depuis Exchange Server 2010 SP1 et fait partie du béa-ba d'une implémentation propre et pouvant monter en charge.

Qu'en est-il d'Outlook Anywhere ou plus précisément du Rpc/HTTP.

Pourquoi faire la distinction? Je m'explique...

Lorsque l'on parle d'Outlook Anywhere, cela représente la fonctionnalité (se connecter sans VPN avec un client lourd, et hors des frontières de l'Entreprise, autrement dit, généralement depuis une connexion Internet lambda et via un Reverse Proxy). La fonctionnalité Outlook Anywhere inclut de facto un ensemble d'aspect techniques: les Web Services (Autodiscover, OAB, EWS) et le fameux Rpc/HTTP.
En mode stricto-sensu Outlook Anywhere, nous n'avons pas accès à l'Active Directory et donc à un "Key Distribution Center" (KDC). La négociation Kerberos ne peut donc se faire. Dès lors, les modes d'authentification possible deviennent "Basic" et "Ntlm". Soit... ça c'était "avant"... :)
Lorsque l'on est en interne, il arrive que l'on veuille forcer l'utilisation du Rpc/HTTP afin de rester dans un mode "Web" et donc passer outre les équipements de sécurité plus facilement. Il arrive aussi que cela soit à des fins de sécurité (un RSSI a plus confiance en SSL qu'en un cryptage MAPI par exemple...). Dès lors, il était donc possible (et recommandé) d'activer le "Ntlm" afin de conserver du Single-Sign On (SSO).

Mais le Kerberos n'était pas disponible... Jusqu'à semble-t-il récemment.

Sachant qu'Exchange 2013 fait seulement du Rpc/HTTP, cela permet de donner un avant goût d'un mode Rpc/HTTP full Kerberos avec Exchange 2010 !
Le principe est simple: il s'agit de permettre à Exchange de répondre au nom de service Outlook Anywhere (un nom généralement externe) et d'activer l'authentification par négociation sur les CAS (ce qui est le cas pour tous les Web Services, mais ne l'est pas par défaut pour le Rpc/HTTP).
  • Pour le premier point, il s'agit d'ajouter le Fqdn d'Outlook Anywhere au compte de service Kerberos d'Exchange (le fameux "AlternateServiceAccount") - cela se fait en utilisant SETSPN (par exemple: setspn -A HTTP/outlookanywhere.domain.com DOMAIN\AlternateServiceAccount)
  • Pour le second point, il faut configurer Outlook Anywhere sur chaque CAS afin d'utiliser le mode "NegoEx" (par exemple:  Get-OutlookAnywhere -Server MonServeurCAS1 -ADPropertiesOnly | Set-OutlookAnywhere -ClientAuthenticationMethod NegoEx -IISAuthenticationMethods Ntlm)
    • Note: la valeur "Ntlm" positionnée pour les méthodes d'authentification IIS configurera en fait le répertoire virtuel "/Rpc" en activant l'authentification intégrée Windows avec les fournisseurs suivants: "Negotiate" et "NTLM" (dans cet ordre).
  • Vous devrez ensuite créer un nouveau pool d'application dans IIS (Application Pool). Nous pouvons le nommer par exemple "MSExchangeRpcProxyAppPool" (même nom qu'Exchange 2013 :)) et utiliser les paramètres suivants:
    • IdentityType: LocalSystem
    • QueueLength: 1000 pour une infrastructure de taille moyenne, 10000 pour une infrastructure devant supporter une majorité de clients en Rpc/Http
    • ProcessModel / LoadUserProfile: False
    • ProcessModel / IdleTimeout: 0
    • Recycling / PeriodicRestart / Time: 0 (jamais)
    • Failure / RapidFailProtection: False
  • Vous devrez ensuite assigner l'Application Pool au répertoire virtuel "/Rpc" (et idéalement, au répertoire virtuel "/RcpWithCert", que nous n'utiliserons pas ici).
Une fois ces modifications effectuées, il est recommandé d'attendre quelques minutes afin que les changement soient effectivement pris en compte.
Il reste un point essentiel, voire deux:
  • Créer un "Split DNS" afin de résoudre le Fqdn d'Outlook Anywhere via un DNS interne. Cela peut se faire facilement si vous avez déjà un split DNS. Sinon, il suffit de créer une zone DNS nommé "outlookanywhere.domain.com" et de créer un enregistrement de type "A" (Host) vide en spécifiant l'adresse IP du load-balancer. La relativité du DNS fait le reste...
  • Sur la partie load-balancer ou sur les CAS si vous ne faites pas de SSL Offloading ou de SSL Briding, et si ce n'était pas déjà le cas, remplacez le certificat de manière à avoir le Fqdn d'Outlook Anywhere en "Subject Name" et les autres noms (internes) en "Subject Alternate Names". Si vous ne voulez/pouvez pas faire ces modifications, vous pouvez configurer l'Outlook Provider "EXPR" afin que le nom pour l'authentification mutuelle SSL se fasse avec le Fqdn porté par le "Subject Name" du certificat. Attention toutefois, cela impacte vos clients "externes" et le nom doit être en adéquation avec le certificat porté par le Reverse Proxy. Par conséquent, la manipulation peut s'avérer plus ou moins complexe en fonction de la configuration en place.
Il est pris l'hypothèse que vous êtes déjà capable de load-balancer le Rpc/HTTP avec une bonne affinité (par exemple, cookie applicatif "OutlookSession") ou sinon n'utilisiez pas d'affinité du tout (le composant RPCHTTP-LB le faisant pour vous côté des serveurs Exchange au prix d'une consommation CPU accrue).
Dès lors, lors du prochain démarrage d'un client Outlook 2010 SP1 et pleinement mis à jour (testé avec les mises à jour de Novembre 2012) et après avoir forcé l'Autodiscover à reconfigurer la partie Rpc/HTTP proxy (un "repair" du profil s'impose, sinon attendre au max 2 heures), le client est maintenant configuré en mode "Negotiate" et non plus "Basic" ou "Ntlm".


Une petite vérification d'impose aussi sur les tickets Kerberos (avec KLIST):



Malheureusement, je n'ai pas encore réussi à faire fonctionner l'authentification par négociation avec un client Outlook 2007 SP3, même pleinement mis à jour. Cependant le mode d'authentification est disponible dans les propriétés Rpc/HTTP d'Outlook 2007 (depuis longtemps en fait).
En effet, lorsque mon client Outlook 2007 tente de se connecter, il échoue et se connecte en Mapi/Rpc classique et la méthode d'authentification se repositionne systématiquement sur "Basic". Il semble donc qu'il ne sache pas interpréter le mode d'authentification NegoEx (ci-dessous "Nego2" dans Outlook 2010 SP1).
Démonstration:


mercredi 14 novembre 2012

[ALERTE]: Exchange Server 2010 SP2 Rollup 5

Certains d'entre vous ont pu voir que le Rollup 5 d'Exchange Server 2010 SP2 a été mis à disposition au téléchargement aujourd'hui.

ATTENTION: suite à l’installation dans mon lab, il s'avère que la mise à jour semble ne pas mettre à jour certains types/fichiers et par conséquent casse certaines fonctionnalités.

Pour l'instant, je conseille de ne pas l'installer. J'ai essayé de prévenir quelques contacts chez Microsoft au sein de la DevTeam en espérant qu'ils retirent le Rollup5 au téléchargement si le bug est avéré.

Ensuite, s'il ne s'agit que de mon lab, tant mieux, mais j'ai comme un doute... :(



mercredi 24 octobre 2012

[INFO]: Exchange/Lync/Office 2013 disponibles sur MSDN !

Déjà, nous y sommes !

Microsoft vient de mettre à disposition sur MSDN une ribambelle de nouvelles versions de leurs produits, estampillés donc "2013".

  • Exchange Server 2013
  • Lync Server 2013
  • Office Web Apps 2013
  • Office 2013 Pro Plus
  • Visio 2013
  • Project 2013
et bien d'autres !

Bon téléchargements :)

vendredi 12 octobre 2012

[INFO]: Exchange Server 2013 est RTM

Cette nuit, le DevTeam Exchange a annoncé la finalisation du code d'Exchange Server 2013, qui atteint donc son build RTM.
 
Depuis quelques mois, l'équipe Exchange a communiqué énormément sur la nouvelle version d'Exchange. Vous retrouverez l'article lié à l'annonce ici: http://blogs.technet.com/b/exchange/archive/2012/10/11/the-new-exchange-reaches-rtm.aspx

Vivement la disponibilité au téléchargement !!!

Stay tuned ;)

mardi 9 octobre 2012

[INFO]: Exchange Server 2010 SP2 Rollup 4-v2

Microsoft a publié aujourd'hui le Rollup 4-v2 d'Exchange Server 2010 Service Pack 2.
http://www.microsoft.com/en-us/download/details.aspx?id=34956

Le build est 14.02.0318.004 alors qu'il était de 14.02.0318.002 pour le Rollup 4 originel.

Pour l'instant l'article de la base de connaissance ne mentionne pas ce qui a été corrigé mais il est fort à parier qu'il concerne un certain nombre de failles de sécurité corrigées récemment par Microsoft.

Mise à jour à 23:53: l'équipe Exchange a publié l'annonce des mises à jour sur son blog.La mise à jour concerne une expiration prématurée de signature de code .NET. Au passage, la mise à jour corrige un bug mineur du moteur de recherche.

samedi 18 août 2012

[TECH]: Compter le nombre de boîtes aux lettres dans une Mailbox Database en seulement quelques millisecondes

Hier, je cherchais je-ne-sais-plus-quoi et je suis tombé sur le blog d'un collègue norvégien, nommé Jan: http://blog.powershell.no/2010/11/21/retrieve-number-of-mailboxes-per-database-in-exchange-server-2010/

Bref, je me suis mis à lire l'article et il s'avère simplement que l'auteur cherchait à savoir comment compter le nombre de BàL par Mailbox Database le plus rapidement possible...

En effet, il y a des techniques plus ou moins rapide, et plus ou moins gourmandes en mémoire. Une technique "simple" est de faire un Get-Mailbox -Database <IdentifiantDB> -ResultSize:Unlimited. Cela retourne une collection ou $null si rien n'a été trouvé.

Au demeurant, le problème majeur de cette technique est qu'elle pourrait être rapide (c'est en fait la plus rapide en utilisant juste la cmdlet Get-Mailbox) mais elle a le gros désavantage de retourner une collection d'objets: c'est lent et cela consomme de la mémoire.

Typiquement, on ferait:
([Object[]] $Mailboxes = Get-Mailbox -Database <IdentifiantDB> -ResultSize:Unlimited).Count

Et si l'on voulait compter toutes les BàL Exchange 2010 (en utilisant la même technique):
([Object[]] (Get-MailboxDatabase | Get-Mailbox -ResultSize:Unlimited)).Count

On obtiendait alors des temps pas terribles (on mesure avec Measure-Command): 35 secondes et quelques pouillemes, mon lab a 8 Databases et environ 1200 BàL. Pis: dans de gros environnments, ce type de commandes échoue systématiquement ou finit par consommer une mémoire infernale (j'ai vu des sessions Powershell à plus de 8GB parfois :p).
Alors la technique de notre ami norvégien 'Jan Egil Ring' est d'utiliser une requête LDAP et de compter le nombre d'objets ayant le 'homeMDB' égal au DistinguishedName de la Database où l'on souhaite compter. Une peu à la Exchange 2000/2003 au fond...

Cela fonctionne très bien et c'est finalement ce que fait la commande Get-Mailbox (en construisant un filtre LDAP et en requêtant l'Active Directory), mais cela prends encore "quelques" secondes (le "quelques" étant variable). D'ailleurs j'utilisais cette technique moi-même avec des résultats que je jugeais alors optimums (j'ai de bons souvenirs d'optimisations de requêtes LDAP dans une grosse forêt multi-domaines avec plus de 200 mille objets...).

Je me suis dit qu'il faisait trop chaud (36°C à l'ombre :p) pour sortir gratter dans le jardin, et me suis lancé un mini-le défit: d'optimiser encore. J'ai finalement trouvé la réponse rapidement (c'est ballot car le soleil n'a pas décliné, et il fait encore 36°C :p).

Parmi les nombreux attributs présent sur un objet Mailbox Database (msExchPrivateMDB), il en est un qui s'appelle le 'homeMDBBL'... 'BL' pour Back Link. Il s'agit donc d'un attribut construit par AD lorsque l'attribut backlinké est modifié. Ici, l'attribut backlinké est le 'homeMDB'. Tiens donc... ? Cela signifie alors que le homeMDBBL contient les DistinguishedNames des BàL de cette Database. Pratique non ? S'agissant d'un attribut multi-valué, il suffit de récupérer l'attribut 'Count' via les interfaces ADSI.

On s'apperçoit que dans la liste il y a toujours une SystemMailbox{<} car à sa création, chaque DB se voit attribuer un GUID et une BàL (rien de nouveau sous le soleil quoi, c'est comme ça depuis Exchange 2000). Bref, on constate donc que le nombre de BàL dans une Mailbox Database est donc égal à 'compte d'entrées dans homeMDBBL moins 1'.

Un petit script que l'on nommera ici Get-MailboxCount.ps1, et voici ce que cela donne (en utilisant 'Measure-Object -Sum' afin de faire la somme:
Soit 50 millisecondes !!!
  • Pas de requête LDAP
  • Interrogation de l'objet AD correspondant à la DB depuis la partition Configuration, donc disponible sur tous les Contrôleurs de Domaine
  • Attribut disponible dans le Global Catalog
  • Si l'objet (ou les objets) Database est déjà stocké dans une variable, on gagne encore quelques millisecondes puisque l'on évite le Get-MailboxDatabase...
Gros handicap toutefois, il devient compliqué d'ajouter des filtres additionels. Mais cela permet d'jà de répondre au besoin initial de compter le nombre de BàL par Mailbox Database. Et vite!

Epatant, non? :)

Vous trouverez le script en question, ainsi que bien d'autres ici: http://sdrv.ms/PtoxZo

mardi 14 août 2012

[TECH]: Let's PowerShell - Scripts d'installation des pré-requis Lync et Exchange - 2010 et 2013...

Si vous me lisez de temps en temps, vous avez probablement remarqué au travers des captures d'écran prises lors de certain tutoriels que j'utilise des scripts faits maison.

Aujourd'hui est jour de fête (ou pas...) car je mets certains de ces scripts à disposition. Rien de révolutionnaire, mais ce sont toujours (je l'espère) de bon exemples.

Scripts de préparation des pré-requis Windows pour Lync
Lync 2010: INS-LS2010-WindowsRolesAndFeatures.ps1
Lync 2013(Preview): INS-LS2013-WindowsRolesAndFeatures.ps1

Scripts de préparation des pré-requis Windows pour Exchange
Il va de soi que les scripts pour Lync 2013 et Exchange 2013 ne sont pas dans leur version définitive, même si très proche. En particulier, la partie concernant la détection du système d'exploitation Windows Server 2012 n'est pas encore finalisée, puisque la version RC est actuellement détectée comme la RTM. Cela sera changé dès que j'aurai pu installer la version RTM de Windows Server 2012, mis à jour le numéro de build en conséquence et validé le changement.

Bonus
Quelques autres scripts en vrac:
Il y a quelques utilitaires sympas (par exemple des commandes PowerShell pour l'AD et sans utiliser le module AD PowerShell de Win 2008 R2), c'est assez basique mais j'en rajouterai probablement au fur et à mesure.

Get-ADSchemaVersion.ps1
Get-ADDomain.ps1, Get-ADDomainController.ps1, Get-ADSchemaHistory.ps1

Amusez-vous bien ! Et profitez de cette fin d'été pour vous mettre à Windows Server 2012 RTM, Lync/Exchange/SharePoint 2013 Preview et Office 365 v2 Preview !!! :)

[TUTORIEL]: Comment créer vous même un répartiteur de charge avec Ubuntu Server et HAProxy

Il y a quelques mois maintenant (plus d'un an en fait!) j'avais promis à certains de publier un guide expliquant comment créer son propre répartiteur de charge (load-balancer) en utilisant Ubuntu Server et HAProxy.

Ce guide, je l'avais commencé fin 2010 dans un but purement pédagogique interne à Avanade. Devant le succès rencontré auprès de certains collègues, je m'étais réfreiné afin de conserver un peu d'avance de connaissance sur la concurrence. Au final, le sujet étant désormais pleinement maîtrisé (tout du moins en ce qui concerne "comment load-balancer Exchange 2010 ou Lync 2010" :)), je mets maintenant le guide à disposition ici.

Attention: le guide est en anglais, mais pas d'inquiétudes toutefois: c'est beaucoup de blabla au début, et pas mal de technique ensuite...


Rappel: ce guide n'est pas là pour vous éviter d'implémenter un "vrai" load-balancer. L'auteur (moi) et les personnes morales ou sociétés dont les noms figurent dans ce guide ne sont aucunement engagées ou responsable de tout problème pouvant découler de l'utilisation de ce guide.

mercredi 8 août 2012

[TECH]: Exchange 2013 Preview, IIS et Kerberos - Ou: questionnement autour du MaxFieldLength

Tous ceux ayant déjà travaillé avec IIS sur SharePoint, Exchange et Lync et ayant "joué" à activer le Kerberos le savent: dans des environnements respectables et où il y a beaucoup de groupes de sécurités, il faut configure le pilote HTTP de Windows afin de supporter des en-têtes (MaxFieldLength) et tailles de requêtes (MaxRequestBytes) supérieures à la normale.

L'article idoine de la KB Microsoft (http://support.microsoft.com/kb/820129) le dit très bien:
Et, pour Exchange Server 2010, la DevTeam avait bien prévu l'augmentation de la taille des ces deux limites au travers d'un script nommé "LargeToken-IIS_EWS.ps1" (disponible dans "$exscript"). Ce qui est intéressant ici ce n'est pas tant que l'équipe Exchange l'avait prévu (à la base il s'agit en fait d'un script créé pour des cas particuliers) mais la valeur de MaxFieldLength qui est donc à son maximum de 64Ko - 2 octets (réservés pour les deux caractères de fin de chaîne en HTTP).

La valeur configurée dans le script d'Exchange Server 2010 est donc alignée avec la base de connaissance IIS de Microsoft. Dans des environnements plus classiques, mettre 65534 pour MaxFieldLength et 65536 pour MaxRequestBytes suffit généralement à résoudre 99.99% des problèmes (Note: MaxRequestBytes doit être à minima supérieur de 2 octets à MaxFieldLength).

Bref, éviter les problèmes Kerberos... Il semblerait que cela soit la volonté de la DevTeam car dans Exchange Server 2013 Preview, on constate que ces deux valeurs sont positionnées par défaut... à 65536 ! (Au passage, on remarque que les scripts en rapport avec Kerberos n'existent plus... :))

La preuve en images:
Là où le bât blesse est que la valeur positionnée par Exchange Server 2013 dépasse le maximum théoriquement configurable. Il faudra donc effectuer quelques tests et vérifier que le pilote HTTP.SYS se comporte correctement sur les deux systèmes supportés (Windows Server 2008 R2 SP1 et +, et 2012 RTM et +). En effet, il arrive parfois qu'une valeur de registre dépassant le maximum autorisé soit traitée comme invalide et donc ignorée (et donc 16Ko ici)... si le code du pilote HTTP.SYS est bien fait, il devrait traiter toute valeur hors limites comme étant la limite (donc ici, dépassant la limite haute: 65536 est corrigé en 65534).
Fait étrange (mais probablement pas exprès :)), Lync Server 2013 ne positionne pas cette valeur. Pourtant, il est fréquent que le Remote Shell Lync ne fonctionne pas pour cette même raison (à cause de la taille du token Kerberos...) et que cela fasse planter le Lync Control Panel .
Donc, sauf erreur de ma part, et étant un puriste, MaxFieldLength devrait être positionné à 65534. Je vais tout de même tenter de prévenir la DevTeam au cas où...

dimanche 22 juillet 2012

[INFO]: Exchange 2013 Preview / Erreurs Securité (ID 4625 / Unknown logon name or password)

Au lendemain de l'installation de mon serveur Exchange 2013 Preview, j'ai remarqué que mes journaux d'évenements de sécurité se remplissaient d'échecs de type "Audit failure" / "An account failed to log on"... (EventID 4625).

Quid? Je vois que le compte qui bombarde mon serveur de demandes d'authentification (et échoue donc), est HealthMailbox4139e7ab8f1048e5a8bc51cca4ec531f@uc-previewlab.com. Le nom du compte ressemble à une adresse E-mail, certes, mais est en fait un UPN (User Principal Name). Une recherche rapide dans mon AD, et je vois que l'utilisateur existe bien. Cependant, l'UPN défini est HealthMailbox4139e7ab8f1048e5a8bc51cca4ec531f@uc-previewlab.org et non ".com".

Hier, j'ai reconfiguré le domaine SMTP par défaut à "uc-previewlab.com" ce qui a eu pour effet de changer toutes les adresses E-mail à cette extension. Il semblerait donc que l'adresse E-mail soit utilisée afin d'authentifier l'utilisateur "HealthMailbox" sans se préoccuper de savoir si elle est bien différente de l'UPN (elle l'est, la plupart du temps :)).

Bref, un coup de "domain.msc", et j'ajoute à ma forêt le suffixe UPN "@uc-previewlab.com". Je change l'UPN de la BàL HealthMailbox et quelques secondes après, les erreurs ont disparu!

Moralité: il s'agit à mon humble avis d'un bug qui j'espère sera corrigé à la sortie du produit.


Log Name:      Security
Source:        Microsoft-Windows-Security-Auditing
Date:          7/22/2012 6:34:00 PM
Event ID:      4625
Task Category: Logon
Level:         Information
Keywords:      Audit Failure
User:          N/A
Computer:      sv-e15pr-1.uc-previewlab.org
Description:
An account failed to log on.

Subject:
 Security ID:  SYSTEM
 Account Name:  SV-E15PR-1$
 Account Domain:  PREVIEW
 Logon ID:  0x3E7

Logon Type:   8
Account For Which Logon Failed:
 Security ID:  NULL SID
 Account Name:  
HealthMailbox4139e7ab8f1048e5a8bc51cca4ec531f@uc-previewlab.com
 Account Domain:  
Failure Information:
 Failure Reason:  Unknown user name or bad password.
 Status:   0xC000006D
 Sub Status:  0xC0000064

Process Information:
 Caller Process ID: 0xe68
 Caller Process Name: C:\Exchange\Bin\MSExchangeHMWorker.exe

Network Information:
 Workstation Name: SV-E15PR-1
 Source Network Address: -
 Source Port:  -

Detailed Authentication Information:
 Logon Process:  Advapi 
 Authentication Package: Negotiate
 Transited Services: -
 Package Name (NTLM only): -
 Key Length:  0