JBoss Community

Re: IronJacamar Oracle Reauthentication support

created by Peter Fry in IronJacamar Development - View the full discussion

Is there a test case for this component. I am trying to support Oracle Proxy Authentication on EAP 6.0.1 but without any joy. My main stumbling block is the configuration of the security section of the datasource:

 

<subsystem xmlns="urn:jboss:domain:datasources:1.1">

 

<xa-datasource jndi-name="java:jboss/datasources/someDS" pool-name="java:jboss/datasources/someDS_Pool">

<datasources>

<xa-datasource-property name="URL"> jdbc:oracle:thin:@%DATABASE_HOST%:%DATABASE_PORT%:%DATABASE_SID%

 

 

<xa-pool>

 

<is-same-rm-override>false</is-same-rm-override>

 

<no-tx-separate-pools>true</no-tx-separate-pools>

 

</xa-pool>

 

<security>

<!--<user-name>USERNAME</user-name>

<password>PASSWORD</password>

<reauth-plugin class-name="org.me.OracleReauthPlugin"/>-->

 

<security-domain>demo</security-domain>

 

</security>

 

<validation>

 

<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/>

 

<stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker"/>

 

<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>

 

</validation>

 

</xa-datasource>

 

<drivers>

 

<driver name="oracle" module="com.oracle">

 

<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>

 

</driver>

 

</drivers>

 

</datasources>

 

</subsystem>

</xa-datasource-property>

 

<driver>oracle</driver>

 

I have added a security domain

 

<subsystem xmlns="urn:jboss:domain:security:1.2">
        <security-domains>
                <security-domain name="other" cache-type="default">
                    <authentication>
                        <login-module code="Remoting" flag="optional">
                            <module-option name="password-stacking" value="useFirstPass"/>
                        </login-module>
                        <login-module code="RealmDirect" flag="required">
                            <module-option name="password-stacking" value="useFirstPass"/>
                        </login-module>
                    </authentication>
                </security-domain>
                <security-domain name="jboss-web-policy" cache-type="default">
                    <authorization>
                        <policy-module code="Delegating" flag="required"/>
                    </authorization>
                </security-domain>
                <security-domain name="jboss-ejb-policy" cache-type="default">
                    <authorization>
                        <policy-module code="Delegating" flag="required"/>
                    </authorization>
                </security-domain>
                <security-domain name="brms" cache-type="default">
                    <authentication>
                        <login-module code="UsersRoles" flag="required">
                            <module-option name="usersProperties" value="${jboss.server.config.dir}/brms-users.properties"/>
                            <module-option name="rolesProperties" value="${jboss.server.config.dir}/brms-roles.properties"/>
                        </login-module>
                    </authentication>
                </security-domain>
                <!-- Introduced for demonstrating Oracle Proxy Authentication -->
    <security-domain name="demo" cache-type="default">
       <authentication>
          <login-module code="SimpleUsers" flag="sufficient">
                <module-option name="username" value="USERNAME"/>
                <module-option name="password" value="PASSWORD"/>
          </login-module>
          <login-module code="UsersRoles" flag="sufficient">
                <module-option name="usersProperties" value="${jboss.server.config.dir}/demo-users.properties"/>
                            <module-option name="rolesProperties" value="${jboss.server.config.dir}/demo-roles.properties"/>
          </login-module>
       </authentication>
    </security-domain>               
</security-domains>
</subsystem>

 

I'm then running a arquillian test

 

import java.security.PrivilegedAction;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.secureejb.JBossLoginContextFactory;
import org.jboss.arquillian.secureejb.demo.SecurityRoles;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.me.TestEjb;

@RunWith(Arquillian.class)
public class OracleReauthPluginTest {

private static final Logger logger = Logger.getLogger(OracleReauthPluginTest.class.getName());

    @EJB
    private TestEjb testEjb;

    @Deployment
    public static WebArchive createTestArchive() {
        WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
                .addClasses(JBossLoginContextFactory.class, SecurityRoles.class, TestEjb.class)
                .addAsWebInfResource("META-INF/ejb-jar.xml").addAsWebInfResource("META-INF/jboss-ejb3.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml").addAsResource("users.properties")
                .addAsResource("roles.properties");
        return webArchive;
    }

    @Test
    public void testAuthorisedSecureOperation() throws LoginException {
        LoginContext loginContext = JBossLoginContextFactory.createLoginContext("user1", "password");
        loginContext.login();
        try {
            Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {

                @Override
                public Void run() {
                 try {
     testEjb.performSecureOperation();
   } catch (SQLException e) {
     logger.log(Level.SEVERE, "EJB oepration failed", e);
   }
                    return null;
                }

            });
        } finally {
            loginContext.logout();
        }
    }
}

 

With the logon context being supplied by

 

package org.jboss.arquillian.secureejb;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.resource.spi.security.PasswordCredential;
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.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

/**
* Provides a {@link LoginContext} for use by unit tests. It is driven by users.properties and roles.properties files as
* described in <a href="https://community.jboss.org/wiki/UsersRolesLoginModule">UsersRolesLoginModule</a>
*/
public class JBossLoginContextFactory {

    static class NamePasswordCallbackHandler implements CallbackHandler {
        private final String username;
        private final String password;

        private NamePasswordCallbackHandler(String username, String password) {
            this.username = username;
            this.password = password;
        }

        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (Callback current : callbacks) {
                if (current instanceof NameCallback) {
                    ((NameCallback) current).setName(username);
                } else if (current instanceof PasswordCallback) {
                    ((PasswordCallback) current).setPassword(password.toCharArray());
                } else {
                    throw new UnsupportedCallbackException(current);
                }
            }
        }
    }

    static class JBossJaasConfiguration extends Configuration {
        private final String configurationName;

        JBossJaasConfiguration(String configurationName) {
            this.configurationName = configurationName;
        }

        @Override
        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
            if (!configurationName.equals(name)) {
                throw new IllegalArgumentException("Unexpected configuration name '" + name + "'");
            }

            return new AppConfigurationEntry[] {

            createUsersRolesLoginModuleConfigEntry(),

            createClientLoginModuleConfigEntry(),

            };
        }

        /**
         * The {@link org.jboss.security.auth.spi.UsersRolesLoginModule} creates the association between users and
         * roles.
         *
         * @return
         */
        private AppConfigurationEntry createUsersRolesLoginModuleConfigEntry() {
            Map<String, String> options = new HashMap<String, String>();
            return new AppConfigurationEntry("org.jboss.security.auth.spi.UsersRolesLoginModule",
                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
        }

        /**
         * The {@link org.jboss.security.ClientLoginModule} associates the user credentials with the
         * {@link org.jboss.security.SecurityContext} where the JBoss security runtime can find it.
         *
         * @return
         */
        private AppConfigurationEntry createClientLoginModuleConfigEntry() {
            Map<String, String> options = new HashMap<String, String>();
            options.put("multi-threaded", "true");
            options.put("restore-login-identity", "true");

            return new AppConfigurationEntry("org.jboss.security.ClientLoginModule",
                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
        }
    }

    /**
     * Obtain a LoginContext configured for use with the ClientLoginModule.
     *
     * @return the configured LoginContext.
     */
    public static LoginContext createLoginContext(final String username, final String password) throws LoginException {
        final String configurationName = "Arquillian Testing";

        CallbackHandler cbh = new JBossLoginContextFactory.NamePasswordCallbackHandler(username, password);
        Configuration config = new JBossJaasConfiguration(configurationName);
        Subject subject = new Subject();
        PasswordCredential credential = new PasswordCredential(username,  password.toCharArray());
       
        subject.getPrivateCredentials().add(credential);
        return new LoginContext(configurationName, subject, cbh, config);
    }

}

 

The problem I have is that in BaseWrapperManagedConnectionFactory.SubjectActions.run() the subject has no private credentials.

 

Is the approach I'm taking (in terms of setting up an integration test) correct? I am hacking around with this.

Reply to this message by going to Community

Start a new discussion in IronJacamar Development at Community