I have created a simple REST Web Service that returns {"code":4,"type":"ok","message":"hello there!"}
from curl -k -u admin:admin -X GET "https://server.running.service:8447/demo/v1/test"
I want to have all users access the web service though Apache Knox so that they can be authenticated. However, when I use curl -k -u admin:admin -X GET "https://server.running.knox:8443/gateway/platform//hello/v1/test"
I get back:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Error 500 Server Error</title>
</head>
<body><h2>HTTP ERROR 500</h2>
<p>Problem accessing /gateway/platform/hello/v1/test. Reason:
<pre> Server Error</pre></p><hr /><i><small>Powered by Jetty://</small></i><br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</body>
</html>
Looking at the Knox gateway.log file I can see that this error:
INFO hadoop.gateway (KnoxLdapRealm.java:getUserDn(556)) - Computed userDn: uid=admin,ou=people,dc=hadoop,dc=apache,dc=org using dnTemplate for principal: admin
2017-03-20 14:15:53,289 INFO hadoop.gateway (AclsAuthorizationFilter.java:doFilter(85)) - Access Granted: true
2017-03-20 14:15:53,296 WARN hadoop.gateway (DefaultDispatch.java:executeOutboundRequest(138)) - Connection exception dispatching request: https://server.running.knox:8443/gateway/platform/hello/v1/test?user.name=admin javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:290)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:259)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:125)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.apache.hadoop.gateway.dispatch.DefaultDispatch.executeOutboundRequest(DefaultDispatch.java:127)
at org.apache.hadoop.gateway.dispatch.DefaultDispatch.executeRequest(DefaultDispatch.java:114)
at org.apache.hadoop.gateway.dispatch.DefaultDispatch.doGet(DefaultDispatch.java:294)
at org.apache.hadoop.gateway.dispatch.GatewayDispatchFilter$GetAdapter.doMethod(GatewayDispatchFilter.java:145)
at org.apache.hadoop.gateway.dispatch.GatewayDispatchFilter.doFilter(GatewayDispatchFilter.java:117)
at org.apache.hadoop.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:61)
at org.apache.hadoop.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:315)
at org.apache.hadoop.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:215)
at org.apache.hadoop.gateway.filter.AclsAuthorizationFilter.doFilter(AclsAuthorizationFilter.java:89)
at org.apache.hadoop.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:315)
at org.apache.hadoop.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:215)
I'm not sure if I made a mistake when adding the service to Knox. I created a rewrite.xml with the following:
<rules>
<rule dir="IN" name="HELLOSERVICE/hello/inbound/root" pattern="*://*:*
/**/hello/">
<rewrite template="{$serviceUrl[HELLOSERVICE]}/"/>
</rule>
<rule dir="IN" name="HELLOSERVICE/hello/inbound/path" pattern="*://*:*/**/hello/{**}">
<rewrite template="{$serviceUrl[HELLOSERVICE]}/{**}"/>
</rule>
<rule dir="IN" name="HELLOSERVICE/hello/inbound/query" pattern="*://*:*/**/hello/{**}?{**}">
<rewrite template="{$serviceUrl[HELLOSERVICE]}/{**}?{**}"/>
</rule>
<rule dir="OUT" name="HELLOSERVICE/hello/outbound/demo/v1">
<match pattern="*://*:*/demo/v1/{**}"/>
<rewrite template="{$frontend[url]}/hello/v1/{**}"/>
</rule>
</rules>
And a service.xml with the following:
<service role="HELLOSERVICE" name="hello" version="0.0.1">
<routes>
<route path="/hello/"/>
<route path="/hello/**"/>
<route path="/hello/**?**"/>
</routes>
</service>
The platform.xml file has:
<topology>
<gateway>
<provider>
<role>authentication</role>
<name>ShiroProvider</name>
<enabled>true</enabled>
<param>
<name>sessionTimeout</name>
<value>30</value>
</param>
<param>
<name>main.ldapRealm</name>
<value>org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm</value>
</param>
<param>
<name>main.ldapRealm.userDnTemplate</name>
<value>uid={0},ou=people,dc=hadoop,dc=apache,dc=org</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.url</name>
<value>ldap://server.running.knox:33389</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.authenticationMechanism</name>
<value>simple</value>
</param>
<param>
<name>urls./**</name>
<value>authcBasic</value>
</param>
</provider>
<provider>
<role>identity-assertion</role>
<name>Default</name>
<enabled>true</enabled>
</provider>
<provider>
<role>authorization</role>
<name>AclsAuthz</name>
<enabled>true</enabled>
</provider>
<provider>
<role>webappsec</role>
<name>WebAppSec</name>
<enabled>true</enabled>
<param><name>csrf.enabled</name><value>false</value></param> <!-- CSRF Disabled -->
<param><name>csrf.customHeader</name><value>X-XSRF-Header</value></param>
<param><name>csrf.methodsToIgnore</name><value>GET,OPTIONS,HEAD</value></param>
<param><name>cors.enabled</name><value>true</value></param>
<param><name>cors.allowOrigin</name><value>*</value></param>
<param><name>cors.allowSubdomains</name><value>false</value></param>
<param><name>cors.supportedMethods</name><value>GET,POST,HEAD,OPTIONS,PUT,DELETE</value></param>
</provider>
</gateway>
<service>
<role>HELLOSERVICE</role>
<url>http://server.running.service:8088/demo</url>
</service>
</topology>
Did I make a mistake setting up Knox? Is there some other configuration I need to do to be able to send commands to my service through Knox?
Looking at the logs it appears that Knox is trying to connect to an https url (https://server.running.knox:8443/gateway/platform/hello/v1/test?user.name=admin)
But I see that you do have http url in your topology file, so might be that an https upgrade happened.
The problem here seems that your backend uses https so you probably need to provision the backend certificate into your Knox cluster i.e. cert for https://server.running.knox need to be added to Knox trust store (gateway.jks)
HTH