Apache Knox, c'est facile !
4 févr. 2019
- Catégories
- Big Data
- Cybersécurité
- Adaltas Summit 2018
- Tags
- Ranger
- LDAP
- Active Directory
- REST
- Knox
- Kerberos [plus][moins]
Ne ratez pas nos articles sur l'open source, le big data et les systèmes distribués, fréquence faible d’un email tous les deux mois.
Apache Knox est le point d’entrée sécurisé d’un cluster Hadoop, mais peut-il être également le point d’entrée de mes applications REST ?
Vue d’ensemble d’Apache Knox
Apache Knox est une passerelle applicative permettant d’interagir, de manière sécurisée, avec les APIs REST et les interfaces utilisateur d’un ou plusieurs clusters Hadoop, qui propose dès l’installation :
- Un support des services (WebHDFS, Apache Oozie, Apache Hive/JDBC, etc.) et des interfaces utilisateurs (Apache Ambari, Apache Ranger, etc.) les plus courants d’un cluster Hadoop ;
- Une intégration forte avec les systèmes d’authentification d’entreprise (Microsoft Active Directory, LDAP, Kerberos, etc.) ;
- Et plusieurs autres fonctionnalités utiles.
En revanche, ce n’est pas une alternative à Kerberos pour une authentification forte d’un cluster Hadoop, ni un canal pour l’acquisition ou l’exportation de gros volumes de données.
Nous pouvons définir les avantages de la passerelle en quatre différentes catégories :
- Sécurité renforcée via l’exposition des services REST et HTTP sans révéler les détails du cluster Hadoop, le filtre sur les vulnérabilités des applications web ou encore l’utilisation du protocole SSL sur des services n’ayant pas cette possibilité ;
- Contrôle centralisé via l’utilisation d’une seule porte d’entrée facilitant l’audit et les autorisations (avec Apache Ranger) ;
- Accès simplifié grâce à l’encapsulation des services avec Kerberos ou encore l’utilisation d’un certificat SSL unique ;
- Intégration d’entreprise via les principales solutions du marché (Microsoft Active Directory, LDAP, Kerberos, etc.) ou en utilisant des solutions personnalisées (Apache Shiro, etc.).
Encapsulation Kerberos
L’encapsulation est essentiellement utilisée pour les produits incompatibles avec le protocole Kerberos. L’utilisateur fournit son identifiant et mot de passe via l’utilisation du protocole HTTP Basic Auth.
Gestion simplifiée des certificats clients
L’utilisateur fait confiance uniquement au certificat d’Apache Knox, on centralise donc les certificats des différents services sur les serveurs Apache Knox et pas sur tous les clients. Très utile lors de la révocation et création d’un nouveau certificat.
Intégration avec Apache Ranger
Apache Knox intègre un agent Apache Ranger permettant de vérifier les autorisations des utilisateurs voulant accéder aux ressources du cluster.
Hadoop URLs VS Knox URLs
L’utilisation des URLs d’Apache Knox permet d’occulter l’architecture du cluster et permet aux utilisateurs de se souvenir que d’une seule URL.
Service | Hadoop URL | Apache Knox URL |
---|---|---|
WebHDFS | http://namenode-host:50070/webhdfs | https://knox-host:8443/gateway/default/webhdfs |
WebHCat | http://webhcat-host:50111/templeton | https://knox-host:8443/gateway/default/templeton |
Apache Oozie | http://oozie-host:11000/oozie | https://knox-host:8443/gateway/default/oozie |
Apache HBase | http://hbase-host:60080 | https://knox-host:8443/gateway/default/hbase |
Apache Hive | http://hive-host:10001/cliservice | https://knox-host:8443/gateway/default/hive |
Personnalisation d’Apache Knox
Pour configurer la passerelle Apache Knox, nous devons modifier les fichiers de type topology
. Ces fichiers sont composés de trois composants : Providers, HA Provider et Services.
Topology
Vous trouverez les fichiers topology
dans le répertoire
. Le nom du fichier topology
dictera l’URL d’Apache Knox, si le fichier se nomme sandbox.xml, l’URL sera : https://knox-host:8443/gateway/sandbox/webhdfs
.
Voici un exemple de fichier topology
:
<topology>
<gateway>
<!-- Authentication provider -->
<provider>
<role>authentication</role>
<name>ShiroProvider</name>
<enabled>true</enabled>
[...]
</provider>
<!-- Identity assertion provider -->
<provider>
<role>identity-assertion</role>
<name>HadoopGroupProvider</name>
<enabled>true</enabled>
[...]
</provider>
<!-- Authorization provider -->
<provider>
<role>authorization</role>
<name>XASecurePDPKnox</name>
<enabled>true</enabled>
[...]
</provider>
<!-- HA provider -->
<provider>
<role>ha</role>
<name>HaProvider</name>
<enabled>true</enabled>
[...]
</provider>
</gateway>
<!-- Services -->
<service>
<role>WEBHDFS</role>
<url>http://webhdfs-host:50070/webhdfs</url>
</service>
</topology>
Attention, si vous utilisez Apache Ambari, les topologies admin
, knoxsso
, manager
et default
doivent être modifiées via l’interface web, sinon, en cas de redémarrage du service, les fichiers seront écrasés.
Provider
Les providers ajoutent de nouvelles fonctionnalités (authentication
, federation
, authorization
, identity-assertion
, etc) à la passerelle qui pourront être utilisées par les différents services, ce sont généralement un ou plusieurs filtres qui sont ajoutés à une ou plusieurs topologies.
La passerelle Apache Knox prend en charge la fédération (federation
) via l’ajout d’en-tête HTTP. La fédération permet de rapidement mettre en place l’authentification unique (SSO) en propageant les informations de l’utilisateur et son groupe. A utiliser uniquement dans un environnement réseau très contrôlé.
Le fournisseur d’authentification (authentication
) par défaut est Apache Shiro (ShiroProvider
). Il est utilisé pour une authentification vers un Active Directory ou un LDAP. Pour une authentification via Kerberos, nous utiliserons HadoopAuth
.
Il existe cinq principaux fournisseurs d’identités (identity-assertion
) :
- Default : c’est le fournisseur par défaut permettant un mappage simple des noms et/ou groupes d’utilisateurs. C’est le responsable de l’établissement de l’identité transmise au reste du cluster ;
- Concat : c’est le fournisseur qui permet la composition d’un nouveau nom et/ou groupes d’utilisateurs en concaténant un préfixe et/ou un suffixe ;
- SwitchCase : ce fournisseur résout le cas où l’écosystème nécessite une casse spécifique pour les noms et/ou groupes d’utilisateurs ;
- Regex : il permet aux identités entrantes d’être traduites à l’aide d’une expression régulière ;
- HadoopGroupProvider : ce fournisseur cherche l’utilisateur au sein d’un groupe permettant de faciliter grandement la mise en place des autorisations (via Apache Ranger).
Dans le cas où vous utilisez le provider HadoopGroupProvider, vous êtes obligés d’utiliser uniquement les groupes pour la mise en place des autorisations (via Apache Ranger), une JIRA (KNOX-821 : Identity Assertion Providers must be able to be chained together) a été ouverte pour pouvoir chaîner ensemble plusieurs fournisseurs d’identités.
Services
Les services quant à eux, ajoutent de nouvelles règles de routage à la passerelle. Les services se trouvent dans le répertoire
. Voici un exemple des fichiers qui composent le service HIVE
:
$ ls -lahR hive/
hive/:
total 12K
drwxr-xr-x 3 knox knox 4.0K Nov 16 2017 .
drwxr-xr-x 84 knox knox 4.0K Nov 16 17:07 ..
drwxr-xr-x 2 knox knox 4.0K Nov 16 2017 0.13.0
hive/0.13.0:
total 16K
drwxr-xr-x 2 knox knox 4.0K Nov 16 2017 .
drwxr-xr-x 3 knox knox 4.0K Nov 16 2017 ..
-rw-r--r-- 1 knox knox 949 May 31 2017 rewrite.xml
-rw-r--r-- 1 knox knox 1.1K May 31 2017 service.xml
Dans le répertoire hive
, nous trouvons le répertoire 0.13.0
(qui correspond à la version du service). Et à l’intérieur de ce dossier, nous trouvons les fichiers rewrite.xml
et service.xml
.
Services personnalisés
Admettons une application REST disponible à l’adresse http://rest-application:8080/api/
. Il suffit de créer un nouveau service
et de l’ajouter dans le fichier topology
.
<topology>
[...]
<!-- Services -->
<service>
<role>{{ service_name | upper }}</role>
<url>http://rest-application:8080</url>
</service>
</topology>
Fichier service.xml
, la valeur de {{ knox_service_version }}
doit être égale au nom du dossier parent.
<service role="{{ service_name | upper }}" name="{{ service_name | lower }}" version="{{ knox_service_version }}">
<policies>
<policy role="webappsec"/>
<policy role="authentication"/>
<policy role="federation"/>
<policy role="identity-assertion"/>
<policy role="authorization"/>
<policy role="rewrite"/>
</policies>
<routes>
<route path="/{{ service_name | lower }}">
<rewrite apply="{{ service_name | upper }}/{{ service_name | lower }}/inbound/root" to="request.url"/>
</route>
<route path="/{{ service_name | lower }}/**">
<rewrite apply="{{ service_name | upper }}/{{ service_name | lower }}/inbound/path" to="request.url"/>
</route>
<route path="/{{ service_name | lower }}/?**">
<rewrite apply="{{ service_name | upper }}/{{ service_name | lower }}/inbound/args" to="request.url"/>
</route>
<route path="/{{ service_name | lower }}/**?**">
<rewrite apply="{{ service_name | upper }}/{{ service_name | lower }}/inbound/pathargs" to="request.url"/>
</route>
</routes>
</service>
Fichier rewrite.xml
où l’on ré-écrit l’URL (en ajoutant ici /api
) :
<rules>
<rule dir="IN" name="{{ service_name | upper }}/{{ service_name | lower }}/inbound/root" pattern="*://*:*/**/{{ service_name | lower }}">
<rewrite template="{$serviceUrl[{{ service_name | upper }}]}/api/{{ service_name | lower }}"/>
</rule>
<rule dir="IN" name="{{ service_name | upper }}/{{ service_name | lower }}/inbound/path" pattern="*://*:*/**/{{ service_name | lower }}/{path=**}">
<rewrite template="{$serviceUrl[{{ service_name | upper }}]}/api/{{ service_name | lower }}/{path=**}"/>
</rule>
<rule dir="IN" name="{{ service_name | upper }}/{{ service_name | lower }}/inbound/args" pattern="*://*:*/**/{{ service_name | lower }}/?{**}">
<rewrite template="{$serviceUrl[{{ service_name | upper }}]}/api/{{ service_name | lower }}/?{**}"/>
</rule>
<rule dir="IN" name="{{ service_name | upper }}/{{ service_name | lower }}/inbound/pathargs" pattern="*://*:*/**/{{ service_name | lower }}/{path=**}?{**}">
<rewrite template="{$serviceUrl[{{ service_name | upper }}]}/api/{{ service_name | lower }}/{path=**}?{**}"/>
</rule>
</rules>
Pour plus de détails concernant la mise en place de services personnalisés derrière Apache Knox, voici un lien vers un article.
Trucs et astuces
Mise en place du SSL
# Requirements
$ export KEYALIAS=gateway-identity
$ export PRIVATEKEYALIAS=gateway-identity-passphrase
$ export KEYPASS=4eTTb03v
$ export P12PASS=$KEYPASS
$ export JKSPASS=$KEYPASS
# Save old Keystore
$ mv /usr/hdp/current/knox-server/data/security/keystores /usr/hdp/current/knox-server/data
$ mkdir /usr/hdp/current/knox-server/data/security/keystores
$ chown knox:knox /usr/hdp/current/knox-server/data/security/keystores
$ chmod 755 /usr/hdp/current/knox-server/data/security/keystores
# Generate Knox Master Key
$ /usr/hdp/current/knox-server/bin/knoxcli.sh create-master --force
> Enter master secret: $JKSPASS
> Enter master secret again: $JKSPASS
# Generate the Keystore
$ openssl pkcs12 -export -in /etc/security/.ssl/`hostname -f`.cer -inkey /etc/security/.ssl/`hostname -f`.key -passin env:KEYPASS \
-out /usr/hdp/current/knox-server/data/security/keystores/gateway.p12 -password env:P12PASS -name $KEYALIAS
$ keytool -importkeystore -deststorepass $JKSPASS -destkeypass $KEYPASS \
-destkeystore /usr/hdp/current/knox-server/data/security/keystores/gateway.jks \
-srckeystore /usr/hdp/current/knox-server/data/security/keystores/gateway.p12 \
-srcstoretype PKCS12 -srcstorepass $P12PASS -alias $KEYALIAS
# Import the parents certificates
$ keytool -import -file /etc/security/.ssl/enterprise.cer -alias enterprise \
-keystore /usr/hdp/current/knox-server/data/security/keystores/gateway.jks -storepass $JKSPASS
# Save the private key in the Keystore
$ /usr/hdp/current/knox-server/bin/knoxcli.sh create-alias $PRIVATEKEYALIAS --value $JKSPASS
Lors de la sauvegarde de la clé privée dans le keystore, la valeur $PRIVATEKEYALIAS
doit obligatoirement être gateway-identity-passphrase
.
Le mot de passe doit correspondre à celui utilisé lors de la génération de la clé maître (Apache Knox Master secret). C’est pour cela que nous utilisons le même mot de passe partout ($JKSPASS
).
Erreurs courantes
Avant toute chose, un redémarrage propre d’Apache Knox permet de résoudre quelques soucis et de purger les logs avant de relancer la requête qui pose problème.
# Stop Apache Knox via Ambari
# Delete topologies and services deployments
$ rm -rf /usr/hdp/current/knox-server/data/deployments/*.topo.*
# Delete JCEKS keystores
$ rm -rf /usr/hdp/current/knox-server/data/security/keystores/*.jceks
# Purge logs
$ rm -rf /var/log/knox/*
# Kill zombie process
$ ps -ef | grep `cat /var/run/knox/gateway.pid`
$ kill -9 `cat /var/run/knox/gateway.pid`
# Start Apache Knox via Ambari
Réponse volumineuse
Si vos requêtes échouent rapidement et retournent une erreur 500, il se peut que la réponse de la requête soit trop volumineuse (8Kb par défaut). Vous trouverez quelque chose comme cela dans le fichier gateway-audit.log :
dispatch|uri|http://<hostname>:10000/cliservice?doAs=<user>|success|Response status: 500
Il suffit de modifier la topologie pour ajouter un paramètre dans le service en question :
<param name="replayBufferSize" value="32" />
Apache Solr
Si vous avez activé l’audit vers Apache Solr dans Apache Ranger (xasecure.audit.destination.solr=true
), il se peut qu’en cas de soucis de système de fichier plein d’Apache Solr, Apache Knox ne puisse plus fonctionner.
Connexions Apache Hive se déconnectant souvent via Apache Knox
Pour corriger ce problème, vous devez ajouter dans le fichier de configuration gateway-site
(ces valeurs sont à modifier selon votre environnement).
gateway.httpclient.connectionTimeout=600000 (10 min)
gateway.httpclient.socketTimeout=600000 (10 min)
gateway.metrics.enabled=false
gateway.jmx.metrics.reporting.enabled=false
gateway.httpclient.maxConnections=128
Comment vérifier mon déploiement ?
Apache Knox propose un client permettant de vérifier plusieurs choses dans le déploiement de votre instance.
Validation du certificat
Validation du certificat utilisé par l’instance Apache Knox, pour vérifier que vous avez bien les certificats de votre entreprise.
$ openssl s_client -showcerts -connect {{ knoxhostname }}:8443
Validation de la topologie
Validation que la description d’un cluster (clustername
équivaut à la topologie) suit les règles de formatage correctes.
$ /usr/hdp/current/knox-server/bin/knoxcli.sh validate-topology [--cluster clustername] | [-- path "path/to/file"]
Authentification et autorisation via LDAP
Cette commande teste la capacité de la configuration d’un cluster (topologie) à authentifier un utilisateur avec les paramètres ShiroProvider
. L’argument --g
liste les groupes dont un utilisateur est membre. Les arguments --u
et --p
sont facultatifs, s’ils ne sont pas fournis, le terminal vous en demandera un.
$ /usr/hdp/current/knox-server/bin/knoxcli.sh user-auth-test [--cluster clustername] [--u username] [--p password] [--g]
Liaison topology / LDAP
Cette commande teste la capacité de la configuration d’un cluster (topologie) à authentifier l’utilisateur fournit uniquement avec les paramètres ShiroProvider
.
$ /usr/hdp/current/knox-server/bin/knoxcli.sh system-user-auth-test [--cluster c] [--d]
Test de la passerelle
En utilisant la méthode d’authentification HTTP Basic Auth :
$ export $KNOX_URL=knox.local
$ curl -vik -u admin:admin-password 'https://$KNOX_URL:8443/gateway/default/webhdfs/v1/?op=LISTSTATUS'
En utilisant la méthode d’authentification Kerberos :
$ export $KNOX_URL=knox.local
$ export $KNOX_USER=knoxuser
$ kdestroy
$ kinit $KNOX_USER
$ curl -i -k --negotiate -X GET -u 'https://$KNOX_URL:8443/gateway/kdefault/webhdfs/v1/?op=LISTSTATUS'
Attention, dans ce cas là, nous utilisons la topologie kdefault
qui utilise quant à elle un provider d’authentification de type HadoopAuth
.
Lecture directe
Le dossier /usr/hdp/current/knox-server/data/deployments/
contient les différents dossiers correspondant à vos différentes topologies. A chaque fois que vous modifiez votre topologie, un nouveau dossier est créé sur la base de {{ topologyname }}.topo.{{ timestamp }}
.
Dans le sous dossier %2F/WEB-INF/
, vous trouverez le fichier rewrite.xml
qui est une concaténation du fichier de topologie et des fichiers de services. Dans ce fichier, vous pouvez vérifier que vos règles de réécriture ont bien été prises en compte.
$ cd /usr/hdp/current/knox-server/data/deployments/
$ ll
total 0
drwxr-xr-x. 4 knox knox 31 22 janv. 16:04 admin.topo.168760a5c28
drwxr-xr-x. 4 knox knox 31 24 janv. 18:53 admin.topo.16880fef4b8
drwxr-xr-x. 4 knox knox 31 22 janv. 16:04 default.topo.168760a5c28
drwxr-xr-x. 5 knox knox 49 22 janv. 16:04 knoxsso.topo.168760a5c28
drwxr-xr-x. 5 knox knox 49 22 janv. 16:04 manager.topo.15f6b1f2888
$ cd default.topo.168760a5c28/%2F/WEB-INF/
$ ll
total 104
-rw-r--r--. 1 knox knox 70632 22 janv. 16:04 gateway.xml
-rw-r--r--. 1 knox knox 1112 22 janv. 16:04 ha.xml
-rw-r--r--. 1 knox knox 19384 22 janv. 16:04 rewrite.xml
-rw-r--r--. 1 knox knox 586 22 janv. 16:04 shiro.ini
-rw-r--r--. 1 knox knox 1700 22 janv. 16:04 web.xml
Apache Knox Ranger plugin debug
Cette configuration permet de voir ce qui est transmis à Apache Ranger via le plugin Apache Knox. Il faut modifier le fichier gateway-log4j.properties
comme ci-dessous. Redémarrez vos instances Apache Knox et consultez les logs dans le fichier ranger.knoxagent.log
.
ranger.knoxagent.logger=DEBUG,console,KNOXAGENT
ranger.knoxagent.log.file=ranger.knoxagent.log
log4j.logger.org.apache.ranger=${ranger.knoxagent.logger}
log4j.additivity.org.apache.ranger=false
log4j.appender.KNOXAGENT=org.apache.log4j.DailyRollingFileAppender
log4j.appender.KNOXAGENT.File=${app.log.dir}/${ranger.knoxagent.log.file}
log4j.appender.KNOXAGENT.layout=org.apache.log4j.PatternLayout
log4j.appender.KNOXAGENT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n %L
log4j.appender.KNOXAGENT.DatePattern=.yyyy-MM-dd
Améliorer les temps de réponse via Apache Knox
Si vous avez des temps de réponses qui sont très supérieurs en passant par Apache Knox, vous pouvez modifier ces différents paramètres dans le fichier de configuration gateway.site
.
gateway.metrics.enabled=false
gateway.jmx.metrics.reporting.enabled=false
gateway.graphite.metrics.reporting.enabled=false
Conclusion
En conclusion, Apache Knox est un outil puissant permettant, à l’aide des audits Apache Ranger, de filtrer et auditer tous les accès à votre ou vos environnements. Mais il permet aussi d’être utilisé comme une passerelle classique devant vos différents services personnalisés moyennant de la configuration. Vous pouvez, par exemple, ajouter une authentification Kerberos devant vos APIs REST qui en sont dépourvues. Maintenant, à vous de jouer et faites nous vos retours dans la section commentaire.
Sources
- http://knox.apache.org/books/knox-0-12-0/user-guide.html
- http://knox.apache.org/books/knox-0-12-0/dev-guide.html
- https://fr.slideshare.net/KevinMinder/knox-hadoopsummit20140505v6pub
- https://issues.apache.org/jira/browse/KNOX-821
- https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.6.3/bk_security/content/configure_ssl_for_knox.html
- https://community.hortonworks.com/content/supportkb/153880/hive-connection-through-knox-disconnects-continuou.html
- https://community.hortonworks.com/articles/114601/how-to-configure-and-troubleshoot-a-knox-topology.html
- https://community.hortonworks.com/articles/113013/how-to-troubleshoot-and-application-behind-apache.html
- https://community.hortonworks.com/content/supportkb/191924/how-to-improve-performance-of-knox-request-per-sec.html
- https://cwiki.apache.org/confluence/display/KNOX/KIP-2+Metrics
- https://issues.apache.org/jira/browse/KNOX-643