From f407aec59ca7635c5bb96b7d562c2dcc8f936dfb Mon Sep 17 00:00:00 2001 From: Stefan Guilhen Date: Tue, 17 Jan 2017 11:53:14 -0200 Subject: [PATCH] [WFLY-6394] Elytron based implementation of the security SPI. --- connector/pom.xml | 4 + .../security/ElytronCallbackHandler.java | 200 +++++++++++++++++- .../security/ElytronSecurityContext.java | 70 ++++-- .../security/ElytronSecurityIntegration.java | 82 ++++--- .../security/ElytronSubjectFactory.java | 124 ++++++++++- ...tractResourceAdapterDeploymentService.java | 7 +- .../AbstractDataSourceService.java | 7 +- pom.xml | 2 +- 8 files changed, 425 insertions(+), 71 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 92fb88241aa7..89d0e7b13e76 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -97,6 +97,10 @@ org.jboss.ironjacamar ironjacamar-validator + + org.jboss.spec.javax.security.auth.message + jboss-jaspi-api_1.1_spec + org.jboss.logging jboss-logging diff --git a/connector/src/main/java/org/jboss/as/connector/security/ElytronCallbackHandler.java b/connector/src/main/java/org/jboss/as/connector/security/ElytronCallbackHandler.java index eace268c0968..270ba5b36ad3 100644 --- a/connector/src/main/java/org/jboss/as/connector/security/ElytronCallbackHandler.java +++ b/connector/src/main/java/org/jboss/as/connector/security/ElytronCallbackHandler.java @@ -19,35 +19,56 @@ import java.io.IOException; import java.io.Serializable; +import java.security.AccessController; +import java.security.Principal; +import java.security.PrivilegedAction; import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.resource.spi.security.PasswordCredential; +import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.message.callback.CallerPrincipalCallback; +import javax.security.auth.message.callback.GroupPrincipalCallback; +import javax.security.auth.message.callback.PasswordValidationCallback; import org.jboss.jca.core.spi.security.Callback; +import org.wildfly.security.auth.principal.NamePrincipal; +import org.wildfly.security.auth.server.RealmUnavailableException; +import org.wildfly.security.auth.server.SecurityDomain; +import org.wildfly.security.auth.server.SecurityIdentity; +import org.wildfly.security.auth.server.ServerAuthenticationContext; +import org.wildfly.security.authz.RoleMapper; +import org.wildfly.security.authz.Roles; +import org.wildfly.security.evidence.PasswordGuessEvidence; +import org.wildfly.security.manager.WildFlySecurityManager; /** - * CallbackHandler implementation for Elytron + * An Elytron based {@link CallbackHandler} implementation designed for the JCA security inflow. It uses the information + * obtained from the {@link javax.security.auth.callback.Callback}s to authenticate and authorize the identity supplied + * by the resource adapter and inserts the {@link SecurityIdentity} representing the authorized identity in the subject's + * private credentials set. * * @author Flavia Rainone + * @author Stefan Guilhen */ public class ElytronCallbackHandler implements CallbackHandler, Serializable { - /** Callback mappings */ - private Callback mappings; + private final SecurityDomain securityDomain; - /** - * Constructor - */ - public ElytronCallbackHandler() { - this(null); - } + /** Callback mappings */ + private final Callback mappings; + // TODO initialize the execution subject at the constructor. + private Subject executionSubject; /** * Constructor * @param mappings The mappings */ - public ElytronCallbackHandler(Callback mappings) { + public ElytronCallbackHandler(final SecurityDomain securityDomain, final Callback mappings) { + this.securityDomain = securityDomain; this.mappings = mappings; } @@ -64,7 +85,164 @@ public void handle(javax.security.auth.callback.Callback[] callbacks) throws Uns { callbacks = mappings.mapCallbacks(callbacks); } - // TODO + + GroupPrincipalCallback groupPrincipalCallback = null; + CallerPrincipalCallback callerPrincipalCallback = null; + PasswordValidationCallback passwordValidationCallback = null; + + for (javax.security.auth.callback.Callback callback : callbacks) { + if (callback instanceof GroupPrincipalCallback) { + groupPrincipalCallback = (GroupPrincipalCallback) callback; + if (executionSubject == null) { + executionSubject = groupPrincipalCallback.getSubject(); + } else if (!executionSubject.equals(groupPrincipalCallback.getSubject())) { + // TODO merge the contents of the subjects? + } + } else if (callback instanceof CallerPrincipalCallback) { + callerPrincipalCallback = (CallerPrincipalCallback) callback; + if (executionSubject == null) { + executionSubject = callerPrincipalCallback.getSubject(); + } else if (!executionSubject.equals(callerPrincipalCallback.getSubject())) { + // TODO merge the contents of the subjects? + } + } else if (callback instanceof PasswordValidationCallback) { + passwordValidationCallback = (PasswordValidationCallback) callback; + if (executionSubject == null) { + executionSubject = passwordValidationCallback.getSubject(); + } else if (!executionSubject.equals(passwordValidationCallback.getSubject())) { + // TODO merge the contents of the subjects? + } + } else { + throw new UnsupportedCallbackException(callback); + } + } + this.processResults(callerPrincipalCallback, groupPrincipalCallback, passwordValidationCallback); + } + } + + protected void processResults(final CallerPrincipalCallback callerPrincipalCallback, final GroupPrincipalCallback groupPrincipalCallback, + final PasswordValidationCallback passwordValidationCallback) throws IOException {//, UnsupportedCallbackException { + + // spec section 16.4.5 - no CallerPrincipalCallback was handled, check the execution subject's principal set. + SecurityIdentity authenticatedIdentity = this.securityDomain.getAnonymousSecurityIdentity(); + Principal callerPrincipal = null; + if (callerPrincipalCallback == null) { + if (executionSubject.getPrincipals().size() == 1) { + Principal subjectPrincipal = executionSubject.getPrincipals().iterator().next(); + callerPrincipal = new NamePrincipal(subjectPrincipal.getName()); + // TODO apply mapping to the principal if needed + } else if (!executionSubject.getPrincipals().isEmpty()) { + // TODO throw exception here (spec violation)? + } + } else { + Principal callbackPrincipal = callerPrincipalCallback.getPrincipal(); + callerPrincipal = callbackPrincipal != null ? new NamePrincipal(callbackPrincipal.getName()) : + callerPrincipalCallback.getName() != null ? new NamePrincipal(callerPrincipalCallback.getName()) : null; + } + + // a null principal is the ra contract for requiring the use of the unauthenticated identity - there's no point trying to authenticate any identity. + if (callerPrincipal != null) { + // check if we have a username/password pair to authenticate - first try the password validation callback. + if (passwordValidationCallback != null) { + authenticatedIdentity = this.authenticate(passwordValidationCallback.getUsername(), passwordValidationCallback.getPassword()); + } else { + // identity not established using the callback - check if the execution subject contains a password credential. + PasswordCredential passwordCredential = this.getPasswordCredential(this.executionSubject); + if (passwordCredential != null) { + authenticatedIdentity = this.authenticate(passwordCredential.getUserName(), passwordCredential.getPassword()); + } + } + } + + // if the caller principal is different from the authenticated identity principal, switch to the caller principal identity. + if (callerPrincipal != null && !callerPrincipal.equals(authenticatedIdentity.getPrincipal())) { + authenticatedIdentity = authenticatedIdentity.createRunAsIdentity(callerPrincipal.getName()); + } + + // if we have new roles coming from the group callback, set a new mapper in the identity. + if (groupPrincipalCallback != null) { + String[] groups = groupPrincipalCallback.getGroups(); + if (groups != null) { + Set roles = new HashSet<>(Arrays.asList(groups)); + // TODO what category should we use here? Is it right to assume every entry in the groups array represents a role? + authenticatedIdentity = authenticatedIdentity.withRoleMapper("jca", RoleMapper.constant(Roles.fromSet(roles))); + } + } + + // set the authenticated identity as a private credential in the subject. + if (executionSubject != null) { + this.addPrivateCredential(executionSubject, authenticatedIdentity); + } + } + + /** + * Authenticate the user with the given credential against the configured Elytron security domain. + * + * @param username the user being authenticated. + * @param credential the credential used as evidence to verify the user's identity. + * @return the authenticated and authorized {@link SecurityIdentity}. + * @throws IOException if an error occurs while authenticating the user. + */ + private SecurityIdentity authenticate(final String username, final char[] credential) throws IOException { + final ServerAuthenticationContext context = this.securityDomain.createNewAuthenticationContext(); + final PasswordGuessEvidence evidence = new PasswordGuessEvidence(credential != null ? credential : null); + try { + context.setAuthenticationName(username); + if (context.verifyEvidence(evidence)) { + if (context.authorize()) { + context.succeed(); + return context.getAuthorizedIdentity(); + } else { + context.fail(); + throw new SecurityException("Authorization failed"); + } + } else { + context.fail(); + throw new SecurityException("Authentication failed"); + } + } catch (IllegalArgumentException | IllegalStateException | RealmUnavailableException e) { + context.fail(); + throw e; + } finally { + if (!context.isDone()) { + context.fail(); + } + evidence.destroy(); + } + } + + protected PasswordCredential getPasswordCredential(final Subject subject) { + PasswordCredential credential = null; + if (subject != null) { + Set credentialSet; + if (!WildFlySecurityManager.isChecking()) { + credentialSet = subject.getPrivateCredentials(PasswordCredential.class); + } else { + credentialSet = AccessController.doPrivileged((PrivilegedAction>) () -> + subject.getPrivateCredentials(PasswordCredential.class)); + } + if (!credentialSet.isEmpty()) { + credential = credentialSet.iterator().next(); + } + } + return credential; + } + + /** + * Add the specified credential to the subject's private credentials set. + * + * @param subject the {@link Subject} to add the credential to. + * @param credential a reference to the credential. + */ + protected void addPrivateCredential(final Subject subject, final Object credential) { + if (!WildFlySecurityManager.isChecking()) { + subject.getPrivateCredentials().add(credential); + } + else { + AccessController.doPrivileged((PrivilegedAction) () -> { + subject.getPrivateCredentials().add(credential); + return null; + }); } } diff --git a/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityContext.java b/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityContext.java index d0d8e0adbbf3..17431de0892e 100644 --- a/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityContext.java +++ b/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityContext.java @@ -15,43 +15,52 @@ */ package org.jboss.as.connector.security; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashSet; +import java.util.Set; + import javax.security.auth.Subject; import org.jboss.jca.core.spi.security.SecurityContext; +import org.wildfly.security.auth.server.SecurityIdentity; +import org.wildfly.security.manager.WildFlySecurityManager; /** - * SecurityContext implementation for Elytron. + * An Elytron based {@link SecurityContext} implementation. * * @author Flavia Rainone + * @author Stefan Guilhen */ public class ElytronSecurityContext implements SecurityContext { - /** - * Constructor - */ - public ElytronSecurityContext() { - } + private Subject authenticatedSubject; - /** - * {@inheritDoc} - */ + @Override public Subject getAuthenticatedSubject() { - // TODO - return null; + return this.authenticatedSubject; } - /** - * {@inheritDoc} - */ - public void setAuthenticatedSubject(Subject subject) { - // TODO + @Override + public void setAuthenticatedSubject(final Subject subject) { + this.authenticatedSubject = subject; } - /** - * {@inheritDoc} - */ + @Override public String[] getRoles() { - return null; // TODO + if (this.authenticatedSubject != null) { + // check if the authenticated subject contains a SecurityIdentity in its private credentials. + Set authenticatedIdentities = this.getPrivateCredentials(SecurityIdentity.class); + // iterate through the identities adding all the roles found. + final Set rolesSet = new HashSet<>(); + for (SecurityIdentity identity : authenticatedIdentities) { + for (String role : identity.getRoles()) { + rolesSet.add(role); + } + } + return rolesSet.toArray(new String[rolesSet.size()]); + } + return new String[0]; } /** @@ -60,6 +69,25 @@ public String[] getRoles() { * @param work executes the work */ public void runWork(Runnable work) { - // TODO + // if we have an authenticated subject we check if it contains a security identity and use the identity to run the work. + if (this.authenticatedSubject != null) { + Set authenticatedIdentities = this.getPrivateCredentials(SecurityIdentity.class); + if (!authenticatedIdentities.isEmpty()) { + SecurityIdentity identity = authenticatedIdentities.iterator().next(); + identity.runAs(work); + return; + } + } + // no authenticated subject found or the subject didn't have a security identity - just run the work. + work.run(); } + + protected Set getPrivateCredentials(Class credentialClass) { + if (!WildFlySecurityManager.isChecking()) { + return this.authenticatedSubject.getPrivateCredentials(credentialClass); + } else { + return AccessController.doPrivileged((PrivilegedAction>) () -> this.authenticatedSubject.getPrivateCredentials(credentialClass)); + } + } + } diff --git a/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityIntegration.java b/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityIntegration.java index 706ef306f4a8..a1e561e7c585 100644 --- a/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityIntegration.java +++ b/connector/src/main/java/org/jboss/as/connector/security/ElytronSecurityIntegration.java @@ -15,63 +15,83 @@ */ package org.jboss.as.connector.security; +import java.security.AccessController; + import javax.security.auth.callback.CallbackHandler; +import org.jboss.as.controller.capability.RuntimeCapability; +import org.jboss.as.server.CurrentServiceContainer; import org.jboss.jca.core.spi.security.Callback; import org.jboss.jca.core.spi.security.SecurityContext; import org.jboss.jca.core.spi.security.SecurityIntegration; +import org.jboss.msc.service.ServiceContainer; +import org.jboss.msc.service.ServiceName; +import org.wildfly.security.auth.server.SecurityDomain; +import org.wildfly.security.manager.WildFlySecurityManager; /** - * SecurityIntegration implementation for Elytron. + * An Elytron based {@link SecurityIntegration} implementation. * * @author Flavia Rainone + * @author Stefan Guilhen */ public class ElytronSecurityIntegration implements SecurityIntegration { - /** - * Constructor - */ - public ElytronSecurityIntegration() { - } - /** - * {@inheritDoc} - */ + private static final String SECURITY_DOMAIN_CAPABILITY = "org.wildfly.security.security-domain"; + + private static final RuntimeCapability SECURITY_DOMAIN_RUNTIME_CAPABILITY = RuntimeCapability + .Builder.of(SECURITY_DOMAIN_CAPABILITY, true, SecurityDomain.class) + .build(); + + private final ThreadLocal securityContext = new ThreadLocal<>(); + + @Override public SecurityContext createSecurityContext(String sd) throws Exception { - // TODO return new ElytronSecurityContext(); } - /** - * {@inheritDoc} - */ + @Override public SecurityContext getSecurityContext() { - // TODO - return new ElytronSecurityContext(); + return this.securityContext.get(); } - /** - * {@inheritDoc} - */ + @Override public void setSecurityContext(SecurityContext context) { - if (context == null) { - // TODO - } - assert context instanceof ElytronSecurityContext; - // TODO + this.securityContext.set(context); } - /** - * {@inheritDoc} - */ + @Override public CallbackHandler createCallbackHandler() { - return new ElytronCallbackHandler(); + // we need a Callback to retrieve the Elytron security domain that will be used by the CallbackHandler. + throw new UnsupportedOperationException(); } - /** - * {@inheritDoc} - */ + @Override public CallbackHandler createCallbackHandler(Callback callback) { - return new ElytronCallbackHandler(callback); + if (callback != null) { + // TODO switch to use the elytron security domain once the callback has that info available. + final String securityDomainName = callback.getDomain(); + // get domain reference from the service container and create the callback handler using the domain. + if (securityDomainName != null) { + final ServiceContainer container = this.currentServiceContainer(); + final ServiceName securityDomainServiceName = SECURITY_DOMAIN_RUNTIME_CAPABILITY.getCapabilityServiceName(securityDomainName); + final SecurityDomain securityDomain = (SecurityDomain) container.getRequiredService(securityDomainServiceName).getValue(); + return new ElytronCallbackHandler(securityDomain, callback); + } + } + // TODO use subsystem logger for the exception. + throw new IllegalArgumentException("Supplied Callback must be non null and must contain an Elytron security domain reference"); } + /** + * Get a reference to the current {@link ServiceContainer}. + * + * @return a reference to the current {@link ServiceContainer}. + */ + private ServiceContainer currentServiceContainer() { + if(WildFlySecurityManager.isChecking()) { + return AccessController.doPrivileged(CurrentServiceContainer.GET_ACTION); + } + return CurrentServiceContainer.getServiceContainer(); + } } diff --git a/connector/src/main/java/org/jboss/as/connector/security/ElytronSubjectFactory.java b/connector/src/main/java/org/jboss/as/connector/security/ElytronSubjectFactory.java index 47270b8d6341..e52f7b296004 100644 --- a/connector/src/main/java/org/jboss/as/connector/security/ElytronSubjectFactory.java +++ b/connector/src/main/java/org/jboss/as/connector/security/ElytronSubjectFactory.java @@ -15,31 +15,82 @@ */ package org.jboss.as.connector.security; +import org.jboss.as.controller.capability.RuntimeCapability; +import org.jboss.as.server.CurrentServiceContainer; import org.jboss.jca.core.spi.security.SubjectFactory; +import org.jboss.msc.service.ServiceContainer; +import org.jboss.msc.service.ServiceName; +import org.wildfly.security.auth.client.AuthenticationConfiguration; +import org.wildfly.security.auth.client.AuthenticationContext; +import org.wildfly.security.auth.client.AuthenticationContextConfigurationClient; +import org.wildfly.security.auth.principal.NamePrincipal; +import org.wildfly.security.manager.WildFlySecurityManager; +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 static org.jboss.as.connector.logging.ConnectorLogger.ROOT_LOGGER; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessController; +import java.security.PrivilegedAction; + /** - * SubjectFactory implementation for Elytron. + * An Elytron based {@link SubjectFactory} implementation. It uses an {@link AuthenticationContext} to select a configuration + * that matches the resource {@link URI} to obtain the username and password pair that will be inserted into the constructed + * {@link Subject} instance. * * @author Flavia Rainone + * @author Stefan Guilhen */ public class ElytronSubjectFactory implements SubjectFactory { + private static final String AUTHENTICATION_CONTEXT_CAPABILITY = "org.wildfly.security.authentication-context"; + + private static final RuntimeCapability AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY = RuntimeCapability + .Builder.of(AUTHENTICATION_CONTEXT_CAPABILITY, true, AuthenticationContext.class) + .build(); + + private static final AuthenticationContextConfigurationClient AUTH_CONFIG_CLIENT = + AccessController.doPrivileged(AuthenticationContextConfigurationClient.ACTION); + + private URI targetURI; + /** * Constructor */ public ElytronSubjectFactory() { + this(null); + } + /** + * Constructor. + * + * @param targetURI the {@link URI} of the target. + */ + public ElytronSubjectFactory(final URI targetURI) { + if (targetURI == null) { + try { + // TODO remove this - used for testing only + this.targetURI = new URI("jdbc://localhost"); + } catch(URISyntaxException e) {} + } + this.targetURI = targetURI; } /** * {@inheritDoc} */ public Subject createSubject() { - Subject subject = null; // TODO + // no authentication configuration name has been supplied - capture the current configuration. + final Subject subject = this.createSubject(AuthenticationContext.captureCurrent()); if (ROOT_LOGGER.isTraceEnabled()) { ROOT_LOGGER.subject(subject, Integer.toHexString(System.identityHashCode(subject))); } @@ -49,15 +100,78 @@ public Subject createSubject() { /** * {@inheritDoc} */ - public Subject createSubject(String authenticationContext) { - Subject subject = null; // TODO - + public Subject createSubject(final String authenticationContextName) { + AuthenticationContext context; + if (authenticationContextName != null && !authenticationContextName.isEmpty()) { + final ServiceContainer container = this.currentServiceContainer(); + final ServiceName authContextServiceName = AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY.getCapabilityServiceName(authenticationContextName); + context = (AuthenticationContext) container.getRequiredService(authContextServiceName).getValue(); + } + else { + context = AuthenticationContext.captureCurrent(); + } + final Subject subject = this.createSubject(context); if (ROOT_LOGGER.isTraceEnabled()) { ROOT_LOGGER.subject(subject, Integer.toHexString(System.identityHashCode(subject))); } return subject; } + /** + * Create a {@link Subject} with the principal and password credential obtained from the authentication configuration + * that matches the target {@link URI}. + * + * @param authenticationContext the {@link AuthenticationContext} used to select a configuration that matches the + * target {@link URI}. + * @return the constructed {@link Subject}. It contains a single principal and a {@link PasswordCredential}. + */ + private Subject createSubject(final AuthenticationContext authenticationContext) { + final AuthenticationConfiguration configuration = AUTH_CONFIG_CLIENT.getAuthenticationConfiguration(this.targetURI, authenticationContext); + final CallbackHandler handler = AUTH_CONFIG_CLIENT.getCallbackHandler(configuration); + final NameCallback nameCallback = new NameCallback("Username: "); + final PasswordCallback passwordCallback = new PasswordCallback("Password: ", false); + try { + handler.handle(new Callback[]{nameCallback, passwordCallback}); + Subject subject = new Subject(); + subject.getPrincipals().add(new NamePrincipal(nameCallback.getName())); + // add the password as a private credential in the Subject. + this.addPrivateCredential(subject, new PasswordCredential(nameCallback.getName(), passwordCallback.getPassword())); + return subject; + } catch(IOException | UnsupportedCallbackException e) { + throw new SecurityException(e); + } + } + + /** + * Get a reference to the current {@link ServiceContainer}. + * + * @return a reference to the current {@link ServiceContainer}. + */ + private ServiceContainer currentServiceContainer() { + if(WildFlySecurityManager.isChecking()) { + return AccessController.doPrivileged(CurrentServiceContainer.GET_ACTION); + } + return CurrentServiceContainer.getServiceContainer(); + } + + /** + * Add the specified credential to the subject's private credentials set. + * + * @param subject the {@link Subject} to add the credential to. + * @param credential a reference to the credential. + */ + private void addPrivateCredential(final Subject subject, final Object credential) { + if (!WildFlySecurityManager.isChecking()) { + subject.getPrivateCredentials().add(credential); + } + else { + AccessController.doPrivileged((PrivilegedAction) () -> { + subject.getPrivateCredentials().add(credential); + return null; + }); + } + } + /** * {@inheritDoc} */ diff --git a/connector/src/main/java/org/jboss/as/connector/services/resourceadapters/deployment/AbstractResourceAdapterDeploymentService.java b/connector/src/main/java/org/jboss/as/connector/services/resourceadapters/deployment/AbstractResourceAdapterDeploymentService.java index a3c375cd2762..4083a46bbd0d 100644 --- a/connector/src/main/java/org/jboss/as/connector/services/resourceadapters/deployment/AbstractResourceAdapterDeploymentService.java +++ b/connector/src/main/java/org/jboss/as/connector/services/resourceadapters/deployment/AbstractResourceAdapterDeploymentService.java @@ -28,6 +28,7 @@ import java.io.File; import java.io.PrintWriter; +import java.net.URISyntaxException; import java.net.URL; import java.security.PrivilegedAction; import java.util.List; @@ -623,7 +624,11 @@ protected org.jboss.jca.core.spi.security.SubjectFactory getSubjectFactory( assert securityMetadata instanceof SecurityMetadata; final String securityDomain = securityMetadata.resolveSecurityDomain(); if (((SecurityMetadata)securityMetadata).isElytronEnabled()) { - return new ElytronSubjectFactory(); + try { + return new ElytronSubjectFactory(this.url.toURI()); + } catch (URISyntaxException e) { + throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(e); + } } else if (securityDomain == null || securityDomain.trim().equals("")) { return null; } else { diff --git a/connector/src/main/java/org/jboss/as/connector/subsystems/datasources/AbstractDataSourceService.java b/connector/src/main/java/org/jboss/as/connector/subsystems/datasources/AbstractDataSourceService.java index 794f0a3c7e52..8c8c9070bcb6 100644 --- a/connector/src/main/java/org/jboss/as/connector/subsystems/datasources/AbstractDataSourceService.java +++ b/connector/src/main/java/org/jboss/as/connector/subsystems/datasources/AbstractDataSourceService.java @@ -27,6 +27,7 @@ import static org.jboss.as.connector.logging.ConnectorLogger.DS_DEPLOYER_LOGGER; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.sql.Driver; import java.util.ArrayList; @@ -438,7 +439,11 @@ protected org.jboss.jca.core.spi.security.SubjectFactory getSubjectFactory( assert credential instanceof Credential; final String securityDomain = credential.getSecurityDomain(); if (((Credential) credential).isElytronEnabled()) { - return new ElytronSubjectFactory(); + try { + return new ElytronSubjectFactory(new java.net.URI(this.dataSourceConfig.getConnectionUrl())); + } catch (URISyntaxException e) { + throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(e); + } } else if (securityDomain == null || securityDomain.trim().equals("") || subjectFactory.getOptionalValue() == null) { return null; } else { diff --git a/pom.xml b/pom.xml index 77f1b11a2f50..0f38b41cdedc 100644 --- a/pom.xml +++ b/pom.xml @@ -161,7 +161,7 @@ 2.2.0.Final 2.0.0.Alpha1 1.0.0.Final - 1.4.0.Final + 1.4.1-SNAPSHOT 7.5.0.Final 10.0.0.Final 5.5.0.Final