/*
* 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.idp.mgt.internal;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants;
import org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.idp.mgt.IdentityProviderManagementException;
import org.wso2.carbon.idp.mgt.IdentityProviderManager;
import org.wso2.carbon.idp.mgt.dao.CacheBackedIdPMgtDAO;
import org.wso2.carbon.idp.mgt.dao.IdPManagementDAO;
import org.wso2.carbon.idp.mgt.listener.IDPMgtAuditLogger;
import org.wso2.carbon.idp.mgt.listener.IdPMgtValidationListener;
import org.wso2.carbon.idp.mgt.listener.IdentityProviderMgtListener;
import org.wso2.carbon.idp.mgt.util.IdPManagementConstants;
import org.wso2.carbon.stratos.common.listeners.TenantMgtListener;
import org.wso2.carbon.user.core.listener.UserOperationEventListener;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.ConfigurationContextService;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @scr.component name="idp.mgt.dscomponent" immediate=true
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
* @scr.reference name="config.context.service"
* interface="org.wso2.carbon.utils.ConfigurationContextService" cardinality="1..1"
* policy="dynamic" bind="setConfigurationContextService"
* unbind="unsetConfigurationContextService"
* @scr.reference name="identityCoreInitializedEventService"
* interface="org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent" cardinality="1..1"
* policy="dynamic" bind="setIdentityCoreInitializedEventService" unbind="unsetIdentityCoreInitializedEventService"
* @scr.reference name="idp.mgt.event.listener.service"
* interface="org.wso2.carbon.idp.mgt.listener.IdentityProviderMgtListener"
* cardinality="0..n" policy="dynamic"
* bind="setIdentityProviderMgtListenerService"
* unbind="unsetIdentityProviderMgtListenerService"
*/
public class IdPManagementServiceComponent {
private static Log log = LogFactory.getLog(IdPManagementServiceComponent.class);
private static RealmService realmService = null;
private static ConfigurationContextService configurationContextService = null;
private static Map<String, IdentityProvider> fileBasedIdPs = new HashMap<String, IdentityProvider>();
private static Set<String> sharedIdps = new HashSet<String>();
private static volatile List<IdentityProviderMgtListener> idpMgtListeners = new ArrayList<>();
/**
* @return
*/
public static Map<String, IdentityProvider> getFileBasedIdPs() {
return fileBasedIdPs;
}
/**
* @return
*/
public static RealmService getRealmService() {
return realmService;
}
/**
* @param rlmService
*/
protected void setRealmService(RealmService rlmService) {
realmService = rlmService;
}
/**
* @return
*/
public static ConfigurationContextService getConfigurationContextService() {
return configurationContextService;
}
/**
* @param service
*/
protected void setConfigurationContextService(ConfigurationContextService service) {
configurationContextService = service;
}
protected void activate(ComponentContext ctxt) {
try {
BundleContext bundleCtx = ctxt.getBundleContext();
TenantManagementListener idPMgtTenantMgtListener = new TenantManagementListener();
ServiceRegistration tenantMgtListenerSR = bundleCtx.registerService(
TenantMgtListener.class.getName(), idPMgtTenantMgtListener, null);
if (tenantMgtListenerSR != null) {
log.debug("Identity Provider Management - TenantMgtListener registered");
} else {
log.error("Identity Provider Management - TenantMgtListener could not be registered");
}
ServiceRegistration userOperationListenerSR = bundleCtx.registerService(
UserOperationEventListener.class.getName(), new UserStoreListener(), null);
if (userOperationListenerSR != null) {
log.debug("Identity Provider Management - UserOperationEventListener registered");
} else {
log.error("Identity Provider Management - UserOperationEventListener could not be registered");
}
ServiceRegistration auditLoggerSR = bundleCtx.registerService(IdentityProviderMgtListener.class.getName()
, new IDPMgtAuditLogger(), null);
if(auditLoggerSR != null) {
log.debug("Identity Provider Management - Audit Logger registered");
} else {
log.error("Identity Provider Management - Error while registering Audit Logger");
}
setIdentityProviderMgtListenerService(new IdPMgtValidationListener());
CacheBackedIdPMgtDAO dao = new CacheBackedIdPMgtDAO(new IdPManagementDAO());
if (dao.getIdPByName(null,
IdentityApplicationConstants.RESIDENT_IDP_RESERVED_NAME,
IdentityTenantUtil.getTenantId(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME),
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME) == null) {
addSuperTenantIdp();
}
buildFileBasedIdPList();
cleanUpRemovedIdps();
log.debug("Identity Provider Management bundle is activated");
} catch (Throwable e) {
log.error("Error while activating Identity Provider Management bundle", e);
}
}
/**
*
*/
private void buildFileBasedIdPList() {
String spConfigDirPath = CarbonUtils.getCarbonConfigDirPath() + File.separator + "identity"
+ File.separator + "identity-providers";
FileInputStream fileInputStream = null;
File spConfigDir = new File(spConfigDirPath);
OMElement documentElement = null;
if (spConfigDir.exists()) {
for (final File fileEntry : spConfigDir.listFiles()) {
try {
if (!fileEntry.isDirectory()) {
fileInputStream = new FileInputStream(new File(fileEntry.getAbsolutePath()));
documentElement = new StAXOMBuilder(fileInputStream).getDocumentElement();
IdentityProvider idp = IdentityProvider.build(documentElement);
if (idp != null) {
IdentityProviderManager idpManager = IdentityProviderManager.getInstance();
String superTenantDN = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
if (isSharedIdP(idp)) {
IdentityProvider currentIdp = idpManager.getIdPByName(idp.getIdentityProviderName(),
superTenantDN);
if (currentIdp != null && !IdentityApplicationConstants.DEFAULT_IDP_CONFIG.equals(
currentIdp.getIdentityProviderName())) {
idpManager.updateIdP(idp.getIdentityProviderName(), idp, superTenantDN);
if (log.isDebugEnabled()) {
log.debug("Shared IdP " + idp.getIdentityProviderName() + " updated");
}
} else {
idpManager.addIdP(idp, superTenantDN);
if (log.isDebugEnabled()) {
log.debug("Shared IdP " + idp.getIdentityProviderName() + " added");
}
}
sharedIdps.add(idp.getIdentityProviderName());
} else {
fileBasedIdPs.put(idp.getIdentityProviderName(), idp);
}
}
}
} catch (Exception e) {
log.error("Error while loading idp from file system.", e);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
}
}
private void cleanUpRemovedIdps() {
IdentityProviderManager idpManager = IdentityProviderManager.getInstance();
String superTenantDN = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
List<IdentityProvider> idPs;
try {
idPs = idpManager.getIdPs(superTenantDN);
} catch (IdentityProviderManagementException e) {
log.error("Error loading IDPs", e);
return;
}
for (IdentityProvider idp : idPs) {
if (isSharedIdP(idp) && !sharedIdps.contains(idp.getIdentityProviderName())) {
//IDP config file has been deleted from filesystem
try {
idpManager.deleteIdP(idp.getIdentityProviderName(), superTenantDN);
if (log.isDebugEnabled()) {
log.debug("Deleted shared IdP with the name : " + idp.getIdentityProviderName());
}
} catch (IdentityProviderManagementException e) {
log.error("Error when deleting IdP " + idp.getIdentityProviderName(), e);
}
}
}
}
private boolean isSharedIdP(IdentityProvider idp) {
return idp != null && idp.getIdentityProviderName() != null && idp.getIdentityProviderName().startsWith
(IdPManagementConstants.SHARED_IDP_PREFIX);
}
/**
* @param ctxt
*/
protected void deactivate(ComponentContext ctxt) {
log.debug("Identity Provider Management bundle is deactivated");
}
/**
* @param realmService
*/
protected void unsetRealmService(RealmService realmService) {
realmService = null;
}
/**
* @param service
*/
protected void unsetConfigurationContextService(ConfigurationContextService service) {
configurationContextService = null;
}
protected void unsetIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) {
/* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core
is started */
}
protected void setIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) {
/* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core
is started */
}
protected void setIdentityProviderMgtListenerService(
IdentityProviderMgtListener identityProviderMgtListenerService) {
idpMgtListeners.add(identityProviderMgtListenerService);
Collections.sort(idpMgtListeners, idpMgtListenerComparator);
}
protected void unsetIdentityProviderMgtListenerService(
IdentityProviderMgtListener identityProviderMgtListenerService) {
idpMgtListeners.remove(identityProviderMgtListenerService);
}
public static Collection<IdentityProviderMgtListener> getIdpMgtListeners() {
return idpMgtListeners;
}
private static Comparator<IdentityProviderMgtListener> idpMgtListenerComparator =
new Comparator<IdentityProviderMgtListener>(){
@Override
public int compare(IdentityProviderMgtListener identityProviderMgtListener1,
IdentityProviderMgtListener identityProviderMgtListener2) {
if (identityProviderMgtListener1.getExecutionOrderId() > identityProviderMgtListener1.getExecutionOrderId()) {
return 1;
} else if (identityProviderMgtListener1.getExecutionOrderId() < identityProviderMgtListener1.getExecutionOrderId()) {
return -1;
} else {
return 0;
}
}
};
private static void addSuperTenantIdp() throws Exception {
try {
IdentityProvider identityProvider = new IdentityProvider();
identityProvider.setIdentityProviderName(IdentityApplicationConstants.RESIDENT_IDP_RESERVED_NAME);
identityProvider.setHomeRealmId(IdentityUtil.getHostName());
identityProvider.setPrimary(true);
IdentityProviderManager.getInstance()
.addResidentIdP(identityProvider, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
} catch (Throwable e) {
throw new Exception("Error when adding Resident Identity Provider entry for super tenant ", e);
}
}
}