Search code examples
websphere-libertyopen-liberty

OpenLiberty ignoring WEB-INF/ibm-application-bnd.xml


My application (my-app.war) has a JAX-RS endpoint, secured with a given role, like this:

Endpoint.java

@Path("endpoint/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@DeclareRoles({"ADMIN_ROLE"})
public class Endpoint {
  @POST
  @RolesAllowed({"ADMIN_ROLE"})
  public void post() {
  }
}

server.xml

<server>
  <featureManager>
    <feature>jaxrs-2.1</feature>
    <feature>appSecurity-3.0</feature>
  </featureManager>

  <application id="my-app" context-root="/" location="my-app.war" type="war">
  </application>

  <variable name="default.http.port" defaultValue="9080"/>
  <variable name="default.https.port" defaultValue="9443"/>

  <httpEndpoint id="defaultHttpEndpoint" httpPort="${default.http.port}" httpsPort="${default.https.port}"/>

  <basicRegistry realm="defaultRealm">
    <user name="test-user" password="test-password"/>
    <group name="ADMIN_GROUP">
      <member name="test-user"/>
    </group>
  </basicRegistry>

</server>

Now I have to bind ADMIN_GROUP to ADMIN_ROLE.

If I do it on server.xml application, then everything works fine:

  <application id="my-app" context-root="/" location="my-app.war" type="war">
    <application-bnd>
      <security-role name="ADMIN_ROLE">
        <group name="ADMIN_GROUP" />
      </security-role>
    </application-bnd>
  </application>

The application is deployed and upon invoking the endpoint without authentication, it returns 403 (authentication required). When supplied with authentication header, it returns 204 (no content) as intended.

Now the problem lies when I try to configure the binding in ibm-application-bnd.xml:

<?xml version="1.0" encoding="UTF-8"?>

<application-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_2.xsd"
  xmlns="http://websphere.ibm.com/xml/ns/javaee"
  version="1.2">
<
  <security-role name="ADMIN_ROLE">
    <group name="ADMIN_GROUP" />
  </security-role>
</application-bnd>

I've put it both in META-INF/ibm-application-bnd.xml and WEB-INF/ibm-application-bnd.xml. But both of them are completely ignored (I've even went as far as adding invalid xml there, but get no error message from OpenLiberty).

Every call to the endpoint returns 403, even when supplied with authentication.

In https://www.ibm.com/docs/en/was-liberty/base?topic=liberty-configuring-authorization-applications-in, it says [emphasis added]:

Configure the authorization information such as the user and group to role mapping. You can configure the authorization table in the following ways:

  • If you have an EAR file, you can add the authorization configuration definition to the ibm-application-bnd.xml or ibm-application-bnd.xmi file.

  • If you have standalone WAR files, you can add the authorization table definitions to the server.xml file under the respective application element. You can use the WebSphere® Application Server Developer Tools for Eclipse to do this.

Does this mean that for war applications the binding MUST BE on server.xml?


Solution

  • Per this answer, META-INF/ibm-application-bnd.xml - though undocumented - can be used inside a web archive.

    Then I've mvn package my project, and inpected it's war file (showing only relevant files):

      Length      Date    Time    Name
    ---------  ---------- -----   ----
            0  2021-04-28 22:13   META-INF/
          131  2021-04-28 22:13   META-INF/MANIFEST.MF
            0  2021-04-28 22:13   WEB-INF/
            0  2021-04-28 22:13   WEB-INF/classes/
            0  2021-04-28 22:13   WEB-INF/classes/META-INF/
            0  2021-04-28 22:13   WEB-INF/lib/
            0  2021-04-22 17:58   WEB-INF/beans.xml
          134  2021-04-28 22:13   WEB-INF/classes/META-INF/ibm-application-bnd.xml
          592  2021-04-28 22:13   WEB-INF/classes/META-INF/persistence.xml
       300365  2021-04-15 09:58   WEB-INF/lib/log4j-api-2.14.1.jar
      1745700  2021-04-15 09:59   WEB-INF/lib/log4j-core-2.14.1.jar
          393  2021-04-28 21:50   WEB-INF/web.xml
            0  2021-04-28 22:13   META-INF/maven/
    ---------                     -------
    

    Now note that there are META-INF/* entries and WEB-INF/classes/META-INF/* entries.

    Then I've found this answer (which is unrelated to liberty/openliberty). It's first sentence struck me in awe:

    It looks like your META-INF folder is in src/main/resources directory.

    Exactly like mine. So I moved META-INF from src/main/resources to src/main/webapp.

    Now the war lists as:

      Length      Date    Time    Name
    ---------  ---------- -----   ----
            0  2021-04-28 22:22   META-INF/
          131  2021-04-28 22:22   META-INF/MANIFEST.MF
            0  2021-04-28 22:22   WEB-INF/
            0  2021-04-28 22:22   WEB-INF/classes/
            0  2021-04-28 22:22   WEB-INF/lib/
          134  2021-04-28 22:13   META-INF/ibm-application-bnd.xml
          592  2021-04-27 10:19   META-INF/persistence.xml
            0  2021-04-22 17:58   WEB-INF/beans.xml
       300365  2021-04-15 09:58   WEB-INF/lib/log4j-api-2.14.1.jar
      1745700  2021-04-15 09:59   WEB-INF/lib/log4j-core-2.14.1.jar
          393  2021-04-28 21:50   WEB-INF/web.xml
            0  2021-04-28 22:22   META-INF/maven/
    ---------                     -------
    

    Now the file ibm-application-bnd.xml gets processed. And it works. EXCEPT THAT...

    This way JPA is not working anymore.

    It seems that META-INF/persistence.xml must be in src/main/resources after all.

    Now I have two META-INF/ folders (¯\_(ツ)_/¯).


    UPDATE

    Apart from having two META-INF/ folders (a problem on its own), now my tests can't access resources from META-INF/ (the other one, in WEB-INF/classes/META-INF is readily available, as every resource inside WEB-INF/classes/).

    Then why would I need to access ibm-application-bnd.xml from tests, you might ask. Because I'm using arquillian, and I need to create a deployment, and I need to include these role <-> group mappings.

    Now I have 3 options:

    1. create a copy of ibm-application-bnd.xml inside src/test/resources; the problem here is that I need to keep both in sync;

    2. add src/main/webapps to the surefire/failsafe classpath (see this answer);

    3. specifically for Liberty/OpenLiberty, I can rely on an implicit mapping (assuming each group bind to a role with the same name; go look for CWWKS2104I here). This is the one I'm choosing for the moment.

    Options 1 and 3 share the same downside: the tested code is not EXACTLY the code that will be deployed to production.

    Option 2 has another downside: when running tests through the IDE, this extra folder must also be added to the classpath (unless the IDE has a very good integration with maven and can read surefire/failsafe configuration).

    The