have you considered using SAML or OIDC? Apache have Fediz project and
RedHat have KeyCloak (merging with PicketLink). it might simplify your
security somewhat. Fediz is an active project with very helpful support
team. KeyCloak is easy to set up and you could be up and running pretty
quickly. They both support RolesAllowed with their connectors which
drop in as jar libs to your catalina_base/lib
On 06/11/2017 16:03, Krzysztof Śmigrodzki wrote:
# Current situation
I write a REST webservice. Most of it will be protected by CLIENT-CERT
mutual SSL authentication. But parts of it related to acquiring client
certificate must be accessible without two-way ssl authentication.
Unfortunately REST structure I've received from above, mixes
authenticated and non-authenticated parts. It looks like this:
GET /rest/entities - protected
POST /rest/entities - unprotected
GET /rest/entities/{id:\d{10}} - protected
PUT /rest/entities/{id:\d{10}} - protected
POST /rest/entities/{id:\d{10}}/users - unprotected
GET /rest/entities/{id:\d{10}}/users - protected
GET /rest/entities/{id:\d{10}}/users/{userId:\d+} - protected
POST /rest/entities/{id:\d{10}}/reports - protected
etc.
I can't describe that requirements in web.xml descriptor's security
constraint to differentiate between CLIENT-CERT protected and
unprotected resources, as web-resource-collection -> url-pattern does
not support true regular expressions (actually url-pattern is dumber
than shell globbing).
# The Problem
I wonder if it is possible to use @RolesAllowed annotation on REST
methods implementations to enforce security constraints.
Currently:
GET on /rest/entities works with this configuration in web.xml
<security-constraint id="requires-cert">
<web-resource-collection>
<description>List of entities</description>
<url-pattern>/rest/entities</url-pattern>
<url-pattern>/rest/entities/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>CERTAUTH</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
<security-role>
<description>Default role added by custom Realm</description>
<role-name>CERTAUTH</role-name>
</security-role>
The same GET fails miserably with 403 HTTP status if I comment out
security-constraint tag and rely on @RolesAllowed({"CERTAUTH"}).
There is no trace of certificate passing through Valve that implements
my custom realm.
I use the following Connector definition in server.xml:
<Connector port="8443" protocol="HTTP/1.1"
maxThreads="150" SSLEnabled="true"
scheme="https" secure="true" xpoweredBy="false"
server="Apache TomEE">
<SSLHostConfig certificateVerification="optional"
truststoreFile="${catalina.base}/conf/truststore.jks"
truststorePassword="*****">
<Certificate
certificateKeystoreFile="${catalina.base}/conf/ksmigrod.noip.me.jks"
certificateKeystorePassword="*****"
certificateKeyAlias="ksmigrod.noip.me"
certificateKeyPassword="*****">
</Certificate>
</SSLHostConfig>
</Connector>
Both times I test it with CURL, issuing the same command:
curl --verbose --cert client.crt --key client.pem
https://ksmigrod.noip.me:8443/api/rest/entities
Is there something I'm missing in configuration of TomEE to make
@RolesAllow work with CLIENT-CERT without detailed config in web.xml, or
shall I use Tomcat's rewrite valve to route unprotected requests to
different path?
Regards,
Krzysztof Śmigrodzki