2016-05-26 8 views
1

Ich habe eine funktionierende Anwendung zur Verwaltung von HDFS mit WebHDFS. Ich muss dies auf einem Kerberos-gesicherten Cluster tun können.Zugriff auf kerberos gesichert WebHDFS ohne SPnego

Das Problem ist, dass es keine Bibliothek oder Erweiterung gibt, um das Ticket für meine App zu verhandeln, ich habe nur einen einfachen HTTP-Client.

Wäre es möglich, einen Java-Service zu erstellen, der den Ticketaustausch abwickelt und das Serviceticket einfach an die App zur Verwendung in einer HTTP-Anforderung weiterleitet? Mit anderen Worten, meine App würde den Java-Dienst bitten, die Tickets zu verhandeln, und es würde das Service-Ticket in einer Zeichenfolge oder einer unbearbeiteten Zeichenfolge zurück an meine App senden und die App würde es einfach an die HTTP-Anfrage anhängen?

EDIT: Gibt es eine ähnlich elegante Lösung wie @SamsonScharfrichter für HTTPfs beschrieben? (Nach meinem Wissen, es unterstützt keine Delegation Tokens)

EDIT2: Hallo Leute, ich bin immer noch völlig verloren. Ich versuche, den Hadoop-Auth-Client ohne Glück herauszufinden. Könnten Sie mir bitte wieder helfen? Ich habe schon Stunden damit verbracht, ohne Glück darüber zu lesen. Die Beispiele sagen, dies zu tun:

* // establishing an initial connection 
* 
* URL url = new URL("http://foo:8080/bar"); 
* AuthenticatedURL.Token token = new AuthenticatedURL.Token(); 
* AuthenticatedURL aUrl = new AuthenticatedURL(); 
* HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection(); 
* .... 
* // use the 'conn' instance 
* .... 

Im bereits hier verloren. Welche erste Verbindung brauche ich? Wie kann

new AuthenticatedURL(url, token).openConnection(); 

nehmen Sie zwei Parameter? Für einen solchen Fall gibt es keinen Konstruktor. (Ich bekomme deswegen einen Fehler). Sollte ein Auftraggeber nicht irgendwo angegeben sein? Es wird wahrscheinlich nicht so einfach sein.

URL url = new URL("http://<host>:14000/webhdfs/v1/?op=liststatus"); 
    AuthenticatedURL.Token token = new AuthenticatedURL.Token(); 

    HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection(url, token); 
+0

Ich denke, es könnte möglich sein, das zu tun, aber es öffnet nur die Sicherheitslücke, die Kerberos geschlossen hat. Ich glaube, Knox/Sentry erlaubt Ihnen den Zugriff auf Daten über einige API-Punkte, nein? –

+0

Danke für einen Hinweis, aber ich kann nicht Knox verwenden, wenn es öffnet, ist das Sicherheitsloch für eine Diskussion, sobald es funktioniert. – MaBu

+0

AFAIK alle Hadoop GUIs und REST-Dienste verwenden ein ** signiertes Cookie **, um die Kerberos-Anmeldeinformationen zwischenzuspeichern - mit Ausnahme von WebHDFS, für das das Delegierungstoken explizit verwaltet werden muss. Vielleicht ist es möglich, den Cookie mit einer HTTP-Bibliothek zu erstellen und ihn dann mit einer anderen Sitzung zu verwenden. Sie sollten versuchen, eine "Debug-Modus" -Verbindung mit HttpFS auszuführen, um zu prüfen, ob ein Cookie beteiligt ist. Und hoffentlich ist Ihr "einfacher HTTP-Client" nicht zu einfach und lässt Sie an Cookies basteln. –

Antwort

4

Verwendung von Java-Code und den Hadoop Java-API eine Kerberized Sitzung zu öffnen, erhält die Delegation Token für Die Sitzung, und übergeben Sie dieses Token an die andere App - wie von @tellisnz vorgeschlagen - hat einen Nachteil: die Java-API erfordert eine ganze Reihe von Abhängigkeiten (dh eine Menge von JARs, sowie Hadoop native Bibliotheken). Wenn Sie Ihre App insbesondere unter Windows ausführen, wird es eine harte Fahrt.

Eine weitere Option ist Java-Code zu verwenden und WebHDFS eine einzige SPNEGOed Abfrage auszuführen und GET die Delegation Token, dann gibt sie an den anderen app - diese Option erfordert absolut keine Hadoop-Bibliothek auf Ihrem Server. Die Barebone-Version würde wie

URL urlGetToken = new URL("http://<host>:<port>/webhdfs/v1/?op=GETDELEGATIONTOKEN") ; 
HttpURLConnection cnxGetToken =(HttpURLConnection) urlGetToken.openConnection() ; 
BufferedReader httpMessage = new BufferedReader(new InputStreamReader(cnxGetToken.getInputStream()), 1024) ; 
Pattern regexHasToken =Pattern.compile("urlString[\": ]+(.[^\" ]+)") ; 
String httpMessageLine ; 
while ((httpMessageLine =httpMessage.readLine()) != null) 
{ Matcher regexToken =regexHasToken.matcher(httpMessageLine) ; 
    if (regexToken.find()) 
    { System.out.println("Use that template: http://<Host>:<Port>/webhdfs/v1%AbsPath%?delegation=" +regexToken.group(1) +"&op=...") ; } 
} 
httpMessage.close() ; 

STHG sein, das ist, was ich HDFS für den Zugriff von einem Windows Powershell-Skript (oder sogar ein Excel-Makro).Achtung: Unter Windows müssen Sie Ihr Kerberos-TGT im laufenden Betrieb erstellen, indem Sie eine JAAS-Konfiguration an die JVM übergeben, die auf die entsprechende Chiffrierschlüsseldatei verweist. Diese Einschränkung gilt jedoch auch für die Java-API.

+1

Vielen Dank, ich werde es auf diese Weise versuchen und Sie wissen lassen, wie alles gelandet ist. – MaBu

+1

Wir haben es geschafft, dies zu lösen, indem wir das Delegierungstoken für WebHDFS und das signierte Cookie für HTTPfs verwenden. Vielen dank für Deine Hilfe. – MaBu

0

Sie einen Blick auf die hadoop-auth client nehmen und erstellen Sie einen Dienst, der die erste Verbindung der Fall ist, dann könnten Sie in der Lage sein, den ‚Authorization‘ und von ‚X-Hadoop-Delegation-Token‘ Header und Cookie zu greifen es und fügen Sie es den Anforderungen Ihres grundlegenden Kunden hinzu.

Zuerst müssen Sie entweder kinit verwendet haben, um Ihren Benutzer für die Anwendung zu authentifizieren, bevor Sie ihn ausführen. Andernfalls müssen Sie für Ihren Benutzer eine JAAS-Anmeldung durchführen, this tutorial bietet einen ziemlich guten Überblick darüber, wie dies zu tun ist.

Dann die Anmeldung WebHDFS/HttpFS zu tun, müssen wir wie etwas tun:

URL url = new URL("http://youhost:8080/your-kerberised-resource"); 
AuthenticatedURL.Token token = new AuthenticatedURL.Token(); 
HttpURLConnection conn = new AuthenticatedURL().openConnection(url, token); 

String authorizationTokenString = conn.getRequestProperty("Authorization"); 
String delegationToken = conn.getRequestProperty("X-Hadoop-Delegation-Token"); 
... 
// do what you have to to get your basic client connection 
... 
myBasicClientConnection.setRequestProperty("Authorization", authorizationTokenString); 
myBasicClientConnection.setRequestProperty("Cookie", "hadoop.auth=" + token.toString()); 
myBasicClientConnection.setRequestProperty("X-Hadoop-Delegation-Token", delegationToken); 
+0

Danke für einen Tipp, den ich mit [webhdfs-java-client] (https://github.com/zxs/webhdfs-java-client/) gemacht habe. Ich würde es wahrscheinlich ändern, um das Dienstticket zurückzugeben, sobald es erhalten wurde. Ich habe mich gefragt, ob das funktionieren würde. – MaBu

+0

Ja, das sieht ein bisschen alt aus. Mit hadoop-auth könnte es so einfach sein wie oben bearbeiten. – tellisnz