Archives de catégorie : Scripting

Gabarit de certificat pour utiliser CMSMessage de Powershell 5.0

Honte à moi. Un certificat auto-signé dans mon dernier billet. J’avoue, je l’ai écrit sur mon canapé, et uniquement survolé la page Technet avant de me rendre compte de mon impardonnable erreur. Vu que le Technet ne donne pas les spécifications du gabarit de certificat à utiliser pour ADCS, je m’y colle en pénitence.

Comme base de travail, j’ai retenu le gabarit user. Pourquoi? Car je compte limiter ce type de certificats aux seuls comptes de services membres d’un groupe spécifique. Pas besoin que tous mes systèmes disposent de ce type de certificat. En plus avec ce choix, je vais limiter l’accès à ce certificat aux seuls comptes de service et non la totalité des comptes qui peuvent accéder au magasin personnel de l’ordinateur avec des privilèges administrateur ou supérieur.

Après, vu que pour utiliser la fonctionnalité CMSMessage, il faut PowerShell 5.0, j’ai choisi de limiter les systèmes éligibles en conséquences. Pour installer de Windows Management Framework 5.0, il faut au minimum un système d’exploitation de génération Windows 7 / Windows 2008 R2.

clip_image001

Dans l’onglet général, on nomme notre nouveau gabarit de certificat « CMS Message », pas grand-chose à dire sinon que ça ne sert à rien de publier le certificat dans l’Active Directory dans notre cas.

clip_image002

Dans l’onglet « Request Handeling », une seule chose compte, la capacité à exporter la clé privée. C’est grâce à elle qu’on sera en mesure de déchiffrer notre CMSMessage.

clip_image003

Pour la construction du Subject Name, il y a eu un peu de travail. Par défaut, le gabarit de certificat était prévu pour construire l’attribut en utilisant les informations issues de l’annuaire Active Directory. Bien, mais le problème, il est rare qu’un compte de service ou même un ordinateur se voit affecté une adresse de messagerie. Pour cela, j’ai dû procéder à quelques adaptations :

  • Ne pas inclure l’adresse de messagerie dans l’attribut Alternate Subject Name
  • Ne pas inclure l’attribut E-Mail
  • Ne pas inclure le DNS Name (pas de sens pour un utilisateur)
  • Mais bien inclure un UPN

clip_image004

C’est maintenant qu’il faut introduire la subtilité. Pour que la commande Protect-CMSMessage accepte d’utiliser notre certificat, il doit avoir un rôle bien particulier. Pas de bol, il est pas dans le gabarit de certificat que nous avons utilisé comme base de travail. Qu’à cela ne tienne, on va le personnaliser.

clip_image005

Pour être sûr que notre certificat ne soit pas détourné pour un autre usage, on va faire le ménage dans les EKU et ne positionner que « Document Encryption ».

clip_image006

Maintenant, c’est mieux.

clip_image007

On approche de la fin. Ne pas limiter la capacité d’enregistrement de certificat, c’est la porte ouverte à toutes les fenêtres, des certificats délivrés à gogo sans se soucier qu’un jour il faudra les renouveler, ce qui bien sûr arrive toujours au pire moment. En limitant la capacité d’enrôlement aux seuls membres d’un groupe, on saura déjà à qui on a délivré ces certificats.

clip_image008

Y a plus qu’à publier notre gabarit de certificat et Zou, à la signature.

clip_image009

Une fois la session ouverte avec notre compte de service, on peut réaliser la demande.

clip_image010

C’est fini. Pour s’assurer que cela fonctionne, une rapide commande Powershell « Get-ChildItem Cert:\CurrentUser\My -DocumentEncryptionCert » nous confirme que nous avons bien un certificat prévu pour cet usage dans le magasin. Vu que c’est le cas, y a plus qu’à chiffrer notre message :

$Cert = Get-ChildItem Cert:\CurrentUser\My -DocumentEncryptionCert

$CMSMessage = Protect-CMSMessage -Content « Ilachangé! » -To $Cert/Thumbprint

clip_image011

 

Aller, je retourne me punir, j’ai du python sur le feu. Je ne déconne pas

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Cacher les mots de passe dans les scripts Powershell

Nous passons tous beaucoup de temps à industrialiser avec PowerShell. Il n’est pas rare que je retrouve les mots de passe codés en dur dans les scripts. Pour éviter ces dérives, j’ai compilé dans ce billet quelques méthodes pour cacher ces mots de passe, du plus simple, au plus sexy

En PowerShell, la gestion des credentials est quelque chose que nous semble très simple. On sait tous que l’on peut « sécuriser » les mots de passe avec le fameux ConvertTo-SecureString. Le problème, c’est que cette fonction est réversible avec la méthode « Get-NetworkCredential ». Pour vous donner une idée, une rapide démonstration :

clip_image002

Le problème, c’est que dans l’exemple ci-dessous, PowerShell utilise Windows Data Protection API (DAPI). Cela signifie que seul le même compte est capable de chiffrer/déchiffrer notre secret. Stocker l’information dans un fichier ou dans le registre. On va devoir ruser pour ne pas utiliser une clé de chiffrement locale au système d’exploitation. Si on creuse un peu la commande ConvertFrom-SecureString, on trouve deux paramètres intéressants :

clip_image004

Donc si on utilise une clé externe de taille assez grande, on devrait être capable de chiffrer nos données en étant indépendant du système d’exploitation. Commençons par chiffrer notre information avec notre nouvelle clé.

$ScriptPath = (Split-Path -parent $MyInvocation.MyCommand.Definition)

[Object] $Cred = $null

[Guid] $Key = « e8bdc7c5-a62c-4fa3-9228-5abe22488141 »

[String] $CredFile = « $ScriptPath\CredData.ps1xml »

if ( $Cred -isnot [System.Management.Automation.PSCredential] )

{

[Object] $Cred = (Get-Credential -Message « Service Account »)

[Object] $CredData = $Cred | Select-Object -Property UserName,@{Name= »SecurePassword »; Expression={ ConvertFrom-SecureString -SecureString $_.Password -Key $Key.ToByteArray() }}

$CredData | Export-CliXml -Path $CredFile -Encoding Unicode -Force

Remove-Variable -Name CredData -Force

}

Get-Content $CredFile

clip_image006

Logiquement, on doit pouvoir faire l’inverse facilement avec le script suivant :

$ScriptPath = (Split-Path -parent $MyInvocation.MyCommand.Definition)

[Guid] $Key = « e8bdc7c5-a62c-4fa3-9228-5abe22488141 »

$CredFile = « CredData.ps1xml »

[Object] $CredData = Import-CliXml -Path ($ScriptPath + »\ » + $CredFile)

if ( $? )

{

$SecurePassword = ConvertTo-SecureString -String $CredData.SecurePassword -Key $Key.ToByteArray()

$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($CredData.UserName, $SecurePassword)

$Credential.GetNetworkCredential() | Format-Table *

}

clip_image008

Note : On m’a fait remarqué cette semaine que cela aurait été encore mieux d’utiliser le paramètre « -SecureKey ». Notre clé aurait alors été encodée dans un System.Security.SecureString. Merci Sylvain.

Le problème, c’est que ma clé est lisible dans le script. Ce qu’il faudrait, c’est de pouvoir la disposer d’un mécanisme me permettant de chiffrer des données avec une clé qui soit reconnue d’autres systèmes mais qu’on ait pas besoin de la même clé. Un truc comme une clé asymétrique. Chiffrer des données avec un certificat, c’est utiliser la clé publique pour cela. Pour déchiffrer, on aura besoin de la clé privée. Nous allons avoir besoin d’un certificat qui devra être présent :

  • Sur le système qui assure le chiffrement du message (en l’occurrence un mot de passe)
  • Sur les systèmes qui devront accéder à cette information

Cela implique que le certificat que nous allons demander devra être :

  • Reconnu comme issu d’une autorité de certification reconnue de toutes les parties
  • Être exportable

Ces points techniques résolus, attaquons nous au chiffrement de notre message avec quelques lignes de PowerShell :

$cert=Get-ChildItem Cert:\LocalMachine\my | where {$_.Subject -like « CN=Powershell Authentification* »}

$Password = ‘Il a changé!’

$EncodedPassword = [System.Text.Encoding]::UTF8.GetBytes($Password)

$EncodedBytes = $Cert.PublicKey.Key.Encrypt($EncodedPassword, $True)

$EncryptedPassword = [System.Convert]::ToBase64String($EncodedBytes)

clip_image010

Quelques explications s’imposent. On commence par localiser le certificat que nous allons utiliser et encoder notre mot de passe au format UTF8. Ceci-fait, on encode notre mot de passe à l’aide de la clé publique de notre certificat et con convertit le tout en Base 64. Ca ressemble plus du tout à notre mot de passe. On peut communiquer cela tel que, aucun risque que cela puisse être décodé sans la privée. Justement, allons voir comment décoder cela sur un autre système avec un peu de PowerShell :

$cert=Get-ChildItem Cert:\LocalMachine\my | where {$_.Subject -like « CN=Powershell Authentification* »}

$Encryptedcontent = Get-Content .\secret.txt

$Encryptedcontent

$EncryptedBytes = [System.Convert]::FromBase64String($Encryptedcontent)

$DecryptedBytes = $Cert.PrivateKey.Decrypt($EncryptedBytes, $True)

$DecryptedPassword = [System.text.Encoding]::UTF8.GetString($DecryptedBytes)

clip_image012

Si on a compris la logique, on commence par reconvertir notre contenu en une chaine de caractères pour laquelle on va utiliser la clé privée de notre certificat pour déchiffrer notre message. L’avantage de cette approche est qu’elle est indépendante du système d’exploitation, même Cross-Plateforme. Autre avantage, on peut limiter l’accès à la clé privée. Il faut juste décider qui à accès à la clé privée.

clip_image014

Ça c’était bien avec les vieilles versions de PowerShell, ça fonctionne super, même avec Orchestrator, c’est pour dire, … On ne peut pas faire plus sexy avec des versions plus récentes ? Oui, car depuis la version 5.0, on dispose de la fonctionnalité CMSMessage. L’aide intégrée de PowerShell ne vas pas vous aider beaucoup.

clip_image016

Avec la version en ligne de Protect-CMSMessage, c’est déjà mieux. On utilise toujours un certificat, sauf que cette fois, notre certificat devra comprendre l’EKU « Document_Encryption » pour qu’on puisse l’utiliser avec la commande Protect-CMSMessage. J’ai donc préparé une demande de certificat en bonne et due forme ou presque. En fait, ce sera un certificat auto-signé (j’ai fait court pour la démonstration).

clip_image018

Au passage, un switch bien pratique que je ne connaissais pas pour filtrer les certificats : Get-ChildItem Cert:\CurrentUser\My -DocumentEncryptionCert

En une seule commande on va être capable de chiffrer notre message : $Message = Protect-CmsMessage -Content $Password -To « *benoit@simplebydesign.fr ». Après, y a plus qu’à empaqueter et transmettre.

clip_image020

De l’autre côté, même principe. On commence par localiser le certificat que nous allons utiliser pour déchiffrer à l’aide de la commande Get-ChildItem Cert:\CurrentUser\My DocumentEncryptionCert. Reste plus qu’à déchiffrer.

clip_image022

Jusque-là, on parlait On-Premises, Old-School IT. Et si on regardait comment faire de même dans Azure. Y a forcément un service pour cela. Oui, C’est Azure Key Vault. Avant cela, faut un peu préparer le terrain. On peut faire cela en PowerShell assez rapidement :

Install-Module AzureRM

Install-AzureRM

clip_image024

Justement, le dernier installé nous intéresse. Continuons notre mise en place, on y reviendra. Continuons avec l’installation du module PowerShell Azure, chargeons tous les modules Azure Resource Managers et celui d’Azure avec les trois commandes suivantes :

Install-Module Azure

Import-AzureRM

Import-module Azure

clip_image026

La première étape d’Azure, c’est l’authentification. Ça se règle en deux commandes PowerShell :

$Cred = get-Credential

Login-AzureRMAccount -Credential $Cred

clip_image028

La commande Get-AzureRMSubscription nous indique que j’ai accès à plusieurs souscriptions. Nous allons nous fixer sur l’une d’entre elle.

clip_image030

Les prérequis sont en place. Nous devons mettre en place notre Azure Key Vault au sein d’un groupe de ressources dédié (sécurité oblige)

New-AzureRmResourceGroup -Name ‘MyKeyVault’ -Location ‘North Europe’

New-AzureRMKeyVault -VaultName ‘MesPrecieux’ -ResourceGroupName ‘MyKeyVault’ -Location’North Europe’

clip_image032

A noter que lors de la création, il faudra prouver son identité. A ce niveau, nous sommes le seul à y avoir accès via l’URL suivante : . Stockons notre mot de passe avec les commandes PowerShell suivantes :

$Password = « Ilachangé! »

$SecretValue = ConvertTo-SecureString $Password -AsPlaintext -Force

Set-AzureRMKeyVaultSecret -VaultName ‘MesPrecieux’ -Name « Password » -SecretValue $SecretValue

clip_image034

Nous pouvons vérifier que nous avons bien un secret dans notre coffre aux précieux :

Get-AzureKeyVaultSecret -VaultName ‘Mesprecieux’

clip_image036

Jusque-là, ça casse pas trois pattes à un canard. Montons un peu le niveau. Si on a un coffre-fort pour nos secrets, la moindre des choses, ce serait de pouvoir retrouver l’historique de notre mot de passe, voyons le résultat de la commande Get-AzureKeyVaultSecret -VaultName ‘Mesprecieux’ -Name ‘Password’ -IncludeVersions.

clip_image038

La ça devient intéressant. Non seulement, on a l’historique des valeurs mais on peut aussi filtrer pour utiliser le dernier disponible. Voyons comment retrouver la dernière version de notre mot de passe :

$liste = get-AzureKeyVaultSecret -VaultName ‘Mesprecieux’ -Name ‘Password’ -IncludeVersions

$Password = $liste | Sort-object -property updated -Descending | select -first 1

$secret = get-AzureKeyVaultSecret -VaultName ‘Mesprecieux’ -Name ‘Password’ -Version $password.Version

$Secret | Get-member

$Secret.SecretValue

$Secret.SecretValueText

clip_image040

Nous avons retrouvé le dernier mot de passe associé. Entre temps, il a été changé (sécurité oblige). OK, c’est pas mal. Le problème, c’est de partager nos secrets. La, Azure Key Vault fait fort car grâce à Azure Resource Manager, on peut déléguer l’accès. La commande ci-dessous délègue l’accès à un utilisateur, uniquement pour lire le contenu de mon coffre.

Set-AzureRmKeyVaultAccessPolicy -VaultName ‘MesPrecieux’ -UserPrincipalName ‘test@XXXXXXXXXX.onMicrosoft.com’ -PermissionsToSecrets ‘Get’

Get-AzureRmKeyVault -VaultName ‘mesprecieux’

clip_image042

Après, j’aurai pu pousser le vice de déléguer uniquement l’accès à mon mot de passe. On peut même autoriser des applications à accéder aux précieux.

Pour les amateurs, quelques lectures supplémentaires :

 

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Un peu de magie avec la QoS Windows

A la base, la fonctionnalité des « Offline Files » est une bonne idée. Le problème, c’est quand on tente de dépasser les limites de nos tuyaux réseau. La volonté de centraliser les données des utilisateurs va rapidement saturer le réseau WAN, c’est ce qui est arrivé à un de mes clients. La situation était telle que les applications métiers devenaient difficile à utiliser à cause de la bande passante consommée pour la synchronisation des données. Un vrai casse-tête, qui a conduit ce client à bloquer le trafic SMB à destination des partages contenant les « Offline Files » en central.

Problématiques posées

Voilà un challenge intéressant. On a beau retourner le problème dans tous les sens, il faudra bien réintroduire le service. C’est pas sans poser quelques problèmes :

  • Réintroduire la fonctionnalité c’est assurément atomiser le réseau. Plus on va attendre, plus les utilisateurs auront accumuler des données à synchroniser
  • Plus on tarde, plus on prend le risque de la perte de données en cas de perte du poste de travail.
  • Les performances du réseau WAN ne sont pas extensibles, rien n’interdit un utilisateur de vouloir synchroniser des Go de données.
  • La dispersion géographique des utilisateurs était pour mon client un véritable problème. Plus de 200 implémentations géographiques avec des utilisateurs essentiellement nomades

 

La solution ne pouvant pas venir de la fonctionnalité « Offline Files », on a donc commencé à chercher ailleurs. Mon premier réflexe a été d’aller faire un tour dans mon éditeur local de stratégies de groupes pour voir si une des nombreuses fonctionnalités natives de Windows ne pourrait pas nous aider. Effectivement, Windows sait faire de la QoS réseau.

clip_image001

 

Si on regarde la fonctionnalité de plus près, c’est pas mal du tout. A la base, cela permet de tagger les flux réseau qui sortent du poste de travail pour que les équipements réseau puissent y associer une politique de QoS. Moins connu, il est aussi possible de maitriser le bande passante consommée directement depuis le poste de travail. En voilà une bonne idée. Techniquement oui mais au final, c’est une fausse bonne idée. Avec plus de 200 implémentations géographiques, c’est autant de situations différentes. Avec les GPO, cela reviendrait à mettre en place autant de stratégie de groupe que d’implémentations géographiques. Après, la fonctionnalité de QoS ne traite réellement que les flux sortants du poste de travail, pas les flux entrants. Lorsqu’on regarde dans la configuration avancée, on constate qu’on ne dispose pas du même niveau de finesse.

clip_image002

 

C’est une politique est globale, pour tous les flux entrants. Le tableau ci-dessous documente la QoS :

Niveau

QoS

0 64Kb
1 256Kb
2 1Mb
3 16Mb

 

La QoS de Windows a aussi ses limites. Si en face le serveur de fichiers avait été un serveur Windows, on aurait pu aussi utiliser la QoS de la même manière. Vu que ce n’était qu’un simple NAS, il ne disposait pas de la fonctionnalité. Dans la pratique, cela va nous poser quelques problèmes :

  • Si un utilisateur ouvre une session sur un poste de travail qui n’est pas le sien, on ne pourra pas maitriser la copie des fichiers
  • Si un utilisateur se voit doté d’un nouveau poste de travail, même punition

 

Malgré ces limitations, j’ai continué mon exploration de la QoS. Certes elle a ses limites mais on peut déjà l’utiliser pour maitriser le flux sortant à destination du NAS. Fallait juste trouver un moyen d’industrialiser un peu tout cela. Quand on pense, industrialisation, on pense rapidement à Powershell. Bingo, je me souviens maintenant qu’il existe un module Powershell introduit avec Windows 8 et Windows 2012. Un peu de recherche et effectivement, le module NetQoS existe bien. Plus important, il existe bien sur le socle Windows 8 de mon client.

clip_image003

 

Une idée commence à germer. Et si on pouvait industrialiser la mise en place d’une politique de QoS au niveau des postes en fonction de sa situation réseau. En voilà un beau challenge. Faisons quelques expériences :

New-NetQosPolicy « Synchro NAS » -NetworkProfile Domain -DSCPAction 40 -DestinationIpAddress <Adresse du mon NAS> -IPProtocol TCP -IPSrcPort 445 -ThrottleRateActionBitsPerSecond 1Mb

clip_image004

Globalement, on dit à Windows de mettre en place une politique de QoS pour limiter le trafic SMB à destination du NAS uniquement pour le cas où la connectivité réseau est de type domaine (pare-feu). Pour vérifier si cela fonctionne, faut des gros fichiers. J’ai créé le script PowerShell suivant :

$Path = « c:\testFile.Txt »

$File = [IO.File]::Create($path)

$File.Setlength(1Gb)

$File.Close

Get-Item $Path

clip_image005

 

OK, 1Mbits, c’est juste un peu trop hardcore, on va passer à 2Mbits en reconfigurant la policy avec la commande PowerShell suivante :

Set-NetQosPolicy -name « Synchro NAS » -ThrottleRateActionBitsPerSecond 2Mb

clip_image006

 

Maintenant, faut des chiffres et prouver que cela fonctionne. Par expérience, l’explorateur Windows, c’est pas fiable. Le petit script PowerShell ci-dessous devrait nous aider :

cls

$startdate = get-date

Write-host « Début de test de copie d’un fichier de 1Go sur un share SMB $(Get-date) »

Copy « C:\Temp\TESTFILE.TXT » « \\<Adresse IP destination>\partage$\Datas\\TESTFILE.TXT » -Force

Write-host « Fin de test de copie d’un fichier de 1Go sur un share SMB $(Get-date) »

$enddate = get-date

Write-Host (New-TimeSpan -Start $startdate -End $enddate).TotalSeconds

clip_image007

 

A quand même, 1217 secondes pour copier mon fichier de 1Go. Au passage, je suis sur un portable en config « Full patate » avec connexion réseau Gigabit et SSD. Sceptique? Peut-être que le gestionnaire de tâche sera plus parlant alors.

clip_image008

 

Oui, il y a des pics de consommation mais ils sont régulés automatiquement. Tentons la même expérience avec une QoS à 5Mb.

clip_image009

 

Déjà, ça va mieux, que 503 secondes. Logiquement avec une QoS à 10Mb, on devrait être deux fois plus rapide, bingo.

clip_image010

 

Avec une QoS à 25Mb, on arrive à 103 secondes. Pour information, sans aucune QoS, le temps de copie de référence est de 42 secondes.

clip_image011

 

Donc, c’est industrialisable. Maintenant, les derniers détails :

  • Comment industrialiser la configuration?
  • Comment centraliser le paramétrage?

 

Comment industrialiser la configuration?

La y a pas 36 solutions. On a vu que les GPO, c’était pas possible. Il faut donc travailler au plus proche du poste. Un script de démarrage exécuté par GPO? Oui mais il ne s’applique que lorsqu’on démarre le système d’exploitation, pas quand l’ordinateur sort de veille. Très logiquement, ce sont les tâches planifiées qui se sont imposées, surtout quand on sait qu’on peut les déclencher quand on en a besoin :

  • A l’ouverture de session
  • Au déverrouillage de session
  • Après période d’activité
  • Sur détection d’un évènement dans les journaux d’évènements

OK pour exécuter un script PowerShell via tâche planifiée mais sous quel contexte? Faudra bien un compte de service, qu’il faudra maintenir. Oui mais c’est pas moi qui vais maintenir ce compte de service. Mon client utilisant Windows 8 sur ses postes de travail, l’utilisation de Group Managed Services Accounts alias GMSA s’impose. Avec Windows 8, ce qui est cool, c’est qu’on peut utiliser ce type de compte pour les tâches planifiées : Windows Server 2012: Group Managed Service Accounts.

 

Comment centraliser le paramétrage?

On sait comment configurer, reste le paramétrage. Un rapide cahier des charges s’impose :

  • Faut que ce soit facile à maintenir et faire évoluer (Que celui qui a proposé une base SQL lève la main, …)
  • Faut que ce soit léger sur le réseau
  • Faut qu’on puisse le faire évoluer rapidement pendant le développement
  • Enfin, toujours respecter la règle de base : Simple by Design

 

OK, on aurait pu développer un Web Service qui délivre la configuration mais c’est un peu too much. On va se contenter d’un simple fichier XML.

clip_image012

 

Effectivement, un fichier XML, c’est simple à maintenir, facile à faire évoluer et ça pèse pas trop lourd sur le réseau. En plus, c’est super simple à utiliser dans le script Powershell que nous exécutons dans notre tâche planifiée.

 

Le tour de magie

Le tour de magie, c’est donc un script Powershell, exécuté dans le contexte d’un compte de service dont nous n’avons pas à maintenir le mot de passe. Ce script va récupérer sa configuration en central dans un partage SMB pour conserver une copie locale en cas d’impossibilité d’accéder au partage. Le script va exploiter le fichier XML pour mettre en place des politiques de QoS pour tous les cas d’usage (interne, externe, VPN …).

clip_image013

 

Au final, ça donne cela.

clip_image014

 

A chaque ouverture de session, déverrouillage de session ou même changement d’état de la connectivité réseau, la politique de QoS est automatiquement adaptée. Donc même en sortie de veille, on s’adapte.

Et maintenant?

Maintenant, le client est en mesure de proposer une politique de QoS pour chaque implémentation géographique. Au début, il va positionner la QoS à une valeur très basse, (genre 1Mb) pour augmenter progressivement jusqu’à trouver le point d’équilibre entre la synchronisation des fichiers des utilisateurs et les applications métiers.

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Kit de survie Scripting Microsoft Azure IAAS

Nouvelle année qui arrive, nouvelles résolutions. Adapté au Geek que je suis, Azure est ma résolution de l’année, que ce soit le grand frère (Microsoft Azure) ou son petit frère (Windows Azure Pack). Pour l’un ou l’autre, on a toujours besoin du module PowerShell "Microsoft Azure". Lorsqu’on ne l’a pas sous la main, y a plusieurs moyens. Le problème, c’est qu’il est mis à jour régulièrement pour intégrer les nouvelles fonctionnalités et que loi de Murphy oblige, c’est à ce moment là qu’on aurait bien besoin de la dernière version et qu’on se trouve privé de connexion Internet qui poutre pour ne pas attendre. passons en revue les différentes possibilités :

  1. La section downloads de Microsoft Azure
  2. Le GITHUB Microsoft Azure
  3. La solution du Geek
  4. La solution du Geek fainéant

Le premier choix est sympa mais un peu lourd. Au moment où j’avais besoin de l’installer j’étais dans une gare SNCF avec une connexion 3G asthmatique (loi de Murphy!). Si j’avais essayé avec la machine virtuelle Windows 7 que j’avais sous la main, je pense que j’y aurait passé beaucoup de temps, le coup à louper son train. En plus, je ne voulais faire que du IAAS, pourquoi aurais-je besoin d’avoir les outils de développement? Un simple ISE PowerShell est c’est partit.

Le second choix était jusqu’à peu ma solution. On y trouve directement le package MSI à installer, parfait pour installer sur ma machine virtuelle. Sauf que dans mon cas, ma machine virtuelle va certainement nécessiter quelques prérequis avant installation vu que c’est un template de Windows 7 qui trainait sur mon portable. Le Geek que je suis ne peut donc pas jouer avec les dernières features de Microsoft Azure. Un Geek sans nouveau jouet, c’est un Geek en manque, surtout à l’approche de Noël. C’est dangereux un Geek en manque.

Mon train étant annoncé en retard, j’ai donc décidé d’explorer une troisième voie, celle du Geek. Pour ceux qui ont osé entrer dans la salle des tortures de Windows Azure Pack, ils ont découvert que le Web Plateform Installer pouvait être utilisé de manière plus intelligente. L’interface graphique se contente juste d’utiliser un fichier XML. Donc on doit pouvoir exploiter cette liste avec la commande "WEBPICMD.EXE /List /ListOption:Available" comme illustré ci-dessous :

clip_image001

 

Donc si on connait le nom du package que l’on veut installer (WindowsAzurePowershellOnly dans mon cas), on peut aller direct à l’essentiel avec la commande "Webpicmd.exe /offline /Products:"WindowsAzurePowerShellOnly" /Path:"F:\Sources".

clip_image002

 

Ce qui est bien, c’est qu’il va aussi télécharger les packages dépendant. Pour certains d’entre eux on ne comprend pas trop ce qu’ils ont de dépendant avec le package demandé mais pour d’autres ça va me sauver la vie vu que mon template de machine virtuelle Windows 7 est un peu ancien. Par contre, il a quand même été nécessaire de downloader 346Mo pour qu’enfin commence le téléchargement de mon package de 13Mo. Bref, c’est bien pour se constituer un kit de survie mais pas optimum quand on est dans l’urgence (Finalement le train serait à l’heure).

clip_image003

Il nous reste donc la quatrième solution, celle du Geek fainéant, à savoir de se créer une machine virtuelle dans Azure depuis le portail et de reproduire la méthode du Geek directement depuis Microsoft Azure. La plus de problème de download, ma machine virtuelle de développement est toujours à portée de main. C’est maintenant ma nouvelle méthode.

Avec un Share SMB créé avec Azure File, je peux facilement récupérer mes scripts et continuer à scripter en attendant mon train. A moi les joies du scripting Azure dans le TER, à scripter entre les gares et lancer les déploiements lors des nombreux arrêts.

BenoîtS – Simple and secure by design but Business compliant (with disruptive flag enabled)

Identifier les GPO préparées pour ADMPWD

Dans la série ADMPWD, une petite problématique d’exploitation. Le commandlet Powershell propose la commande Register-ADMPWDWithGPO permet de référencer le Client-Side extension lié à ADMPWD. techniquement, la commande se contente de configurer l’attribut ‘gpcmachineextensionnames’ avec le bon contenu : L’identifiant du Client-Side Extension d’ADMPWD.

 

C’est bien mais comment vérifier que c’est bien fait? Pour cela, il faut faire le travail nous même. le script ci-dessous permet de rechercher parmi toutes les GPO celles pour lesquelles l’attribut ‘gpcmachineextensionnames’ a été configuré pour ADMPWD.

$allGPOs = ([adsisearcher]'(objectCategory=groupPolicyContainer)’).FindAll()

$allGPOs | ForEach-Object {

    if ($_.Properties.gpcmachineextensionnames -ne $null)

    {

        $content = $_.Properties.gpcmachineextensionnames

        If ($content -match ‘{D76B9641-3288-4f75-942D-087DE603E3EA}{D76B9641-3288-4f75-942D-087DE603E3EA}]’)         

{

            $_.Properties.displayname

        }

    }

}

BenoîtS – Simple and secure by design but business compliant

MS14-025: Vulnerability in Group Policy Preferences could allow elevation of privilege

Les GPO de préférences sont une évolution intéressante des GPO introduite avec Windows 2008. Cependant, il y a une petite faiblesse que Microsoft a enfin corrigé. Les GPO de préférences peuvent être utilisées pour créer/ mettre à jour des comptes de services sur les systèmes gérés. Problème, il faut bien stocker le mot de passe dans la GPO. Avec un peu de recherche dans le répertoire SYSVOL d’une GPO utilisant la fonctionnalité incriminée, on trouve le fichier GROUPS.XML :

INITIALDISCLOSE

Déjà en 2009, l’équipe Group Policy reconnaissait que les mots de passe manipulés par les GPO de préférence étaient plus “masqués” que “chiffrés” et qu’il fallait bien évaluer le risque. A la vue de l’illustration ci-dessus, on pourrait penser que le mot de passe est bien chiffré. Vrai, il est chiffré en AES 256 et faux car la clé est disponible sur le MSDN. Pour vous en convaincre, exécutez le script Get-SettingsWithCPassword.ps1 mis à disposition avec la KB2962486 (il faut toujours lire un KB jusqu’au bout).

DISCLOSE1

Dans l’illustration ci-dessus le script a identifié une GPO avec un mot de passe masqué. Il a juste été nécessaire d’accéder à mon répertoire SYSVOL ou a une sauvegarde des GPO. Pour rappel toute GPO est librement accessible en lecture par défaut. 

Installer la KB2962486 ne fait que bloquer l’usage de la fonctionnalité, cela ne fait pas le ménage à votre place (d’ou l’intérêt de lire une KB jusqu’au bout). Le problème, c’est qu’il y a des développeurs Powershell talentueux qui ont développé des scripts plus complet, voire même trop  :

FINALDISCLOSE

Dans l’exemple ci-dessus, le script va jusqu’à révéler le mot de passe associé au compte “SECOURS_ADM”. Pour rappel, cette information est en libre accès (sauf si on retire le droit “read” sur la GPO pour les utilisateurs).

Que fait la KB alors? Ben elle corrige l’interface d’édition des stratégies de groupe de préférence pour nous empêcher d’utiliser la fonctionnalité.

NEW

C’est bien mais pour cela, il faut s’assurer de patcher tous les systèmes sur lesquels un administrateur utilisera l’éditeur de stratégies de groupes pour manipuler son contenu. Cela implique donc de patcher :

  • Les contrôleurs de domaine (GPMC est nativement installé)
  • Les serveurs membres (GPMC est potentiellement installé)
  • Les stations de travail (GPMC peut être installé si les RSAT sont installés)

 

En conclusion :

  • Abandonnez immédiatement l’utilisation des GPO de préférence pour manipuler les comptes & mots de passe
  • Faites la chasse aux stratégies de groupe utilisant cette fonctionnalité
  • Installez le correctifs sur tous les systèmes ou GPMC est potentiellement installé (pour éviter qu’un Administrateur ne recréé une GPO de préférence avec un mot de passe)
  • Formez vos Admins pour ne plus utiliser cette fonctionnalité!

 

Enfin, si c’est pour gérer le mot de passe Administrateur local de vos stations de travail, la solution ADMPWD est faite pour cela.

 

BenoitS – Simple and Secure by Design but Business compliant

Windows Command reference

Powershell est certainement l’avenir du scripting. Pourtant, celui-ci présente encore certaines lacunes. Comment manipuler des objets de sites avec le commandlet Active Directory? Il arrive encore souvent qu’ou doive encore faire référence aux bon vieux exécutables mis à disposition dans Windows pour les intégrer dans nos scripts PowerShell.

Pour cela encore faut-il qu’on connaisse l’existence de ces exécutables et savoir à quoi ils servent. Pour adresser cette problématique, Microsoft vient de mettre à disposition un fichier CHM présentant tous ces outils avec les syntaxes associées.

Benoits – Simple and Secure by Design  but Business compliant.

Technet Script Center Gallery

Pour ceux que le scripting intéresse, Microsoft vient de mettre en ligne la “Technet Script Center Gallery”. Globalement, c’est une bibliothèque de tous les scripts développés par Microsoft mais aussi par la communauté (Il est même possible d’en soumettre).

 

Tous les domaines du scripting sont abordés ainsi que les langages (VBScript, PowerShell, …). Bref, un lien à conserver précieusement pour éviter de passer son temps à redévelopper la roue.

 

Benoîts – Simple and Secure by Design (J’insiste sur le Secure)

Une librairie PowerShell pour Hyper-V

Pour ceux qui ne peuvent mettre en œuvre SCVMM pour gérer Hyper-V, on constate que Microsoft n’a pas donné grand chose pour scripter son administration. Si WMI ne vous rebute pas, vous pouvez toujours vous orienter vers le site web MSDN de Microsoft pour y trouver les API mises à disposition par Microsoft. Mais alors pourquoi pas de provider PowerShell?

 

Heureusement, un certain James O’Neill a eu la bonne idée de développer une librairie PowerShell pour gérer Hyper-V. Il est disponible sur CodePlex chez Microsoft à cette adresse.

 

Maintenant, plus d’excuse pour ne plus utiliser Hyper-V dans un environnement de production.

 

BenoîtS- Simple and Secure by Design (J’insiste sur le Secure)

Comment détecter UAC dans les VbScript?

Je suis actuellement sur un développement VBScript autour de Windows Server 2008 et j’ai bloqué sur une question propre à Windows. Mon script refusait de fonctionner s’il n’était pas exécuté avec un jeton de sécurité complet. UAC me bloquait.

 

Question : Comment détecter que mon jeton de sécurité dispose bien de tous les privilèges? La réponse, je l’ai trouvé dans un billet sur le blog de John Howard “Senior Program Manager”, plus précisément spécialiste d’Hyper-V : How to detect UAC elevation from VBScript. Comme quoi on a toujours besoin du bon vieux “WHOAMI”.

 

Grand merci monsieur John Howard, car là je séchais complètement.

 

BenoîtS – Simple and Secure by Design (J’insiste sur le Secure)