# 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

Reply via email to