Apache Knox, c'est facile !

Apache Knox, c'est facile !

Vous appréciez notre travail......nous recrutons !

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 :

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.).

Exemple d'architecture Apache Knox

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.

Cinématique d'encapsulation Kerberos

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.

Gestion des certificats via Apache Knox

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.

Cinématique de fonctionnement du plugin Apache Knox pour Apache Ranger

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.

ServiceHadoop URLApache Knox URL
WebHDFShttp://namenode-host:50070/webhdfshttps://knox-host:8443/gateway/default/webhdfs
WebHCathttp://webhcat-host:50111/templetonhttps://knox-host:8443/gateway/default/templeton
Apache Ooziehttp://oozie-host:11000/ooziehttps://knox-host:8443/gateway/default/oozie
Apache HBasehttp://hbase-host:60080https://knox-host:8443/gateway/default/hbase
Apache Hivehttp://hive-host:10001/cliservicehttps://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 /conf/topologies. 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 /data/services. 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

Partagez cet article

Canada - Maroc - France

Nous sommes une équipe passionnée par l'Open Source, le Big Data et les technologies associées telles que le Cloud, le Data Engineering, la Data Science le DevOps…

Nous fournissons à nos clients un savoir faire reconnu sur la manière d'utiliser les technologies pour convertir leurs cas d'usage en projets exploités en production, sur la façon de réduire les coûts et d'accélérer les livraisons de nouvelles fonctionnalités.

Si vous appréciez la qualité de nos publications, nous vous invitons à nous contacter en vue de coopérer ensemble.

Support Ukrain