/* * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.identity.thrift.authentication.internal; import org.apache.axiom.om.OMElement; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.thrift.protocol.TCompactProtocol; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; import org.wso2.carbon.base.ServerConfiguration; import org.wso2.carbon.identity.thrift.authentication.AuthenticatorServlet; import org.wso2.carbon.identity.thrift.authentication.TCPThriftAuthenticationService; import org.wso2.carbon.identity.thrift.authentication.ThriftAuthenticatorService; import org.wso2.carbon.identity.thrift.authentication.dao.DBThriftSessionDAO; import org.wso2.carbon.identity.thrift.authentication.dao.ThriftSessionDAO; import org.wso2.carbon.identity.thrift.authentication.internal.generatedCode.AuthenticatorService; import org.wso2.carbon.identity.thrift.authentication.internal.util.HostAddressFinder; import org.wso2.carbon.identity.thrift.authentication.internal.util.ThriftAuthenticationConfigParser; import org.wso2.carbon.identity.thrift.authentication.internal.util.ThriftAuthenticationConstants; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.ConfigurationContextService; import javax.servlet.ServletException; import java.net.MalformedURLException; import java.net.URL; import java.util.Hashtable; /** * @scr.component name="org.wso2.carbon.identity.thrift.authentication.internal.ThriftAuthenticationServiceComponent" immediate="true" * @scr.reference name="http.service" interface="org.osgi.service.http.HttpService" * cardinality="1..1" policy="dynamic" bind="setHttpService" unbind="unsetHttpService" * @scr.reference name="org.wso2.carbon.user.core" * interface="org.wso2.carbon.user.core.service.RealmService" * cardinality="1..1" policy="dynamic" bind="setRealmService" unbind="unsetRealmService" * @scr.reference name="configuration.context" * interface="org.wso2.carbon.utils.ConfigurationContextService" * cardinality="1..1" policy="dynamic" bind="setConfigurationContext" unbind="unsetConfigurationContext" */ public class ThriftAuthenticationServiceComponent { private static Log log = LogFactory.getLog(ThriftAuthenticationServiceComponent.class); private static HttpService httpServiceInstance; private static RealmService realmServiceInstance; private ServiceRegistration thriftAuthenticationService; private ConfigurationContextService configurationContext; private TCPThriftAuthenticationService TCPThriftAuthenticationService; public static int readPortOffset() { return CarbonUtils. getPortFromServerConfig(ThriftAuthenticationConstants.CARBON_CONFIG_PORT_OFFSET_NODE) + 1; } protected void activate(ComponentContext compCtx) { try { //configure ThriftSessionDAO ThriftSessionDAO thriftSessionDAO; try { OMElement thriftSessionDAOElement = ThriftAuthenticationConfigParser.getInstance() .getConfigElement("ThriftSessionDAO"); thriftSessionDAO = ((ThriftSessionDAO) Class.forName(thriftSessionDAOElement.getText()).newInstance()).getInstance(); } catch (Throwable throwable) { log.error("Error in loading ThriftSessionDAO hence using default org.wso2.carbon.identity.thrift.authentication.dao.DBThriftSessionDAO, ", throwable); thriftSessionDAO = new DBThriftSessionDAO(); } //configure thriftSessionTimeout in ms long thriftSessionTimeout; try { OMElement thriftSessionTimeoutElement = ThriftAuthenticationConfigParser.getInstance() .getConfigElement("ThriftSessionTimeout"); thriftSessionTimeout = Long.parseLong(thriftSessionTimeoutElement.getText()); } catch (Throwable throwable) { log.error("Error in loading ThriftSessionTimeout hence using the default: 30min, ", throwable); thriftSessionTimeout = 60000L * 30; } //get an instance of this to register as an osgi service ThriftAuthenticatorServiceImpl thriftAuthenticatorServiceImpl = new ThriftAuthenticatorServiceImpl(getRealmServiceInstance(), thriftSessionDAO, thriftSessionTimeout); //register as an osgi service thriftAuthenticationService = compCtx.getBundleContext().registerService( ThriftAuthenticatorService.class.getName(), thriftAuthenticatorServiceImpl, null); //register AuthenticatorServiceImpl as a thrift service. startThriftServices(thriftAuthenticatorServiceImpl); } catch (RuntimeException e) { log.error("Error in starting Thrift Authentication Service ", e); } catch (Throwable e) { log.error("Error in starting Thrift Authentication Service ", e); } //populate thrift sessions from db, if there is any in the db } protected void deactivate(ComponentContext compCtx) { if (TCPThriftAuthenticationService != null) { TCPThriftAuthenticationService.stop(); } compCtx.getBundleContext().ungetService(thriftAuthenticationService.getReference()); } public static HttpService getHttpServiceInstance() { return httpServiceInstance; } public static void setHttpServiceInstance(HttpService httpServiceInstance) { ThriftAuthenticationServiceComponent.httpServiceInstance = httpServiceInstance; } public static RealmService getRealmServiceInstance() { return realmServiceInstance; } public static void setRealmServiceInstance(RealmService realmServiceInstance) { ThriftAuthenticationServiceComponent.realmServiceInstance = realmServiceInstance; } protected void setHttpService(HttpService httpService) { setHttpServiceInstance(httpService); } protected void unsetHttpService(HttpService httpService) { setHttpServiceInstance(null); } protected void setRealmService(RealmService realmService) { setRealmServiceInstance(realmService); } protected void unsetRealmService(RealmService realmService) { setRealmServiceInstance(null); } protected void setConfigurationContext(ConfigurationContextService configurationContext) { this.configurationContext = configurationContext; } protected void unsetConfigurationContext(ConfigurationContextService configurationContext) { this.configurationContext = null; } private void startThriftServices(ThriftAuthenticatorService thriftAuthenticatorService) throws Exception { startThriftHttpAuthenticatorService(thriftAuthenticatorService); startThriftTcpAuthenticatorService(thriftAuthenticatorService); } private void startThriftHttpAuthenticatorService(ThriftAuthenticatorService thriftAuthenticatorService) { // Authenticator service should be exposed over SSL. Since Thrift 0.5 doesn't have support // for SSL transport this is commented out for now until later Thrift version is used. Using // servlet based authenticator service for authentication for now. try { AuthenticatorService.Processor authServiceProcessor = new AuthenticatorService.Processor( new AuthenticatorServiceImpl(thriftAuthenticatorService)); TCompactProtocol.Factory inProtFactory = new TCompactProtocol.Factory(); TCompactProtocol.Factory outProtFactory = new TCompactProtocol.Factory(); getHttpServiceInstance().registerServlet("/thriftAuthenticator", new AuthenticatorServlet(authServiceProcessor, inProtFactory, outProtFactory), new Hashtable(), getHttpServiceInstance().createDefaultHttpContext()); } catch (ServletException e) { log.error("Unable to start Thrift Authenticator Service." + e); } catch (NamespaceException e) { log.error("Unable to start Thrift Authenticator Service" + e); } } private void startThriftTcpAuthenticatorService(ThriftAuthenticatorService thriftAuthenticatorService) throws Exception { int portOffset = readPortOffset(); ServerConfiguration serverConfig = ServerConfiguration.getInstance(); String serverUrl = CarbonUtils.getServerURL(serverConfig, configurationContext.getServerConfigContext()); OMElement hostnameElement = ThriftAuthenticationConfigParser.getInstance().getConfigElement("Hostname"); String hostName; if (hostnameElement == null) { try { hostName = new URL(serverUrl).getHost(); } catch (MalformedURLException e) { hostName = HostAddressFinder.findAddress("localhost"); if (!serverUrl.matches("local:/.*/services/")) { log.info("Thrift Authentication Service url :" + serverUrl + " is using local, hence hostname is assigned as '" + hostName + "'"); } } } else { hostName = hostnameElement.getText(); } OMElement portElement = ThriftAuthenticationConfigParser.getInstance().getConfigElement("Port"); int port; if (portElement != null) { port = Integer.parseInt(portElement.getText()); } else { throw new Exception("Error, Thrift Authentication Service config does not have a port defined!"); } port = port + portOffset; String keyStore = serverConfig.getFirstProperty("Security.KeyStore.Location"); if (keyStore == null) { keyStore = System.getProperty("Security.KeyStore.Location"); if (keyStore == null) { throw new Exception("Cannot initialize Thrift Authentication Service, Security.KeyStore.Location is null"); } } String keyStorePassword = serverConfig.getFirstProperty("Security.KeyStore.Password"); if (keyStorePassword == null) { keyStorePassword = System.getProperty("Security.KeyStore.Password"); if (keyStorePassword == null) { throw new Exception("Cannot initialize Thrift Authentication Service, Security.KeyStore.Password is null "); } } OMElement clientTimeoutElement = ThriftAuthenticationConfigParser.getInstance().getConfigElement(ThriftAuthenticationConstants.CLIENT_TIMEOUT); int clientTimeout; if (clientTimeoutElement != null) { try { clientTimeout = Integer.parseInt(clientTimeoutElement.getText()); } catch (Throwable e) { String msg = "Error, in Thrift Auth Client Timeout, hence using the default timeout: " + ThriftAuthenticationConstants.DEFAULT_CLIENT_TIMEOUT + "ms"; log.error(msg + e); clientTimeout = ThriftAuthenticationConstants.DEFAULT_CLIENT_TIMEOUT; } } else { String msg = "Thrift Authentication Service Client Timeout is not set, hence using the default timeout: " + ThriftAuthenticationConstants.DEFAULT_CLIENT_TIMEOUT + "ms"; log.info(msg); clientTimeout = ThriftAuthenticationConstants.DEFAULT_CLIENT_TIMEOUT; } TCPThriftAuthenticationService = new TCPThriftAuthenticationService(hostName, port, keyStore, keyStorePassword, clientTimeout, thriftAuthenticatorService); TCPThriftAuthenticationService.start(); } }