Search code examples
dockertomcat8web.xmlhttp-method

security-constraint in web.xml not working with http-method - Tomcat in a Docker container


I have read several of the other answers and have tried a couple of suggestions, but no matter what I have tried to this point I am unable to exclude OPTIONS as an allowed http-method for TOMEE/TOMCAT running in a Docker container.

The web.xml file is located in the /usr/local/tomee/webapps/ROOT/WEB-INF directory:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <resource-ref id="dataSource-appDB">
    <res-ref-name>jdbc/app</res-ref-name>
    <mapped-name>java:comp/env/jdbc/app</mapped-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
  </resource-ref>

  <error-page>
      <exception-type>org.springframework.security.web.firewall.RequestRejectedException</exception-type>
      <location>/errors/400</location>
  </error-page>

  <error-page>
      <exception-type>java.lang.IllegalArgumentException</exception-type>
      <location>/errors/400</location>
  </error-page>

  <security-constraint>
      <web-resource-collection>
          <web-resource-name>restricted methods</web-resource-name>
          <url-pattern>/v1/*</url-pattern>
          <http-method>OPTIONS</http-method>
      </web-resource-collection>
  </security-constraint>

</web-app>

When I cURL an endpoint for the allowed http methods, OPTIONS is still there:

>curl -i --request-target "*" -X OPTIONS http://localhost/v1/healthcheck.html
HTTP/1.1 200
Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS
Content-Length: 0
Date: Fri, 06 Jan 2023 16:00:14 GMT
Server: no information

I have tried running with/without <auth-constraint /> and get the same result.

Here is the Dockerfile running the container:

FROM amazoncorretto:11-alpine-jdk

ENV PATH /usr/local/tomee/bin:$PATH
RUN mkdir -p /usr/local/tomee
ENV TZ America/New_York

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ /etc/timezone
WORKDIR /usr/local/tomee

# add the things we need to build the image 
RUN apk update \
    &&  apk add sudo \
    &&  apk add tar \
    &&  apk add gpg \
    &&  apk add curl \
    &&  apk add gpg-agent \
    &&  apk add bash
# add the users and sudo for the security scanner
RUN adduser -S tomee
RUN addgroup tomee \
    && addgroup tomee tomee
RUN addgroup sudo \
    && addgroup tomee sudo
    
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# download and import the GPG keys
RUN set -x \
    && curl -fsSL 'https://www.apache.org/dist/tomee/KEYS' -o GPG_KEYS | awk -F ' = ' '$1 ~ /^ +Key fingerprint$/ { gsub(" ", "", $2); print $2 }' | sort -u \
    && gpg --import GPG_KEYS

# verify keys
RUN set -xe \
    && for key in $GPG_KEYS; do \
        gpg --batch --keyserver hkp://keyserver.ubuntu.com --recv-keys "$key" || \
        gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys "$key" ; \
    done

# TOMEE variables
# Apache changes the version from time to time and removes the old version.
# When they do that, you have to go to https://dist.apache.org/repos/dist/release/tomee/ to what see version is available
# then match that here
ENV TOMEE_VER 8.0.13
ENV TOMEE_BUILD webprofile

# set up Apache/TOMEE
RUN set -x \
    && curl -fSL https://dist.apache.org/repos/dist/release/tomee/tomee-${TOMEE_VER}/apache-tomee-${TOMEE_VER}-${TOMEE_BUILD}.tar.gz.asc -o tomee.tar.gz.asc \
    && curl -fSL https://dist.apache.org/repos/dist/release/tomee/tomee-${TOMEE_VER}/apache-tomee-${TOMEE_VER}-${TOMEE_BUILD}.tar.gz -o tomee.tar.gz \
    && gpg --batch --verify tomee.tar.gz.asc tomee.tar.gz \
    && tar -zxf tomee.tar.gz \
    && mv apache-tomee-${TOMEE_BUILD}-${TOMEE_VER}/* /usr/local/tomee \
    && rm -Rf apache-tomee-${TOMEE_BUILD}-${TOMEE_VER} \
    && rm -Rf /usr/local/tomee/webapps/docs \
    && rm bin/*.bat \
    && rm tomee.tar.gz* \
    && chown -R tomee:tomee /usr/local/tomee 


# put everything in the right place with the correct permissions
COPY $PWD/server.xml /usr/local/tomee/conf/
RUN chown -R tomee:tomee /usr/local/tomee/conf
COPY $PWD/app-war/target/app/META-INF/ /usr/local/tomee/webapps/ROOT/META-INF/
COPY $PWD/app-war/target/app/WEB-INF/ /usr/local/tomee/webapps/ROOT/WEB-INF/
COPY $PWD/app-war/target/app.war /usr/local/tomee/webapps/ROOT.war
RUN chown -R tomee:tomee /usr/local/tomee/webapps/
    
USER tomee
EXPOSE 8080
CMD ["catalina.sh", "run"]

I start the container with docker-compose:

version: "3.0"

services: 
  app-internal:
    image: job/app-internal:0.0.1500
    container_name: app-internal
    ports:
      - "80:8080"
    environment: 
      - SPRING_PROFILES_ACTIVE=l1,app-internal
      - JBOSS_ENV=l1
      - PLATFORM_ENV=aws
      - DEV_ENV=local
      - JAVA_OPTS=-Xmn100m -Xmx1024m -Xms1024m

Am I missing something obvious?


Solution

  • The <security-constraint> doesn't influence the "Allow" header in OPTIONS replay.

    The Allow header is based on existence of onX handlers in the servlet. It is implemented in HttpServlet.doOptions.

    from Java™ Servlet Specification Version 2.5:

    The OPTIONS request determines which HTTP methods the server supports and returns an appropriate heade. For example, if a servlet overrides doGet, this method returns the following header:

    Allow: GET, HEAD, TRACE, OPTIONS