/* * JBoss, Home of Professional Open Source. * Copyright 2011, 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.as.web.test; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ATTRIBUTE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION; import static org.jboss.as.web.Constants.ACCESS_LOG; import static org.jboss.as.web.Constants.CONFIGURATION; import static org.jboss.as.web.Constants.CONNECTOR; import static org.jboss.as.web.Constants.DIRECTORY; import static org.jboss.as.web.Constants.PREFIX; import static org.jboss.as.web.Constants.SETTING; import static org.jboss.as.web.Constants.SSL; import static org.jboss.as.web.Constants.SSO; import static org.jboss.as.web.Constants.VIRTUAL_SERVER; import static org.jboss.as.web.WebExtension.SUBSYSTEM_NAME; import java.io.IOException; import java.io.Serializable; import java.util.List; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.ProcessType; import org.jboss.as.controller.RunningMode; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.transform.OperationTransformer.TransformedOperation; import org.jboss.as.model.test.FailedOperationTransformationConfig; import org.jboss.as.model.test.FailedOperationTransformationConfig.RejectExpressionsConfig; import org.jboss.as.model.test.ModelFixer; import org.jboss.as.model.test.ModelTestControllerVersion; import org.jboss.as.model.test.ModelTestUtils; import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest; import org.jboss.as.subsystem.test.AdditionalInitialization; import org.jboss.as.subsystem.test.KernelServices; import org.jboss.as.subsystem.test.KernelServicesBuilder; import org.jboss.as.web.WebExtension; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.dmr.Property; import org.junit.Assert; import org.junit.Test; /** * @author Jean-Frederic Clere * @author Kabir Khan */ public class WebSubsystemTestCase extends AbstractSubsystemBaseTest { static { System.setProperty("jboss.server.config.dir", "target/jbossas"); } public WebSubsystemTestCase() { super(WebExtension.SUBSYSTEM_NAME, new WebExtension()); } @Override protected String getSubsystemXml() throws IOException { return readResource("subsystem-2.2.0.xml"); } @Override protected String getSubsystemXml(String configId) throws IOException { return readResource(configId); } @Override protected AdditionalInitialization createAdditionalInitialization() { return new TestAdditionalInitialization(); } @Override protected void compareXml(String configId, String original, String marshalled) throws Exception { super.compareXml(configId, original, marshalled, true); } @Test public void testAliases() throws Exception { KernelServices services = createKernelServicesBuilder(createAdditionalInitialization()) .setSubsystemXmlResource("subsystem.xml") .build(); ModelNode noAliasModel = services.readWholeModel(); ModelNode aliasModel = services.readWholeModel(true); testSSLAlias(services, noAliasModel, aliasModel); testSSOAlias(services, noAliasModel, aliasModel); testAccessLogAlias(services, noAliasModel, aliasModel); } @Test public void testTransformationEAP620() throws Exception { testTransformation_1_3_0(ModelTestControllerVersion.EAP_6_2_0); } @Test public void testTransformationEAP630() throws Exception { testTransformation_1_4_0(ModelTestControllerVersion.EAP_6_3_0); } @Test public void testRejectingTransformersAS620() throws Exception { testRejectingTransformers_1_3_0(ModelTestControllerVersion.EAP_6_2_0); } @Test public void testRejectingTransformersAS630() throws Exception { testRejectingTransformers_1_4_0(ModelTestControllerVersion.EAP_6_3_0); } //no need to test target 6.4 as current == 6.4 private void testTransformation_1_4_0(ModelTestControllerVersion controllerVersion) throws Exception { ModelVersion modelVersion = ModelVersion.create(1, 4, 0); String subsystemXml = readResource("subsystem-1.4.0.xml"); KernelServicesBuilder builder = createKernelServicesBuilder(createAdditionalInitialization()) .setSubsystemXml(subsystemXml); builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion) .addMavenResourceURL("org.jboss.as:jboss-as-web:" + controllerVersion.getMavenGavVersion()) .setExtensionClassName("org.jboss.as.web.WebExtension") .configureReverseControllerCheck(createAdditionalInitialization(), null); KernelServices mainServices = builder.build(); KernelServices legacyServices = mainServices.getLegacyServices(modelVersion); Assert.assertTrue(mainServices.isSuccessfulBoot()); Assert.assertTrue(legacyServices.isSuccessfulBoot()); checkSubsystemModelTransformation(mainServices, modelVersion, new ModelFixer.CumulativeModelFixer(SSLConfigurationNameFixer.INSTANCE, AccessLogPrefixFixer_1_2_0.INSTANCE)); } private void testTransformation_1_3_0(ModelTestControllerVersion controllerVersion) throws Exception { ModelVersion modelVersion = ModelVersion.create(1, 3, 0); String subsystemXml = readResource("subsystem-1.3.0.xml"); KernelServicesBuilder builder = createKernelServicesBuilder(createAdditionalInitialization()) .setSubsystemXml(subsystemXml); builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion) .addMavenResourceURL("org.jboss.as:jboss-as-web:" + controllerVersion.getMavenGavVersion()) .setExtensionClassName("org.jboss.as.web.WebExtension") .configureReverseControllerCheck(createAdditionalInitialization(), null); KernelServices mainServices = builder.build(); KernelServices legacyServices = mainServices.getLegacyServices(modelVersion); Assert.assertTrue(mainServices.isSuccessfulBoot()); Assert.assertTrue(legacyServices.isSuccessfulBoot()); checkSubsystemModelTransformation(mainServices, modelVersion, new ModelFixer.CumulativeModelFixer(SSLConfigurationNameFixer.INSTANCE, AccessLogPrefixFixer_1_2_0.INSTANCE)); } private void testRejectingTransformers_1_3_0(ModelTestControllerVersion controllerVersion) throws Exception { ModelVersion modelVersion = ModelVersion.create(1, 3, 0); KernelServicesBuilder builder = createKernelServicesBuilder(createAdditionalInitialization()); builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion) .addMavenResourceURL("org.jboss.as:jboss-as-web:" + controllerVersion.getMavenGavVersion()) .setExtensionClassName("org.jboss.as.web.WebExtension") .configureReverseControllerCheck(createAdditionalInitialization(), null); KernelServices mainServices = builder.build(); KernelServices legacyServices = mainServices.getLegacyServices(modelVersion); Assert.assertTrue("main services did not boot", mainServices.isSuccessfulBoot()); Assert.assertTrue(legacyServices.isSuccessfulBoot()); final PathAddress subsystem = PathAddress.EMPTY_ADDRESS.append("subsystem", "web"); List<ModelNode> xmlOps = builder.parseXmlResource("subsystem-2.2.0.xml"); FailedOperationTransformationConfig config = new FailedOperationTransformationConfig() .addFailedAttribute(subsystem, new IntExpressionConfig("default-session-timeout")) .addFailedAttribute(subsystem.append(PathElement.pathElement("connector", "http")), new FailedOperationTransformationConfig.NewAttributesConfig("redirect-binding", "proxy-binding")) .addFailedAttribute(subsystem.append("virtual-server", "default-host").append("configuration", "sso"), new BooleanExpressionConfig("http-only")); ModelTestUtils.checkFailedTransformedBootOperations(mainServices, modelVersion, xmlOps, config); checkUndefinedCipherSuite(mainServices, modelVersion); } private void testRejectingTransformers_1_4_0(ModelTestControllerVersion controllerVersion) throws Exception { ModelVersion modelVersion = ModelVersion.create(1, 4, 0); KernelServicesBuilder builder = createKernelServicesBuilder(createAdditionalInitialization()); builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion) .addMavenResourceURL("org.jboss.as:jboss-as-web:" + controllerVersion.getMavenGavVersion()) .setExtensionClassName("org.jboss.as.web.WebExtension") .configureReverseControllerCheck(createAdditionalInitialization(), null); KernelServices mainServices = builder.build(); KernelServices legacyServices = mainServices.getLegacyServices(modelVersion); Assert.assertTrue("main services did not boot", mainServices.isSuccessfulBoot()); Assert.assertTrue(legacyServices.isSuccessfulBoot()); final PathAddress subsystem = PathAddress.EMPTY_ADDRESS.append("subsystem", "web"); List<ModelNode> xmlOps = builder.parseXmlResource("subsystem-2.2.0.xml"); FailedOperationTransformationConfig config = new FailedOperationTransformationConfig() .addFailedAttribute(subsystem, new IntExpressionConfig("default-session-timeout")) .addFailedAttribute(subsystem.append("virtual-server", "default-host").append("configuration", "sso"), new BooleanExpressionConfig("http-only")); ModelTestUtils.checkFailedTransformedBootOperations(mainServices, modelVersion, xmlOps, config); } private void checkUndefinedCipherSuite(KernelServices services, ModelVersion version) throws Exception { final ModelNode success = new ModelNode(); success.get(ModelDescriptionConstants.OUTCOME).set(ModelDescriptionConstants.SUCCESS); success.get(ModelDescriptionConstants.RESULT); success.protect(); PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, getMainSubsystemName()), PathElement.pathElement("connector", "https"), PathElement.pathElement("configuration", "ssl")); ModelNode op = Util.createOperation(WRITE_ATTRIBUTE_OPERATION, addr); op.get(NAME).set("cipher-suite"); op.get(VALUE).set(new ModelNode()); TransformedOperation transOp = services.transformOperation(version, op); Assert.assertTrue(transOp.rejectOperation(success)); op.get(VALUE).set("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); transOp = services.transformOperation(version, op); Assert.assertFalse(transOp.rejectOperation(success)); } private void testSSLAlias(KernelServices services, ModelNode noAliasModel, ModelNode aliasModel) throws Exception { //Check the aliased entry is not there String[] targetAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, CONNECTOR, "https", CONFIGURATION, SSL); String[] aliasAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, CONNECTOR, "https", SSL, CONFIGURATION); testAliases(services, noAliasModel, aliasModel, targetAddr, aliasAddr); testChangeAttribute(services, "ca-certificate-password", "pwd123", "123pwd", targetAddr, aliasAddr); } private void testSSOAlias(KernelServices services, ModelNode noAliasModel, ModelNode aliasModel) throws Exception { String[] targetAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", CONFIGURATION, SSO); String[] aliasAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", SSO, CONFIGURATION); testAliases(services, noAliasModel, aliasModel, targetAddr, aliasAddr); testChangeAttribute(services, "domain", "domain123", "123domain", targetAddr, aliasAddr); } private void testAccessLogAlias(KernelServices services, ModelNode noAliasModel, ModelNode aliasModel) throws Exception { String[] targetAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", CONFIGURATION, ACCESS_LOG); String[] aliasAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", ACCESS_LOG, CONFIGURATION); testAliases(services, noAliasModel, aliasModel, targetAddr, aliasAddr); //Check the aliased child entry is not there String[] targetChildMainAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", CONFIGURATION, ACCESS_LOG, SETTING, DIRECTORY); String[] targetChildAliasAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", CONFIGURATION, ACCESS_LOG, DIRECTORY, CONFIGURATION); Assert.assertTrue(noAliasModel.get(targetChildMainAddr).isDefined()); Assert.assertFalse(noAliasModel.get(targetChildAliasAddr).isDefined()); //Check the aliased child entry is there String[] aliasChildMainAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", ACCESS_LOG, CONFIGURATION, SETTING, DIRECTORY); String[] aliasChildAliasAddr = getAddress(SUBSYSTEM, SUBSYSTEM_NAME, VIRTUAL_SERVER, "default-host", ACCESS_LOG, CONFIGURATION, DIRECTORY, CONFIGURATION); Assert.assertEquals(aliasModel.get(targetChildMainAddr), aliasModel.get(targetChildAliasAddr)); Assert.assertEquals(aliasModel.get(aliasChildMainAddr), aliasModel.get(targetChildAliasAddr)); Assert.assertEquals(aliasModel.get(aliasChildMainAddr), aliasModel.get(aliasChildAliasAddr)); testChangeAttribute(services, "pattern", "pattern123", "123pattern", targetAddr, aliasAddr); testChangeAttribute(services, "path", "path123", "123path", targetChildMainAddr, targetChildAliasAddr); testChangeAttribute(services, "path", "path345", "345path", targetChildMainAddr, aliasChildAliasAddr); testChangeAttribute(services, "path", "path678", "678path", targetChildMainAddr, aliasChildMainAddr); } private void testAliases(KernelServices services, ModelNode noAliasModel, ModelNode aliasModel, String[] targetAddr, String[] aliasAddr) throws Exception { //Check the aliased entry is not there Assert.assertTrue(noAliasModel.get(targetAddr).isDefined()); Assert.assertFalse(noAliasModel.get(aliasAddr).isDefined()); //Check the aliased version is there Assert.assertEquals(aliasModel.get(targetAddr), aliasModel.get(aliasAddr)); } private void testChangeAttribute(KernelServices services, String attributeName, String value1, String value2, String[] targetAddr, String[] aliasAddr) throws Exception { writeAttribute(services, attributeName, value1, aliasAddr); Assert.assertEquals(value1, readAttribute(services, attributeName, aliasAddr)); Assert.assertEquals(value1, readAttribute(services, attributeName, targetAddr)); writeAttribute(services, attributeName, value2, targetAddr); Assert.assertEquals(value2, readAttribute(services, attributeName, aliasAddr)); Assert.assertEquals(value2, readAttribute(services, attributeName, targetAddr)); } private void writeAttribute(KernelServices services, String name, String value, String... address) throws Exception { ModelNode op = createOperation(WRITE_ATTRIBUTE_OPERATION, address); op.get(NAME).set(name); op.get(VALUE).set(value); services.executeForResult(op); } private String readAttribute(KernelServices services, String name, String... address) throws Exception { ModelNode op = createOperation(READ_ATTRIBUTE_OPERATION, address); op.get(NAME).set(name); ModelNode result = services.executeForResult(op); if (result.isDefined()) { return result.asString(); } return null; } private ModelNode createOperation(String operationName, String... address) { ModelNode operation = new ModelNode(); operation.get(OP).set(operationName); if (address.length > 0) { if (address.length % 2 != 0) { throw new IllegalArgumentException("Address must be in pairs"); } for (int i = 0; i < address.length; i += 2) { operation.get(OP_ADDR).add(address[i], address[i + 1]); } } else { operation.get(OP_ADDR).setEmptyList(); } return operation; } private String[] getAddress(String... addr) { return addr; } // TODO WFCORE-1353 means this doesn't have to always fail now; consider just deleting this // @Override // protected void validateDescribeOperation(KernelServices hc, AdditionalInitialization serverInit, ModelNode expectedModel) throws Exception { // final ModelNode operation = createDescribeOperation(); // final ModelNode result = hc.executeOperation(operation); // Assert.assertTrue("The subsystem describe operation must fail", // result.hasDefined(ModelDescriptionConstants.FAILURE_DESCRIPTION)); // } private static class SSLConfigurationNameFixer implements ModelFixer { private static final ModelFixer INSTANCE = new SSLConfigurationNameFixer(); @Override public ModelNode fixModel(ModelNode modelNode) { //In the current and legacy models this is handled by a read attribute handler rather than existing in the model modelNode.get("connector","https", "configuration", "ssl", "name").set("ssl"); return modelNode; } } private static class AccessLogPrefixFixer_1_2_0 implements ModelFixer { private static final ModelFixer INSTANCE = new AccessLogPrefixFixer_1_2_0(); @Override public ModelNode fixModel(ModelNode modelNode) { if (modelNode.hasDefined(VIRTUAL_SERVER)) { for (Property property : modelNode.get(VIRTUAL_SERVER).asPropertyList()) { ModelNode virtualServer = property.getValue(); if (virtualServer.hasDefined(CONFIGURATION)) { if (virtualServer.get(CONFIGURATION).hasDefined(ACCESS_LOG)) { ModelNode prefix = virtualServer.get(CONFIGURATION, ACCESS_LOG, PREFIX); if (prefix.getType() == ModelType.BOOLEAN) { modelNode.get(VIRTUAL_SERVER, property.getName(), CONFIGURATION, ACCESS_LOG, PREFIX).set("access_log."); } } } } } return modelNode; } } private static final class IntExpressionConfig extends RejectExpressionsConfig { public IntExpressionConfig(String... attributes) { // FIXME GlobalSessionTimeOutConfig constructor super(attributes); } @Override protected ModelNode correctValue(ModelNode toResolve, boolean isWriteAttribute) { ModelNode value = super.correctValue(toResolve, isWriteAttribute); return new ModelNode(value.asInt()); } } private static final class BooleanExpressionConfig extends RejectExpressionsConfig { public BooleanExpressionConfig(String... attributes) { // FIXME GlobalSessionTimeOutConfig constructor super(attributes); } @Override protected ModelNode correctValue(ModelNode toResolve, boolean isWriteAttribute) { ModelNode value = super.correctValue(toResolve, isWriteAttribute); return new ModelNode(value.asBoolean()); } } private static class TestAdditionalInitialization extends AdditionalInitialization implements Serializable { private static final long serialVersionUID = 1L; @Override protected ProcessType getProcessType() { return ProcessType.HOST_CONTROLLER; } @Override protected RunningMode getRunningMode() { return RunningMode.ADMIN_ONLY; } } }