vault-ssh-otp unter windows ( ohne sshpass )

Vault ist ein Passwort Manager und mehr für den professionellen Einsatz. Die Sicherheitsfeatures sind beeindruckend und das alles in einem OpenSource Tool das keinen Cent kostet. Unter anderem bietet das Tool die Möglichkeit OneTimePasswords (otp) zu erstellen. Unter Linux sind die otp einfach zu nutzen unter Windows leider nicht ganz so einfach.

Um eine ähnlich komfortabele Lösung für Windows Benutzer zu bieten habe ich hier ein kleines Powershell Skript geschrieben.
Es wird putty vorausgesetzt anderenfalls umschreiben ;-)

Hier gehts zu Vault von Hashicorp : https://www.vaultproject.io/

Eine Anmeldung mit einem Token sieht dann so aus :
vault-ssh-windows token
Eine Anmeldung mit user/pass ist auch möglich:
vault-ssh-windows userpass


# vault-ssh.ps1 for windows tested on Powershell 5.1
# you need an puuty installation, NOT ONLY THE EXE FILE !
# read parameter
param (
    [string]$VR,
    [string]$VU,
    [string]$VI,
    [string]$VUU,
    [string]$LM="t",
    [int]$d=0
)
# function
function show_help {
  Write-Host ""
  Write-Host "-VR Vault Role"
  Write-Host "-VU User for target host"
  Write-Host "-VI IP address for target host"
  Write-Host "-LM define the login method ( use u / t for userpass / token default ist token)"
  Write-Host "      if you use userpass -VUU is required"
  Write-Host "        -VUU vault username"
  Write-Host "-d 1 activate debug mode (default is -d 0)"
  Write-Host ""
  Write-Host "examples :"
  Write-Host "---------------------------------------------------------------"
  Write-Host "                            TOKEN"
  Write-Host "---------------------------------------------------------------"
  write-Host "vault-ssh.ps1 -VR admin -VU root -VI 192.168.2.1"
  Write-Host "---------------------------------------------------------------"
  Write-Host "                            USERPASS"
  Write-Host "---------------------------------------------------------------"
  write-Host "vault-ssh.ps1 -VR admin -VU root -VI 192.168.2.1 -LM u -VUU YOUR_USERNAME"
  Write-Host " "
  
  exit 0
}
# check parameter
if ([string]::IsNullOrWhitespace($VR) -or [string]::IsNullOrWhitespace($VU) -or [string]::IsNullOrWhitespace($VI)) {
  Write-Host -ForegroundColor Yellow "not enough parameter !"
  show_help
}
# get vault address
try {
    $VAULT_SRV=$env:VAULT_ADDR
} catch {
    Write-Host -ForegroundColor Red "Environment Variable VAULT_ADDR not found please set the Enviroment with 'setx VAULT_ADDR ADDRESS_TO_VAULT_HA'"
    exit 99
}
# get vault master #
try {
  # /sys/leader
  $VAULT_LEADER=Invoke-RestMethod -Method Get -Uri "$VAULT_SRV/v1/sys/leader" | ConvertTo-Json | ConvertFrom-Json
  [string]$VAULT_LEADER_ADDR=$VAULT_LEADER.leader_address
  # debug output
  if ( $d -eq 1 ) { Write-Host -ForegroundColor Yellow "Leader : $VAULT_LEADER_ADDR " }
  if ( $VAULT_LEADER_ADDR -ne $VAULT_SRV ) {
    # debug output
    if ( $d -eq 1 ) { Write-Host -ForegroundColor Red "$VAULT_SRV is not the leader connect to $VAULT_LEADER_ADDR instead" $msg }
    $VAULT_SRV=$VAULT_LEADER_ADDR
  } else {
    # debug output
    if ( $d -eq 1 ) { Write-Host -ForegroundColor Yellow "VAULT_ADDR is the leader address" }
  }
} catch {
  Write-Host -ForegroundColor Red "could not get vault master !"
  Exit 99
} 
# check vault health 
try {
    $VAULT_REQ=Invoke-WebRequest -Uri "$VAULT_SRV/v1/sys/health" -Method GET -UseBasicParsing
    $VAULT_STATUS=$VAULT_REQ.StatusCode
    switch ($VAULT_STATUS) {
        # check status code 
        200 { 
              $msg="VAULT is initialized, unsealed, and active"
              $vok="Green"
            }
        429 { 
              $msg="VAULT is unsealed and standby"
              $vok="Yellow"
            }
        472 { 
              $msg="VAULT is in data recovery mode replication secondary and active"
              $vok="Yellow"
            }
        473 { 
              $msg="VAULT is in performance standby"
              $vok="Yellow"
            }
        501 { $msg="VAULT is not initialized"
              $vok="Red"
            }
        503 { 
              $msg="VAULT ist sealed"
              $vok="Red"
            }
    }
} catch {
    Write-Host -ForegroundColor Red "Could not check vault status ! is the address correct ? $VAULT_SRV"
    Exit 97
}
# debug output 
if ( $d -eq 1 ) { Write-Host -ForegroundColor $vok $msg }
switch ($LM) {
  "t" {
      # get vault-token 
      try {
        $VAULT_TOKEN=$env:VAULT_TOKEN
        if ([string]::IsNullOrWhitespace($VAULT_TOKEN)) {
          # if no enviroment set ask for token
          $VAULT_TOKEN=Read-Host -AsSecureString "Need your vault token ! "
          }
        } catch {
          Write-Host -ForegroundColor Red "an error occured - vault token"
          Exit 98
        }
        # no token no cookies 
        if ([string]::IsNullOrWhitespace([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($VAULT_TOKEN)))) { Write-Host -Foreground Red "no token given ... how do you think does an authentification work ?" ; exit 90}
        # get ssh otp from vault 
        $vhead = @{
          'X-Vault-Token' = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($VAULT_TOKEN))
        }
        $VAULT_OTP_REQ=Invoke-RestMethod -Uri $VAULT_SRV/v1/ssh/creds/$VR -Method Post -headers $vhead -Body "{ `"ip`": `"$VI`" }" | ConvertTo-Json | ConvertFrom-Json
        $VAULT_OTP=$VAULT_OTP_REQ.data.key
        # run putty 
        try {
          putty.exe -ssh $VU@$VI -pw $VAULT_OTP
        } catch {
          Write-Host -ForegroundColor Red "putty.exe not find please define the path in enviroment variables"
          Exit 96
        }
      }
    "u" {
      $VUP=Read-Host -AsSecureString "please enter you vault password "
      $VUP_E = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($VUP))
      try {
        # login vault 
        $VLogIn=Invoke-RestMethod -Uri $VAULT_SRV/v1/auth/userpass/login/$VUU -Method Post -Body "{ `"username`": `"$VUU`" , `"password`": `"$VUP_E`"}" | ConvertTo-Json | ConvertFrom-Json
      } catch {
        Write-Host -ForegroundColor Red "Wrong Password ?"
        Exit 92
      }
      $vhead = @{
        # set token to client_token get from login 
        'X-Vault-Token' = $VLogIn.auth.client_token
      }
      try {
        # get otp password 
        $VAULT_OTP_REQ=Invoke-RestMethod -Uri $VAULT_SRV/v1/ssh/creds/$VR -Method Post -headers $vhead -Body "{ `"ip`": `"$VI`" }" | ConvertTo-Json | ConvertFrom-Json
      } catch {
        Write-Host -ForegroundColor Red "could not get client_token"
        Exit 93
      }
      $VAULT_OTP=$VAULT_OTP_REQ.data.key
       # run putty 
       try {
        putty.exe -ssh $VU@$VI -pw $VAULT_OTP
       } catch {
        Write-Host -ForegroundColor Red "putty.exe not find please define the path in enviroment variables"
        Exit 96
      }
  }
}


Quellen :
https://www.hashicorp.com/

Exchange: Mitglieder einer dynamischen Verteilerliste mit Powershell ermitteln

Skript zum Abfragen der Mitglieder in einer dynamischen Verteilerlisten:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
$DDL = “Name-der-Verteilerliste”
Get-DynamicDistributionGroup $DDL | ForEach {Get-Recipient -RecipientPreviewFilter $_.RecipientFilter -OrganizationalUnit $_.RecipientContainer} | Select DisplayName,PrimarySMTPAddress | Format-Table 

Hinweis: Die erste Zeile braucht man nur, wenn das Powershell-Skript außerhalb der Exchange-Powershell laufen lässt. Diese lädt die Exchange-Verwaltungsmodule!

Exchange 2013: Powershell Error : FailureCategory=Cafe-SendFailure FullyQualifiedErrorId : -2144108477

Problem:
Szenario: Windows Server 2008 R2 aktuell gepatcht - Exchange 2013 CU14 installiert

Beim Versuch auf die Powershell zuzugreifen, wird folgender Fehler mehrfach ausgegeben:
VERBOSE: Connecting to exchange2013. New-PSSession : [exchange2013] Connecting to remote server exchange2013 failed with the following error message : [ClientAccessServer=exchange2013,BackEndServer=exchange2013,RequestId=fd9724cd-19fb-4842-b30d-c9c4b976119f,TimeStamp =2016-03-24 18:55:58] [FailureCategory=Cafe-SendFailure] For more information, see the about_Remote_Troubleshooting He lp topic. At line:1 char:1 + New-PSSession -ConnectionURI “$connectionUri” -ConfigurationName Microsoft CategoryInfo : OpenError: (System.Manageme….RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotin gTransportException + FullyQualifiedErrorId : -2144108477,PSSessionOpenFailed


Lösung:
Nach etwas Recherche war mir klar, dass es mit dem SSL-Zertifikat von Exchange zu tun haben muss.

1. Lösungsansatz:
Bitte prüfen Sie im IIS-Manager ob sowohl bei der "Default Web Site" und der "Exchange Back End" unter "Bindungen" -> HTTPS das richtige (oder überhaupt ein gültiges) SSL-Zertifikat zugewiesen ist. Eventuell bei der Powershell-Website unter "Exchange Back End" auch mal bei den "SSL-Einstellungen" den Haken bei "SSL erforderlich" entfernen - somit wird das SSL-Zertifikat ignoriert und man kann prüfen, ob dann die Powershell-Verbindung funktioniert.

2. Lösungsansatz (Fehler bei mir):
Nachdem das Zertifikat in Ordnung war, musste ich nach einem anderem Fehler suchen.
Fündig würde ich im Ereignisprotokoll hier habe ich folgenden Eintrag gefunden:
Schannel - Event-ID: 36885
Bei der Nachfrage der Clientauthentifizierung sendet dieser Server eine Liste vertrauenswürdiger Zertifizierungsstellen an den Client. Der Client verwendet diese Liste, um ein Clientzertifikat auszuwählen, das für den Server vertrauenswürdig ist. Momentan vertraut dieser Server sehr vielen Zertifizierungsstellen, sodass die Liste zu lang ist. Die Liste wurde abgeschnitten. Der Administrator dieses Computer sollte die für Clientauthentifizierung vertrauenswürdigen Zertifizierungsstellen überprüfen und diejenigen entfernen, die nicht unbedingt als vertrauenswürdig eingestuft werden müssen.
Mit dieser Meldung habe ich mittels Zertifikats-MMC ein mal die "Vertrauenswürdigen Stammzertifikatsstellen überprüft" und hier 299(!!) Zertifikate gefunden, die Großteils mir überhaupt nicht bekannt waren. Eine weitere Suche im Netz hat folgenden Microsoft-Artikel hervorgebracht: Microsoft: SSL/TLS communication problems after you install KB931125
Hier wird beschrieben, dass so etwas auftreten kann, nach der Installation des Updates KB931125.
Die Lsöung im Artikel habe ich wie folgt durchgeführt:

1.) Öffnen Sie den Registry-Editor (regedit.exe)
2.) Navigieren Sie zu folgendem Pfad: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\Certificates
3.) Exportieren Sie diesen Pfad sicherheitshalber und löschen Sie Ihn danach!

Danach hatte ich nur noch ca. 20 Zertifikate in den vertrauenswürdigen Stammzertifikatsstellen und meine Powershell und alle HTTPS-Seiten auf meinem Exchange 2013 liesen sich problemlos öffnen!

Quelle der Lösungsfindung:
blackseals.net: Liste der vertrauenswürdigen Stamm-Zertifizierungsstellen ist zu lang
Microsoft: SSL/TLS communication problems after you install KB931125

Server 2008 R2 - Add-WindowsFeature NET-HTTP-Activation - 0x800f081f

Problem:
Bei meiner Exchange-Installation wollte ich auf einem Server 2008R2 mittels Powershell alle nötigen Features hinzufügen. Dabei ist mir die Routine immer bei der Installation "NET-HTTP-Activation" auf den Fehler 0x800f081f gelaufen.


Lösung:
Nach einigem Probieren bin ich auf einen Eintrag im Internet gestoßen, wie man das .NetFX3 manuell installieren kann.
Hierzu bitte eine Installations-DVD in das Laufwerk legen (hier E:) und den folgenden Befehl als Administrator starten:

DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:E:\sources\sxs

Wobei Source: eventuell angepasst werden muss, je nachdem wo das Laufwerk gemountet ist.

Danach ließ sich die die NET-HTTP-Activation problemlos per Powershell installieren.

Installierte Rollen & Features eines Servers anzeigen

Wenn man die installierten Rollen & Features eines Servers anzeigen möchte ist der schnellste Weg die Powershell.
Hierführ wird .NET Framework 4.5 und Powershell 4.0 benötigt.

Der Befehl dafür lautet :
Get-WindowsFeature | Where installed -eq true




Bitte schaut nach ob es ein aktuelleres Update für .NET Framework gibt zum Zeitpunkt der Erstellung war das aktuellste Release 4.5.2


Downloads :
.NET Framework 4.5
Powershell 4.0
“Sicher ist, dass nichts sicher ist. Selbst das nicht.”
Joachim Ringelnatz