# 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