Interesting....

Almost the entirety of Knox request/response processing is done in
ServletFilters that represent each Provider along the chain as well as the
dispatch to backend services or the JAXRS service of a Knox API.

We could do this inside of a Provider filter but that would limit the
details provided to the application logic of the GatewayServlet rather than
being more container managed - I would think.
That may also be the case for custom error pages in the web.xml - but it
could at least be pattern matched across multiple servlets in the webapp if
need be.

I will give it some more thought and maybe find some time to try out the
web.xml change.

On Tue, Sep 10, 2019 at 2:36 PM jeff saremi <[email protected]> wrote:

> So continuing with the assumption that the problem must be me, I decided
> to create a small app which uses jetty and a web.xml plus two servlets to
> demonstrate the intent.
> It worked perfectly the first time!
> Here's the link to the application. The web.xml is modeled after what I
> modified last in knox.
> I tested the app with the following URL's and each time I got the expected
> result:
> http://localhost:8080/?error=503
>
> {"error": {"code":503,"uri":"/"}}
>
>
> https://1drv.ms/u/s!AmK9GYfTgrv-psxYrFLkiSd-Qpiv4Q?e=oge5qY
>
> So currently I'm sitting at the point that I cannot seem to be able to
> inject any additional servlets and any error redirections in Knox
>
> If someone tells me the first/last entry point in the application where I
> have the chance to intercept all errors/messages before going back to the
> user I would really appreciate it. This way I can modify the source code
> and be done with this with no messy web.xml and additional servlets.
>
> thanks
>
> ------------------------------
> *From:* jeff saremi <[email protected]>
> *Sent:* Monday, September 9, 2019 9:53 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: Adding a web.xml to gateway.jar
>
> I got further by making sure that the startup scripts do not touch the
> topology file anymore.
> I can see the deployment staying the same as I modified it
> However there must be something wrong with my web.xml or the servlet ,
> since all requests  mow return a 503 which does not seem to be initiated by
> the gateway logic itself. It could be that my web.xml is invalid or my
> servlet creates an infinite loop or something like that.
> I've got some investigating to do.
> Basically this the last version of the web.xml (truncated):
>
>   <servlet>
>     <servlet-name>default-knox-gateway-servlet</servlet-name>
>     <servlet-class>org.apache.knox.gateway.GatewayServlet</servlet-class>
>     <init-param>
>       <param-name>gatewayDescriptorLocation</param-name>
>       <param-value>/WEB-INF/gateway.xml</param-value>
>     </init-param>
>   </servlet>
>   <servlet>
>     <servlet-name>exception-handler-servlet</servlet-name>
>     <servlet-class>ExceptionHandlerServlet</servlet-class>
>   </servlet>
>   <servlet-mapping>
>     <servlet-name>exception-handler-servlet</servlet-name>
>     <url-pattern>/ExceptionHandler</url-pattern>
>   </servlet-mapping>
>   <servlet-mapping>
>     <servlet-name>default-knox-gateway-servlet</servlet-name>
>     <url-pattern>/*</url-pattern>
>   </servlet-mapping>
> ...
>     <param-name>rewriteDescriptorLocation</param-name>
>     <param-value>/WEB-INF/rewrite.xml</param-value>
>   </context-param>
>   <error-page>
>     <error-code>503</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>400</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>401</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>404</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
> </web-app>
>
>
> The Servlet file:
> ------------------------------
>
>     try {
>     // Analyze the servlet exception
>     Throwable throwable = (Throwable)
> request.getAttribute("javax.servlet.error.exception");
>     Integer statusCode = (Integer)
> request.getAttribute("javax.servlet.error.status_code");
>     String servletName = (String)
> request.getAttribute("javax.servlet.error.servlet_name");
>     if (servletName == null) {
>       servletName = "Unknown";
>     }
>     String requestUri = (String)
> request.getAttribute("javax.servlet.error.request_uri");
>     if (requestUri == null) {
>       requestUri = "Unknown";
>     }
>
>     // Set response content type
>     response.setContentType("application/json");
>
>     PrintWriter out = response.getWriter();
>     out.write("{");
>     if(statusCode != 500){
>       out.write("\"error\": {");
>       out.write("\"code\":"+statusCode+",");
>       out.write("\"uri\":\""+requestUri+"\"}");
>     } else {
>       out.write("\"exception\":{");
>       out.write("\"servletName\":\""+servletName+"\",");
>
> out.write("\"exceptionClass\":\""+throwable.getClass().getName()+"\",");
>       out.write("\"uri\":\""+requestUri+"\",");
>       out.write("\"message\":\""+throwable.getMessage()+"\"}");
>     }
>     out.write("}");
>     } catch (Throwable e) {
>         log("Error inside ExceptionHandler: " + e.getMessage());
>     }
>
> Sample error returned by knox:
> ------------------------------------------
>
> root@clustertest:~# curl -iku user:password -X GET
> https://gateway-svc:8443/gateway/default/webhdfs/v1/?op=LISTSTATUS
> HTTP/1.1 503 Service Unavailable
> Date: Tue, 10 Sep 2019 04:40:19 GMT
> Cache-Control: must-revalidate,no-cache,no-store
> Content-Type: text/html;charset=iso-8859-1
> Content-Length: 364
> Server: Jetty(9.4.12.v20180830)
>
> <html>
> <head>
> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
> <title>Error 503 Service Unavailable</title>
> </head>
> <body><h2>HTTP ERROR 503</h2>
> <p>Problem accessing /gateway/default/webhdfs/v1/. Reason:
> <pre>    Service Unavailable</pre></p><hr><a href="
> http://eclipse.org/jetty";>Powered by Jetty:// 9.4.12.v20180830</a><hr/>
>
> </body>
> </html>
>
> ------------------------------
> *From:* jeff saremi <[email protected]>
> *Sent:* Monday, September 9, 2019 8:12 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: Adding a web.xml to gateway.jar
>
> Good pointers.
> We're not using Ambari or any gui to do this. All command line.
> This is the supervisord config file:
>
> root@gateway-0:/opt/supervisor/conf.d# ls
> knox.conf
> root@gateway-0:/opt/supervisor/conf.d# cat knox.conf
> [program:knoxgateway]
> command=/opt/knox/bin/gateway-launcher.sh
> stopasgroup=true
> startretries=3
>
> What makes a deployment to take place?
> What command lines should I be looking for?
> The only thing i see relevant is that the conf/topologies/default.xml is
> touched (re-created from a template file)
> Could that be causing a re-deployment?
>
> ------------------------------
> *From:* larry mccay <[email protected]>
> *Sent:* Monday, September 9, 2019 4:53 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: Adding a web.xml to gateway.jar
>
> Interesting.
> I'm not really familiar with Supervisord but it seems to be not only
> restarting the process but causing the redeployment of the topologies.
> Is it making an Ambari API call to restart Knox or something like that?
>
> The short term goal needs to be a restart that doesn't redeploy and the
> reuse of the web.xml.
> This would be just to verify that what you want to do works as expected
> then we would need to add the error handling to the ShrinkWrap code that
> generates the web.xml in the Knox deployment machinery.
>
> If you are using a default.xml topology that sounds like you are using
> Ambari and HDP?
> Are you able to remove Knox from the Supervisord monitoring temporarily or
> even just turn it off?
>
> If so, we can then stop the Knox process via Ambari then restart Knox
> manually.
> If you restart from Ambari it will push out configuration again and you
> will get a new deployment - so don't do that.
>
> A simple restart without config being changed will just load the previous
> web.xml and webapp without deploying a new one.
>
> On Mon, Sep 9, 2019 at 7:10 PM jeff saremi <[email protected]> wrote:
>
> Larry
> I created a jar file out of a single ExceptionServlet and placed in
> GATEWAY_HOME/ext:
>
> root@gateway-0:/opt/knox# ls -l ext
> total 12
> -rw-r--r-- 1 root root   83 Sep  6 00:23 README
> -rwxr-xr-- 1 root root 1704 Sep  9 22:41 error-servlet.jar
> drwxr--r-- 2 root root 4096 Sep  6 00:23 native
>
> root@gateway-0:/opt/knox# jar tvf ext/error-servlet.jar
>      0 Mon Sep 09 15:24:44 UTC 2019 META-INF/
>     64 Mon Sep 09 15:24:44 UTC 2019 META-INF/MANIFEST.MF
>   2382 Mon Sep 09 15:23:54 UTC 2019 ExceptionHandlerServlet.class
>
> Since I appear to be using 'default' in my URLs I'm guessing that would be
> the right topology. So i went to data/deployments and modified the
> following web.xml:
> data/deployments/default.topo.16d08ec29f0
>
> updated web.xml:
>
>
> root@gateway-0:/opt/knox# tail -25
> data/deployments/default.topo.16d08ec29f0/%2F/WEB-INF/web.xml
>     <param-value>/WEB-INF/rewrite.xml</param-value>
>   </context-param>
>
>   <error-page>
>     <error-code>400</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>401</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>404</error-code>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <exception-type>java.lang.Throwable</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <exception-type>javax.servlet.ServletException</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>
> </web-app>
>
> I then killed the running process (since it was started by the Supervisor
> d) and it restarted itself
>
> The response were identical to before meaning that my servlet was never hit
>
> Looking at the deployment folder, I see that there's another 'default*'
> folder is created with updated timestamp. And the new web.xml there does
> not have any of my changes of course
>
> If I were to make these changes to the web.xml permenant, where would be
> the right location, given that the web.xml seems to be created on the fly.
>
>
>
> ------------------------------
> *From:* jeff saremi <[email protected]>
> *Sent:* Saturday, September 7, 2019 4:28 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: Adding a web.xml to gateway.jar
>
> Great suggestions! Thanks Larry
> I will work on getting the web.xml and the servlet integrated
> Completely agreed on the vulnerability side. We may expose this in a DEBUG
> version and not the release or provide a config value...
> ------------------------------
> *From:* larry mccay <[email protected]>
> *Sent:* Friday, September 6, 2019 7:25 PM
> *To:* [email protected] <[email protected]>
> *Subject:* Re: Adding a web.xml to gateway.jar
>
> Hi Jeff -
>
> This is an interesting idea and we should consider discussing this as a
> feature of Knox rather than just something that you are trying to hack into
> an existing release/deployment.
>
> In order to get this to work, I would first change the web.xml in the
> deployments directory for a given topology and add the servlet to the in a
> jar within {GATEWAY_HOME}/ext directory.
> Stop and start the server and it should hopefully pickup the changed
> web.xml file.
>
> In order to cause a 500, I think just dispatching to an invalid URL would
> result in a 500 with a connection exception.
>
> See if that web.xml will work and we can take it from there.
>
> It should be noted that surfacing the details of a webappexception may
> expose sensitive information about the server and you may not want to
> always have this enabled.
>
> HTH.
>
> --larry
>
> On Fri, Sep 6, 2019 at 9:37 PM jeff saremi <[email protected]> wrote:
>
>
> Ultimately I am trying to make sure when an HTTP 500 error happens the
> exception message and stacktrace are returned in the response, in the
> gateway
> So I decided to add a web.xml and overwrite parts of error handling there
> to the gateway project. (added
> to gateway-server-launcher/src/main/resources/META-INF/web.xml)
>
> root@gateway-0:/opt/knox/bin# cat META-INF/web.xml
> <?xml version="1.0" encoding="UTF-8"?>
> <!--
>   Licensed to ...
> -->
> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns="
> http://java.sun.com/xml/ns/javaee"; xsi:schemaLocation="
> http://java.sun.com/xml/ns/javaee
> http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"; version="3.0">
>   <error-page>
>     <error-code>400</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>401</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <error-code>404</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <exception-type>java.lang.Throwable</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
>   <error-page>
>     <exception-type>javax.servlet.ServletException</exception-type>
>     <location>/ExceptionHandler</location>
>   </error-page>
> </web-app>
>
> And then I added the following Servlet (added it
> to 
> gateway-util-common/src/main/java/org/apache/knox/gateway/servlet/ExceptionHandlerServlet.java)
>
>
> @WebServlet("/ExceptionHandler")
> public class ExceptionHandlerServlet extends HttpServlet {
>   private static final long serialVersionUID = 1L;
>
>   protected void service(HttpServletRequest request,
>     HttpServletResponse response) throws ServletException, IOException {
>     // Analyze the servlet exception
>     Throwable throwable = (Throwable)
> request.getAttribute("javax.servlet.error.exception");
>     Integer statusCode = (Integer)
> request.getAttribute("javax.servlet.error.status_code");
>     String servletName = (String)
> request.getAttribute("javax.servlet.error.servlet_name");
>     if (servletName == null) {
>       servletName = "Unknown";
>     }
>     String requestUri = (String)
> request.getAttribute("javax.servlet.error.request_uri");
>     if (requestUri == null) {
>       requestUri = "Unknown";
>     }
>
>     // Set response content type
>     response.setContentType("text/html");
>
>     PrintWriter out = response.getWriter();
>     out.write("<html><head><title>Exception/Error
> Details</title></head><body>");
>     if(statusCode != 500){
>       out.write("<h3>Error Details</h3>");
>       out.write("<strong>Status Code</strong>:"+statusCode+"<br>");
>       out.write("<strong>Requested URI</strong>:"+requestUri);
>     } else {
>       out.write("<h3>Exception Details</h3>");
>       out.write("<ul><li>Servlet Name:"+servletName+"</li>");
>       out.write("<li>Exception
> Name:"+throwable.getClass().getName()+"</li>");
>       out.write("<li>Requested URI:"+requestUri+"</li>");
>       out.write("<li>Exception Message:"+throwable.getMessage()+"</li>");
>       out.write("</ul>");
>     }
>
>     out.write("<br><br>");
>     out.write("</body></html>");
>   }
> }
>
>
> I see that the application is launched using gateway.jar. And i also see
> my web.xml inside that jar. However I'm not able to get anything returned
> from this servlet!
>
> I honestly don't know how to repro a 500. But I could do a 400, 401, and
> 404. Neither of them got intercepted by the Exception servlet i wrote.
>
> Here are some examples I ran. Note in the first one, a 400 is returned
> along with some exception message. that's what i want to do for 500 or
> verify that it's being done. However I haven't been able to (using text
> search) find out where in the code this response is formed like this
>
> root@clustertest:/tests/knox# curl -iku root:goodpassword -X GET
> https://gateway-svc:8443/gateway/default/webhdfs/v1/?op=STATUS
> HTTP/1.1 400 Bad Request
> Date: Fri, 06 Sep 2019 23:42:42 GMT
> Set-Cookie:
> KNOXSESSIONID=node01q5krk3jp1c9dzv3fc3t5tkgh4.node0;Path=/gateway/default;Secure;HttpOnly
> Expires: Thu, 01 Jan 1970 00:00:00 GMT
> Set-Cookie: rememberMe=deleteMe; Path=/gateway/default; Max-Age=0;
> Expires=Thu, 05-Sep-2019 23:42:43 GMT
> Date: Fri, 06 Sep 2019 23:42:43 GMT
> Cache-Control: no-cache
> Expires: Fri, 06 Sep 2019 23:42:45 GMT
> Date: Fri, 06 Sep 2019 23:42:45 GMT
> Pragma: no-cache
> X-FRAME-OPTIONS: SAMEORIGIN
> Content-Type: application/json;charset=utf-8
> Transfer-Encoding: chunked
> Server: Jetty(9.4.12.v20180830)
>
> {"RemoteException":{"exception":"IllegalArgumentException","javaClassName":"java.lang.IllegalArgumentException","message":"Invalid
> value for webhdfs parameter \"op\": STATUS is not a valid GET operation."}}
>
>
> root@clustertest:/tests/knox# curl -iku root:goodpassword -X GET
> https://gateway-svc:8443/gateway/default/webhdfs/v1/?op=LISTSTATUS
> HTTP/1.1 200 OK
> Date: Fri, 06 Sep 2019 23:43:29 GMT
> Set-Cookie:
> KNOXSESSIONID=node0iz11bxvbn318h7zow5z977pc5.node0;Path=/gateway/default;Secure;HttpOnly
> Expires: Thu, 01 Jan 1970 00:00:00 GMT
> Set-Cookie: rememberMe=deleteMe; Path=/gateway/default; Max-Age=0;
> Expires=Thu, 05-Sep-2019 23:43:30 GMT
> Date: Fri, 06 Sep 2019 23:43:30 GMT
> Cache-Control: no-cache
> Expires: Fri, 06 Sep 2019 23:43:30 GMT
> Date: Fri, 06 Sep 2019 23:43:30 GMT
> Pragma: no-cache
> X-FRAME-OPTIONS: SAMEORIGIN
> Content-Type: application/json;charset=utf-8
> Transfer-Encoding: chunked
> Server: Jetty(9.4.12.v20180830)
>
>
> {"FileStatuses":{"FileStatus":[{"accessTime":0,"blockSize":0,"childrenNum":0,"fileId":16411,"group":"supergroup","length":0,"modificationTime":1567812978306,"owner":"root","pathSuffix":"jar","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":0,"blockSize":0,"childrenNum":6,"fileId":16389,"group":"supergroup","length":0,"modificationTime":1567812975255,"owner":"root","pathSuffix":"livy","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":16386,"group":"supergroup","length":0,"modificationTime":1567812943856,"owner":"root","pathSuffix":"spark","permission":"775","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":16387,"group":"supergroup","length":0,"modificationTime":1567813293988,"owner":"root","pathSuffix":"spark-events","permission":"733","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":0,"blockSize":0,"childrenNum":2,"fileId":16395,"group":"supergroup","length":0,"modificationTime":1567813273907,"owner":"root","pathSuffix":"tmp","permission":"1777","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":16412,"group":"supergroup","length":0,"modificationTime":1567813267540,"owner":"root","pathSuffix":"user","permission":"777","replication":0,"storagePolicy":0,"type":"DIRECTORY"}]}}
>
>
> root@clustertest:/tests/knox# curl -iku root:goodpassword -X GET
> https://gateway-svc:8443/gateway/default/webhdfs/v2/?op=LISTSTATUS
> HTTP/1.1 404 Not Found
> Date: Fri, 06 Sep 2019 23:43:53 GMT
> Content-Length: 0
> Server: Jetty(9.4.12.v20180830)
>
> root@clustertest:/tests/knox# curl -iku root:badpassword -X GET
> https://gateway-svc:8443/gateway/default/webhdfs/v1/?op=LISTSTATUS
> HTTP/1.1 401 Unauthorized
> Date: Fri, 06 Sep 2019 23:44:17 GMT
> Set-Cookie: rememberMe=deleteMe; Path=/gateway/default; Max-Age=0;
> Expires=Thu, 05-Sep-2019 23:44:17 GMT
> WWW-Authenticate: BASIC realm="application"
> Content-Length: 0
> Server: Jetty(9.4.12.v20180830)
>
>
>
>
>
>
>

Reply via email to