Package ch.entwine.weblounge.kernel.security

Source Code of ch.entwine.weblounge.kernel.security.SpringSecurityConfigurationService

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2011 The Weblounge Team
*  http://weblounge.o2it.ch
*
*  This program 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
*  of the License, or (at your option) any later version.
*
*  This program 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 program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.kernel.security;

import static ch.entwine.weblounge.dispatcher.SharedHttpContext.CONTEXT_ID;
import static ch.entwine.weblounge.dispatcher.SharedHttpContext.PATTERN;
import static ch.entwine.weblounge.dispatcher.SharedHttpContext.SERVICE_RANKING;
import static ch.entwine.weblounge.dispatcher.SharedHttpContext.WEBLOUNGE_CONTEXT_ID;

import ch.entwine.weblounge.common.impl.util.config.ConfigurationUtils;
import ch.entwine.weblounge.common.security.Security;
import ch.entwine.weblounge.kernel.site.SiteManager;

import org.apache.felix.webconsole.WebConsoleSecurityProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.osgi.context.ConfigurableOsgiBundleApplicationContext;
import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext;

import java.io.IOException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;

import javax.servlet.Filter;

/**
* Read the <code>security.xml</code> defining the general security constraints
* from the bundle resources.
* <p>
* After the configuration is read, the service registers a {@link Filter} which
* enforces the security policy at runtime.
*/
public class SpringSecurityConfigurationService implements ManagedService {

  /** Logging facility */
  private static final Logger logger = LoggerFactory.getLogger(SpringSecurityConfigurationService.class);

  /** Service pid, used to look up the service configuration */
  public static final String SERVICE_PID = "ch.entwine.weblounge.security";

  /** Name of the configuration file */
  public static final String SECURITY_CONFIG_FILE = "/security/security.xml";

  /** Configuration key for the enabled/disabled configuration */
  public static final String OPT_ENABLED = "security.enabled";

  /** The related spring security service */
  protected SpringSecurityServiceImpl securityService = null;

  /** The current bundle context */
  protected BundleContext bundleCtx = null;

  /** The spring security filter */
  protected SecurityFilter securityFilter = null;

  /** The web console security */
  protected WebConsoleSecurityProvider webConsoleProvider = null;

  /** Reference to the security marker */
  protected ServiceRegistration securityMarker = null;

  /** Is security enabled */
  protected boolean securityEnabled = true;

  /** The security filter registration */
  protected ServiceRegistration securityFilterRegistration = null;

  /** The registration for the web console security provider */
  protected ServiceRegistration webConsoleSecurityRegistration = null;

  /** The sites that are online */
  protected SiteManager sites = null;

  /**
   * Callback from the OSGi environment on service activation.
   *
   * @param ctx
   *          the component context
   * @throws IOException
   *           if reading the service configuration fails
   * @throws ConfigurationException
   *           if the service configuration is malformed
   */
  void activate(ComponentContext ctx) throws IOException,
  ConfigurationException {
    bundleCtx = ctx.getBundleContext();

    // Try to get hold of the service configuration
    ServiceReference configAdminRef = bundleCtx.getServiceReference(ConfigurationAdmin.class.getName());
    if (configAdminRef != null) {
      ConfigurationAdmin configAdmin = (ConfigurationAdmin) bundleCtx.getService(configAdminRef);
      Dictionary<?, ?> config = configAdmin.getConfiguration(SERVICE_PID).getProperties();
      if (config != null) {
        updated(config);
      } else {
        logger.debug("No customized security configuration found");
      }
    } else {
      logger.debug("No configuration admin service found while looking for security configuration");
    }

    // Create the spring security context
    URL securityConfig = bundleCtx.getBundle().getResource(SECURITY_CONFIG_FILE);
    ConfigurableOsgiBundleApplicationContext springContext = null;
    springContext = new OsgiBundleXmlApplicationContext(new String[] { securityConfig.toExternalForm() });
    springContext.setBundleContext(bundleCtx);
    springContext.refresh();

    // Get the security filter chain from the spring context
    Filter defaultSecurityFilter = (Filter) springContext.getBean("springSecurityFilterChain");
    securityFilter = new SecurityFilter(securityService, sites, defaultSecurityFilter);

    // Create the web console security provider
    webConsoleProvider = new WebloungeWebConsoleSecurityProvider(securityService);

    // Activate the security filters
    if (securityEnabled) {
      startSecurity();
    } else {
      logger.info("Security is turned off by configuration");
    }

    // Tell the security service abut the current policy
    securityService.setEnabled(securityEnabled);

    // Register the security marker
    publishSecurityMarker();
  }

  /**
   * Callback from OSGi environment on service inactivation.
   *
   * @param ctx
   *          the component context
   */
  void deactivate(ComponentContext ctx) {
    logger.info("Tearing down spring security");

    // Unregister the security filters
    if (securityFilterRegistration != null) {
      stopSecurity();
    }

    // Remove the security marker
    if (securityMarker != null) {
      try {
        securityMarker.unregister();
      } catch (IllegalStateException e) {
        // Never mind, the service has been unregistered already
      } catch (Throwable t) {
        logger.error("Unregistering security context failed: {}", t.getMessage());
      }
    }

  }

  /**
   * {@inheritDoc}
   *
   * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
   */
  @SuppressWarnings("rawtypes")
  public void updated(Dictionary properties) throws ConfigurationException {
    if (properties == null) {
      logger.debug("No customized security configuration found");
      return;
    }

    String enabledProperty = (String) properties.get(OPT_ENABLED);
    boolean isEnabled = ConfigurationUtils.isTrue(enabledProperty, true);

    // Enable/disable security
    if (isEnabled != this.securityEnabled) {
      if (isEnabled) {
        startSecurity();
      } else {
        stopSecurity();
      }
    }

    // Tell the security service abut the current policy
    securityService.setEnabled(isEnabled);

    // Store the security enabled setting
    this.securityEnabled = isEnabled;
  }

  /**
   * Activates security by registering both a security filter and a web console
   * security provider.
   */
  private void startSecurity() {
    logger.info("Enabling spring security");
    Dictionary<String, String> props = new Hashtable<String, String>();
    props.put(PATTERN, ".*");
    props.put(CONTEXT_ID, WEBLOUNGE_CONTEXT_ID);
    props.put(SERVICE_RANKING, "0");
    props.put("security", "weblounge");
    try {
      securityFilterRegistration = bundleCtx.registerService(Filter.class.getName(), securityFilter, props);
      logger.debug("Spring security context registered");
    } catch (Throwable t) {
      logger.error("Error registering security context: {}", t.getMessage());
    }

    logger.info("Securing the Felix management console");
    try {
      webConsoleSecurityRegistration = bundleCtx.registerService(WebConsoleSecurityProvider.class.getName(), webConsoleProvider, null);
      logger.debug("Web console security provider registered");
    } catch (Throwable t) {
      logger.error("Error registering web console security provider: {}", t.getMessage());
    }
  }

  /**
   * Registers the security marker in the OSGi registry.
   */
  private void publishSecurityMarker() {
    Dictionary<String, String> securityProperties = new Hashtable<String, String>();
    bundleCtx.registerService(Security.class.getName(), new Security() {
    }, securityProperties);
  }

  /**
   * Deactivates security by unregistering both the security filter and the web
   * console security provider.
   */
  private void stopSecurity() {
    logger.info("Disabling spring security");
    if (securityFilterRegistration != null) {
      try {
        securityFilterRegistration.unregister();
        logger.debug("Spring security context unregistered");
      } catch (IllegalStateException e) {
        // Never mind, the service has been unregistered already
      } catch (Throwable t) {
        logger.error("Unregistering security context", t.getMessage());
      }
    }

    logger.info("Disabling web console security provider");
    if (webConsoleSecurityRegistration != null) {
      try {
        webConsoleSecurityRegistration.unregister();
        logger.debug("Web console security provider unregistered");
      } catch (IllegalStateException e) {
        logger.debug("Web console security provider was already unregistered");
      } catch (Throwable t) {
        logger.error("Unregistering web console security provider", t.getMessage());
      }
    }
  }

  /**
   * Callback from OSGi to set the spring security service.
   *
   * @param securityService
   *          the security service
   */
  void setSecurityService(SpringSecurityServiceImpl securityService) {
    this.securityService = securityService;
  }

  /**
   * Callback for OSGi to set the site manager.
   *
   * @param siteManager
   *          the site manager
   */
  void setSiteManager(SiteManager siteManager) {
    this.sites = siteManager;
  }

  /**
   * Callback for OSGi to remove the site manager.
   *
   * @param siteManager
   *          the site manager
   */
  void removeSiteManager(SiteManager siteManager) {
    this.sites = null;
  }

}
TOP

Related Classes of ch.entwine.weblounge.kernel.security.SpringSecurityConfigurationService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.