Rewriting paths with undertow-handlers.conf doesn't work as expected - jboss7.x

Background
JBoss 7.1.5 EAP back-end with an Angular 7 UI.
I need to make JBoss aware of the UI's routes, but rewrite them all to the UI's index page for routing by Angular.
The project is structured thus:
webapp/
WEB-INF/
undertow-handlers.conf
web.xml
...etc
login/
background.jpg
login.jsp
index.jsp
assets/*
...html
...js
...css
index.jsp simply response.sendRedirect("index.html")s, where index.html is part of the assets produced by the Angular CLI. JavaScript and HTML is served from webapp/, images from webapp/assets/.
Configuration
From standalone-full.xml
<subsystem xmlns="urn:jboss:domain:undertow:4.0">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="http" socket-binding="http" redirect-socket="https"/>
<host name="default-host" alias="localhost,workstation">
<location name="/" handler="welcome-content"/>
<filter-ref name="request-dumper"/>
</host>
</server>
<servlet-container name="default">
<jsp-config x-powered-by="false"/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<filters>
<filter name="request-dumper" module="io.undertow.core" class-name="io.undertow.server.handlers.RequestDumpingHandler"/>
</filters>
</subsystem>
and
<subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
<virtual-server name="default-host">
<alias name="localhost"/>
<alias name="workstation"/>
</virtual-server>
</subsystem>
With the above configuration, I see the expected server log:
[org.wildfly.extension.undertow] (ServerService Thread Pool -- 84) WFLYUT0021: Registered web context: '/' for server 'default-server'
And I can access the site's login page, and the URI / serves the main angular index page and assets as expected.
Problem
What I need is for paths in this context (like /base or /shop/60) to be handled by Angular, so redirected to index.
As a simple test based on this answer, I have tried this single rule in WEB-INF/undertow-handlers.conf:
exists(%{RELATIVE_PATH}) -> done
path-prefix('/') -> rewrite('/');
but it seems to do nothing at all as I get a 404.
I've tried -> rewrite('/index.html') and -> rewrite('/index.jsp') to no avail.
The file is clearly being read, though, because if I put garbage into the file it throws an exception in the server log.
UT000045: Error parsing predicated handler string Invalid expression:
# path('/base') -> rewrite('/')
What have I missed?
I'm quite a neophyte to JBoss and the whole Undertow ecosystem; please let me know what other details I should add to this question.
Curiosity
With request dumper activated, I see a single initial request to / made by JBoss (User-Agent=Java/1.8.0_181) immediately after booting, but when I navigate to / from a browser, I don't see that request in the dump. But I do see the failed request for /base. Why is that?

I'm serving an Angular 8 SPA from /gui (like you my API is in another servlet). All I had to do with Undertow 2.0.15 (EAP 7.2) was add a WEB-INF/undertow-handlers.conf with:
path-prefix['gui'] and not file(%U) -> rewrite('/gui/index.html')
I would guess that if your SPA is served at / you could just:
not file(%U) -> rewrite('/index.html')

I had two problems:
I was missing rules, and I has misunderstood the function of path-prefix (which matches on complete and non-terminal path segments, rather than acting like a regex ^(group)).
My final, working undertow-handlers.conf looks like this:
regex('/login(.*)') -> done;
path-prefix('/assets') -> done;
regex('(.*).js') -> done;
regex('(.*).map') -> done;
regex('(.*).svg') -> done;
regex('(.*).png') -> done;
regex('(.*).eot') -> done;
regex('(.*).woff2') -> done;
regex('(.*).html') -> done;
path('/') -> rewrite('/index.html');
path('/base') -> rewrite('index.html');
path-prefix('/shop') -> rewrite('index.html');
...and all my other angular routes
Note that /base is a terminal path segment, and matches with path, whereas /shop/60 takes an additional path parameter, so requires path-prefex.
For whatever reason, the solution proposed in the linked question above, simply capturing it all with path-prefix('/') didn't work in my case.
Possibly-heplful side-note: we have a REST server that serves from /RestService/ in another servlet context, so no rules were needed to allow that to continue to work.
Additionally, I was using webpack's development proxy server through ng hmr, and needed to add byPassProxy rules equivalent to the undertow rules, as well.
I'm happy for improvements on this: please don't hesitate to comment or add another answer.

Related

Custom error page in tomcat for HTTP 501 error

Before anything else, I've already read all those solutions that says I put an error-page block in my application's or tomcat's conf/web.xml and add an error-code block inside with the corresponding location and those didn't work (did those for 404 errors and those worked).
What I already did inside my application's and tomcat's web.xml:
<error-page> <!-- this worked -->
<error-code>404</error-code>
<location>/pageNotFound.html</location>
</error-page>
<error-page> <!-- this did not work -->
<error-code>501</error-code>
<location>/pageNotFound.html</location>
</error-page>
I'm using Tomcat 8.5.63, and the goal is to remove the "Apache Tomcat/8.5.63" part on the response whenever a 501 error appears.
I want to remove this part:
tomcat error response page
The way I'm testing this is that I intercept a request using a pentest tool (I'm using burp suite community) and modify a request to include a Transfer-Encoding: cow header (yes I know that header is invalid).
Any ideas on how to implement a custom page so that the 501 can be handled properly?
The error pages you declare are used in two situations:
To allow developers to customize the appearance of content returned to a Web client
when a servlet generates an error, the deployment descriptor defines a list of error
page descriptions. The syntax allows the configuration of resources to be returned by
the container either when a servlet or filter calls sendError on the response for
specific status codes, or if the servlet generates an exception or error that propagates
to the container.
(Servlet 4.0 Specification, section 10.9.2)
In your case the error happens much earlier during the processing of the HTTP request itself. Therefore you need to modify the server's configuration (server.xml) and add a custom ErrorReportValve (cf. documentation). If all you want is to omit the server's version string, just add:
<Host>
<Valve className="org.apache.catalina.valves.ErrorReportValve" showServerInfo="false" />
...
</Host>

Flex2gateway not working on https/ssl on websphere

We are upgrading our ColdFusion 9 non-ssl application to ColdFusion 11 ssl enabled setup using Websphere.
We have a few flex components that utilize Flex2Gateway to call remote services. The application/Flex2gateway calls work fine with http but not on https.
The following urls give me a blank page which as per Adobe forums mean that Flex2Gateway is setup right:
http://example.com/flex2gateway
https://example.com/flex2gateway
The app calls the non-ssl url(not sure why):
http://example.com/flex2gateway and then gets redirected to
https://example.com/flex2gateway
When I look at the browser developer tools(IE, Chrome) the redirection from
http://example.com/flex2gateway to https://example.com/flex2gateway
seems to be working fine. Can anybody provide some insights on a possible solution?
Here is my remoting-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<adapters>
<adapter-definition id="cf-object"
class="coldfusion.flash.messaging.ColdFusionAdapter" default="true"/>
<adapter-definition id="java-object"
class="flex.messaging.services.remoting.adapters.JavaAdapter"/>
</adapters>
<default-channels>
<channel ref="my-cfamf-secure"/>
</default-channels>
<destination id="ColdFusion">
<channels>
<channel ref="my-cfamf-secure"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
I do see the following in services-config.xml and I did uncomment the WebsphereLoginCommand option but saw no difference.
<security>
<login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/>
<!-- Uncomment the correct app server
<login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
<login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/>
<login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/>
-->
UPDATE: I got https disabled on our server and receive the below error now when I try to access flex component:
faultCode:Client.Error.MessageSend faultString:'Send Failed' faultDetail:'Channel.Connect.Failed error NetConection.Call.Failed: HTTP: Failed:url: 'http://example.com/flex2gateway/"

unable to set security domain via jboss-web.xml

We have an app that is being deployed as an ear. Within this ear, there is a war that needs to use a specific security domain.
To achieve this, we have configured the standalone-full-ha.xml with the following security section
<security-domain name="ourDomain" cache-type="default">
<authentication>
<login-module code="blah.blah.OurDomain" flag="required" />
</authentication>
</security-domain>
ear/war/WEB-INF/jboss-web.xml is configured as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>Quark</security-domain>
<disable-audit>true</disable-audit>
</jboss-web>
With this configuration, the app tries to authenticate against the "other" domain which is there in JBoss by default.
log entries as follows:
TRACE [org.jboss.security] (http-/127.0.0.1:8080-6) PBOX000224: End getAppConfigurationEntry(other), AuthInfo: AppConfigurationEntry[]:
[0]
LoginModule Class: org.jboss.as.security.remoting.RemotingLoginModule
ControlFlag: LoginModuleControlFlag: optional
Options:
name=password-stacking, value=useFirstPass
[1]
LoginModule Class: org.jboss.as.security.RealmDirectLoginModule
ControlFlag: LoginModuleControlFlag: required
Options:
name=password-stacking, value=useFirstPass
When trying to define this as part of the ear in ear/META-INF/jboss-app.xml, that made the whole thing blow up pretty spectacularly - so figured that was less likely to be the way to resolve this.
If the default security domain is changed to ourDomain however, it all works as expected.
This doesn't seem to be a big deal - however, it feels better to be able to leave as much of the configuration in the app as possible.
Any pointers to resolve this appreciated.
Your security domain name specified in jboss-web.xml needs to match the name of some security domain in your JBoss config, in your case the web descriptor specifies Quark while the security subsystem defined domain named ourDomain.
Whenever JBoss can not find the security domain you request in your jboss-web.xml, it will fallback to the default security domain, which in case of 7.x is named other.

Enabling JBoss AS 7 Directory Listings

I have the following directory structure deployed to JBoss AS 7.1.1.Final (under standalone/deployments):
doc.war
-> module1
-> index.html
-> module2
-> index.html
As you can see, there's no index.html under doc.war. When I browse to localhost:8080/doc/module1/, the correct index.html is displayed, but when I browse to localhost:8080/doc/, JBoss shows an error message (404 - The requested resource is not available).
I think this is related to the fact that directory listings are turned off by default in JBoss AS 7. How can I enable directory listings, either globally or more specifically for this one application?
Edit
Based on Mukul Goel's answer, I ran the CLI command to add the static-resources feature, restarted the server and retried the request, but it didn't work.
Here's the relevant snippet from the standalone.xml file. Please note that I have the native connector enabled.
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="true">
<configuration>
<static-resources listings="true"/>
</configuration>
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https"/>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
Here's the error message that JBoss is showing:
Update
So the conclusion to this seems to be that there is an issue with the official JBoss 7.1.1.Final (http://www.jboss.org/jbossas/downloads) download. I didn't manage to get Directory Listings working with this version. Trying a later version (from the JBoss CI server at https://ci.jboss.org/jenkins/job/JBoss-AS-7.x-latest/), I was able to see the directory listings after applying the config change that Mukul Goel had suggested below.
A potential source of this issue could be the version of JBossWeb that is used in JBoss. The official 7.1.1.Final bundles JBossWeb 7.0.13. Mukul (see below) was able to get it working running a version of JBoss that bundles JBossWeb 7.0.16.
I'm accepting Mukul Goel's answer as solving this issue, but be aware that it will probably not work with the official 7.1.1.Final download.
Yes you are right, directory listings are by default disabled (a security measure)
To enable directory listing in JBOSS
Try running the following CLI command to enable diectory listing:
In Domain Mode
/profile=full/subsystem=web/configuration=static-resources/:write-attribute(name=listings,value=true)
.
In Standalone Mode
/subsystem=web/configuration=static-resources/:write-attribute(name=listings,value=true)
It will generate following kind of configuration :
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
<configuration>
<static-resources listings="true"/>
</configuration>
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
UPDATE:
Tried it myself as the user is facing problems
RAN CLI command for the standaloneMode
This was generated, note that the native is disabled also there is no HTTPS connector generated for me (Don`t know why it is showing enabled for you? are you using openSSL somewhere? )
I created a sample webprojet(a client side project) with two htmls ,published it to jboss and hit url
http://localhost:8080/sample/
and this is the screenshot of directory listing
The command worked it for me, So that does turns on Directory listing on JBOSS AS7.1.1 Final(I am also using the same version)
So the question comes down to rest of your server configuration, your application structure, technologies you are using, springs etc and also if you are using some ssl library.
UPDATE 2
Suggested a fresh download and reconfigure environment and see
nwinkler was still facing issues even with a fresh distribution (JbossWeb 7.0.13) So suggested to take nightly builds from
ci.jboss.org/jenkins/job/JBoss-AS-7.x-latest
Just go to the link and download whats under last successful artifact
And the problem was resolved. Looks like some bug with jbossWeb 7.0.13
Do go through the comments, the discussion might be helpful

Getting request and creating HTTP response using Tomcat

I am currently trying to use embeded Tomcat for my application and am trying to set it up to get the URL of the http request.
Some Background:
I am using the same code as in the first answer for the post here : Howto embed Tomcat 6?
The only change I have made is :
private String catalinaHome = "/home/xyz/tomcat"; // This dir is created and has full access permissions
Also , I am looking at: http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/startup/Embedded.html
There are no server.xml and tomcat-users.xml that I could find, so I created a tomcat-users.xml since I was getting an exception :Memory database file /home/xyz/tomcat/conf/tomcat-users.xml cannot be read .
tomcat-users.xml:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>
The code uses container.setRealm(new MemoryRealm());
It appears from here : http://tomcat.apache.org/tomcat-4.1-doc/catalina/funcspecs/fs-memory-realm.html that I should have a server.xml file and there should already be one created by default.
1] Do I need to create a server.xml, what should be the default in it ?
I have put a file with default from here : http://www.akadia.com/download/soug/tomcat/html/tomcat_server_xml.html , but just want to know what is the right thing to do ?
2]When I access http://localhost:8089/mywebapp/index.html, all i get is The requested resource () is not available, though I have an index.html page at the "webappDir" in the code
3] My only need from the embedded tomcat is to intercept so as to get the URL passed to tomcat in my code. I can then parse the URL [do my stuff] and then create a http payload and send an http response back.
I would appreciate any pointers, especially for 3] ?
Thanks!
Ok, for your first question, yo do not need server.xml. If you check the code of your initial post they are setting the parameters there. So that is what server.xml would encapsulate. In reality what happens is that Tomcat will parse server.xml for the properties you are defining on your java file where you instanciate the catalina call to start. But since it is embedded you are setting all those parameters on you class instead.
For your second question, check your logs directory and see what is being parsed. Something is happening after your service starts because it should already redirect you once you call the port. either way, just try http://localhost:8089 and see what you get back in return from tomcat. It should give you some kind of response back from the server itself.
if you do it like this "http://localhost:8089/mywebapp/index.html" you are trying to access a created context, and that might not be configured correctly, but that is just a guess right now.
Try this first and tell me what you get back. we can troubleshoot from this point and see if I can help more in that sense.
Quick question, is this windows or linux you are installing on?
If it is linux the configurations filea are located usually on /etc/tomcat6. (at least on ubuntu they are). Reply back with the version you have installed. I might be able to help you out.
I guess I should also elaborate here a little more. Tomcat is a service in linux as well, so in ubuntu you have to start tomcat in order to access it.
$: sudo service tomcat6 start
then it starts tomcat on port 8080 (usually if not changed) of your localhost. hence you type localhost:8080 to access the website for configuration of tomcat that gives you a It works prompt for you.
Let me know if you have more questions, I will try to respond to the best of my knowledge