Skip to content

Commit

Permalink
TEIID-2915: Adding kerberoes delegation to REST based web service
Browse files Browse the repository at this point in the history
  • Loading branch information
rareddy committed May 28, 2014
1 parent ef875b5 commit 671a280
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 45 deletions.
Expand Up @@ -27,26 +27,16 @@
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.Future;

import javax.activation.DataSource;
import javax.resource.ResourceException;
import javax.security.auth.Subject;
import javax.ws.rs.core.Response.Status;
import javax.xml.namespace.QName;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Binding;
import javax.xml.ws.Dispatch;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Response;
import javax.xml.ws.Service;
import javax.xml.ws.*;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

Expand All @@ -61,6 +51,7 @@
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.ietf.jgss.GSSCredential;
import org.teiid.core.util.ArgCheck;
import org.teiid.core.util.Base64;
import org.teiid.core.util.StringUtil;
Expand Down Expand Up @@ -137,10 +128,13 @@ public DataSource invoke(DataSource msg) {
}
String username = (String) this.requestContext.get(Dispatch.USERNAME_PROPERTY);
String password = (String) this.requestContext.get(Dispatch.PASSWORD_PROPERTY);

if (username != null) {
this.client.header("Authorization", "Basic " + Base64.encodeBytes((username + ':' + password).getBytes())); //$NON-NLS-1$ //$NON-NLS-2$
}
else if (this.requestContext.get(GSSCredential.class.getName()) != null) {
WebClient.getConfig(this.client).getRequestContext().put(GSSCredential.class.getName(), this.requestContext.get(GSSCredential.class.getName()));
}

InputStream payload = null;
if (msg != null) {
Expand Down Expand Up @@ -369,6 +363,20 @@ private <T> void setDispatchProperties(Dispatch<T> dispatch) {
dispatch.getRequestContext().put(Dispatch.USERNAME_PROPERTY, userName);
dispatch.getRequestContext().put(Dispatch.PASSWORD_PROPERTY, password);
}
else if (this.mcf.getAsSecurityType() == WSManagedConnectionFactory.SecurityType.Kerberos) {
boolean credentialFound = false;
Subject subject = ConnectionContext.getSubject();
if (subject != null) {
GSSCredential credential = ConnectionContext.getSecurityCredential(subject, GSSCredential.class);
if (credential != null) {
dispatch.getRequestContext().put(GSSCredential.class.getName(), credential);
credentialFound = true;
}
}
if (!credentialFound) {
throw new WebServiceException(WSManagedConnectionFactory.UTIL.getString("no_gss_credential")); //$NON-NLS-1$
}
}

if (this.mcf.getRequestTimeout() != null){
dispatch.getRequestContext().put(RECEIVE_TIMEOUT, this.mcf.getRequestTimeout());
Expand Down
Expand Up @@ -46,7 +46,7 @@ public class WSManagedConnectionFactory extends BasicManagedConnectionFactory {

public static final BundleUtil UTIL = BundleUtil.getBundleUtil(WSManagedConnectionFactory.class);

public enum SecurityType {None,HTTPBasic,WSSecurity}
public enum SecurityType {None,HTTPBasic,WSSecurity,Kerberos}

//ws properties
private String endPoint;
Expand Down
2 changes: 1 addition & 1 deletion connectors/connector-ws/src/main/rar/META-INF/ra.xml
Expand Up @@ -47,7 +47,7 @@
</config-property>

<config-property>
<description>{$display:"WebService Security Used",$allowed:["None","HTTPBasic","WSSecurity"], $description:"Type of Authentication to used with the web service.", $required:"true", $defaultValue:"None"}</description>
<description>{$display:"WebService Security Used",$allowed:["None","HTTPBasic","WSSecurity", "Kerberos"], $description:"Type of Authentication to used with the web service.", $required:"true", $defaultValue:"None"}</description>
<config-property-name>SecurityType</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>None</config-property-value>
Expand Down
Expand Up @@ -22,4 +22,5 @@

null_endpoint=An endpoint must be specified by the procedure call or have a default value set by the EndPoint datasource property.
null_default_endpoint=The use of a relative endpoint in a procedure call requires a a default endpoint on the datasource.
no_cert=No trusted certificate found
no_cert=No trusted certificate found
no_gss_credential=Kerberoes delegation is configured to be used with web service, however delegation credentail is not found in the Subject
16 changes: 14 additions & 2 deletions engine/src/main/java/org/teiid/dqp/service/GSSResult.java
Expand Up @@ -21,16 +21,20 @@
*/
package org.teiid.dqp.service;

import org.ietf.jgss.GSSCredential;


public class GSSResult {
private byte[] serviceToken;
private boolean authenticated;
private Object securityContext;
private String userName;
private GSSCredential delegationCredentail;

public GSSResult(byte[] token, boolean authenticated) {
public GSSResult(byte[] token, boolean authenticated, GSSCredential cred) {
this.serviceToken = token;
this.authenticated = authenticated;
this.delegationCredentail = cred;
}

public boolean isAuthenticated() {
Expand All @@ -55,5 +59,13 @@ public String getUserName() {

public void setUserName(String name) {
this.userName = name;
}
}

public GSSCredential getDelegationCredentail() {
return delegationCredentail;
}

public void setDelegationCredentail(GSSCredential delegationCredentail) {
this.delegationCredentail = delegationCredentail;
}
}
Expand Up @@ -27,6 +27,8 @@
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.security.AuthenticationManager;
import org.jboss.security.SecurityContext;
Expand Down Expand Up @@ -128,8 +130,14 @@ public GSSResult neogitiateGssLogin(String securityDomain, byte[] serviceTicket)

private GSSResult buildGSSResult(NegotiationContext context, String securityDomain) throws LoginException {
if (context.getResponseMessage() instanceof KerberosMessage) {
KerberosMessage km = (KerberosMessage)context.getResponseMessage();
return new GSSResult(km.getToken(), context.isAuthenticated());
try {
KerberosMessage km = (KerberosMessage)context.getResponseMessage();
GSSContext securityContext = (GSSContext) context.getSchemeContext();
return new GSSResult(km.getToken(), context.isAuthenticated(), securityContext.getDelegCred());
} catch (GSSException e) {
// login exception can not take exception
throw new LoginException(e.getMessage());
}
}
throw new LoginException(IntegrationPlugin.Util.gs(IntegrationPlugin.Event.TEIID50103, securityDomain));
}
Expand Down
27 changes: 9 additions & 18 deletions runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
Expand Up @@ -21,7 +21,10 @@
*/
package org.teiid.odbc;

import static org.teiid.odbc.PGUtil.*;
import static org.teiid.odbc.PGUtil.PG_TYPE_FLOAT4;
import static org.teiid.odbc.PGUtil.PG_TYPE_FLOAT8;
import static org.teiid.odbc.PGUtil.PG_TYPE_NUMERIC;
import static org.teiid.odbc.PGUtil.convertType;

import java.io.IOException;
import java.net.InetSocketAddress;
Expand All @@ -30,18 +33,12 @@
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.ietf.jgss.GSSCredential;
import org.teiid.adminapi.VDB;
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.client.RequestMessage.ResultsMode;
Expand All @@ -53,22 +50,15 @@
import org.teiid.core.util.StringUtil;
import org.teiid.deployers.PgCatalogMetadataStore;
import org.teiid.dqp.service.SessionService;
import org.teiid.jdbc.ConnectionImpl;
import org.teiid.jdbc.PreparedStatementImpl;
import org.teiid.jdbc.ResultSetImpl;
import org.teiid.jdbc.StatementImpl;
import org.teiid.jdbc.TeiidDriver;
import org.teiid.jdbc.*;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.net.socket.AuthenticationType;
import org.teiid.net.socket.SocketServerConnection;
import org.teiid.odbc.PGUtil.PgColInfo;
import org.teiid.query.parser.SQLParserUtil;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.transport.LocalServerConnection;
import org.teiid.transport.LogonImpl;
import org.teiid.transport.ODBCClientInstance;
import org.teiid.transport.PgBackendProtocol;
import org.teiid.transport.*;
import org.teiid.transport.PgFrontendProtocol.NullTerminatedStringDataInputStream;

/**
Expand Down Expand Up @@ -240,6 +230,7 @@ else if (authType.equals(AuthenticationType.GSS)) {
serviceToken = (byte[])result.getProperty(ILogon.KRB5TOKEN);
if (Boolean.TRUE.equals(result.getProperty(ILogon.KRB5_ESTABLISHED))) {
info.put(ILogon.KRB5TOKEN, serviceToken);
info.put(GSSCredential.class.getName(), result.getProperty(GSSCredential.class.getName()));
}
else {
this.client.authenticationGSSContinue(serviceToken);
Expand Down
20 changes: 13 additions & 7 deletions runtime/src/main/java/org/teiid/transport/LogonImpl.java
Expand Up @@ -29,12 +29,9 @@

import javax.security.auth.login.LoginException;

import org.ietf.jgss.GSSCredential;
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.client.security.ILogon;
import org.teiid.client.security.InvalidSessionException;
import org.teiid.client.security.LogonException;
import org.teiid.client.security.LogonResult;
import org.teiid.client.security.SessionToken;
import org.teiid.client.security.*;
import org.teiid.client.util.ResultsFuture;
import org.teiid.core.CoreConstants;
import org.teiid.core.TeiidComponentException;
Expand Down Expand Up @@ -131,6 +128,11 @@ private LogonResult logon(Properties connProps, byte[] krb5ServiceTicket, Authen

try {
SessionMetadata sessionInfo = service.createSession(vdbName, vdbVersion, authType, user,credential, applicationName, connProps);

if (connProps.get(GSSCredential.class.getName()) != null) {
sessionInfo.getSubject().getPrivateCredentials().add(connProps.get(GSSCredential.class.getName()));
}

updateDQPContext(sessionInfo);
if (DQPWorkContext.getWorkContext().getClientAddress() == null) {
sessionInfo.setEmbedded(true);
Expand Down Expand Up @@ -181,13 +183,17 @@ public LogonResult neogitiateGssLogin(Properties connProps, byte[] serviceTicket
LogonResult logonResult = new LogonResult(new SessionToken(0, "temp"), "internal", 0, "internal"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
logonResult.addProperty(ILogon.KRB5TOKEN, result.getServiceToken());
logonResult.addProperty(ILogon.KRB5_ESTABLISHED, new Boolean(result.isAuthenticated()));
if (result.isAuthenticated()) {
logonResult.addProperty(GSSCredential.class.getName(), result.getDelegationCredentail());
}
return logonResult;
}

// GSS API (jdbc) will make the session in one single call
connProps.put(ILogon.KRB5TOKEN, result.getServiceToken());
LogonResult loginInResult = logon(connProps);
return loginInResult;
connProps.put(GSSCredential.class.getName(), result.getDelegationCredentail());
LogonResult logonResult = logon(connProps);
return logonResult;
} catch (LoginException e) {
throw new LogonException(RuntimePlugin.Event.TEIID40014, e, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40014));
}
Expand Down

0 comments on commit 671a280

Please sign in to comment.