ADMIN

2021

12

2021-12-01T12:00:00

Small Business IT

PRAXIS

034

Netzwerkmanagement

PowerShell

PowerShell Crescendo

Neue Harmonien

von Tam Hanna

Veröffentlicht in Ausgabe 12/2021 - PRAXIS

PowerShell Crescendo erlaubt, Befehle anderer Shell-Umgebungen in PowerShell-Cmdlets und -Module umzuwandeln und sie mit allen Vorteilen und dem Komfort der PowerShell-Umgebung zu nutzen. So lassen sich derartige Befehle in die Pipeline geben oder mit Parametern steuern. Wie Admins eine Crescendo-Umgebung aufsetzen und diese dann für Linux nutzen, zeigt dieser Workshop.

Crescendo ist derzeit als Technical Preview verfügbar und alle hier besprochenen Vorgehensweisen können sich mit dem nächsten Release ändern. Da ein einmal heruntergeladenes Crescendo-Paket und die von ihm generierten Wrapper jedoch ohne Internetverbindung funktionieren, lässt sich Ihre Umgebung durch Nicht-Einspielen von Updates beziehungsweise Nicht-Neutranspilieren der Wrapper stabil halten.
Einrichtung der Crescendo-Arbeitsumgebung
Crescendo arbeitet in einem zweistufigen Prozess: Vor der Nutzung eines Kommandozeilenwerkzeugs müssen Sie einen Wrapper mit der Crescendo-Arbeitsumgebung und einer oder mehreren JSON-Steuerungsdateien transpilieren. Ist dies erfolgreich, erhalten Sie ein gewöhnliches PowerShell-Modul, das Sie in so gut wie allen PowerShell-Versionen verwenden können. Diese zweigeteilte Vorgehensweise zeigt sich auch in den Systemanforderungen, denn für das Erzeugen eines auf Crescendo basierenden Pakets benötigen Sie die PowerShell in Version 7.0 und die Ausführung der Module erfolgt dann in der Windows PowerShell 5.1 oder der PowerShell 7.0.
Für diesen Workshop nutzen wir eine Windows-10-Workstation. Ärgerlicherweise enthält sie von Haus aus die PowerShell in Version 5. Rufen Sie deshalb [1] auf, wo Sie ein GitHub-Repository finden, in dem Microsoft die aktuelle stabile Version der PowerShell zur Verfügung stellt. Derzeit ist dies die Datei "PowerShell-7.1.4-win-x64.msi", die Sie installieren und die PowerShell 7 starten.
Crescendo ist derzeit als Technical Preview verfügbar und alle hier besprochenen Vorgehensweisen können sich mit dem nächsten Release ändern. Da ein einmal heruntergeladenes Crescendo-Paket und die von ihm generierten Wrapper jedoch ohne Internetverbindung funktionieren, lässt sich Ihre Umgebung durch Nicht-Einspielen von Updates beziehungsweise Nicht-Neutranspilieren der Wrapper stabil halten.
Einrichtung der Crescendo-Arbeitsumgebung
Crescendo arbeitet in einem zweistufigen Prozess: Vor der Nutzung eines Kommandozeilenwerkzeugs müssen Sie einen Wrapper mit der Crescendo-Arbeitsumgebung und einer oder mehreren JSON-Steuerungsdateien transpilieren. Ist dies erfolgreich, erhalten Sie ein gewöhnliches PowerShell-Modul, das Sie in so gut wie allen PowerShell-Versionen verwenden können. Diese zweigeteilte Vorgehensweise zeigt sich auch in den Systemanforderungen, denn für das Erzeugen eines auf Crescendo basierenden Pakets benötigen Sie die PowerShell in Version 7.0 und die Ausführung der Module erfolgt dann in der Windows PowerShell 5.1 oder der PowerShell 7.0.
Für diesen Workshop nutzen wir eine Windows-10-Workstation. Ärgerlicherweise enthält sie von Haus aus die PowerShell in Version 5. Rufen Sie deshalb [1] auf, wo Sie ein GitHub-Repository finden, in dem Microsoft die aktuelle stabile Version der PowerShell zur Verfügung stellt. Derzeit ist dies die Datei "PowerShell-7.1.4-win-x64.msi", die Sie installieren und die PowerShell 7 starten.
Möchten Sie unterschiedliche PowerShell-Versionen auseinanderhalten, bietet sich die Abfrage $PSVersionTable an. Beachten Sie, dass die so erzeugte Tabelle eine Gruppe von Attributen mit verschiedenen Datentypen zurückliefert. Nutzen Sie die Inhalte der Tabelle mit einem Skript, erlaubt PowerShell das gezielte Ansprechen einzelner Felder via $PSVersionTable.PSVersion.
Für das Herunterladen des Crescendo-Transpilers benötigen Sie folgendes Kommando. Eventuelle Sicherheitsanfragen, die auf ein nicht-vertrauenswürdiges Paket-Repository hinweisen, müssen Sie abnicken:
Install-Module Microsoft.PowerShell.Crescendo -AllowPrerelease
Nach erfolgreicher Installation ist Ihre PowerShell um einige Cmdlets reicher. Außerdem finden Sie den Ordner "C:\Users \ <Benutzer> \ Documents \ PowerShell \ Modules \ Microsoft.PowerShell.Crescendo \ 0.6.1 \ Samples" mit einigen für unixoide Kommandos vorgesehenen Beispieldateien.
Ausführen von Befehlen
Die häufigste Anwendung von Crescendo-generierten Wrappern ist das Verpacken von Kommandozeilenbefehlen in die Verb-Nomen-Form. Zur Erinnerung: Alle PowerShell-Kommandos beginnen mit einem Verb, das die vom jeweiligen Befehl zu bewerkstelligende Aufgabe beschreibt. Danach folgt ein Nomen, das das Ziel der vom Verb ausgelösten Handlung beschreibt.
In der Crescendo Preview 3 (das dritte Vorschau-Release erlaubt das Kombinieren mehrerer Kommandos in einer JSON-Datei) sehen Kommando-Deklarationen wie in Listing 1 aus. Neben der für die Deklaration der XML-Syntax verwendeten Zeile "$schema…" sehen Sie das Commands-Array, das die im Wrapper zu verpackenden Befehle auflistet. Jedes Kommando hat die Felder "Verb" und "Noun", die die PowerShell-Verben und -Nomen festlegen, die das Kommando aktivieren. Unter "OriginalName" finden Sie den Pfad zur auszuführenden Datei.
Listing 1: Kommando-Deklaration
{     "$schema":  "./Microsoft.PowerShell.Crescendo.Schema.json",    "Commands": [      {        "Verb": "New",        "Noun": "Command1",        "OriginalName": "<Pfad><Kommando>"      },      {        "Verb": "New",        "Noun": "Command2",        "OriginalName": "<Pfad><Kommando>"      } . . .     ] }
Bevor wir das weitere Vorgehen beschreiben, ein kurzer Hinweis: Möchten Sie Ihr Cmdlet in die Aufrufkonventionen der PowerShell einbinden, sollten Sie sich auf die von Microsoft freigegebenen Verben beschränken beziehungsweise diese nutzen, wenn sie zu Ihrer Aufgabe passen. Unter [2] findet sich eine Liste der Verben und der von Microsoft vorgesehenen "Rollen" und [3] zeigt Ihnen die Crescendo-Cmdlets samt ihren Parametern.
Als erstes Ausführungsziel dient "winver", das ein Pop-up-Fenster mit der gerade aktuellen Windows-Version öffnet. Zur Erzeugung eines Crescendo-Wrappers benötigen Sie eine JSON-Datei:
notepad runwinver.json
Die folgende Struktur führt winver aus:
{
"$schema" : "./Microsoft.PowerShell.Crescendo.Schema.json",
"Verb": Run",
"Noun": "TamsWinVer",
"OriginalName":"/Windows/System32/winver.exe",
"Parameters": []
}
Neben der für die PowerShell notwendigen Attribute "Verb" und "Noun" müssen Sie im Feld "OriginalName" den Pfad zu "winver.exe" angeben. Im Verzeichnis "C:\Windows" liegende Pfade dürfen Sie dabei wie gezeigt abkürzen. Da unser Werkzeug ohne Parameter auskommt, übergeben wir ein leeres Feld an das Parameter-Array.
Vielleicht haben Sie bereits bemerkt, dass sich in der Zeile "Verb": Run" ein fehlendes Anführungszeichen versteckt. Warum dies so ist, zeigt sich im Folgenden: Weisen Sie Crescendo dazu an, eine Transpilation durchzuführen:
Export-CrescendoModule -ConfigurationFile "runwinver.json" -ModuleName 'TansWinver.psm1'
Der Parameter "ConfigurationFile" verweist dabei auf die JSON-Datei, während "ModuleName" den Namen der zu erzeugenden PSM1-Datei angibt. Crescendo generiert ein natives PowerShell-Modul, das Sie auch abseits der Crescendo-Runtime verwenden dürfen. Der JSON-Parser bemerkt das fehlende Anführungszeichen und beendet die Bearbeitung mit einer Fehlermeldung. Korrigieren Sie die JSON-Datei und befehligen sie eine weitere Transpilation.
Bild 1: Der zweite Aufruf des Export-CrescendoModule-Befehls scheitert mit einer Fehlermeldung, die uns darauf hinweist, dass die Datei bereits existiert.
Lästigen Fehler umgehen
Ursache dieses widersinnigen Verhaltens ist, dass Crescendo immer Ausgabedateien generiert – explizit auch dann, wenn die Transpilation der JSON-Datei fehlschlägt oder keine brauchbaren Informationen liefert. Der Export-CrescendoModule-Befehl generiert bei der oben gezeigten Parametrisierung die Dateien "TansWinver.psd1" und "TansWinver.psm1", die Sie vor dem nächsten Erzeugen löschen müssen.
In der Theorie dürfen Sie die korrigierte Datei zur Transpilation bringen. In der Praxis scheitert das Export-CrescendoModule-Kommando mit der Fehlermeldung "You cannot call a method on a null-valued expression" abermals. Damit ist unsere anfängliche Warnung im Bezug auf Änderungen am Verhalten von Crescendo gerechtfertigt. Microsoft hat in Preview 3 am Dateiformat geschraubt, um die parallele Ausführung mehrerer Kommandos zu ermöglichen. Vorher im Internet veröffentlichte Dokumente, die diese Änderungen nicht nachvollziehen, verloren dadurch ihre Gültigkeit. Eine für Crescendo Preview 3 brauchbare JSON-Datei benötigt ein, das momentan nur den für den Aufruf von winver notwendigen Befehl aufnimmt (Listing 2).
Listing 2: Commands-Array für JSON-Datei
{     "$schema": "../src/Microsoft.PowerShell.Crescendo.Schema.json",    "Commands": [      {        "Verb": "Run",        "Noun": "TamsWinVer",        "OriginalName": ""/Windows/System32/winver.exe",",        "Parameters": []         }        ] }
Eine weitere Änderung betrifft den an "$schema" übergebenen Pfad. Crescendo funktionierte in unseren Tests am besten, wenn wir das Arbeitsverzeichnis "C:\ Users \ <Benutzer> \ Documents \ PowerShell \ Modules \ Microsoft.PowerShell.Crescendo \ 0.6.1 \ Samples" verwendeten. Im nächsten Schritt bietet sich eine Überprüfung der in der Datei enthaltenen Informationen an:
Import-CommandConfiguration .\tamswinver.Crescendo.json
Die Analyse der JSON-Datei führt zur Ausgabe aller in ihr enthaltenen Kommandos. Die Nutzung des Import-CommandConfiguration-Cmdlets ist bequem, weil das Kommando keine Metadateien erzeugt. Es ist für Tests geeignet, um grobe Syntax- und sonstige Fehler auszuschließen. Finden Sie in der Tabelle alle Kommandos, die Sie in Ihrer JSON-Datei angelegt haben, ist diese wahrscheinlich funktionsfähig. Im nächsten Schritt müssen Sie eine Transpilation befehligen:
Export-CrescendoModule -ModuleName "tamswinver1.psm1" -ConfigurationFile ".\tamswinver.Crescendo.json"
Die Verwendung von winver ist an dieser Stelle insofern günstig, als das Programm bei Aktivierung eine sichtbare Aktion ausführt. Während der Transpilation kam es bei uns reproduzierbar zu einer Aktivierung des Programms. Berücksichtigen Sie dies, falls Sie ein Programm mit potenziell schädlichen Nebeneffekten ausführen. Nun können Sie die erzeugte Datei wie ein gewöhnliches PowerShell-Modul laden:
Import-Module -Name '.\<tamswinver1.psm1>'
Die PowerShell 7.1.4 wirft ob der Verwendung eines "ungültigen" Verbs die Fehlermeldung "WARNING: The names of some imported commands from the module ..." aus. Sie informiert, dass das Cmdlet in manchen Auflistungsbefehlen nicht erscheint. Dies ist für unsere Experimente kein Problem, winver lässt sich nun per Run-TamsWinVer aktivieren.
Zu guter Letzt löschen Sie das Modul aus dem Modul-Verzeichnis der lokalen PowerShell. Dies erfolgt über Remove-Module, wobei Sie den Namen der PSM1-Datei ohne Dateiendung übergeben.
Bild 2: Von Crescendo anzusprechende Werkzeuge müssen auf der für die Transpilation zuständigen Maschine nicht installiert sein.
PowerShell für linux-basierte Befehle
PowerShell bringt von Haus aus umfangreiche Cmdlets mit, die die meisten unter Windows auftretenden Administrationsaufgaben bewerkstelligen. Beim Einsatz der PowerShell unter unixoiden Betriebssystemen müssen Sie viele Kommandozeilenwerkzeuge von Hand aufrufen. Daher ist unser nächstes Testobjekt "ifconfig" (das Unix-Äquivalent zum Kommandozeilen-IP-Konfigurationsprogramm "ipconfig".) Microsoft bietet mit der Datei "ifconfig.Crescendo.json" ein schlüsselfertiges Programmbeispiel an, das Sie im ersten Schritt analysieren:
Import-CommandConfiguration .\ifconfig.Crescendo.json
So erhalten Sie die in Bild 3 gezeigte Befehlstabelle. Beachten Sie, dass wir Crescendo unter Windows 10 ausführen – einem Betriebssystem, das mit ifconfig nichts anzufangen weiß. Die Ausgabe mit Informationen über die Steuerungsdatei zeigt diverse Metadaten. Das liegt daran, dass die Crescendo-Spezifikation nicht nur das Festlegen der auszuführenden Befehle und von ihnen benötigten Parameter erlaubt. Microsoft ermöglicht das Hinterlegen von Informationen, welche die PowerShell danach ins Hilfesystem einbindet.
Öffnen Sie die Datei "ifconfig.Crescendo. json" in einem Editor Ihrer Wahl, zeigt sie sich wie in Listing 3. Sowohl Visual Studio als auch die Basisversion Visual Studio Code bearbeiten PowerShell-Dateien mit Syntaxhervorhebung – wir raten davon ab, PowerShell-Skripte mit Notepad.exe zu bearbeiten.
Listing 3: Inhalt von "ifconfig.Crescendo.json"
{     "$schema": "../src/Microsoft.PowerShell.Crescendo.Schema.json",    "Commands": [      {        "Verb": "Invoke",        "Noun": "ifconfig",        "Description": "This is a description of the proxy",        "OriginalName": "ifconfig",        ""Aliases": [           "Get-NetworkConfiguration"        ],        "Usage": {           "Synopsis": "Run invoke-ifconfig"        },        "Parameters": [        {              "Name": "Interface",              "OriginalName": "",              "Description": "This is the description for a parameter",              "ParameterType": "string",             "DefaultValue": ""        }      ]    }   ] }
Der Parameter "OriginalName" nimmt auch hier den Namen der Binärdatei auf, die die PowerShell aktivieren soll. Unix-Kommandos beschreiben Sie in der Welt von Crescendo im Allgemeinen nicht durch einen festen Pfad, sondern durch den in der Kommandozeile einzugebenden Namen. Es spricht natürlich nichts dagegen, in "empfindlichen" Situationen den vollen Pfad der Binärdatei anzugeben. Als Nächstes finden sich einige Metadaten. Neben dem Aliases-Block, der zusätzliche für die Aktivierung des Kommandos vorgesehene Strings anliefert, existiert ein Usage-Block für Hilfetexte.
Bild 3: Der von Crescendo generierte Wrapper funktioniert unter Ubuntu problemlos.
Parameter nutzen
Die von Crescendo verpackten Kommandos nehmen in vielen Fällen Parameter entgegen, die dem Nutzer die Anpassung des Programmverhaltens erlauben. PowerShell-Cmdlets sind ebenfalls parametrierbar, weshalb Microsoft in der Crescendo-Umgebung ein Werkzeug zur Übergabe von Parametern anlegt. Spezifischerweise nimmt der Commands-Block ein weiteres Feld entgegen, das die Parameter beschreibt. Wichtig ist, dass Sie in Ihrem Crescendo-Wrapper nicht alle von der aufgerufenen Binärdatei unterstützten Parameter deklarieren müssen. Es reicht aus, wenn Sie nur jene Einstellungen exponieren, die Sie für den Aufrufer ansprechbar machen wollen. Im Fall unseres ifconfig-Wrappers war der nach Ansicht des Entwicklers einzige nützliche Parameter der Name des zu analysierenden Netzwerk-Interfaces ("Name": "Interface").
Analog zum Commands-Block gibt es auch hier ein OriginalName-Feld. Es legt nun fest, unter welchem "Präfix" die aufzurufende Binärdatei das Anliefern der Informationen erwartet. In "Description" dürfen Sie abermals Informationen unterbringen, die dem Nutzer mehr Informationen über die Rolle des Parameters aufzeigen. Mit "ParameterType" definieren Sie den erlaubten Datentyp, "DefaultValue" ist der zu übergebende Standardwert. Im Bereich der Datentypen dürfen Sie alle von der PowerShell unterstützten Variablenarten einschreiben – neben dem hier verwendeten String wäre auch Integer ein gangbarer Datentyp.
Das Parameters-Array erlaubt die Festlegung optionaler Zusatzattribute. Übergeben sie beispielsweise ""Mandatory": true", ist der Aufrufer des Wrappers verpflichtet, diesem Parameter einen Wert zuzuweisen:
"Parameters": [
   {
…"Name": "Id",
…"OriginalName": "",
…"Mandatory": true,
…"ValueFromPipelineByPropertyName": true
.}
],
Ein weiteres schönes Beispiel für Crescendo-Parameter findet sich im Wrapper um das Unix-Utility "tar", der erstens einen Präfix für den Parameter definiert und zweitens festlegt, dass sich der Parameter als Bit-Schalter auswirken soll:
{
      "Name" : "Detail",
      "OriginalName" : "-l",
      "ParameterType" : "switch"
},
Mit dem "ParameterType" auf "switch" konfigurierte Parameter bekommen im Rahmen des Aufrufs des Wrappers keinen Wert angeliefert. Der Nutzer des Wrappers darf den Parameter nur weglassen oder anführen – findet er sich im Aufruf des von Crescendo generierten Cmdlets, zeigt er sich auch im Aufruf der Binärdatei.
Die nächste Amtshandlung im Bezug auf ifconfig ist abermals die Transpilation des Wrappers in PowerShell-Code. Beachten Sie, dass wir den folgenden Befehl nach wie vor unter Windows ausführen:
Export-CrescendoModule -ModuleName ".\ifconfig1.psm1" -ConfigurationFile ".\ifconfig.Crescendo.json"
Die PowerShell erweist sich im Bereich der Skriptausführung als flexibel. Es spricht theoretisch nichts dagegen, unser Modul nach folgendem Schema in den Cmdlets-Cache der Windows-10-Workstation einzupflegen und es dort auszuführen:
Import-Module -Name .\ifconfig1.psm1
 
Invoke-ifconfig
Doch wegen des Fehlens einer ifconfig-Binärdatei scheitert die Programmausführung mit einem Fehler.
Crescendo-Wrapper unter Ubuntu ausführen
Ubuntu 20.04 LTS bringt eine Version von ifconfig mit. Leider stattet Canonical die Linux-Distribution von Haus aus nicht mit einem PowerShell-Interpreter aus, weshalb Sie diesen installieren:
sudo apt-get update
 
sudo apt-get install -y wget apt-transport-https software-properties-common
 
wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
 
sudo dpkg -i packages-microsoft-prod.deb
 
sudo apt-get update
 
sudo apt-get install -y powershell
Nach dem erfolgreichen Durchlaufen lässt sich die PowerShell per pwsh starten. Übertragen Sie im nächsten Schritt die Dateien von der Windows-Workstation auf den Unix-Rechner und installieren Sie diese:
Import-Module -Name './ifconfig1.psm1' -Force
Nun lässt sich ifconfig aus der PowerShell per Invoke-ifconfig aufrufen. Dank der Parameterdeklaration dürfen Sie zudem festlegen, welches Netzwerk-Interface interessant ist (Invoke-ifconfig eth0).
Verarbeitung der Kommandoausgabe
Die PowerShell implementiert im Bereich der Datenverarbeitung wie zuvor besprochen eine Art Objektorientierung. Viele Cmdlets liefern Informationen in Form von "Structs" zurück. Skripte dürfen so die enthaltenen Werte gezielt ansprechen, um nur benötigte Teile der Informationen weiterzuverarbeiten.
Daraus folgt, dass PowerShell Crescendo in diesem Bereich ebenfalls eine Logik anbietet, die die von Kommandozeilenwerkzeugen zurückgegebenen Ergebnisse ins PowerShell-idiomatische Format bringt. Der einfachste Handler ist ein Inline-Element. Dabei handelt es sich um eine einzelne Codezeile, die die angelieferten Ergebnisse direkt in ein PowerShell-Objekt konvertiert (Listing 4).
Listing 4: Konvertieren der Ergebnisse in ein PowerShell-Objekt
{     "$schema": "../src/Microsoft.PowerShell.Crescendo.Schema.json",    "Commands": [      {       "Verb": "New",        "Noun": "Command1",        "OriginalName": "<path><command>",        "OutputHandlers": [          {             "ParameterSetName": "viaInline",             "HandlerType": "Inline",             "Handler": "$args[0] | ConvertFrom-Json"          }        ]     },
Alternativ dazu haben Sie die Option, die Verarbeitung durch ein dediziertes Skript zu erledigen. Hierfür ist ein OutputHandler vom Typ "Script" verantwortlich, der nach folgendem Schema ein mehr oder weniger beliebiges anderes Skript aufruft:
{
."Verb": "New",
."Noun": "Command2",
."OriginalName":"<path><command>",
."OutputHandlers": [
…{
… "ParameterSetName": "viaScript",
… "HandlerType": "Script",
… "Handler": "Convert-GetDate.ps1"
…}
.]
}
Zu guter Letzt erlaubt Crescendo, schon in der PowerShell-Umgebung befindliche Funktionen zur Datenverarbeitung zu verwenden. Hierzu setzen Sie den HandlerType auf "Function":
{
."Verb": "New",
."Noun": "Command3",
."OriginalName":"<path><command>",
."OutputHandlers": [
…{
… "ParameterSetName": "viaFunction",
… "HandlerType": "Function",
… "Handler": "Convert-GetDate"
…}
.]
}
Beachten Sie bei der Verwendung von "Function", dass die Nutzung einer "hauseigenen" PowerShell-Funktion eine Beziehung zwischen dem Crescendo-Wrapper und dieser Funktion herstellt. Beim Verteilen des Wrappers müssen Sie darauf achten, diese Beziehung (meist manuell) herzustellen. Ein als "HandlerType:Script" angelegtes Skript transpiliert Crescendo in den Wrapper, weshalb sie es beim Austeilen nicht separat mitliefern müssen.
Fazit
Microsoft bietet Administratoren mit PowerShell Crescendo ein schlagkräftiges Werkzeug, dass die Reichweite der PowerShell weit über den Windows-Bereich ergänzt. Dazu plant Microsoft über kurz oder lang ein GitHub-artiges Verzeichnis, in dem Administratoren und Entwickler Crescendo-Wrapper austauschen können. Im Zusammenspiel mit der Verfügbarkeit der PowerShell für verschiedene Nicht-Microsoft-Betriebssysteme entwickelt sich die Skriptumgebung zu einem wahren Tausendsassa.
(jp)
Link-Codes