/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.deployment.security;
import java.util.ArrayList;
import javax.management.ObjectName;
import javax.xml.bind.JAXBElement;
import org.jboss.deployers.spi.DeploymentException;
import org.jboss.deployers.spi.deployer.DeploymentStages;
import org.jboss.deployers.spi.deployer.helpers.AbstractDeployer;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.metadata.javaee.support.IdMetaData;
import org.jboss.security.acl.config.ACLConfiguration;
import org.jboss.security.authorization.PolicyRegistration;
import org.jboss.system.metadata.ServiceAttributeMetaData;
import org.jboss.system.metadata.ServiceConstructorMetaData;
import org.jboss.system.metadata.ServiceDependencyMetaData;
import org.jboss.system.metadata.ServiceDependencyValueMetaData;
import org.jboss.system.metadata.ServiceMetaData;
/**
* Abstract Security Deployer Sets up the top level JaccPolicy service beans
*
* @author Anil.Saldhana@redhat.com
* @since Feb 18, 2008
* @version $Revision: 86077 $
*/
public abstract class AbstractSecurityDeployer<T extends IdMetaData> extends AbstractDeployer
{
private static final String JACC_ATTACHMENT_NAME = "jboss.jacc";
private static final String BASE_OBJECT_NAME = "jboss.jacc:service=jacc,id=";
/** Attachment name for the JAXB model for xacml config - match the one from XacmlConfigParsingDeployer */
private static final String XACML_ATTACHMENT_NAME = "xacml.config";
private PolicyRegistration policyRegistration;
/**
*
* @return
*/
public PolicyRegistration getPolicyRegistration()
{
return this.policyRegistration;
}
/**
*
* @param policyRegistration
*/
public void setPolicyRegistration(PolicyRegistration policyRegistration)
{
this.policyRegistration = policyRegistration;
}
public AbstractSecurityDeployer()
{
setStage(DeploymentStages.POST_CLASSLOADER);
setInput(getMetaDataClassType());
setOutput(ServiceMetaData.class);
addOutput(JACC_ATTACHMENT_NAME);
}
public void deploy(DeploymentUnit unit) throws DeploymentException
{
T metaData = unit.getAttachment(getMetaDataClassType());
if (metaData == null)
return;
String contextId = unit.getSimpleName();
// Is the war the top level deployment?
// DeploymentUnit topUnit = unit.getTopLevel();
if (unit.getParent() == null || getParentJaccPolicyBean(unit) == null)
{
createTopLevelServiceBeanWithMetaData(contextId, unit, metaData);
}
else
{
ServiceMetaData subjaccPolicy = getServiceMetaData();
String deploymentName = unit.getSimpleName();
try
{
subjaccPolicy.setObjectName(new ObjectName(getObjectName(unit)));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
// Provide a constructor for the service bean
ServiceConstructorMetaData serviceConstructor = new ServiceConstructorMetaData();
serviceConstructor.setSignature(new String[]{String.class.getName(), getMetaDataClassType().getName()});
serviceConstructor.setParameters(new Object[]{deploymentName, metaData});
subjaccPolicy.setConstructor(serviceConstructor);
ArrayList<ServiceMetaData> services = new ArrayList<ServiceMetaData>();
services.add(subjaccPolicy);
unit.addAttachment(JACC_ATTACHMENT_NAME, subjaccPolicy, ServiceMetaData.class);
// Add a dependence into the parent JaccPolicy
ServiceMetaData parentServiceMetaData = this.getParentJaccPolicyBean(unit);
if (parentServiceMetaData != null)
{
ServiceDependencyMetaData serviceDependencyMetaData = new ServiceDependencyMetaData();
serviceDependencyMetaData.setIDependOnObjectName(subjaccPolicy.getObjectName());
parentServiceMetaData.addDependency(serviceDependencyMetaData);
// Add an attribute in the parent service
ServiceAttributeMetaData serviceAttributeMetaData = new ServiceAttributeMetaData();
serviceAttributeMetaData.setName("PolicyConfigurationFacadeMBean");
ServiceDependencyValueMetaData dependencyValue = new ServiceDependencyValueMetaData();
dependencyValue.setDependency(subjaccPolicy.getObjectName().toString());
dependencyValue.setProxyType("attribute");
serviceAttributeMetaData.setValue(dependencyValue);
parentServiceMetaData.addAttribute(serviceAttributeMetaData);
}
}
/** Register XACML/ACL policies if present in the deployment */
if(this.policyRegistration != null)
{
String xacmlType = PolicyRegistration.XACML;
JAXBElement<?> policyConfig = (JAXBElement<?>) unit.getAttachment(XACML_ATTACHMENT_NAME);
if(policyConfig != null)
this.policyRegistration.registerPolicyConfig(contextId, xacmlType, policyConfig);
String aclType = PolicyRegistration.ACL;
ACLConfiguration aclConfig = (ACLConfiguration) unit.getAttachment(ACLConfiguration.class.getName());
if(aclConfig != null)
this.policyRegistration.registerPolicyConfig(contextId, aclType, aclConfig);
}
}
@Override
public void undeploy(DeploymentUnit unit)
{
unit.removeAttachment(JACC_ATTACHMENT_NAME);
// unregister any XACML or ACL policies associated with the deployment unit.
String contextId = unit.getSimpleName();
if (this.policyRegistration != null)
{
this.policyRegistration.deRegisterPolicy(contextId, PolicyRegistration.XACML);
this.policyRegistration.deRegisterPolicy(contextId, PolicyRegistration.ACL);
}
}
private void createTopLevelServiceBeanWithMetaData(String contextId, DeploymentUnit unit, T deployment)
{
// Provide a constructor for the service bean
ServiceConstructorMetaData serviceConstructor = new ServiceConstructorMetaData();
serviceConstructor.setSignature(new String[]{String.class.getName(), this.getMetaDataClassType().getName(),
Boolean.class.getName()});
serviceConstructor.setParameters(new Object[]{contextId, deployment, Boolean.TRUE});
createJaccPolicyBean(serviceConstructor, unit);
}
private void createJaccPolicyBean(ServiceConstructorMetaData serviceConstructor, DeploymentUnit unit)
{
// Create a Service Bean for the JACC Policy
ServiceMetaData jaccPolicy = new ServiceMetaData();
jaccPolicy.setCode(getJaccPolicyName());
try
{
jaccPolicy.setObjectName(new ObjectName(getObjectName(unit)));
}
catch (Exception e)
{
throw new RuntimeException(e);
}
// Provide a constructor for the service bean
jaccPolicy.setConstructor(serviceConstructor);
ArrayList<ServiceMetaData> services = new ArrayList<ServiceMetaData>();
services.add(jaccPolicy);
unit.addAttachment(JACC_ATTACHMENT_NAME, jaccPolicy, ServiceMetaData.class);
}
private ServiceMetaData getParentJaccPolicyBean(DeploymentUnit childDU)
{
DeploymentUnit parentDU = childDU.getParent();
while (parentDU != null)
{
ServiceMetaData parentJacc = (ServiceMetaData) parentDU.getAttachment(JACC_ATTACHMENT_NAME);
if (parentJacc != null)
return parentJacc;
parentDU = parentDU.getParent();
}
return null;
}
/**
* Get the name of the JaccPolicy subclass (EjbJaccPolicy,WebJaccPolicy etc)
*
* @return
*/
protected abstract String getJaccPolicyName();
/**
* Return the type of metadata
*
* @return
*/
protected abstract Class<T> getMetaDataClassType();
/**
* Get the top level service bean meta data
*
* @return
*/
protected abstract ServiceMetaData getServiceMetaData();
/**
* Qualify the object name with parent name just to avoid conflicts with deployments with the same name in multiple
* archives
*/
private String getObjectName(DeploymentUnit unit)
{
String deploymentName = unit.getName();
DeploymentUnit parentDU = unit.getParent();
String parentDeploymentName = parentDU != null ? ",parent=\"" + parentDU.getSimpleName() + "\"" : "";
return BASE_OBJECT_NAME + "\"" + deploymentName + "\"" + parentDeploymentName;
}
}