Déployer Juniper vMX sur ESXi n'est pas plug-n-play et demande quelques manipulations manuelles.
vMX demande la mise en place de plusieurs réseaux isolés :
J'ai modifié les paramètres de sécurité pour ne pas être limité lors de mes séances de test mais ce n'est pas obligatoire.
Afin d'avoir un accès OOB à VCP, on activera un port série. L'accès se fait par telnet sur l'hôte ESXi. Par défaut, cet accès est bloqué par le pare-feu de ESXi, on commence par l'activer :
On peut ensuite commencer le déploiement de l'OVA fourni par Juniper :
Enfin, on ajoute le port série :
Aucun autre paramêtre n'a besoin d'être modifié.
VCP est déployé, on peut démarrer la machine virtuelle. Sur mon hôte de laboratoire, le démarrage est un petit peu long mais au bout de quelques minutes, on arrive au prompt :
Une fois la machine déployée, il faut modifier sa configuration pour ajouter des resources :
On peut maintenant démarrer la machine VFP, l'arrivée au prompt devrait être assez rapide :
Une fois les deux machines démarrées, on peu se connecter au port série de VCP avec :
$ telnet esxi-host 12323
Trying esxi-host...
Connected to esxi-host.
Escape character is '^]'.
FreeBSD/amd64 (Amnesiac) (ttyu0)
login: root
Last login: Sun Jul 4 12:11:27 on ttyu0
--- JUNOS 18.2R1.9 Kernel 64-bit JNPR-11.0-20180614.6c3f819_buil
root@:~ # cli
root>
On peut vérifier que la communication avec VFP se fait bien :
root> show chassis fpc
Temp CPU Utilization (%) CPU Utilization (%) Memory Utilization (%)
Slot State (C) Total Interrupt 1min 5min 15min DRAM (MB) Heap Buffer
0 Online Testing 13 0 11 9 4 2047 7 0
root> ping 128.0.0.16 routing-instance __juniper_private1__
PING 128.0.0.16 (128.0.0.16): 56 data bytes
64 bytes from 128.0.0.16: icmp_seq=0 ttl=64 time=0.153 ms
64 bytes from 128.0.0.16: icmp_seq=1 ttl=64 time=0.153 ms
^C
--- 128.0.0.16 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.153/0.153/0.153/0.000 ms
Et que les ports de communications sont prêts :
root> show interfaces terse ge-*
Interface Admin Link Proto Local Remote
ge-0/0/0 up up
ge-0/0/1 up down
ge-0/0/2 up down
ge-0/0/3 up down
ge-0/0/4 up down
ge-0/0/5 up down
ge-0/0/6 up down
ge-0/0/7 up down
ge-0/0/8 up down
ge-0/0/9 up down
Il ne reste plus qu'à configurer le routeur !
J'ai découvert il y'a quelques mois Chocolatey et son compagnon BoxStarter, solution de déploiement d'environnements Windows.
Aussi utiles que soient ces applications, j'ai rencontré deux problèmes lors de leur utilisation:
L'idée était également de pouvoir héberger les paquets sur mon portable (sous Linux) et configurer des VM Windows sans avoir à démarrer une machine Windows au préalable. J'ai donc effectué un travail d'ingénierie inverse pour reproduire le comportement du serveur NuGet en Python. Le résultat s'appelle Chocorepo et est disponible ici.
Si vous souhaitez utiliser Chocorepo, gardez en tête qu'il n'a pas été développé pour être utilisé en environnement hostile et est proposé sans aucunes garanties
Chocorepo est développé en Python. Il utilise plusieurs modules dont WSGI pour la gestion des requètes HTTP et Pyslet pour la gestion du protocole OData.
La bibliothèque Pyslet possède l'avantage de masquer une grande partie de la "plomberie" qui doit être mise en place pour offrir un service OData. Il suffit de lui fournir un fichier de méta-données (fichier XML) et de définir des classes pour chaque fonctions que l'on souhaite proposer, Pyslet s'occupe de gérer les appels et les réponses.
Pour Chocolatey, le fichier de méta-données se trouve à l'adresse https://chocolatey.org/api/v2/$metadata.
Chocorepo utilise une base de données SQLite3 pour stocker les informations à propos des paquets disponibles (nom, version, description, auteur, etc.). Les fichiers de base de données sont créés à partir du fichier de méta-données s'ils n'existent pas. Par défaut, les fichiers s'appellent dbrepo.db (qui contient la liste des paquets et les informations associées) et dbstream.db (qui contient une copie du fichier .nupkg de chaque paquet disponible).
Chocorepo a été développé pour offrir son service derrière un proxy Nginx et il écoutera les requètes sur http://127.0.0.1:8080/ (modifiable grâce aux variables SERVICE_PORT et SERVE_ADDRESS du fichier repo.py).
L'installation de Chocorepo est simple et se fait en 4 étapes :
Récupération des sources de Chocorepo :
$ git clone https://github.com/ledeuns/chocorepo
Récupération du fichier de méta-données :
$ curl -o metadata.xml https://chocolatey.org/api/v2/\$metadata
Configuration de Chocorepo en éditant les variables SERVICE_PORT, SERVICE_ROOT et SERVE_ADDRESS au début du fichier repo.py. SERVICE_ROOT est la plus importante car elle est utilisée par le client NuGet pour localiser les fichiers de description .nupkg.
Lancement de Chocorepo :
$ python repo.py
La configuration de Nginx se limite à l'ajout d'un VirtualHost et la configuration du proxy :
server {
root /home/pkg; # Where .nupkg files are stored
index index.html index.htm;
server_name chocopkg;
location /nuget/ {
proxy_pass http://127.0.0.1:8080/nuget/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_connect_timeout 10;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_redirect off;
proxy_set_header Connection close;
proxy_pass_header Content-Disposition;
proxy_pass_header Content-Length;
proxy_hide_header Content-Type;
add_header Content-Type application/atom+xml;
}
}
Un paquet NuGet (extension .nupkg) est basiquement un fichier .zip contenant la description du paquet (fichier .nuspec) et les directives d'installation sous forme de script Powershell. Pour faire simple, je vais prendre l'exemple de Notepad++.
Le fichier d'installation chocolateyInstall.ps1 ressemble à :
$packageName = 'notepadplusplus'
$installerType = 'EXE'
$url = 'http://chocopkg/npp.6.6.9.Installer.exe'
$url64 = $url
$silentArgs = '/S'
$validExitCodes = @(0)
Install-ChocolateyPackage "$packageName" "$installerType" "$silentArgs" "$url" "$url64" -validExitCodes $validExitCodes
Le nom du paquet, le type d'installeur et les URL de téléchargement du programme d'installation sont les paramètres les plus importants. Les paquets peuvent posséder un script d'installation plus complexe, c'est simplement du Powershell.
Le fichier de description notepadplusplus.nuspec ressemble à :
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>notepadplusplus</id>
<version>6.6.9</version>
<title>Notepad++</title>
<authors>Don Ho</authors>
<owners>Denis</owners>
<projectUrl>http://notepad-plus-plus.org/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Notepad++ est un editeur de texte sous licence GPL. Fonctionne sous Windows</description>
<summary>Notepad++ est un éditeur de texte.</summary>
<tags>editeur texte notepadplusplus windows gpl</tags>
<releaseNotes />
<copyright />
</metadata>
</package>
Seuls les balises <id/>, <version/> et <requireLicenseAcceptance/> sont obligatoires. Les autres sont fortement recommandées afin de fournir aux utilisateurs un minimum d'informations sur la fonction du logiciel proposé.
Un dossier est créé pour le paquet notepadplusplus :
Le fichier notepadplusplus.nuspec est déposé dans le dossier notepadplusplus et le fichier chocolateyInstall.ps1 dans le dossier tools. La dernière étape consiste à générer le fichier notepadplusplus.nupkg avec NuGet (fourni avec Chocolatey) :
La paramètre -NoPackageAnalysis permet de passer outre le test de conformité de NuGet.
Je rappelle que Chocorepo n'est pas développé pour gérer les paquets NuGet malicieux, n'importez pas de fichiers dont vous ignorez la provenance.
Le programme import.py permet d'importer un paquet NuGet dans la base de données de Chocorepo :
$ python import.py notepadplusplus.nupkg
Pour installer un paquet provenant de notre dépot privé, il faut rajouter le paramètre -source à Chocolatey :
N'hésitez pas à me faire un retour si vous l'utilisez et à proposer une PR sur GitHub.
Il existe de multiples plate-formes de virtualisation et il arrive parfois que l'ont ai besoin de migrer une machine virtuelle d'une solution à une autre. Dernièrement, un partenaire utilisant Hyper-V de Microsoft nous a fourni une VM à intégrer dans un socle VMware vCloud Director.
Il nous a envoyé un fichier .vhd. Ce format n'est pas exploitable tel quel par VMware mais heureusement plusieurs outils permettent, après quelques manipulations, de convertir celui-ci en vApp utilisable.
La migration se fait en 4 étapes :
La première étape consiste a convertir le fichier .vhd en format .ovf grâce à VirtualBox. On crée une nouvelle machine virtuelle avec VirtualBox :
La seule information importante concerne le type et la version du système d'exploitation installé dans le .vhd. Les autres propriétés pourront être modifiées dans vCloud. Pour le disque dur virtuel, nous allons attacher le fichier .vhd fourni par le partenaire :
La dernière manipulation consiste à convertir la machine nouvellement créée en fichier .ovf en utilisant la fonction Fichier/Exporter une application virtuelle de VirtualBox :
Nous obtenons plusieurs fichiers à la fin de la conversion :
$ ls
VHD2OVF-disk1.vmdk VHD2OVF.mf VHD2OVF.ovf
Avant de pouvoir déployer la machine, il faut éditer le fichier .ovf pour l'adapter en supprimant les périphériques n'existant pas sur la plate-forme vCloud : contrôleur disque, carte son, carte réseau, etc.
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Caption>SCSIController</rasd:Caption>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>SCSIController</rasd:ElementName>
<rasd:InstanceID>5</rasd:InstanceID>
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item>
Afin de rendre le fichier acceptable par vCloud, il faut générer un condensat SHA-1 du fichier .ovf et inscrire le résultat dans le fichier Manifest (.mf) généré par VirtualBox.
Nous avons maintenant un modèle OVF valide que nous pouvons envoyer sur la plate-forme vCloud. Pour cela, nous allons utiliser le programme ovftool issu du kit VMware Open Virtualization Format Tool. Pour cela, nous avons besoin de plusieurs informations :
Une fois toutes ces informations en main, on lance la commande :
ovftool --vCloudTemplate VHD2OVF.ovf \
"vcloud://identifiant:mot_de_passe@adresse_du_serveur:443?org=nom_de_lorganisation&vappTemplate=VHD2OVF&catalog=nom_du_catalogue&vdc=nom_du_vdc"
Si l'envoi s'est bien passé, on retrouve la vApp dans vCloud, il ne reste plus qu'à déployer et éditer les propriétés pour ajouter une interface réseau, de la mémoire, etc.
Lors de la refonte de l'infrastructure d'interconnexion des sites d'un client, j'ai été confronté à un problème de validation de la nouvelle solution. Afin de m'assurer que le paramètrage des routeurs est valide et qu'il n'y aura pas de surprise lors du déploiement (on branche et ça fonctionne, surtout pour les sites distants de plusieurs centaines de kilomètres et n'ayant pas de technicien sur site), il m'a fallu tester au plus proche des conditions réelles. Le client possède sur certains sites des connexions ADSL dont l'authentification est basée sur PPPoE. J'ai donc mis en place un serveur PPPoE qui m'a permis de contrôler la conformité des configurations. Pour cela, j'ai utilisé npppd(8) disponible de base avec OpenBSD. Voici l'architecture mise en place :
Tous les routeurs clients sont configurés pour monter une session PPPoE sur l'interface WAN qui est reliée au switch (switch qui joue le rôle du modem/bridge des sites du client). Le configuration du routeur OpenBSD est la suivante :
Activer le routage (le fournisseur d'accès du clien ne propose pas d'IPv6) :
# sysctl -w net.inet.ip.forwarding=1
net.inet.ip.forwarding: 0 -> 1
Activer le support de pipex(4) :
# sysctl -w net.pipex.enable=1
net.pipex.enable: 0 -> 1
Ajouter les identifiants du FAI du client dans le fichier /etc/npppd/npppd-users :
fti/siteA:\
:password=pwsiteA:\
:framed-ip-address=192.0.2.10:
fti/siteB:\
:password=pwsiteB:\
:framed-ip-address=192.0.2.24:
fti/siteC:\
:password=pwsiteC:\
:framed-ip-address=198.51.100.71:
fti/siteD:\
:password=pwsiteD:\
:framed-ip-address=203.0.113.114:
fti/siteE:\
:password=pwsiteE:\
:framed-ip-address=203.0.113.80:
(Les valeurs framed-ip-address étaient configurées avec les adresses IP fixes fournies par le FAI du client)
Configurer npppd(8) grâce au fichier /etc/npppd/npppd.conf :
tunnel PPPOE protocol pppoe {
listen on interface rl0
authentication-method pap chap
pppoe-service-name "Mandarine"
}
ipcp IPCP {
pool-address 192.0.2.1-192.0.2.254
pool-address 198.51.100.1-198.51.100.254
pool-address 203.0.113.1-203.0.113.254
}
interface tun0 address 192.168.1.1 ipcp IPCP
authentication LOCAL type local {
users-file "/etc/npppd/npppd-users"
}
bind tunnel from PPPOE authenticated by LOCAL to tun0
Lancer npppd(8) :
# npppd -d
[...]
2014-07-06 12:02:26:INFO: Loading pool config successfully.
2014-07-06 12:02:26:INFO: pppoed Listening on rl0 (PPPoE) [PPPOE] using=/dev/bpf1 address=xx:xx:xx:xx:xx:xx
Vérifier que les routeurs clients sont connectés :
$ npppctl sess br
Ppp Id Assigned IPv4 Username Proto Tunnel From
---------- --------------- -------------------- ----- -------------------------
6 192.0.2.10 fti/siteA PPPOE 00:xx:xx:xx:xx:aa
7 203.0.113.114 fti/siteD PPPOE 00:xx:xx:xx:xx:ad
8 192.0.2.24 fti/siteB PPPOE 00:xx:xx:xx:xx:ab
9 198.51.100.71 fti/siteC PPPOE 00:xx:xx:xx:xx:ac
10 203.0.113.80 fti/siteE PPPOE 00:xx:xx:xx:xx:ae
Tester le routage depuis le routeur OpenBSD :
$ ping 198.51.100.71
PING 198.51.100.71 (198.51.100.71): 56 data bytes
64 bytes from 198.51.100.71: icmp_seq=0 ttl=255 time=0.363 ms
64 bytes from 198.51.100.71: icmp_seq=1 ttl=255 time=0.296 ms
Tester depuis un routeur client :
Router> ping 203.0.113.80
PING 203.0.113.80 (203.0.113.80) 56(84) bytes of data.
64 bytes from 203.0.113.80: icmp_seq=1 ttl=128 time=1.01 ms
64 bytes from 203.0.113.80: icmp_seq=2 ttl=128 time=1.07 ms
Les clients et le routeur sont visibles les uns des autres sur le réseau. Depuis le réseau d'un site client, j'arrive à atteindre le réseau d'un autre site donc tout fonctionne, il n'y a plus qu'à déployer.
L'un de mes clients utilise des applications Java que les developpeurs n'ont pas signé numériquement ou dont la signature est invalide. De ce fait, les versions de Java récentes (Oracle JRE > 7u25) affichent des alertes lors du lancement de l'application qui agacent les utilisateurs.
La solution la plus naturelle est de demander aux développeurs de faire leur travail correctement (signer numériquement les applets) mais ce n'est pas toujours possible (développeur injoignable par exemple). Il y'a également l'option consistant à conserver une version antédiluvienne de Java mais je vous assure que vous ne voulez pas faire ça...
Et dans ce cas, c'est à l'administrateur de mettre en place une solution permettant de valider l'application grâce aux Deployment Rule Sets
Pour mettre en place ces règles de déploiement, nous avons besoin :
jar
, jarsigner
, keytool
Une autorité de certification a été créée avec OpenSSL, on a donc deux fichiers .PEM : la clé privée (cakey.pem) et la clé publique (cacert.pem). La première étape consiste à créer un magasin de clefs utilisable avec les outils Java. On le créé en important un fichier au format PKCS#12 :
$ openssl pkcs12 -export -out cacert.p12 -inkey cakey.pem -in cacert.pem
$ keytool -importkeystore -destkeystore caclient.jks -srckeystore cacert.p12 \
-srcstoretype PKCS12 -alias CAClient
Dans un éditeur de texte, on crée un fichier .XML contenant les règles de déploiement. Ici, c'est très simple si l'adresse de l'applet commence par http://srvapplet:8080
elle est considérée comme sûre :
<!-- ruleset.xml -->
<ruleset version="1.0+">
<rule>
<id location="http://srvapplet:8080" />
<action permission="run" />
</rule>
</ruleset>
L'étape suivante consiste à mettre ce fichier .XML dans un .JAR puis de signer le .JAR avec notre autorité de certification :
$ jar -cvf DeploymentRuleSet.jar ruleset.xml
$ jarsigner -verbose -keystore caclient.jks -signedjar DeploymentRuleSet.jar \
DeploymentRuleSet.jar CAClient
Finalement on installe l'autorité de certification (à coup de GPO, c'est très facile) et on copie le fichier DeploymentRuleSet.jar
dans le dossier %windir%\Sun\Java\Deployment
sur les postes des utilisateurs.
L'application est maintenant considerée comme sûre par la machine virtuelle Java.
Lors de l'utilisation du SDK de l'API VMWare VIX, j'ai rencontré un problème sur une machine Debian Wheezy. Tous les programmes utilisant cette API se finissaient avec une erreur de segmentation.
$ /usr/share/doc/vmware-vix/samples/fhostopen
Erreur de segmentation
L'erreur provient de l'ordre de chargement des bibliothèques. Ce patch permet de corriger ce problème.
Le site du constructeur OCZ propose un outil pour mettre à jour le micrologiciel de ses produits pour les systèmes Microsoft Windows et Apple MacOS X mais la seule alternative lorsque l'on utilise un système Linux est de télécharger l'image du CD de démarrage, la graver, booter dessus et espérer que l'interface réseau soit reconnue par le système. Et si ce n'est pas le cas (comme sur ma machine), impossible de télécharger le firmware et de flasher le SSD.
La solution consiste à extraire l'outil de mise à jour et à le lancer de façon autonome depuis le système d'exploitation courant. Voici les différentes étapes à effectuer :
Dézipper l'archive ZIP
$ unzip OCZ_PC_Bootable_Tools_v4.3.03740.zip
Monter l'image ISO obtenue
$ sudo mount PC_BootableTools_v4.3-4.3.0.3740.iso /mnt -o loop
Décompresser le fichier core.gz
$ cp /mnt/boot/core.gz . && gunzip core.gz
$ sudo umount /mnt
Extraire le contenu de "core" avec l'aide du paquetage "squashfs-tools"
$ cpio -i < core
$ for i in `ls ./tmp/builtin/optional/ocz*.tcz`; do unsquashfs -f -d . $i; done
Lancer la boite à outils OCZ
$ sudo ./usr/local/bin/OCZToolbox