All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.granite.auth.saml.util.OSGiConfigUtil Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.granite.auth.saml.util;

import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_DISABLE_MISSING_USERS;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_GROUP_PATH_PREFIX;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_NAME;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_USER_AUTO_MEMBERSHIP;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_USER_MEMBERSHIP_NESTING_DEPTH;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_USER_PATH_PREFIX;
import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl.PARAM_USER_PROPERTY_MAPPING;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncHandlerMapping;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.granite.auth.saml.SamlIdentitySync;

public class OSGiConfigUtil {

    private static final Logger log = LoggerFactory.getLogger(OSGiConfigUtil.class);

    private static final String DEFAULT_SYNC_HANDLER_PID = "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler";
    private static final String EXTERNAL_LOGIN_MODULE_FACTORY_PID = "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory";

    public static Configuration setupSyncHandler(ConfigurationAdmin configurationAdmin, String id,
            String userIntermediatePath, boolean addGroupMemberships, Set defaultGroups,
            String[] synchronizeAttributes) {
        Configuration conf = getConfiguration(configurationAdmin, id, PARAM_NAME, DEFAULT_SYNC_HANDLER_PID);
        if (conf != null) {
            return conf;
        }

        Dictionary props = new Hashtable();
        props.put(PARAM_NAME, id);
        props.put(PARAM_DISABLE_MISSING_USERS, true);
        props.put(PARAM_USER_PATH_PREFIX, userIntermediatePath);
        props.put(PARAM_USER_AUTO_MEMBERSHIP, defaultGroups.toArray(new String[0]));
        if (addGroupMemberships) {
            props.put(PARAM_USER_MEMBERSHIP_NESTING_DEPTH, 1);
        } else {
            props.put(PARAM_USER_MEMBERSHIP_NESTING_DEPTH, 0);
        }

        // it turns out the SAML attributes and the ExtIdp sync attributes are
        // defined in reverse
        List mappingU = new ArrayList();
        mappingU.add(SamlIdentitySync.PROPERTY_SAML_RESPONSE + "=" + SamlIdentitySync.PROPERTY_SAML_RESPONSE);
        for (String att : synchronizeAttributes) {
            String[] kv = att.trim().split("=");
            if (kv.length != 2) {
                continue;
            }
            mappingU.add(kv[1] + "=" + kv[0]);
        }
        props.put(PARAM_USER_PROPERTY_MAPPING, mappingU);
        props.put(PARAM_GROUP_PATH_PREFIX, userIntermediatePath);
        return create(configurationAdmin, DEFAULT_SYNC_HANDLER_PID, props);
    }

    public static Configuration setupExternalLoginModule(ConfigurationAdmin configurationAdmin, String id) {
        Configuration conf = getConfiguration(configurationAdmin, id, SyncHandlerMapping.PARAM_SYNC_HANDLER_NAME,
                EXTERNAL_LOGIN_MODULE_FACTORY_PID);
        if (conf == null) {
            Dictionary props = new Hashtable();
            props.put(SyncHandlerMapping.PARAM_IDP_NAME, id);
            props.put(SyncHandlerMapping.PARAM_SYNC_HANDLER_NAME, id);
            return create(configurationAdmin, EXTERNAL_LOGIN_MODULE_FACTORY_PID, props);
        }
        return conf;
    }

    private static Configuration getConfiguration(ConfigurationAdmin configurationAdmin, String configId, String filter,
            String serviceFactoryPid) {
        try {
            Configuration[] configurations = configurationAdmin.listConfigurations("(&(" + filter + "=" + configId + ")"
                    + "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + serviceFactoryPid + "))");
            if (configurations != null && configurations.length >= 1) {
                return configurations[0];
            } else {
                return null;
            }
        } catch (IOException | InvalidSyntaxException e) {
            log.debug("Error while listing {}={} for {}.", filter, configId, serviceFactoryPid, e);
            return null;
        }
    }

    private static Configuration create(ConfigurationAdmin configurationAdmin, String pid,
            Dictionary props) {
        Configuration conf = null;
        try {
            conf = configurationAdmin.createFactoryConfiguration(pid, null);
            conf.update(props);
        } catch (IOException e) {
            if (conf != null) {
                deleteConfiguration(configurationAdmin, conf.getPid());
                conf = null;
            }
            log.error("Error creating configuration for {}", pid, e);
        }
        return conf;
    }

    public static void deleteConfiguration(ConfigurationAdmin configurationAdmin, String pid) {
        try {
            Configuration c = configurationAdmin.getConfiguration(pid);
            c.delete();
        } catch (IOException | IllegalStateException e) {
            log.error("Error deleting configuration", e);
        }
    }

    // ------

    /**
     * The name of the repository descriptor providing the ID of the repository
     * instance.
     */
    private static final String REPO_DESC_ID = "crx.repository.systemid";

    /**
     * The name of the repository descriptor providing the repository cluster ID
     * of the cluster the bound repository is a node of.
     */
    private static final String REPO_DESC_CLUSTER_ID = "crx.cluster.id";

    /**
     * Determine the unique ID of this repository
     * 
     * @param repository
     * @param settings
     * @return the unique id
     */
    public static String getRepositoryId(SlingRepository repository, SlingSettingsService settings) {
        String id = repository.getDescriptor(REPO_DESC_CLUSTER_ID);
        if (id == null) {
            id = repository.getDescriptor(REPO_DESC_ID);
            if (id == null) {
                // fallback to Sling ID
                id = settings.getSlingId();
                if (id == null) {
                    id = UUID.randomUUID().toString();
                    log.error(
                            "RequestHelper: Failure to acquire unique ID for this token authenticator. Using random UUID {}",
                            id);
                }
            }
        }
        return id;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy