mod_cluster widfly 9 and client certificate 2 way SSL - wildfly

I have one problem when i am configuring 2 way SSL (client certificate) with mod_cluster on wildfly 9.0.2
-Direct connection on wildfly on port 8443 (like https://wildflyserver:8443/context) is working,
-AJP connector connection between apache and wildfly and mod_cluster is not working
-There is no HTTPS connector ?
<mod-cluster-config advertise-socket="modcluster" proxies="mc-proxy1" advertise="false" connector="http-default">
<dynamic-load-provider>
<load-metric type="cpu"/>
</dynamic-load-provider>
<ssl key-alias="aofweb" password="XXXXXX" certificate-key-file="${jboss.domain.config.dir}/keystoreWeb.jks" cipher-suite="ALL" protocol="TLSv1" ca-certificate-file="${jboss.domain.config.dir}/keystoreWeb.jks"/>
</mod-cluster-config>
-When i am using http redirect to https with web.xml configuration and redirect-socket binding the URL changes from https://apacheserver/context to https://wildflyserver:8443/context, if i had a directive preserveProxyhost it does'nt work too,
anybody have a solution ?

i manage to do it , i configure "ajp" connection , in listener scheme https,
in case of in httpd listener certificate-forwarding=true and redirection on https,
in web.xml auth-method to CLIENT-CERT and transport-guarantee to CONFIDENTIAL,
and then the most important in apache, client verification mandatory and forward cert data :
SSLHonorCipherOrder on
SSLVerifyClient require
SSLVerifyDepth 10
#THE CA USED TO GENERATE CLIENT CERTIFICATE
SSLCACertificateFile /etc/httpd/certs/cacert.pem
SSLOptions +ExportCertData
SSLOptions +StdEnvVars
Require all granted
tell me if you have problem :
widlfy 9.0
apache 2.4
mod_proxy_ajp
mod_ssl
mod_proxy
modcluster 1.3.1

Related

Why does keycloak-client-adapter connect on http?

I am running a JEE app on a Wildfly server behind an Apache reverse proxy. Using the keycloak-client-adapter it connects to a Keycloak server also behind a apache reverse proxy. Both reverse proxies terminate the SSL connecion and connect to the Wildfly server by http.
When I am opening the JEE app, I am redirected to Keycloak and after I have entered my password I am also redirect to my app - all on SSL through the reverse proxy. But then I get a 403 - the reason for this: The App Wildfly tries to connect to Keycloak to validate the token on http. This is neither allowed ("ssl-required": "all" in keycloak.json and setup in realm) nor is http active at all.
From the app wildfly server.log
Adapter requires SSL. Request: http://www.domain.tld/myapp/
I have setup the reverse proxy of Keycloak according to the documentation, .well-known/openid-configuration looks good - all URLs are https
keycloak.json
{
"realm": "myrealm",
"auth-server-url": "https://sso.domain.tld/auth",
"ssl-required": "all",
"resource": "myresource",
"verify-token-audience": true,
"credentials": {
"secret": "secret"
},
"use-resource-role-mappings": true,
"confidential-port": 443,
"policy-enforcer": {}
}
Settings of the reverse proxy for the app
ProxyPreserveHost On
ProxyPass /myapp http://127.0.0.1:8080/myapp
ProxyPassReverse /myapp https://www.domain.tld/myapp
Anyone an idea how to force https on the validation? That should be the last step to get the setup running.

HA Proxy support for HTTP/2 backend servers in http mode

I have a tomcat 9.0.2 server supporting HTTP/2 and running on TLS1.2. Below is the connector configuration in server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
address="0.0.0.0"
maxThreads="150" SSLEnabled="true" asyncTimeout="10000" maxHeaderCount="50"
maxPostSize="1048576" scheme="https" secure="true" compression="force"
compressionMinSize="2048" maxConnections="10000">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig protocols="TLSv1.2">
<Certificate certificateKeystoreFile="${keystore.file.path}"
certificateKeystorePassword="${keystore.password}"
certificateKeyAlias="${server.cert.alias}"
certificateKeystoreType="${keystore.type}" />
</SSLHostConfig>
</Connector>
I am using HA Proxy 1.8 and configuration is like below
frontend mydomain-ux
mode http
bind <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem
http-request set-var(txn.path) path
acl mydomain hdr_end(host) -i mydomain.com
use_backend mydomain_server if mydomain
backend mydomain_server
mode http
server mydomain_backeend_server <server-ip>:8443 ssl
Since, I have multiple backends based on host, I cannot use TCP mode and do pass through HTTP/2 SSL termination
Is there a way I can have HTTP/2 termination in backend mode http ?
As far as I'm aware HAProxy does not support HTTP/2 on the back end. They only recently announced front end support. (Edit 18th Jan 2019 - since added in v1.9 - https://www.haproxy.com/blog/haproxy-1-9-has-arrived/).
Even without backend HTTP/2 support, it is possible to terminate the front end on HTTPS, and then forward to the back end on TCP (without HTTPS), and it may be possible to use the SNI part of the HTTPS to do the optional routing you want (this is completely untested btw):
frontend mydomain-ux
mode tcp
bind <ip>:8080 ssl crt /etc/certs/mydomain.com.cert.pem alpn h2,http/1.1
use_backend mydomain_server if { ssl_fc_sni mydomain.com}
use_backend mydomain_server2 if { ssl_fc_sni mydomain2.com }
default_backend mydomain_server
backend mydomain_server
mode tcp
server mydomain_backeend_server <server-ip>:8081
This would allow your backend to speak HTTP/2 on port 8081 but without HTTPS (port 8443), and even works on HAProxy before 1.8 (when front end HTTP/2 support was added). However it would mean your Tomcat would need to be setup without SSL.
HAProxy also do not recommend using the SNI host for routing as discussed in this answer and in the the mailing thread it refers to. Plus additionally SNI support is not universal (though to all practical intents it is unless supporting really old browsers like IE8 on XP).
The other question you should ask yourself is if you really need HTTP/2 in the backend or if just supporting this at the HAProxy level is enough?
I have done a full h2 pipe base on the previous post by Barry Pollard with some modification and It's work good enough to be use in dev for now. Some futher test are need to clear the path to production. But at least its work.
h2 clear text (h2c) is'nt supported by browser as google want everybody to use ssl but it works fine between 2 httpd server (tested with apache, but not with nginx or tomcat or whatever else httpd).
frontend mydomain-ux
mode tcp
bind 0.0.0.0:443 ssl crt /etc/ssl/tdl.pem alpn h2,h2c,http/1.1
bind 0.0.0.0:80 alpn h2,h2c,http/1.1
use_backend mydomain_server if { ssl_fc_alpn -i h2 }
default_backend mydomain_server
backend mydomain_server
mode tcp
http-request add-header X-Forwarded-Proto https
server mydomain_backeend_server 1.1.1.1:80
server mydomain_backeend_server2 1.1.1.2:80
here is what i can see from the backend access_log:
1.1.1.3 - - [17/Jan/2019:10:57:49 -0500] "GET / HTTP/2.0" 403 3985 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"

why is keycloak removing the SSL in the redirect uri?

We have a simple requirement where:
PS: https:/ === https://
When user hits https:/company_landing.company.com , they should be redirected to keycloak login page (at https:/ourcompany-keycloak.company.com). User enters his/her keycloak login credentials. Upon successful login to keycloak , they will be presented to the company_landing page.
The trouble is :
When User types - https:/company_landing.company.com
Keycloak tries to bring up the landing page but gives 500 Internal server error and says "Incorrect redirect uri" and in the browser I see this:
https:/ourcompany-keycloak.company.com/auth/realms/realm1/tokens/login?client_id=company_dev&state=aaaafffff-559d-4312-a8be-123412341234&redirect_uri=http%3A%2F%2Fcompany_landing.company.com%3A8081%2F%3Fauth_callback%3D1
If you observe the redirect uri above, I think the problem is that instead of https the redirect uri starts with http and http:/company-landing.company.com doesn't exist.
Settings:
keycloak settings: -
Realm --> settings --> login : Require SSL = all Requests (tried with "external" also)
Applications-->realm1-->settings-->Redirect URI = https://company_landing.company.com/*
AWS load balancer:
Port config: 443(https) forwarding to 8443
I am confused as to why it is stripping the SSL? The above works fine when testing on local environment(probably because its http://localhost) but this always gives an invalid redirect url when trying to access any link that is ssl encrypted.
-mm
You have to add the following property in the proxy configuration json file, (by default proxy.json) as an application attribute (same level as "adapter-config"):
"proxy-address-forwarding" : true,
This configuration attribute is not documented, however present in the sources of the proxy configuration: https://github.com/keycloak/keycloak/blob/master/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyConfig.java
You don't need a certificate to be installed or use changes in adapter config.
This needs to be done in your standalone.xml, standalone-ha or domain.xml (as the case may be) as documented in the Keycloak document reverse proxy section https://www.keycloak.org/docs/latest/server_installation/index.html#_setting-up-a-load-balancer-or-proxy
Assuming that your reverse proxy doesn’t use port 8443 for SSL you also need to configure what port HTTPS traffic is redirected to.
<subsystem xmlns="urn:jboss:domain:undertow:4.0">
...
<http-listener name="default" socket-binding="http"
proxy-address-forwarding="true" redirect-socket="proxy-https"/>
...
</subsystem>
Add the redirect-socket attribute to the http-listener element. The value should be proxy-https which points to a socket binding you also need to define.
Then add a new socket-binding element to the socket-binding-group element:
<socket-binding-group name="standard-sockets" default-interface="public"
port-offset="${jboss.socket.binding.port-offset:0}">
...
<socket-binding name="proxy-https" port="443"/>
...
</socket-binding-group>

Spring Security X.509 Preauth

I'm using Spring Security 2.x's Preauthentication with X.509 certificates.
I get the certificateText via HttpServletRequest.getAttribute("CERTIFICATE").
Sometimes, the above call returns "" (empty). I believe it occurs when the HTTP session has expired.
What would explain why HttpServletRequest.getAttribute("CERT") returns empty?
EDIT In Kerberos, for example, the ticket is available in every HTTP request. Is the cert not always in X.509 HTTP requests?
Please access to certificate using this code:
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
Certificate is always populated to request after successful client certificate authentication.
Ensure your support long certificate chain:
Add the max_packet_size propery to the worker.properties file
worker.ajp13w.max_packet_size=65536
Add the packetSize propery to the configuration of Ajp connector in the Tomcat configuration \conf\server.xml
<Connector port="8089"
enableLookups="false" redirectPort="8443" protocol="AJP/1.3" packetSize="65536"/>
Apache logs:
http://httpd.apache.org/docs/2.2/logs.html#accesslog
http://httpd.apache.org/docs/2.2/logs.html#errorlog
http://httpd.apache.org/docs/2.2/mod/core.html#loglevel

link apache web server on port 80 and tomcat webapp on port 8080

On port 80 I have normal apache web server.
On port 8080 I have tomcat with client and server side stuff.
My goal is:
www.mydomain.com renders a static and SEO friendly index.html while javascript stuff is loading.
In the header of this index.html I load www.mydomain.com:8080/myapp/stuff.js
stuff.js is compiled with gwt and calls a RootLayoutPanel.get().add(nice_panel) which will remove static content and show dynamic widgets. It also calls servlets (server side code).
Problem: for security reasons, browsers wont let me load www.mydomain.com:8080/myapp/stuff.js because it is on a different port.
Wrong attempt: I tried to create a symlink from "normal" apache web server directory to the tomcat webapp containing stuff.js. I am now able to load stuff.js because its url is: www.mydomain.com/mysymlink_to_tomcat/stuff.js. But stuff.js is not able anymore to call servlets on server side again because of browsers security rules ("XMLHttpRequest cannot load ... origin ...is not allowed by Access-Control-Allow-Origin").
I would like to avoid the "crazy" solution of redirect from index.html to tomcat with header('location: http://mydomain.com:8080/another_index_on_tomcat.html'). This solution works but it has many drawbacks (SEO...)
What would be the best approach ?
Thanks.
You have basically two solutions:
make it work with the 2 origins: use the xsiframe linker in GWT to allow the page on :80 to load the script from :8080 (for readers: it's not about loading, it's about what the script does).
Add the following to your `gwt.xml:
<add-linker name='xsiframe' />
That unfortunately won't solve your issue with GWT-RPC (o whatever you use to talk to the server). For that, there's CORS.
use a single origin: use Apache's mod_proxy (or mod_jk) to proxy your Tomcat through your Apache. Nobody will ever use :8080, everything will go through :80. See Using Tomcat with Apache HTTPD and a proxy at https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuideRPCDeployment
And of course there's also the solution of ditching the HTTPD and serving everything with Tomcat (recent Java and Tomcat versions have fixed their slowness issues).
I'm not sure if this would avoid the security error, but you could try an iframe. On apache, you have the index and an iframe to the tomcat, where the JS loads inside the iframe. Dunno if that will help with the SEO problem.
The best solution would be to redirect the port 80 calls to 8080 on apache when the client call is asking for a tomcat application.
Install mod_jk on apache and configure it to mount a context on the path you want
example: (edit /mods_enabled/jk.conf)
# Configure access to jk-status and jk-manager
# If you want to make this available in a virtual host,
# either move this block into the virtual host
# or copy it logically there by including "JkMountCopy On"
# in the virtual host.
# Add an appropriate authentication method here!
<Location /jk-status>
# Inside Location we can omit the URL in JkMount
JkMount jk-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
<Location /jk-manager>
# Inside Location we can omit the URL in JkMount
JkMount jk-manager
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
JkMount /*/myAppDir/* ajp13
Then add a virtual host in your site settings (edit /apache2/sites-enabled/)
<VirtualHost *:80>
. Here is the rest of the
. of the config of
. the host
# Tomcat jk connector settings
JkMount /*.jsp ajp13_worker
JkMount /myAppDir/* ajp13_worker
JkMount /myAppDir* ajp13_worker
JKMount /manager* ajp13_worker
JkMount /manager/* ajp13_worker
</VirtualHost>
And you should also edit the server.xml file and inside the tag write and comment the previous Host name="localhost"
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Host name="localhost" appBase="webapps" unpackWARs="true"
autoDeploy="true" >
<Context path="/" docBase="/var/lib/tomcat7/webapps/myAppDir/"
debug="0" reloadable="true" />
<!-- please notes on logs down below -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="/var/lib/tomcat7/logs" prefix="tomcat_access_"
suffix=".log" pattern="common" resolveHosts="false" />
</Host>
The only thing left to do is edit the workers.properties file and add
worker.myapp2.port=8009
worker.myapp2.host=localhost
worker.myapp2.type=ajp13
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=ajp13_worker
Then you should be set to work, and when a url containing the myAppDir appears, the apache server will redirect the calls to tomcat the answer will come back from apache.