12 Replies Latest reply on Sep 23, 2013 7:09 AM by Nicky Mølholm

    default-missing-method-permissions-deny-access in standalone.xml is not honored

    Nicky Mølholm Newbie

      Hi,

       

      ( I am using JBoss 7.2.0.Final "Janus". )

       

      I have a secured EJB - it is annotated with @SecurityDomain.

       

      None of the methods is annotated with @RolesAllowed, @PermitAll, @DenyAll etc.

       

      As a result JBoss AS implicitly sees all methods as being annotated with @DenyAll.

       

      So in an attempt to make JBoss AS see them as @PermitAll I edited standalone.xml, and added the following stanza:

      <subsystem xmlns="urn:jboss:domain:ejb3:1.4">
        <default-missing-method-permissions-deny-access value="false"/>
       ....
      </subsystem>
      

       

      Note the value of "false" - ie. JBoss AS should not treat un-annotated methods as @DenyAll.

       

      My problem is: It makes no difference what the value is here (in standalone.xml).

       

      (I have tried annotating the EJB with @PermitAll - which works fines; ie. access is granted).

       

      Can you help me realize what I am doing wrong here?

       

      Thank you guys

        • 1. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
          jaikiran pai Master

          Are you sure you are making changes to the correct configuration xml? Also, please post the relevant bean code and the exception stacktrace that you are seeing.

          • 2. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
            Nicky Mølholm Newbie

            Hi - thanks for answering.

             

            I don't see any stacktraces actually.

             

            I am editing Work/JBoss7/jboss-as/standalone/configuration/standalone.xml - and running JBoss AS from the standalone "profile". Where Work/JBoss7 is the folder where to I have copied JBoss 7 AS.

             

            Also - I have seen default-missing-method-permissions-deny-access=false change in jboss-cli (under [standalone@localhost:9999 /] ls /subsystem=ejb3).

             

            As I understand it - a value of false indicates: "un-annotated" methods are regarded as @PermitAll. Is this understanding correct? I might have misunderstood along the way

            • 3. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
              Nicky Mølholm Newbie

              I have had TRACE enabled on "org.jboss.security" - but it doesn't tell me anything useful....

               

              Any suggestion to where (if possible) I can enable further relevant trace ?

               

              Thanks in advance,

              Nicky

              • 4. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                Wolf-Dieter Fink Master

                That should work.

                Could you post the EJB class with annotation and the stacktrace if you see the invocation failure?

                • 5. Re: Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                  Nicky Mølholm Newbie

                  Hi Wolf-Dieter !

                   

                  This is an anonymous version of my bean:

                   

                  @Stateless
                  @Local(HelloService.class)
                  @WebService(name = "helloService", serviceName = "helloService", endpointInterface="com.acme.HelloWebService")
                  @WebContext(contextRoot = "/hello/greeter", urlPattern = "/Hello", authMethod="BASIC", secureWSDLAccess = false)
                  @SecurityDomain(value = "GREETERDOMAIN")
                  @Interceptors(HelloInterceptor.class)
                  public class HelloWebServiceImpl implements HelloWebService {
                  ...
                  }
                  

                   

                  - There is no Exception stacktrace whatsoever.

                   

                   

                  Thanks,

                  Nicky

                  • 6. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                    Nicky Mølholm Newbie

                    Follow-up: I just invoked a method on a similar secure bean in a super simple EJB-JAR - using the built-in application security realm of JBoss AS.

                     

                    The behavior is different: I see an Exception from org.jboss.as.ejb3.security.AuthorizationInterceptor.

                     

                    So I'll investigate further on my part and get back to this thread...

                     

                    (Thank you guys)

                    • 7. Re: Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                      Nicky Mølholm Newbie

                      Hi Jaikiran and Wolf-Dieter !

                       

                      So I have had some time to investigate it further.

                       

                      It propose that there are a few problems in JBoss AS 7.2 when you :

                      • Create a secured EJB (in my case: with the @SecurityDomain annotation) , and
                      • That EJB has a WebService view (in my case: with the @WebService annotation), and
                      • That EJB is guarded by HTTP basic authentication (in my case: @org.jboss.ws.api.annotation.WebContext)

                       

                      The problems that I have observed (assume in all cases that I have provided valid HTTP basic authentication credentials):

                      • This flag is not honored: <s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
                        • ( Both in jboss-ejb3.xml and standalone.xml and perhaps also in clustered version )
                        • I have tested it on a @WebContext @SecurityDomain @WebService without any other security related annotations
                        • (Note: The flag actually works if you omit @WebContext)
                      • I can only invoke the EJB's method when i put a @PermitAll on the class level (it might work with @RolesAllowed to...haven't tested that)
                        • That same annotation does not work on the EJB method itself
                        • Actually I found that having @PermitAll on both the class and the method makes the bean behave as if implicit @DenyAll behavior was active
                      • When I attempt to invoke the EJB's web service methods with valid HTTP basic authentication credentials, but when the implicit @DenyAll annotation is active, then I do not see any evidence in the log.
                        • This is in contrast to the "normal" situation (without the @WebContext annotation) : here one will see authorization Exception stacktraces.

                       

                      So this is the EJB:

                      package greeter;
                      
                      import javax.annotation.PostConstruct;
                      import javax.annotation.PreDestroy;
                      import javax.ejb.Singleton;
                      import javax.ejb.Startup;
                      import javax.jws.WebService;
                      
                      import org.jboss.ejb3.annotation.SecurityDomain;
                      
                      @Singleton
                      @Startup
                      @WebService
                      @SecurityDomain("other")
                      //@org.jboss.ws.api.annotation.WebContext(contextRoot = "/greeter-0.0.1-SNAPSHOT", urlPattern = "/Greeter", authMethod = "BASIC", secureWSDLAccess = false)
                      //@javax.annotation.security.PermitAll
                      public class Greeter {
                      
                          // SEE doc here: https://docs.jboss.org/author/display/AS72/Securing+EJBs
                      
                           @javax.annotation.security.PermitAll // <-- Enable this and access is suddenly denied !
                          public String sayHello(String name) {
                              System.out.println("******** Greeter.sayHello(" + name + ")");
                              return "Hello " + name;
                          }
                      
                          @PostConstruct
                          public void startup() {
                              System.out.println("******** Greeter.startup()");
                          }
                      
                          @PreDestroy
                          public void stop() {
                              System.out.println("******** Greeter.stop()");
                          }
                      }
                      

                       

                       

                      And this is jboss-ejb3.xml:

                      <?xml version="1.0" encoding="UTF-8"?>
                      <jboss:jboss xmlns="http://java.sun.com/xml/ns/javaee"
                        xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:s="urn:security:1.1" version="3.1" impl-version="2.0">
                      
                        <assembly-descriptor>
                        <s:security>
                        <ejb-name>Greeter</ejb-name>
                        <s:missing-method-permissions-deny-access>true</s:missing-method-permissions-deny-access>
                        </s:security>
                        </assembly-descriptor>
                      
                        <!-- <s:security-domain>other</s:security-domain> -->
                      
                      </jboss:jboss>
                      

                       

                      And this is some test code I've been using (also tested through SoapUI...):

                      package greeter;
                      
                      
                      import static junit.framework.Assert.assertTrue;
                      
                      
                      import java.io.ByteArrayInputStream;
                      import java.io.IOException;
                      import java.io.InputStreamReader;
                      
                      
                      import javax.xml.namespace.QName;
                      import javax.xml.transform.Source;
                      import javax.xml.transform.stream.StreamSource;
                      import javax.xml.ws.Dispatch;
                      import javax.xml.ws.Service;
                      import javax.xml.ws.http.HTTPBinding;
                      
                      
                      import org.junit.Test;
                      
                      
                      // RUN ME:
                      // mvn clean package jboss-as:deploy -Dmaven.test.skip=true && mvn test
                      
                      
                      // GOOD:
                      // <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://greeter/"><return>Hello
                      // Milo</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
                      
                      
                      // BAD:
                      // JBWEB000123: Access to the specified resource has been forbidden.
                      // JBWEB000121: This request requires HTTP authentication
                      public class GreeterIntegrationTest {
                      
                      
                          @Test
                          public void goodCredentials() throws Exception {
                      
                      
                              Dispatch<Source> wsClient = createWebServiceClient("aben", "aben1234!");
                      
                      
                              String soapRequest = createRequestGreeting("sayHello", "Milo");
                      
                      
                              String soapResponse = dispatchInvoke(wsClient, soapRequest);
                      
                      
                              dumpResponse(soapResponse);
                      
                      
                              assertTrue(soapResponse.contains("Milo"));
                          }
                          
                          @Test
                          public void badCredentials() throws Exception {
                      
                      
                              Dispatch<Source> wsClient = createWebServiceClient("INVALID", "INVALID");
                      
                      
                              String soapRequest = createRequestGreeting("sayHello", "Milo");
                      
                      
                              String soapResponse = dispatchInvoke(wsClient, soapRequest);
                      
                      
                              dumpResponse(soapResponse);
                      
                      
                              assertTrue(soapResponse.contains("Milo"));
                          }
                      
                      
                          private String dispatchInvoke(Dispatch<Source> dispatch, String request) throws IOException {
                      
                      
                              Source soapRequest = new StreamSource(new ByteArrayInputStream(request.toString().getBytes()));
                      
                      
                              Source soapResponse = dispatch.invoke(soapRequest);
                      
                      
                              return sourceToString(soapResponse);
                          }
                      
                      
                          private Dispatch<Source> createWebServiceClient(String user, String pass) {
                      
                      
                              final String namespace = "http://greeter/";
                              final QName serviceName = new QName(namespace, "GreeterService");
                              final QName portName = new QName(namespace, "Greeter");
                              final String endpointAddress = "http://localhost:8080/greeter-0.0.1-SNAPSHOT/Greeter";
                      
                      
                              Service service = Service.create(serviceName);
                              service.addPort(portName, HTTPBinding.HTTP_BINDING, endpointAddress);
                      
                      
                              Dispatch<Source> dispatch = service.createDispatch(portName, Source.class, Service.Mode.MESSAGE);
                      
                      
                              dispatch.getRequestContext().put(Dispatch.USERNAME_PROPERTY, user);
                              dispatch.getRequestContext().put(Dispatch.PASSWORD_PROPERTY, pass);
                      
                      
                              return dispatch;
                          }
                      
                      
                          private String sourceToString(Source soapResponse) throws IOException {
                      
                      
                              InputStreamReader reader = new InputStreamReader(((StreamSource) soapResponse).getInputStream());
                              StringBuilder result = new StringBuilder();
                              char[] chars = new char[42];
                              for (int c = 0; (c = reader.read(chars)) > 0;) {
                                  result.append(new String(chars, 0, c));
                              }
                              reader.close();
                              return result.toString();
                          }
                      
                      
                          private String createRequestGreeting(String operation, String caller) {
                              StringBuilder request = new StringBuilder();
                              request.append("<?xml version='1.0' encoding='UTF-8'?>");
                              request.append("<soap:Envelope");
                              request.append("    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'");
                              request.append("    xmlns:q0='http://greeter/'>");
                              request.append("   ");
                              request.append("  <soap:Body>");
                              request.append("    <q0:").append(operation).append(">");
                              request.append("        <arg0>").append(caller).append("</arg0>");
                              request.append("    </q0:").append(operation).append(">");
                              request.append("  </soap:Body>");
                              request.append("   ");
                              request.append("</soap:Envelope>");
                              return request.toString();
                          }
                      
                      
                          private void dumpResponse(String soapResponse) {
                              System.out.println("--->");
                      
                      
                              if (soapResponse.contains("JBWEB0")) {
                                  String errorMsg = soapResponse.replaceAll(".*(JBWEB0.*?\\.).*", "ERROR!! $1");
                                  System.out.printf("%s%n%n", errorMsg);
                              }
                      
                      
                              System.out.println(soapResponse);
                      
                      
                              System.out.println("<---");
                          }
                      
                      
                      }
                      
                      • 8. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                        Nicky Mølholm Newbie

                        Further investigation shows that the problem seems to be in some jboss web source code.

                         

                        The EJB container never gets a chance to to "its stuff" - as in reading and honoring the default-missing-method-permissions-deny-access flag etc.

                         

                        I am currently looking into the source code to see what is happening....

                        • 9. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                          Nicky Mølholm Newbie

                          My final conclusions for this forum thread:

                           

                          • When you add the @WebContext annotation on an EJB you effectively enable authorization (in addition to authentication) in Web container code (in code from the "jboss web" project).
                          • This code silently rejects access to methods exposed through the EJB web service view if there is no security annotations on the EJB bean class
                            • You can put @RolesAllowed or @PermitAll on your EJB's web service view methods - but they are never honored by JBoss AS
                              • ...But: if you put these annotations on your bean class, then access is granted as expected
                            • You can set 'missing-method-permissions-deny-access' to false (in JBoss AS' profile configuration file or the JBoss AS specific module DD file) - but it is never used by JBoss AS

                           

                          So I propose that these two situations are "bugs".

                           

                          Now - since the problem seems to occur in layers above the EJB container - I will create a thread in a more appropriate forum. These issues has nothing todo with the EJB container*. I will get back to this thread and update it with an appropriate link to the new thread.

                           

                          * I suspect this: If the upper Web container layer correctly can propagate the method invocation to the EJB container - then appropriate authorizations check will follow - and ultimately fixing these issues.

                          • 10. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                            jaikiran pai Master

                            That looks like a webservices integration bug. Can you file a JIRA here https://issues.jboss.org/browse/WFLY  and attach with it a simple application to reproduce this please?

                            • 11. Re: default-missing-method-permissions-deny-access in standalone.xml is not honored
                              Nicky Mølholm Newbie

                              Absolutely - thank you.

                               

                              I will put a link to the JIRA on this thread once it is done.