10 Replies Latest reply: Oct 4, 2012 5:19 AM by kieselhorst RSS

    Security propagation from remote EJB clients to AS7

    rodakr Novice

      Hi guys

       

      Would it be possible to add support to remote EJB AS7 Client JAAS Security Context Propagation ?

      Something like to get Subject from Call context on client Side and forward it to Server Side and let the Security Real to deside for authentication/authorization.

       

      This wuold be realy helpful,  AS7 EJB remote Client without Security is pretty useless... and since beta1 Server Sider requres Authenticated users.. :-)

        • 1. Re: Security propagation from remote EJB clients to AS7
          rodakr Novice

          .. it would make sence require security from ejb remote clients as well

          • 2. Re: Security propagation from remote EJB clients to AS7
            jaikiran pai Master

            Yes, it's planned for upcoming releases. We did not want to hold up Beta1 release for this since we wanted to users to be able to start using the other EJB remoting bits that had been implemented.

            • 3. Re: Security propagation from remote EJB clients to AS7
              Darran Lofthouse Master

              Yes this is being implemented this week.

              • 4. Re: Security propagation from remote EJB clients to AS7
                rodakr Novice

                Great news!

                 

                Thank you

                • 5. Re: Security propagation from remote EJB clients to AS7
                  rodakr Novice

                  Hi

                   

                  AS 7.1 CR1b1 is out. Is there some security bits, which can be used ?

                   

                  1)

                  Can you provide client sample code using SASL Security ( for now PLAIN example would be enought ).

                   

                  ( or just add this example to https://docs.jboss.org/author/display/AS71/Developer+Guide#DeveloperGuide-EJBinvocationsfromaremoteclientusingJNDI )

                   

                  2)

                  I looked in source code of  org.jboss.sasl.JBossSaslProvider.java  ( jboss-sasl-1.0.0.Beta9.jar )

                   

                  Ony SASL MECH I see here are:

                   

                  "ANONYMOUS"

                  "PLAIN",

                  "DIGEST-MD5",

                  "JBOSS-LOCAL-USER"

                   

                  Could you also add "GSSAPI"  (  here how to from Darran Lofthouse http://community.jboss.org/wiki/SASLAndKerberos )

                   

                  Basically I would like to do this but with AS7.1:

                   

                  http://community.jboss.org/wiki/EJB3AuthenticationWithSPNEGO

                   

                  I tried to call remote ejb after sucessfull JAAS Login, but JAAS Login Context seams to not get propagatet to Server over Jboss Remote...

                   

                  Here how I tried ( the same Code but calling Web URL Secured with SPNEGO works, so KRB5 Java Setup is ok)  :

                   

                   

                   

                  import java.io.BufferedReader;

                  import java.io.IOException;

                  import java.io.InputStreamReader;

                  import java.security.AccessController;

                  import java.security.Principal;

                  import java.security.PrivilegedExceptionAction;

                  import java.security.Security;

                  import java.util.Collections;

                  import java.util.Hashtable;

                  import java.util.Properties;

                  import java.util.Set;

                   

                  import javax.naming.Context;

                  import javax.naming.InitialContext;

                  import javax.naming.NamingException;

                  import javax.security.auth.Subject;

                  import javax.security.auth.callback.Callback;

                  import javax.security.auth.callback.CallbackHandler;

                  import javax.security.auth.callback.NameCallback;

                  import javax.security.auth.callback.PasswordCallback;

                  import javax.security.auth.callback.TextInputCallback;

                  import javax.security.auth.callback.TextOutputCallback;

                  import javax.security.auth.callback.UnsupportedCallbackException;

                  import javax.security.auth.login.LoginContext;

                  import javax.security.sasl.Sasl;

                  import javax.security.sasl.SaslClient;

                  import javax.security.sasl.SaslException;

                   

                  import test.ejb3.TestServiceItf;

                   

                  public class TestServiceClient {

                      static String JAAS_CONFIG_ENTRY = "com.sun.security.jgss.krb5.initiate";

                      static BufferedReader br = new BufferedReader( new InputStreamReader (System.in));

                   

                   

                   

                      public static void main(String[] args) throws Exception {

                   

                   

                          LoginContext lc = null;

                          try {

                              System.out.println("\n >> Enter Win user Name : ");

                              String callbackUser  = br.readLine ();

                              System.out.println("\n >> Enter Win User AD password : ");

                   

                              String callbackPwd  = br.readLine ();

                   

                              // jaas collback might be needed for ticket refresh...

                              lc = new LoginContext(JAAS_CONFIG_ENTRY,new NamePasswordCallbackHandler2(callbackUser,callbackPwd ));

                   

                              lc.login();

                              //and get a subject

                              Subject mySubject = lc.getSubject();

                              System.out.println(" *********??????????********>>>> subject: "+mySubject);

                              Set<Principal> sp = mySubject.getPrincipals();

                              if ( sp == null ) System.out.println(" 0 principals ");

                              else {

                                  System.out.println(+sp.size()+" principals");

                                  for ( Principal p : sp ) {

                                      System.out.println("principal name :"+p.getName());

                                  }

                              }

                              // in case if not passed to java as property..

                              System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");

                              System.setProperty( "sun.security.krb5.debug", "true");

                   

                   

                              PrivilegedExceptionAction<String> action = new GetAction( null, null  );

                              //jaas call the service

                              String aRet = (String)mySubject.doAs(mySubject, action);

                   

                              // successfuly called, read returned values

                              System.out.println("successfully caled protected Method  : "+aRet);

                          } catch (Exception e) {

                              e.printStackTrace();

                              System.exit(-1);

                          }

                      }

                   

                      /**

                       *  dummy readLine Helper

                       * @return

                       */

                   

                      public static String readLine(String message)

                          {

                              String s = null;

                              System.out.println(message);

                              try {

                                  InputStreamReader converter = new InputStreamReader(System.in);

                                  BufferedReader in = new BufferedReader(converter);

                                  s = in.readLine();

                              } catch (Exception e) {

                                  System.out.println("Error! Exception: "+e);

                              } finally {

                                  System.out.println("");

                              }

                              return s;

                          }

                   

                   

                   

                   

                   

                   

                  }

                   

                  class GetAction implements PrivilegedExceptionAction<String> {

                   

                      private String toke;

                      private String user;

                      private String testEjbItf="test.ejb3.TestServiceItf";

                      // context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);

                      private String testEjbJndi="ejb:/sl-securityTestEjb3//TestServiceSLEJB3Bean!test.ejb3.TestServiceItf";

                   

                   

                      public GetAction(String user , String token) {

                          this.user = user;

                          this.toke=token;

                   

                      }

                   

                      static {

                   

                          try {

                              Sasl.createSaslClient(new String[]{"PLAIN"}, null, "remoting", "linux2", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("auser","apassword" ) );

                          } catch (SaslException e) {

                              // TODO Auto-generated catch block

                              e.printStackTrace();

                          }

                   

                          }

                   

                      // make shure

                      public String run() throws Exception {

                   

                          //Sasl.createSaslClient(new String[]{"GSSAPI"}, null, "remoting", "linux2", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("xxx","yyy" ) );

                          //Sasl.createSaslClient(new String[]{"PLAIN"}, null, "remoting", "linux2", Collections.EMPTY_MAP, new NamePasswordCallbackHandler2("xxx","yyy" ) );

                          javax.security.auth.Subject currentSubject = javax.security.auth.Subject.getSubject( AccessController.getContext());

                          if ( currentSubject == null ) System.out.println(" our Action runs as Subject: null ");

                          else System.out.println(" our Action runs as Subject: "+currentSubject.toString());

                          Context ctx = getInitialContext();

                          System.out.println("Initial Context created");

                          System.out.println("lookup"+testEjbJndi+" @RolesAllowed({\"BackofficeRole\"})");

                          Class itfClass = Thread.currentThread().getContextClassLoader().loadClass(testEjbItf);

                          TestServiceItf testService = (TestServiceItf)  ctx.lookup(testEjbJndi);

                          System.out.println("lookup testEjbJndi successful");

                          System.out.println(" call unsecured Method permittAllMethod()");

                          Subject asu = testService.permittAllMethod(" calling unsecured");

                          System.out.println(" successfully called, received Subject: "+asu);

                          System.out.println(" call secured Method with role "+testService.BACKOFFICE_ROLE);

                          asu = testService.pwvAuthenticatorSecuredMethod(" calling secured");

                          System.out.println(" successfully called, received Subject: "+asu);

                          return "Test ok";

                      }

                   

                      private static Context getInitialContext() throws NamingException {

                           final Hashtable jndiProperties = new Hashtable();

                           jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

                           jndiProperties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");

                           final Context context = new InitialContext(jndiProperties);

                           return context;

                          }

                   

                   

                  }

                   

                  class NamePasswordCallbackHandler2 implements CallbackHandler

                  {

                      /**

                       * The username to be provided when prompted.

                       */

                      private String username;

                   

                      /**

                       * The password to be provided when prompted.

                       */

                      private String password;

                   

                      private String url;

                   

                      /**

                       * Create a new NamePasswordCallbackHandler (required Cams default

                       * constructor that is dynamically called by the authentication

                       * server).

                       * @param anURL

                       * @param callbackPwd

                       * @param callbackUser

                       */

                      public NamePasswordCallbackHandler2(String callbackUser, String callbackPwd)

                      {

                          this.username = callbackUser;

                          this.password = callbackPwd;

                      }

                   

                   

                      /**

                       * Set the username.

                       *

                       * @param username the username to be provided to a NameCallback.

                       */

                      public void setUsername(String username)

                      {

                          if (username == null)

                          {

                              this.username = "";

                              return;

                          }

                   

                          this.username = username;

                      }

                   

                      /**

                       * Set the password.

                       *

                       * @param password the password to be provided to a PasswordCallback.

                       */

                      public void setPassword(String password)

                      {

                          if (password == null)

                          {

                              this.password = "";

                              return;

                          }

                   

                          this.password = password;

                      }

                   

                      public void handle(Callback[] callbacks)

                      throws IOException, UnsupportedCallbackException

                    {

                      for(int i = 0; i < callbacks.length; i++)

                      {

                        if(callbacks[i] instanceof TextOutputCallback)

                        {

                          // Display the message according to the specified type

                          TextOutputCallback toc = (TextOutputCallback)callbacks[i];

                          switch(toc.getMessageType())

                          {

                          case TextOutputCallback.INFORMATION:

                            log(toc.getMessage());

                            break;

                          case TextOutputCallback.ERROR:

                            log("ERROR: " + toc.getMessage());

                            break;

                          case TextOutputCallback.WARNING:

                            log("WARNING: " + toc.getMessage());

                            break;

                          default:

                            throw new IOException("Unsupported message type: "+toc.getMessageType());

                          }

                        }

                        else if(callbacks[i] instanceof NameCallback)

                        {

                          // If username not supplied on cmd line, prompt the user for the username.

                          NameCallback nc = (NameCallback)callbacks[i];

                          if (username == null || username.isEmpty()) {

                            System.err.print(nc.getPrompt());

                            System.err.flush();

                            nc.setName((new BufferedReader(new InputStreamReader(System.in))).readLine());

                          }

                          else {

                            log("username: "+username);

                            nc.setName(username);

                          }

                        }

                        else if(callbacks[i] instanceof PasswordCallback)

                        {

                          PasswordCallback pc = (PasswordCallback)callbacks[i];

                   

                          // If password not supplied on cmd line, prompt the user for the password.

                          if (password == null || password.isEmpty()) {

                            System.err.print(pc.getPrompt());

                            System.err.flush();

                   

                            // Note: JAAS specifies that the password is a char[] rather than a String

                            String tmpPassword = (new BufferedReader(new InputStreamReader(System.in))).readLine();

                            int passLen = tmpPassword.length();

                            char[] passwordArray = new char[passLen];

                            for(int passIdx = 0; passIdx < passLen; passIdx++)

                              passwordArray[passIdx] = tmpPassword.charAt(passIdx);

                            pc.setPassword(passwordArray);

                          }

                          else {

                            String tPass = new String();

                            for(int p = 0; p < password.length(); p++)

                              tPass += "*";

                            log("password: "+tPass);

                            pc.setPassword(password.toCharArray());

                          }       

                        }

                        else if(callbacks[i] instanceof TextInputCallback)

                        {

                          // Prompt the user for the username

                          TextInputCallback callback = (TextInputCallback)callbacks[i];

                          System.err.print(callback.getPrompt());

                          System.err.flush();

                          callback.setText((new BufferedReader(new InputStreamReader(System.in))).readLine());

                        }

                        else

                        {

                          throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");

                        }

                      }

                    }

                   

                    private void log(String str) { System.out.println(str); }

                   

                   

                  Happy New Year

                   

                  Radek Rodak

                  • 6. Re: Security propagation from remote EJB clients to AS7
                    Jan Snelders Newbie

                    Darran Lofthouse wrote:

                     

                    Yes this is being implemented this week.

                    Does this mean remote authentication (Standalone Client --> Secured EJB) isn't working at all so far in JBoss 7.1 CR1? Also not for the documented authentication.login modules at https://docs.jboss.org/author/display/AS71/Authentication+Modules?

                     

                    If so, I would like to know which JIRA Issue(s) we can track in order to know when we can start trying/testing remote authentication.

                     

                    Thanks in advance for any help.

                    • 7. Re: Security propagation from remote EJB clients to AS7
                      Oleg Stepanov Newbie

                      Please guys, any clues on this? How can I get a remote EJB client authenticated on AS 7? Whatever I've tried so far results in 'anonymous' principal being seen by EJBs on the server...

                      • 8. Re: Security propagation from remote EJB clients to AS7
                        Jan Snelders Newbie

                        No clues here unfortunately.
                        I'm trying the nighlty builds on a regular basis without success: https://community.jboss.org/thread/176963?tstart=0. Apparently I'm also looking at an anomymous principal?

                         

                        I don't see any other posts about remote EJB authentication problems answered so far.

                        • 9. Re: Security propagation from remote EJB clients to AS7
                          kieselhorst Newbie

                          IMHO authentication works with the latest version, but the propagation of the JAAS LoginContext (ClientLoginModule) is still unsupported. This means if you call javax.ejb.EJBContext.getCallerPrincipal(), lookup javax.security.auth.Subject.container via javax.security.jacc.PolicyContext or similar you will get the default user specified in the client properties or on the remote-outbound-connection.

                           

                          I'd greatly appreciate any samples on how to implement remote client calls with different authentications in AS7.

                          • 10. Re: Security propagation from remote EJB clients to AS7
                            kieselhorst Newbie

                            This thread also deals with this issue and contains a JIRA reference: https://issues.jboss.org/browse/AS7-5047