- Subscribe to RSS Feed
- Mark Question as New
- Mark Question as Read
- Float this Question for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page
Authentication with the Zeppelin REST API
- Labels:
-
Apache Zeppelin
Created ‎08-22-2016 05:54 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to use the Sandbox to perform queries against Zeppelin's Notebook REST API. Previously Zeppelin did not require any credentials to access notebooks. Now that they use authentication I can't seem to find a way to access it. I haven't found any documentation either.
I made the following cURL request:
curl -i -X GET http://sandbox.hortonworks.com:9995/api/notebook
This gives me a redirect with the following response:
HTTP/1.1 302 Found Date: Wed, 17 Aug 2016 08:24:39 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 8:24:39 AM UTC Set-Cookie: JSESSIONID=6b055152-eb81-4c86-8976-61e85d0541cf; Path=/; HttpOnly Location: http://sandbox.hortonworks.com:9995/api/login;JSESSIONID=6b055152-eb81-4c86-8976-61e85d0541cf Content-Length: 0 Server: Jetty(9.2.15.v20160210)
Looks like it's a redirect to /api/login
So let's try /api/login and see what happens
curl -i -X GET http://sandbox.hortonworks.com:9995/api/login
This gives the following response:
HTTP/1.1 500 Server Error Date: Wed, 17 Aug 2016 08:25:53 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 8:25:53 AM UTC Content-Type: text/html; charset=ISO-8859-1 Cache-Control: must-revalidate,no-cache,no-store Content-Length: 9546 Connection: close Server: Jetty(9.2.15.v20160210) <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Error 500 Server Error</title> </head> <body><h2>HTTP ERROR 500</h2> <p>Problem accessing /api/login. Reason: <pre> Server Error</pre></p><h3>Caused by:</h3><pre>javax.servlet.ServletException: Filtered request failed. at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:384) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.apache.zeppelin.server.CorsFilter.doFilter(CorsFilter.java:72) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.AbstractMethodError: javax.ws.rs.core.Response.getStatusInfo()Ljavax/ws/rs/core/Response$StatusType; at javax.ws.rs.WebApplicationException.validate(WebApplicationException.java:186) at javax.ws.rs.ClientErrorException.<init>(ClientErrorException.java:88) at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:503) at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:207) at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:103) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153) at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:211) at javax.servlet.http.HttpServlet.service(HttpServlet.java:575) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61) at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) ... 22 more </pre> <h3>Caused by:</h3><pre>java.lang.AbstractMethodError: javax.ws.rs.core.Response.getStatusInfo()Ljavax/ws/rs/core/Response$StatusType; at javax.ws.rs.WebApplicationException.validate(WebApplicationException.java:186) at javax.ws.rs.ClientErrorException.<init>(ClientErrorException.java:88) at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:503) at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:207) at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:103) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153) at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:211) at javax.servlet.http.HttpServlet.service(HttpServlet.java:575) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61) at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.apache.zeppelin.server.CorsFilter.doFilter(CorsFilter.java:72) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Thread.java:745) </pre> <hr><i><small>Powered by Jetty://</small></i><hr/> </body> </html>
It's just an HTML page about the server error. I couldn't find anything in the docs on authentication.
Does anyone know how to use the REST API now that it's locked down?
Created ‎08-22-2016 08:49 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So after some more investigation and toying around with the API I've found the solution.
The first step is to authentic through the API with a POST to /api/login
curl -i --data 'userName=admin&password=password1' -X POST http://127.0.0.1:9995/api/login
This should return a response like the following:
HTTP/1.1 200 OK Date: Wed, 17 Aug 2016 10:07:22 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 10:07:22 AM UTC Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 10:07:22 GMT Set-Cookie: JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 10:07:22 GMT Content-Type: application/json Date: Wed, 17 Aug 2016 10:07:22 GMT Content-Length: 118 Server: Jetty(9.2.15.v20160210) {"status":"OK","message":"","body":{"principal":"admin","ticket":"47a1fe3a-593d-47ce-85bb-f6e7238c6dcb","roles":"[]"}}
The important thing to see here is the Set-Cookie in the response headers.
Look for the following:
Set-Cookie: JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly
Using this cookie we can make authorized request to the API by simply setting this as a cookie in the cURL request.
curl -i -b 'JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly' http://sandbox.hortonworks.com:9995/api/notebook
This request should now return a 200 OK response after adding the JSESSIONID cookie.
HTTP/1.1 200 OK Date: Wed, 17 Aug 2016 10:10:44 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 10:10:44 AM UTC Content-Type: application/json Date: Wed, 17 Aug 2016 10:10:44 GMT Content-Length: 1012 Server: Jetty(9.2.15.v20160210) {"status":"OK","message":"","body":[{"id":"2BSVACJ42","name":"/demo/note1"},{"id":"2BVBPU1VY","name":"/demo/note2"},{"id":"2APFTN3NY","name":"AON Demo"},{"id":"2ANT56EHN","name":"Australian Dataset (Hive example)"},{"id":"2ANTDG878","name":"Australian Dataset (SparkSQL example)"},{"id":"2B48PF7SN","name":"Hello World Tutorial"},{"id":"2AS5TY6AQ","name":"IoT Data Analysis (Keynote Demo)"},{"id":"2BFGYS3YT","name":"Lab 101: Intro to Spark with Python"},{"id":"2BJVW65WS","name":"Lab 102: Intro to Spark with Scala"},{"id":"2BNDT63TY","name":"Lab 201: Intro to Machine Learning with Spark"},{"id":"2B21B3AYC","name":"Phoenix demo"},{"id":"2BB5CUPUW","name":"Predicting airline delays"},{"id":"2BAVUZ7NA","name":"Sensors \u0026 Machines Predictive Analysis"},{"id":"2BBBW75VS","name":"Single view demo"},{"id":"2BEQE47HR","name":"Tutorial - Hands-on Tour of Apache Spark in 5 Minutes"},{"id":"2A94M5J1Z","name":"Zeppelin Tutorial"},{"id":"2B4TWGC8M","name":"magellan-blog"},{"id":"2B522V3X8","name":"twitter"}]}
Created ‎08-22-2016 08:22 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After doing a bit of investigating I found that I can make a successful POST to the /api/login which results in a JSON response with a ticket.
curl -i --data 'userName=admin&password=password1' -X POST http://sandbox.hortonworks.com:9995/api/login HTTP/1.1 200 OK Date: Wed, 17 Aug 2016 09:44:57 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 9:44:57 AM UTC Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 09:44:57 GMT Set-Cookie: JSESSIONID=84983c45-ceca-4db3-a366-9eab27399a68; Path=/; HttpOnly Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 09:44:57 GMT Content-Type: application/json Date: Wed, 17 Aug 2016 09:44:57 GMT Content-Length: 118 Server: Jetty(9.2.15.v20160210) {"status":"OK","message":"","body":{"principal":"admin","ticket":"47a1fe3a-593d-47ce-85bb-f6e7238c6dcb","roles":"[]"}}
Is there anything I can do with the ticket to authenticate against a notebook request?
Created ‎08-22-2016 08:49 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So after some more investigation and toying around with the API I've found the solution.
The first step is to authentic through the API with a POST to /api/login
curl -i --data 'userName=admin&password=password1' -X POST http://127.0.0.1:9995/api/login
This should return a response like the following:
HTTP/1.1 200 OK Date: Wed, 17 Aug 2016 10:07:22 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 10:07:22 AM UTC Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 10:07:22 GMT Set-Cookie: JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 16-Aug-2016 10:07:22 GMT Content-Type: application/json Date: Wed, 17 Aug 2016 10:07:22 GMT Content-Length: 118 Server: Jetty(9.2.15.v20160210) {"status":"OK","message":"","body":{"principal":"admin","ticket":"47a1fe3a-593d-47ce-85bb-f6e7238c6dcb","roles":"[]"}}
The important thing to see here is the Set-Cookie in the response headers.
Look for the following:
Set-Cookie: JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly
Using this cookie we can make authorized request to the API by simply setting this as a cookie in the cURL request.
curl -i -b 'JSESSIONID=b1f15e00-4571-4079-a699-338bf619b0c4; Path=/; HttpOnly' http://sandbox.hortonworks.com:9995/api/notebook
This request should now return a 200 OK response after adding the JSESSIONID cookie.
HTTP/1.1 200 OK Date: Wed, 17 Aug 2016 10:10:44 GMT Access-Control-Allow-Origin: Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: authorization,Content-Type Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, HEAD, DELETE Date: Wednesday, August 17, 2016 10:10:44 AM UTC Content-Type: application/json Date: Wed, 17 Aug 2016 10:10:44 GMT Content-Length: 1012 Server: Jetty(9.2.15.v20160210) {"status":"OK","message":"","body":[{"id":"2BSVACJ42","name":"/demo/note1"},{"id":"2BVBPU1VY","name":"/demo/note2"},{"id":"2APFTN3NY","name":"AON Demo"},{"id":"2ANT56EHN","name":"Australian Dataset (Hive example)"},{"id":"2ANTDG878","name":"Australian Dataset (SparkSQL example)"},{"id":"2B48PF7SN","name":"Hello World Tutorial"},{"id":"2AS5TY6AQ","name":"IoT Data Analysis (Keynote Demo)"},{"id":"2BFGYS3YT","name":"Lab 101: Intro to Spark with Python"},{"id":"2BJVW65WS","name":"Lab 102: Intro to Spark with Scala"},{"id":"2BNDT63TY","name":"Lab 201: Intro to Machine Learning with Spark"},{"id":"2B21B3AYC","name":"Phoenix demo"},{"id":"2BB5CUPUW","name":"Predicting airline delays"},{"id":"2BAVUZ7NA","name":"Sensors \u0026 Machines Predictive Analysis"},{"id":"2BBBW75VS","name":"Single view demo"},{"id":"2BEQE47HR","name":"Tutorial - Hands-on Tour of Apache Spark in 5 Minutes"},{"id":"2A94M5J1Z","name":"Zeppelin Tutorial"},{"id":"2B4TWGC8M","name":"magellan-blog"},{"id":"2B522V3X8","name":"twitter"}]}
Created ‎03-15-2017 06:56 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just using cookie like zblanco said
Created ‎05-09-2018 03:46 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I was able to succesfully post to the api/login to get the cookie and then post a notebook to the user's account using Postman. I am also able to log into the web browser successfully. However, I noticed that the notebooks when I log into Zeppelin through the browser are a different set of notebooks than when I log into zeppelin using the cookie.
Created ‎11-03-2018 07:50 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you please share how you did it? I´m also trying to replicate it in Postman but so far with no success....
