Apr 03 2013

Powershell: Exchange et Oracle, secure string.

Nous allons utiliser dans cet article des cmdlets pour se connecter à une base Oracle, qui contient les données RH et vérifier si chaque employé dispose d’une boite Email sous Exchange 2010. L’attribut commun entre les deux systèmes peut être filtré avec les cmdlets Exchange, ce qui est conseillé pour la performance du script. Nous choisirons le CustomAttribute13 pour notre exemple.

Pour pouvoir interroger la base Oracle vous pouvez installer ODAC 64bits sur un Windows-64bits. Lancer une installation en indiquant d’installer uniquement le provider ODP.NET Pour votre version de Framework. Dans notre cas:

install.bat odp.net2 c:\oracle myhome true

Ensuite pour interroger la base avec PowerShell, il suffit de faire appel à l’assembly Oracle.DataAccess.dll apportée par ODAC-64bits:

$Assemblyfile = "C:\oracle\odp.net\bin\2.x\Oracle.DataAccess.dll"
[Reflection.Assembly]::LoadFile($AssemblyFile) | out-null

Lire cet article pour plus d’informations.

Lors de la connexion à la base Oracle, nous voulons protéger le mot de passe d’accès à la base de données. Pour cela nous allons utiliser un secure string, Le fichier cred.txt sera généré avec le compte lançant la tâche planifiée Exchange.

generatePasswordFile

Si la lecture du fichier par un autre compte est effectuée, elle échoue:

failedpassword

Une fois le fichier généré:

read-host -assecurestring "pass" | convertfrom -secure string | out-file c:\cred.txt

Nous lançons la connexion à la base Oracle:

#Read $Pword from file.
$Pword = get-content cred.txt | convertto-securestring
$user = "adm"
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
 
$OracleConnection = New-Object -TypeName Oracle.DataAccess.Client.OracleConnection
 
#Change host, Port, Service_Name values
$connectionString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(Host=ldap389-oraclesrv)(Port=1532)))(CONNECT_DATA=(SERVICE_NAME=HR1)));User ID="+$credential.GetNetworkCredential().username+";Password="+$credential.GetNetworkCredential().password
$OracleConnection.ConnectionString = $ConnectionString
$OracleConnection.Open()

Nous cherchons les employés commençant dans 3 jours, il suffit pour cela de convertir les dates dans notre requête:

#Date in format MM/DD/YYYY HH:MI:SS, +3 days from now
 
$date = Get-Date((get-date).addDays(+3)) -format "MM/dd/yyyy hh:mm:ss"
#Get users starting in 3 days in HR database, change table (LDAP389FAMILY), and attributes: HRCODE is customAttribute13
$CommandText  = "SELECT HRCODE,START_DATE FROM LDAP389FAMILY WHERE START_DATE BETWEEN SYSTEMDATE AND to_date('"+$date+"', 'MM/DD/YYYY HH24:MI:SS')"
 
#Launching query
$OracleCommand = New-Object -TypeName Oracle.DataAccess.Client.OracleCommand
$OracleCommand.CommandText = $CommandText
$OracleCommand.Connection = $OracleConnection
$OracleDataAdapter = New-Object -TypeName Oracle.DataAccess.Client.OracleDataAdapter
$OracleDataAdapter.SelectCommand = $OracleCommand
$DataSet = New-Object -TypeName System.Data.DataSet
$OracleDataAdapter.Fill($DataSet)
$OracleDataAdapter.Dispose()
$OracleCommand.Dispose()
$OracleConnection.Close()
$Oracleresults = $DataSet.Tables[0]

La tâche planifiée réalise la connexion à Exchange comme décrit dans ce précédent post, elle se lance avec le compte AD autorisé à lire le secure string:

#With this command you do not need to install the Exchange Management Shell on the server, change the fqdn Cas-server.ldap389.local
 
$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Cas-server.ldap389.local/PowerShell/
Import-PSSession $s -allowclobber

Dans le cas d’une tâche planifiée le mot de passe du compte AD est mis en cache dans LSAsecrets. Pour une meilleure protection du mot de passe du compte lançant la tâche planifiée vous pouvez utiliser un gMSA sous Windows 2012: Le compte a des droits limités et le mot de passe est régulièrement mis à jour, le hash mot de passe est stocké aussi dans LSAsecrets.

Le script compare ensuite les valeurs de CustomAttribute13 du compte Exchange et le HRCODE de la base Oracle qui sont les attributs communs entre les deux systèmes. Si la BAL est créée ou non, l’information est affichée:

foreach($Oracleresult in $Oracleresults)
{$customAttr13 = $Oracleresult.HRCODE
 
#Check if mailbox was created:  
$mbx = get-mailbox -filter "(CustomAttribute13 -eq '$customAttr13')"
	if($mbx){
	write-host '--------------------------------------------------'
	write-host 'MBX already created'
	write-host 'Exchange information'
	$mbx | select CustomAttribute13,WindowsEmailAddress,whencreated
	write-host 'HRCODE: '$customAttr13
	write-host 'Start date: '$Oracleresult.START_DATE
	}
	#Mailbox is not created:  
	else{
	write-host '--------------------------------------------------'
	write-host 'Create MBX ASAP'
	write-host 'HRCODE '$customAttr13
	write-host 'Start date: '$Oracleresult.START_DATE
	}
}

Pour télécharger le script complet c’est ici:

Plus d’excuses pour créer une BAL 2 semaines après qu’une personne soit arrivée 😉

This post is also available in: Anglais

6 Comments

  • By r0llb4ck, May 6, 2013 @ 1:37 pm

    because you’are hungry

    http://roo7break.co.uk/?page_id=611

  • By r0llb4ck, May 6, 2013 @ 1:40 pm

    sinon pour les operations de base sur oracle, le framework .net inclut system.data.oracleclient (system.data.dll)

    pourquoi installer le client fournit par Oracle (ô désespoir, qu’ont-ils fait d’open solaris ?)

  • By ldap389, May 6, 2013 @ 3:01 pm

    Bonne question 🙂 J’ai d’ailleurs d’abord utilisé le framework MS mais j’ai rencontré des soucis de performance.
    Ce framework est marqué comme “deprecated”.
    MS conseille l’utilisation de framework tierces depuis 2009:
    http://blogs.msdn.com/b/adonet/archive/2009/06/15/system-data-oracleclient-update.aspx

  • By r0llb4ck, May 7, 2013 @ 6:34 am

    Je suis de mauvaise foi, car dans mes dev, j’utilise le client Oracle !
    Par contre, quand on charge l’assembly dans la session Powershell, est-il nécessaire de préciser le chemin d’accès complet à l’assembly ?
    Il me semble (de souvenir) , que l’assembly est installé dans le GAC, endroit de recherche par défaut des assemblies.
    En précisant le chemin d’accès complet, on peut laisser “fuiter ” quelques petites infos…

  • By r0llb4ck, May 7, 2013 @ 6:38 am

    oops : utilisation de Assembly.LoadFile() : je sors !

  • By ldap389, May 7, 2013 @ 9:11 am

    Pas grave, de toute manière…

    Oracle

Other Links to this Post

RSS feed for comments on this post. TrackBack URI

Leave a comment

*

WordPress Themes

Blossom Icon Set

Software Top Blogs