Skip to content

Commit

Permalink
Merge pull request #430 from rareddy/TEIID-3380
Browse files Browse the repository at this point in the history
TEIID-3380: Merging the AuthenticationHandler and SecurityHelper into on...
  • Loading branch information
rareddy committed Mar 20, 2015
2 parents 84b363e + e1842aa commit f5a1d9d
Show file tree
Hide file tree
Showing 17 changed files with 334 additions and 364 deletions.
12 changes: 10 additions & 2 deletions engine/src/main/java/org/teiid/security/SecurityHelper.java
Expand Up @@ -25,6 +25,9 @@
import java.security.Principal;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import org.teiid.dqp.service.GSSResult;

public interface SecurityHelper {

Expand All @@ -39,6 +42,11 @@ public interface SecurityHelper {
Subject getSubjectInContext(String securityDomain);

boolean sameSubject(String securityDomain, Object context, Subject subject);

String getSecurityDomain(Object context);

TeiidLoginContext authenticate(String securityDomain, String userName, Credentials credentials, String applicationName)
throws LoginException;

GSSResult neogitiateGssLogin(String securityDomain, byte[] serviceTicket) throws LoginException;

TeiidLoginContext passThroughLogin(String securityDomain, String userName) throws LoginException;
}
Expand Up @@ -20,7 +20,7 @@
* 02110-1301 USA.
*/

package org.teiid.services;
package org.teiid.security;

import javax.security.auth.Subject;

Expand Down
Expand Up @@ -22,12 +22,15 @@

package org.teiid.dqp.internal.process;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.security.Principal;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import org.junit.Test;
import org.mockito.Mockito;
Expand All @@ -36,7 +39,10 @@
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.dqp.service.GSSResult;
import org.teiid.security.Credentials;
import org.teiid.security.SecurityHelper;
import org.teiid.security.TeiidLoginContext;


public class TestDQPWorkContext {
Expand Down Expand Up @@ -97,10 +103,6 @@ public boolean sameSubject(String securityDomain, Object context, Subject subjec
return mycontext == context;
}
@Override
public Subject getSubjectInContext(String securityDomain) {
return null;
}
@Override
public Object getSecurityContext() {
return this.mycontext;
}
Expand All @@ -118,16 +120,30 @@ public Object associateSecurityContext(Object context) {
this.mycontext = context;
return old;
}
@Override
public String getSecurityDomain(Object context) {
return null;
}
@Override
public Subject getSubjectInContext(String securityDomain) {
return null;
}
@Override
public TeiidLoginContext authenticate(String securityDomain, String userName, Credentials credentials,
String applicationName) throws LoginException {
return null;
}
@Override
public GSSResult neogitiateGssLogin(String securityDomain, byte[] serviceTicket) throws LoginException {
return null;
}
@Override
public TeiidLoginContext passThroughLogin(String securityDomain, String userName) throws LoginException {
return null;
}
};
Object previousSC = sc.createSecurityContext("test", null, null, null); //$NON-NLS-1$
sc.associateSecurityContext(previousSC);

DQPWorkContext message = new DQPWorkContext() {
public Subject getSubject() {
@Override
public Subject getSubject() {
return new Subject();
}
};
Expand Down
Expand Up @@ -24,17 +24,39 @@

import java.io.Serializable;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.jboss.as.security.plugins.SecurityDomainContext;
import org.jboss.as.server.CurrentServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.security.AuthenticationManager;
import org.jboss.security.SecurityContext;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.SubjectInfo;
import org.jboss.security.negotiation.Constants;
import org.jboss.security.negotiation.common.NegotiationContext;
import org.jboss.security.negotiation.spnego.KerberosMessage;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.dqp.service.GSSResult;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.security.Credentials;
import org.teiid.security.SecurityHelper;
import org.teiid.security.TeiidLoginContext;
import org.teiid.services.SessionServiceImpl;

public class JBossSecurityHelper implements SecurityHelper, Serializable {
private static final long serialVersionUID = 3598997061994110254L;

public static final String AT = "@"; //$NON-NLS-1$

@Override
public Object associateSecurityContext(Object newContext) {
SecurityContext context = SecurityActions.getSecurityContext();
Expand Down Expand Up @@ -88,9 +110,126 @@ public boolean sameSubject(String securityDomain, Object context, Subject subjec
return false;
}

@Override
public String getSecurityDomain(Object context) {
return ((SecurityContext)context).getSecurityDomain();
}

@Override
public TeiidLoginContext authenticate(String domain, String userName, Credentials credentials, String applicationName)
throws LoginException {
final String baseUsername = SessionServiceImpl.getBaseUsername(userName);

// If username specifies a domain (user@domain) only that domain is authenticated against.
// If username specifies no domain, then all domains are tried in order.
// this is the configured login for teiid
SecurityDomainContext securityDomainContext = getSecurityDomainContext(domain);
if (securityDomainContext != null) {
AuthenticationManager authManager = securityDomainContext.getAuthenticationManager();
if (authManager != null) {
Principal userPrincipal = new SimplePrincipal(userName);
Subject subject = new Subject();
String credString = credentials==null?null:new String(credentials.getCredentialsAsCharArray());
boolean isValid = authManager.isValid(userPrincipal, credString, subject);
if (isValid) {
String qualifiedUserName = baseUsername+AT+domain;
Object securityContext = createSecurityContext(domain, userPrincipal, credString, subject);
LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"Logon successful for \"", userName, "\""}); //$NON-NLS-1$ //$NON-NLS-2$
return new TeiidLoginContext(qualifiedUserName, subject, domain, securityContext);
}
}
}
throw new LoginException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50072, userName ));
}

@Override
public GSSResult neogitiateGssLogin(String securityDomain, byte[] serviceTicket) throws LoginException {

SecurityDomainContext securityDomainContext = getSecurityDomainContext(securityDomain);
if (securityDomainContext != null) {
AuthenticationManager authManager = securityDomainContext.getAuthenticationManager();

if (authManager != null) {
Object previous = null;
NegotiationContext context = new NegotiationContext();
context.setRequestMessage(new KerberosMessage(Constants.KERBEROS_V5, serviceTicket));

try {
context.associate();
SecurityContext securityContext = (SecurityContext)createSecurityContext(securityDomain, new SimplePrincipal("temp"), null, new Subject()); //$NON-NLS-1$
previous = associateSecurityContext(securityContext);

Subject subject = new Subject();
boolean isValid = authManager.isValid(null, null, subject);
if (isValid) {

Principal principal = null;
for(Principal p:subject.getPrincipals()) {
principal = p;
break;
}

Object sc = createSecurityContext(securityDomain, principal, null, subject);
LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"Logon successful though GSS API"}); //$NON-NLS-1$
GSSResult result = buildGSSResult(context, securityDomain);
result.setSecurityContext(sc);
result.setUserName(principal.getName());
return result;
}
LoginException le = (LoginException)securityContext.getData().get("org.jboss.security.exception"); //$NON-NLS-1$
if (le != null) {
if (le.getMessage().equals("Continuation Required.")) { //$NON-NLS-1$
return buildGSSResult(context, securityDomain);
}
throw le;
}
} finally {
associateSecurityContext(previous);
context.clear();
}
}
}
throw new LoginException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50072, "GSS Auth" )); //$NON-NLS-1$
}

private GSSResult buildGSSResult(NegotiationContext context, String securityDomain) throws LoginException {
if (context.getResponseMessage() instanceof KerberosMessage) {
try {
KerberosMessage km = (KerberosMessage)context.getResponseMessage();
GSSContext securityContext = (GSSContext) context.getSchemeContext();
return new GSSResult(km.getToken(), context.isAuthenticated(), securityContext.getCredDelegState()?securityContext.getDelegCred():null);
} catch (GSSException e) {
// login exception can not take exception
throw new LoginException(e.getMessage());
}
}
throw new LoginException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50103, securityDomain));
}

protected SecurityDomainContext getSecurityDomainContext(String securityDomain) {
if (securityDomain != null && !securityDomain.isEmpty()) {
ServiceName name = ServiceName.JBOSS.append("security", "security-domain", securityDomain); //$NON-NLS-1$ //$NON-NLS-2$
ServiceController<SecurityDomainContext> controller = (ServiceController<SecurityDomainContext>) CurrentServiceContainer.getServiceContainer().getService(name);
if (controller != null) {
return controller.getService().getValue();
}
}
return null;
}

private String getUserName(Subject subject, String userName) {
Set<Principal> principals = subject.getPrincipals();
for (Principal p:principals) {
if (p instanceof Group) {
continue;
}
return p.getName();
}
return SessionServiceImpl.getBaseUsername(userName);
}

@Override
public TeiidLoginContext passThroughLogin(String securityDomain, String userName) throws LoginException {
Subject existing = getSubjectInContext(securityDomain);
if (existing != null) {
return new TeiidLoginContext(getUserName(existing, userName) + AT + securityDomain, existing, securityDomain,
getSecurityContext());
}
throw new LoginException(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40087));
}
}

0 comments on commit f5a1d9d

Please sign in to comment.