SMS Passcode: Login mit sAMAccountName unterbinden

SMS Passcode ist eine Software für die 2-Faktor-Authentifizierung. Sie generiert OTPs die dem User auf verschiedenen Wegen zugestellt werden können, z.B. via Software Token App auf dem Handy, E-Mail, Telefonanruf, API, oder eben SMS. SMS Passcode setzt dabei auf den Network Policy Server (den RADIUS Dienst von Microsoft) auf. SMS Passcode lässt sich durch die RADIUS Architektur sehr einfach an jeden RADIUS kompatiblen Dienst anbinden, u.a. an den Citrix NetScaler.

SMS Passcode kann Passwörter bzw. User Accounts mit „Windows NT“ über das Active Directory (via Computer Account in der Domäne) oder LDAP (via LDAP Bind) auflösen. Auch im LDAP Mode ist aber trotz richtiger Konfiguration auch immer der Login via sAMAccountName möglich, selbst wenn der sAMAccountName explizit nicht als Benutzername angegeben oder importiert wird.

Problematisch ist dies in Multi-Domain-Setups, in denen ausschließlich mit einem Login mit dem userPrincipalName gerechnet wird, etwa wenn Citrix StoreFront ohne Default Domains betrieben wird. Hier funktioniert nur der Login mit dem Domänenprefix (DOMAIN\username) bzw. dem userPrincipalName (user@domain.local).

Falls User aus der Gewohnheit heraus den Login mittels sAMAccountName versuchen klappt dieser zwar, das NetScaler Gateway kennt jedoch die für das SSO nötige Domain des Users nicht. Die Folge ist eine „Permission Denied“ Fehlermeldung von Storefront nach erfolgreicher Authentifizierung.

Es gibt jedoch eine einfache Möglichkeit Loginversuche via SAM auf der Windows NPS Ebene zu unterbinden, um Benutzer nicht in dieses Problem laufen zu lassen.

SMS Passcode - NPS Policy

In der Connection Request Policy im NPS kann eine Condition für den Usernamen konfiguriert werden. Hier sind auch Regular Expressions supported.

# Regular Expression für den userPrincipalName
^.*\@.*$

Mit dieser Condition wird geprüft ob der Username mindestens ein @-Zeichen enthält. Falls nicht, greift die Policy nicht. Gibt es keine andere machende Policy, schlägt der Login komplett fehl.

NetScaler Gateway Nagios Plugin

Ich habe gestern einen sehr interessanten Beitrag zum Thema Storefront und cURL gefunden (Login to Storefront with cURL). In diesem Blog ist beschrieben wie man mittels PowerShell den Login auf einem NetScaler Gateway durchführen kann um sich ein funktionierendes ICA File herunterladen zu können.

Auf dieser Basis habe ich mich mal an die Arbeit gemacht und das ganze in Perl und LWP übersetzt. Entstanden ist ein weiteres, kleines Nagios Plugin zur Überwachung eines Citrix NetScaler Gateway Deployments in Verbindung mit

-bash# ./check_netscaler_gateway.pl -H citrix.example.com -u monitoring -p password -S Lab -v
** POST https://citrix.example.com/cgi/login ==> 302 Object Moved
** POST https://citrix.example.com/cgi/setclient?wica ==> 200 OK
** POST https://citrix.example.com/Citrix/LabWeb/Home/Configuration ==> 200 OK
** POST https://citrix.example.com/Citrix/LabWeb/Authentication/GetAuthMethods ==> 200 OK
** POST https://citrix.example.com/Citrix/LabWeb/GatewayAuth/Login ==> 200 OK
** POST https://citrix.example.com/Citrix/LabWeb/Resources/List ==> 200 OK
** GET https://citrix.example.com/cgi/logout ==> 200 OK
NetScaler Gateway OK - Admin Desktop; CAD Desktop; Calculator; HDX Desktop; HDX TS Desktop; Server 2016 Desktop; Windows 8 Desktop; XA 2012 Desktop;

Das Plugin emuliert den kompletten Login Prozess eines Users von NetScaler Gateway über SSO zum Storefront bis hin zum Auflisten der Applikationen. Der Code steht auf GitHub bereit.

Im Fehlerfall lässt sich mittels –verbose Parameter direkt feststellen an welcher Stelle es Probleme gibt.

NetScaler Nagios Plugin (check_netscaler)

Mein NetScaler Nagios Monitoring Plugin (auf Perl Basis) steht nun auf GitHub zum Download zur Verfügung. Dokumentation und einige Beispiele für die Verwendung finden sich direkt auf der GitHub Seite.

https://github.com/slauger/check_netscaler

Das Plugin arbeitet komplett über die NITRO REST API des Citrix NetScalers. Das Plugin unterstützt aktuell folgende Kommandos.

  • state – Prüft den Status eines vServers, eines Services oder einer Servicegruppe ab.
  • above, below – Prüfung einer Response aus der API mit einen Schwellwert.
  • string, string_now – Prüfung ob ein String in einer API Response enthalten ist (oder nicht).
  • sslcert – Prüfung der Gültigkeit von SSL Zertifikaten auf dem NetScaler.
  • nsconfig – Prüfung ob alle Konfigurationsänderungen auf der Appliance gespeichert wurden.
# NetScaler::LBvServer
./check_netscaler.pl -H ${IPADDR} -s -C state -o lbvserver

# NetScaler::LBvServer::Website
./check_netscaler.pl -H ${IPADDR} -s -C state -o lbvserver -n vs_lb_http_webserver

# NetScaler::Services::Webserver
./check_netscaler.pl -H ${IPADDR} -s -C state -o service -n svc_webserver

# NetScaler::Certs
./check_netscaler.pl -H ${IPADDR} -s -C sslcert -w 30 -c 10

# NetScaler::Config
./check_netscaler.pl -H ${IPADDR} -s -C nsconfig

Ich freue mich über Fragen, Anregungen, Wünsche und natürlich auch Pull Requests.

Puppet Module mittels r10k über Puppetfile deployen

Hier ein kurzer Überblick über mein aktuelles Management meiner Puppet Module und Manifests mittels r10k. Das Tool r10k kümmert sich darum, das aus einem Git-Branch innerhalb eines Repositories mit Puppet Code ein nutzbares Puppet Environment wird. Das unten stehende Setup läuft nun bereits seit einigen Monaten so produktiv und ich bin wirklich sehr zufrieden mit r10k.

Meine eigentliche r10k Konfiguration ist sehr einfach gehalten. Ich lasse ausschließlich ein Verzeichnis /etc/puppet/environments deployen, in dem ich alle Dateien und Verzeichnise ablege. Zwecks Performance handelt es sich bei diesem Verzeichnis um ein tmpfs. Ein globales Manifest oder globale Module gibt es nicht. Hiera liegt ebenfalls im environment Verzeichnis.

# /etc/environment.conf
---
:cachedir: /var/cache/r10k
:sources:
   :environments:
     remote: ssh://root@localhost/opt/puppet/environments.git
     basedir: /etc/puppet/environments

Hier ein kurzer Ausschnitt über den Aufbau des Git-Repositories. Der Masterbranch wurde von „master“ umbenannt in „production“, um hier mit Puppet auf einen gemeinsamen Nenner zu kommen. Aktuell gibt es zwei Branches: production und testing.

658084 drwxr-xr-x 10 root root 4.0K May 10 22:30 .
702437 drwxr-xr-x  3 root root 4.0K Dec 18  2014 ..
715811 -rw-r--r--  1 root root  207 Apr 30 21:50 environment.conf
832255 drwxr-xr-x 28 root root 4.0K Apr 30 21:57 forge/
658085 drwxr-xr-x  8 root root 4.0K Jul 14 22:56 .git
133592 drwxr-xr-x  4 root root 4.0K May 10 22:28 hieradata/
659093 drwxr-xr-x  2 root root 4.0K Apr 28 21:28 manifests/
659095 drwxr-xr-x 24 root root 4.0K May 10 21:59 modules/
718207 -rw-r--r--  1 root root 2.0K May 10 22:30 Puppetfile
727181 drwxr-xr-x 26 root root 4.0K Apr 30 21:56 puppetlabs/
658124 -rw-r--r--  1 root root    2 Dec 18  2014 README
727182 drwxr-xr-x 10 root root 4.0K Apr 30 21:56 theforeman/
659308 drwxr-xr-x  2 root root 4.0K Dec 18  2014 tools/

Die Modulpfade werden mit einer environment.conf konfiguriert. Dies hat den schönen Vorteil, das man hier sauber zwischen Testing und Production trennen kann und je nach Branch zusäzliche Verzeichnise ohne viel Aufwand einbringen kann. Die Trennung nach Quelle der Module ist einfach Geschmackssache und hat keinen wirklichen technischen Vorteil.

# environment.conf
modulepath = puppetlabs:theforeman:forge:modules:/etc/puppet/modules:/usr/share/puppet/modules
manifest = manifests
#config_version = get_environment_commit.sh
#environment_timeout = 180

Die eigentliche Logik für alle „externen“ Module liegt in der Datei „Puppetfile“. Dieses File wird von r10k je nach Wunsch bei jedem Deployment evaluiert. Dort können Module aus Git und SVN-Repos oder aber Module aus der Puppet Forge (Forge API) eingebunden werden. Hier noch eine Doku von Puppetlabs zum Thema Puppetfile. Hier meine momentane Konfiguration, mit der ich sehr glücklich bin (aufklappen, um die komplette Config zu sehen).

#!/usr/bin/env ruby
#^syntax detection

# puppetlabs
moduledir 'puppetlabs'
mod 'puppetlabs/acl'
mod 'puppetlabs/apt'
mod 'puppetlabs/activemq'
mod 'puppetlabs/apache'
mod 'puppetlabs/concat'
mod 'puppetlabs/corosync'
mod 'puppetlabs/dism'
mod 'puppetlabs/firewall'
mod 'puppetlabs/inifile'
mod 'puppetlabs/java'
mod 'puppetlabs/java_ks'
mod 'puppetlabs/mssql'
mod 'puppetlabs/mysql'
mod 'puppetlabs/ntp'
mod 'puppetlabs/postgresql'
mod 'puppetlabs/powershell'
mod 'puppetlabs/puppetdb'
mod 'puppetlabs/rabbitmq'
mod 'puppetlabs/reboot'
mod 'puppetlabs/registry'
mod 'puppetlabs/stdlib'
mod 'puppetlabs/vcsrepo'
mod 'puppetlabs/win_desktop_shortcut'
mod 'puppetlabs/xinetd'
# conflicts with theforeman/git
#mod 'puppetlabs/git'

# theforeman
moduledir 'theforeman'
mod 'concat_native', :git => 'https://github.com/theforeman/puppet-concat_native.git'
mod 'dhcp', :git => 'https://github.com/theforeman/puppet-dhcp.git'
mod 'dns', :git => 'https://github.com/theforeman/puppet-dns.git'
mod 'foreman', :git => 'https://github.com/theforeman/puppet-foreman.git'
mod 'foreman_proxy', :git => 'https://github.com/theforeman/puppet-foreman_proxy.git'
mod 'git', :git => 'https://github.com/theforeman/puppet-git.git'
mod 'puppet', :git => 'https://github.com/theforeman/puppet-puppet.git'
mod 'tftp', :git => 'https://github.com/theforeman/puppet-tftp.git'

# forge
moduledir 'forge'
mod 'acme/sysstat'
mod 'adrien/alternatives'
mod 'akumria/nullmailer'
mod 'crayfishx/gemsource'
mod 'darin/zypprepo'
mod 'duritong/trocla'
mod 'elasticsearch/logstash'
mod 'garethr/erlang'
mod 'hunner/hiera'
mod 'ispavailability/file_concat'
mod 'jdowning/rbenv'
mod 'liamjbennett/win_facts'
mod 'nanliu/staging'
mod 'pdxcat/collectd'
mod 'richardc/datacat'
mod 'rismoney/chocolatey'
mod 'rtyler/jenkins'
mod 'saz/memcached'
mod 'saz/sudo'
#mod 'spotify/puppetexplorer'
mod 'stahnma/epel'
mod 'thias/mailman'
mod 'thias/postfix'
mod 'thomasvandoren/etckeeper'
#mod 'wcooley/nss_pam_ldapd'
mod 'yguenane/authconfig'
mod 'ghoneycutt/dnsclient'

Wer genau hinsieht bemerkt hier das ich alle Module des Foreman Projekts immer aus dem GitHub Masterbranch ziehe. GitHub würde ich generell als Anlaufstelle für Foreman weiterempfehlen. Das Projekt Foreman bringt seine Updates nur sehr unregelmäßig in die Forge ein, wodurch man dann auf wichtige Features wie Support für den Puppetserver sehr lange warten oder gar komplett verzichten müsste.

Bei obiger Konfiguration handelt es sich um das Testing Environment. Das schöne an r10k in Zusammenhang mit einem Puppetfile ist, das auch hier das branchen ohne Probleme funktioniert. Währand ich mich in meinem Test-Environment z.B. immer auf die aktuellsten Versionen oder den Masterbranch bei GitHub ausrollen kann, ist es mir auch möglich Module auf gewisse Versionsstände zu pinnen.

# Pinnen auf einen commit (auch möglich: tags oder branches)
mod 'apache',
  :git    => 'https://github.com/puppetlabs/puppetlabs-apache',
  :commit => 'a0224412893d39463a4fde82887312b279f83e1b'

# Das ganze mit Modulen aus der Puppet Forge
mod 'puppetlabs/apache', '0.10.0'

Dadurch können alle Updates von externen Modulen „sanft“ eingeführt werden und durch alle Environments getestet werden.

Der Worklow bei der Modulentwicklung gestaltet sich dann wie folgt.

# Änderungen am Git-Repo durchführen und commiten
root@foreman01.linux-dev.de:/opt/puppet/environments.git
-bash# git commit -a -m "Neues Feature"
[production 9a5a113] Neues Feature
 1 file changed, 3 insertions(+)

# Push zum Remote
root@foreman01.linux-dev.de:/opt/puppet/environments.git
-bash# git push
Counting objects: 11, done.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 535 bytes, done.
Total 6 (delta 4), reused 0 (delta 0)
To git@intern01.linux-dev.de:/opt/git/environments.git
   36a61ec..9a5a113  production -> production

# Deployment aller Branches via r10k
root@foreman01.linux-dev.de:/opt/puppet/environments.git/modules
-bash# r10k deploy environment -v -p
[R10K::Action::Deploy::Environment - INFO] Deploying environment /etc/puppet/environments/testing
[R10K::Action::Deploy::Environment - INFO] Deploying environment /etc/puppet/environments/production

[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/puppetlabs/acl
[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/puppetlabs/apt
...
[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/theforeman/concat_native
[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/theforeman/dhcp
...
[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/forge/sysstat
[R10K::Action::Deploy::Environment - INFO] Deploying module /etc/puppet/environments/production/forge/alternatives
...

Je nach Bedarf kann man r10 mit oder ohne den Parameter „-p“ ausführen. Mit „-p“ wird das Puppetfile evaluiert und die Module aus der Forge bzw. GitHub eingebunden. Lässt man den Parameter weg, werden ausschließlich die Environments ausgerollt. Empehlenswert ist evtl. auch einen Post-Commit Hook in der Repository für r10k einzurichten. Hat man mehrere Master im Einsatz können die Tools ansible oder mcollective hier unterstützen.

Citrix NetScaler 11: A+ Rating bei Qualys SSL Labs

Update 12.07.2017: der Beitrag wurde auf die aktuellen Gegebenheiten angepasst.

Qualys SSL LabsNachfolgend ein kurzes Cheat-Sheet, um für Webseiten, die auf bzw. hinter einem Citrix NetScaler gehostet sind beim SSL Test von Qualys für seine Webseite ein A+ zu erhalten. Dank NetScaler Version 11 ist dies nun endlich auch für die virtuellen VPX Appliances möglich.

Zunächst benötigt man eine eigene Ciphergruppe, die den Security Standard etwas höher setzt, als die von Haus aus mitgelieferten Gruppen.

add ssl cipher cipher_custom_secure
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-ECDHE-RSA-AES256-GCM-SHA384
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-ECDHE-RSA-AES128-GCM-SHA256
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-ECDHE-RSA-AES-256-SHA384
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-ECDHE-RSA-AES-128-SHA256
bind ssl cipher cipher_custom_secure -cipherName TLS1-ECDHE-RSA-AES256-SHA
bind ssl cipher cipher_custom_secure -cipherName TLS1-ECDHE-RSA-AES128-SHA
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-DHE-RSA-AES256-GCM-SHA384
bind ssl cipher cipher_custom_secure -cipherName TLS1.2-DHE-RSA-AES128-GCM-SHA256
bind ssl cipher cipher_custom_secure -cipherName TLS1-DHE-RSA-AES-256-CBC-SHA
bind ssl cipher cipher_custom_secure -cipherName TLS1-DHE-RSA-AES-128-CBC-SHA
bind ssl cipher cipher_custom_secure -cipherName TLS1-AES-256-CBC-SHA
bind ssl cipher cipher_custom_secure -cipherName TLS1-AES-128-CBC-SHA

Am einfachsten ist es die Einstellungen global mittels SSL Default Profile zu konfigurieren. Das Default Profile muss jedoch zunächst aktiviert werden.

set ssl parameter -defaultProfile ENABLED
Y

Im Anschluss kann die neue Cipher Gruppe an die Default Profiles für Frontend und Backend gebunden werden.

bind ssl profile ns_default_ssl_profile_frontend -cipherName cipher_custom_secure
unbind ssl profile ns_default_ssl_profile_frontend -cipherName DEFAULT

bind ssl profile ns_default_ssl_profile_backend -cipherName cipher_custom_secure
unbind ssl profile ns_default_ssl_profile_backend -cipherName DEFAULT_BACKEND

Die SSL Renegotiation wird auf NONSECURE konfiguriert.

set ssl profile ns_default_ssl_profile_frontend -denySSLReneg NONSECURE
set ssl profile ns_default_ssl_profile_backend -denySSLReneg NONSECURE

Zusätzlich benötigt man noch eine Rewrite Policy, um den HTTP STS Header in die Server Response einzufügen. Der folgende Befehl aktiviert die Policy global (Priorität 100).

add rewrite action act_rewrite_inject_http_sts_header insert_http_header Strict-Transport-Security "\"max-age=31536000\""
add rewrite policy pol_rewrite_inject_http_sts_header true act_rewrite_inject_http_sts_header
bind rewrite global pol_rewrite_inject_http_sts_header 100 NEXT -type RES_OVERRIDE