/*
* JBoss, Home of Professional Open Source.
* Copyright (C) 2008 Red Hat, Inc.
* Licensed to Red Hat, Inc. under one or more contributor
* license agreements. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.transport;
import static org.junit.Assert.*;
import java.util.Properties;
import javax.security.auth.Subject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.teiid.adminapi.VDB.Status;
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.client.security.ILogon;
import org.teiid.client.security.LogonException;
import org.teiid.client.security.LogonResult;
import org.teiid.client.security.SessionToken;
import org.teiid.core.util.Base64;
import org.teiid.deployers.VDBRepository;
import org.teiid.dqp.internal.process.DQPWorkContext;
import org.teiid.dqp.service.SessionService;
import org.teiid.net.TeiidURL;
import org.teiid.net.socket.AuthenticationType;
import org.teiid.runtime.DoNothingSecurityHelper;
import org.teiid.services.SessionServiceImpl;
@SuppressWarnings("nls")
public class TestLogonImpl {
SessionServiceImpl ssi;
@Before
public void setup() {
ssi = new SessionServiceImpl();
ssi.setSecurityHelper(new DoNothingSecurityHelper() {
@Override
public Subject getSubjectInContext(String securityDomain) {
if (securityDomain.equals("SC")) {
return new Subject();
}
return null;
}
});
}
@Test
public void testLogonResult() throws Exception {
SessionService ssi = Mockito.mock(SessionService.class);
Mockito.stub(ssi.getAuthenticationType(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).toReturn(AuthenticationType.USERPASSWORD);
DQPWorkContext.setWorkContext(new DQPWorkContext());
String userName = "Fred"; //$NON-NLS-1$
String applicationName = "test"; //$NON-NLS-1$
Properties p = new Properties();
p.setProperty(TeiidURL.CONNECTION.USER_NAME, userName);
p.setProperty(TeiidURL.CONNECTION.APP_NAME, applicationName);
p.setProperty(TeiidURL.JDBC.VDB_NAME, "x");
p.setProperty(TeiidURL.JDBC.VDB_VERSION, "1");
SessionMetadata session = new SessionMetadata();
session.setUserName(userName);
session.setApplicationName(applicationName);
session.setSessionId(String.valueOf(1));
session.setSessionToken(new SessionToken(1, userName));
Mockito.stub(ssi.createSession("x", "1", AuthenticationType.USERPASSWORD, userName, null, applicationName,p)).toReturn(session);
LogonImpl impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
LogonResult result = impl.logon(p);
assertEquals(userName, result.getUserName());
assertEquals(String.valueOf(1), result.getSessionID());
}
@Test
public void testLogonAuthenticationType() throws Exception {
VDBRepository repo = Mockito.mock(VDBRepository.class);
VDBMetaData vdb = new VDBMetaData();
vdb.addProperty(SessionServiceImpl.GSS_PATTERN_PROPERTY, "GSS");
vdb.setName("name");
vdb.setVersion(1);
vdb.setStatus(Status.ACTIVE);
Mockito.stub(repo.getLiveVDB("name", "1")).toReturn(vdb);
ssi.setVDBRepository(repo);
ssi.setSecurityDomain("SC");
// default transport - what Teiid has before TEIID-2863
ssi.setAuthenticationType(AuthenticationType.USERPASSWORD); // this is transport default
DQPWorkContext.setWorkContext(new DQPWorkContext());
Properties p = buildProperties("fred", "name");
LogonImpl impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
LogonResult result = impl.logon(p);
assertEquals("fred", result.getUserName());
// if no preference then choose USERPASSWORD
ssi.setAuthenticationType(AuthenticationType.USERPASSWORD); // this is transport default
DQPWorkContext.setWorkContext(new DQPWorkContext());
p = buildProperties("fred", "name");
impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
result = impl.logon(p);
assertEquals("fred", result.getUserName());
// if user name is set to "GSS", then the preference is set to "GSS"
ssi.setAuthenticationType(AuthenticationType.USERPASSWORD); // this is transport default
DQPWorkContext.setWorkContext(new DQPWorkContext());
p = buildProperties("GSS", "name");
FakeGssLogonImpl fimpl = new FakeGssLogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
fimpl.addToken("bytes".getBytes(), new Subject());
p.put(ILogon.KRB5TOKEN, "bytes".getBytes());
result = fimpl.logon(p);
assertEquals("GSS", result.getUserName());
// if the transport default defined as GSS, then preference is USERPASSWORD, additional challenge
ssi.setAuthenticationType(AuthenticationType.GSS);
DQPWorkContext.setWorkContext(new DQPWorkContext());
p = buildProperties("fred", "name");
impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
result = impl.logon(p);
assertEquals(AuthenticationType.GSS, result.getProperty("authType"));
}
@Test
public void testLogonAuthenticationTypeByVDB() throws Exception {
VDBRepository repo = Mockito.mock(VDBRepository.class);
ssi.setVDBRepository(repo);
// when VDB value is is avavailble this will not be used
ssi.setAuthenticationType(AuthenticationType.GSS);
// default transport - what Teiid has before TEIID-2863
addVdb(repo, "name", "SC", AuthenticationType.USERPASSWORD.name());
DQPWorkContext.setWorkContext(new DQPWorkContext());
Properties p = buildProperties("fred", "name");
LogonImpl impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
LogonResult result = impl.logon(p);
assertEquals("fred", result.getUserName());
// if no preference then choose USERPASSWORD
VDBMetaData metadata = addVdb(repo, "name1", "SC", AuthenticationType.USERPASSWORD.name());
metadata.addProperty(SessionServiceImpl.GSS_PATTERN_PROPERTY, "GSS");
DQPWorkContext.setWorkContext(new DQPWorkContext());
impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
p = buildProperties("fred", "name1");
result = impl.logon(p);
assertEquals("fred", result.getUserName());
p = buildProperties("GSS", "name1");
FakeGssLogonImpl fimpl = new FakeGssLogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
fimpl.addToken("bytes".getBytes(), new Subject());
p.put(ILogon.KRB5TOKEN, "bytes".getBytes());
result = fimpl.logon(p);
assertEquals("GSS", result.getUserName());
// here preference is GSS
try {
p = buildProperties("GSS", "name");
result = impl.logon(p);
assertEquals("GSS", result.getUserName());
} catch(LogonException e) {
}
// if the transport default defined as GSS, then preference is USERPASSWORD, additional challenge
addVdb(repo, "name2", "SC", "GSS");
DQPWorkContext.setWorkContext(new DQPWorkContext());
impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
p = buildProperties("fred", "name2");
result = impl.logon(p);
assertEquals(AuthenticationType.GSS, result.getProperty("authType"));
// doesn't match gss pattern
metadata.addProperty(SessionServiceImpl.GSS_PATTERN_PROPERTY, "GSS");
DQPWorkContext.setWorkContext(new DQPWorkContext());
impl = new LogonImpl(ssi, "fakeCluster"); //$NON-NLS-1$
p = buildProperties(null, "name1");
result = impl.logon(p);
assertEquals("anonymous", result.getUserName());
}
private Properties buildProperties(String userName, String vdbName) {
Properties p = new Properties();
if (userName != null) {
p.setProperty(TeiidURL.CONNECTION.USER_NAME, userName);
}
p.setProperty(TeiidURL.CONNECTION.APP_NAME, "test");
p.setProperty(TeiidURL.JDBC.VDB_NAME, vdbName);
p.setProperty(TeiidURL.JDBC.VDB_VERSION, "1");
return p;
}
private VDBMetaData addVdb(VDBRepository repo, String name, String sc, String authenticationType) {
VDBMetaData vdb = new VDBMetaData();
vdb.setName(name);
vdb.setVersion(1);
vdb.setStatus(Status.ACTIVE);
Mockito.stub(repo.getLiveVDB(name, "1")).toReturn(vdb);
vdb.addProperty(SessionServiceImpl.SECURITY_DOMAIN_PROPERTY, sc);
vdb.addProperty(SessionServiceImpl.AUTHENTICATION_TYPE_PROPERTY, authenticationType);
return vdb;
}
class FakeGssLogonImpl extends LogonImpl {
public FakeGssLogonImpl(SessionService service, String clusterName) {
super(service, clusterName);
}
//DoNothingSecurityHelper expects Subjects as security contexts
public void addToken(byte[] token, Subject securityContext) {
this.gssServiceTickets.put(Base64.encodeBytes(MD5(token)), securityContext);
}
}
}