PowerShell: Remote Sessions (Mandant anlegen ab 2013 R2)

13. August 2015 00:56

Szenario: Wenn in einer Datenbank kein Mandant vorhanden ist, ist ab NAV 2013 R2 kein Start des Windowsclient mehr möglich, da dieser aus der Entwicklungsumgebung nicht mehr angelegt werden kann.

Mit der PowerShell ist das bei laufender Serverinstanz jederzeit möglich, dazu kann man sich entweder auf dem Server per Remotedesktopverbindung als Adminstrator anmelden und das dort direkt vornehmen oder eleganter lokal aus der eigenen PowerShell durch Aufbau einer separaten Session. Das hat auch den Vorteil, dass man dort u.U. nicht einem anderen Kollegen eine bereits laufende Remotesession am Server abklemmt :wink: .

Voraussetzung: Ab Windows Server 2012 ist Enable-PSRemoting freigegeben, bei älteren Servern muss man dieses manuell machen.

Die notwendigen Befehle bei manueller Eingabe und einer Ausführung im Batch unterschieden sich dabei.
Für beide Verfahren gilt:
Dass man als Adminstrator angemeldet ist (die NavAdminTools sind sonst nicht nutzbar) sollte man natürlich bei der Eingabe aller Befehle grundsätzlich beachten. Die NAV-Cmdlets selber sind unkritisch, aber ein falscher PowerShell-Befehl im falschen Verzeichnis kann fatale Folgen für das Serverbetriebssystem haben :!:

Beispiel manuelle Eingabe
Anmeldung am Server NAVSERVER1 mittels Enter-PSSession als Administrator, um dort für die Datenbank mit dem laufenden NAV-Serverdienst NAMENAVSERVICE1 einen Mandanten TEST123 anzulegen.
Code:
Enter-PSSession -computerName NAVSERVER1 -credential <domainname>\administrator

Passwort2.png

Nach Eingabe des Passworts kann man fortfahren, der Servername wird mit eckigen Klammern angezeigt.
[NAVSERVER1]: gefolgt von "PS" und dem Serverpfad in dem man sich befindet (Vorgabepfad ist der "Documents"-Ordner).
Import der NavAdminTools, Laufwerk C: ist jetzt das Serverlaufwerk. Bei NAV 2015 im Pfad 80 statt 71 eintragen.
Code:
Import-Module "C:\Program Files\Microsoft Dynamics NAV\71\Service\NavAdminTool.ps1" -force | out-null

New-NAVCompany ausführen
Code:
New-NAVCompany -ServerInstance NAMENAVSERVICE1 -Tenant Default -CompanyName TEST123

Remotesession verlassen um lokal weiterzuarbeiten:
Code:
Exit-PSSession


Codeblock im Batch
Zur Laufzeit eines Skripts dagegen funktioniert Enter-PSSession nicht, auch wenn hier das Anmeldefenster zur Eingabe des Administratorpassworts erscheint, da dieser Befehl nur für interaktive Benutzung gedacht ist.
Statt dessen wird hier nach Eingabe des Passworts mit Get-Credential (der ebenfalls das obige Fenster aufruft) mit New-PSSession eine Variable $MySession belegt und durch Invoke-Command die Befehlszeilen übergeben.
Code:
$cred = Get-Credential <domainname>\administrator
$MySession = New-PSSession -computerName NAVSERVER1 -credential $cred
invoke-command -Session $MySession -scriptblock {Import-Module "C:\Program Files\Microsoft Dynamics NAV\71\Service\NavAdminTool.ps1" -force | out-null}
invoke-command -Session $MySession -scriptblock {New-NAVCompany -ServerInstance NAMENAVSERVICE1 -Tenant Default -CompanyName TEST123}
Remove-PSSession $MySession
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Schemasynchronisierung vorschalten

14. August 2015 11:00

Da für neue Mandanten die Schemasynchronisierung jeweils aktuell sein muss, kann man das ggf. über diese Zusatzzeile vorher mit erledigen lassen
Code:
invoke-command -Session $MySession -scriptblock {Sync-NAVTenant -ServerInstance NAMENAVSERVICE1 -Force -Mode Sync}

Für Testdatenbanken kann man aus dem -Mode Sync ein -Mode ForceSync machen, dann werden Altlasten in um- und ausgebauten Feldern gelöscht. Den Mode-Schalter gibt es erst ab NAV 2015, in NAV 2013 R2 gilt hier die Clienteinstellung unter Optionen "Datenverlust durch Tabellenänderung verhindern".

Code:
$cred = Get-Credential <domainname>\administrator
$MySession = New-PSSession -computerName NAVSERVER1 -credential $cred
invoke-command -Session $MySession -scriptblock {Import-Module "C:\Program Files\Microsoft Dynamics NAV\71\Service\NavAdminTool.ps1" -force | out-null}
invoke-command -Session $MySession -scriptblock {Sync-NAVTenant -ServerInstance NAMENAVSERVICE1 -Force -Mode Sync}
invoke-command -Session $MySession -scriptblock {New-NAVCompany -ServerInstance NAMENAVSERVICE1 -Tenant Default -CompanyName TEST123}
Remove-PSSession $MySession

Passwort aus verschlüsselter Datei auslesen (Single-User)

15. Dezember 2015 11:38

Falls die Serveranmeldung nicht jedesmal manuell erfolgen soll, kann man das Passwort verschlüsselt mittels ConvertTo-SecureString in einer Datei abspeichern und diese dann zur Laufzeit auslesen.

Dazu wird einmalig in der Powershell das Passwort in einer verschlüsselten Datei gespeichert, hier auf Laufwerk X: im Temp-Ordner.
Code:
"P@ssWord1" | ConvertTo-SecureString -AsPlainText -Force | Out-File "X:\Temp\Passwort.xxx"


Der Anfang vom Inhalt einer solchen Datei sieht dann z.B. so aus:
passwort.png

Im Skript werden dann diese Zeilen hinzugefügt, hier natürlich für <domainname> die eigene Domäne einsetzen und den Dateipfad anpassen :wink:
Code:
$User = '<domainname>\administrator'
$File = "X:\Temp\Passwort.xxx"
$cred = New-Object -TypeName System.Management.Automation.PSCredential ` -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)

…und diese entfernt.
Code:
$cred = Get-Credential <domainname>\administrator

Dadurch wird die Anmeldefenster unterbunden und das Skript meldet sich selbstständig am Server an.

Im obigen Beispiel wird ohne Verschlüsselungskey gearbeitet, dadurch ist die Verschlüsselung vom User und der Hardware abhängig (Data Protection application programming interface (DPAPI)), andere User-Hardware-Kombinationen können die Datei nicht entschlüsseln. Beim Wechsel der eigenen Hardware müssen die verschlüsselten Passworte neu erzeugt werden.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Verschlüsselungen im Multi-User-Betrieb

15. Dezember 2015 13:09

Falls die Anmeldungen von jedem beliebigen User (der das Skript ausführen kann) vorgenommen werden sollen, müssen die Dateien durch einen bekannten zusätzlichen Schlüssel allgemein lesbar verschlüsselt werden und die Skripte diesen Key ebenfalls enthalten.

Durch den Zusatzparameter -key kann über ein Array mit 16, 24 oder 32 Byte dieser Schlüssel mitgegeben werden.
Hier in der einfachsten Form als Array 1..16.
Code:
"P@ssWord1" | ConvertTo-SecureString -key (1..16) -AsPlainText -Force | Out-File "X:\Temp\Passwort.xxx"

Falls man das Passwort in der PowerShell verdeckt eingeben möchte, den Anfang der Zeile durch Read-Host "<Text im Eingabefenster>" -AsSecureString ersetzen:
Code:
Read-Host "Enter Password" -AsSecureString | ConvertTo-SecureString -key (1..16) -AsPlainText -Force | Out-File "X:\Temp\Passwort.xxx"

ReadPassword.png

Im Skript das Keyarray analog als Parameter mit dazu, um die Entschlüsselung hardwareunabhängig vorzunehmen.
Code:
$cred = New-Object -TypeName System.Management.Automation.PSCredential ` -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString -key (1..16))
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.