/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., 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.controller.access.rbac; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ACCESS_CONSTRAINTS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.APPLICATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ATTRIBUTES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CHILDREN; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INHERITED; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MODEL_DESCRIPTION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATIONS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_DESCRIPTION_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RECURSIVE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SENSITIVE; import java.util.List; import org.jboss.as.controller.AbstractAddStepHandler; import org.jboss.as.controller.AbstractRemoveStepHandler; import org.jboss.as.controller.AbstractWriteAttributeHandler; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.ManagementModel; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationDefinition; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.ProcessType; import org.jboss.as.controller.ResourceDefinition; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; import org.jboss.as.controller.SimpleOperationDefinitionBuilder; import org.jboss.as.controller.SimpleResourceDefinition; import org.jboss.as.controller.access.constraint.ApplicationTypeConfig; import org.jboss.as.controller.access.constraint.SensitivityClassification; import org.jboss.as.controller.access.management.AccessConstraintDefinition; import org.jboss.as.controller.access.management.ApplicationTypeAccessConstraintDefinition; import org.jboss.as.controller.access.management.SensitiveTargetAccessConstraintDefinition; import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.operations.global.GlobalOperationHandlers; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.test.AbstractControllerTestBase; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.dmr.Property; import org.junit.Assert; import org.junit.Test; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ public class ReadResourceDescriptionAccessConstraintDefinitionTestCase extends AbstractControllerTestBase { private static final String SOCKET_CONFIG_NAME = SensitivityClassification.SOCKET_CONFIG.getName(); private static final String DEPLOYMENT_NAME = ApplicationTypeConfig.DEPLOYMENT.getName(); private static final AccessConstraintDefinition SOCKET_CONFIG_SENSITIVE_CONSTRAINT = new SensitiveTargetAccessConstraintDefinition(SensitivityClassification.SOCKET_CONFIG); private static final AccessConstraintDefinition SENSITIVE_CONSTRAINT = new SensitiveTargetAccessConstraintDefinition(new SensitivityClassification("test", "SENSITIVE-CONSTRAINT", true, true, true)); private static final AccessConstraintDefinition DEPLOYMENT_APPLICATION_CONSTRAINT = new ApplicationTypeAccessConstraintDefinition(ApplicationTypeConfig.DEPLOYMENT); private static final AccessConstraintDefinition APPLICATION_CONSTRAINT = new ApplicationTypeAccessConstraintDefinition(new ApplicationTypeConfig("test", "APPLICATION-CONSTRAINT", true)); private static final OperationDefinition CUSTOM_OPERATION = new SimpleOperationDefinitionBuilder("custom", new NonResolvingResourceDescriptionResolver()) .addAccessConstraint(SOCKET_CONFIG_SENSITIVE_CONSTRAINT) .build(); private static final AttributeDefinition STANDARD_ATTR = SimpleAttributeDefinitionBuilder.create("attribute-with-no-constraints", ModelType.STRING, false) .build(); private static final AttributeDefinition SENSITIVE_ATTR = SimpleAttributeDefinitionBuilder.create("attribute-with-sensitive-constraints", ModelType.STRING, false) .addAccessConstraint(SOCKET_CONFIG_SENSITIVE_CONSTRAINT) .addAccessConstraint(SENSITIVE_CONSTRAINT) .build(); private static final AttributeDefinition APPLICATION_ATTR = SimpleAttributeDefinitionBuilder.create("attribute-with-application-constraints", ModelType.STRING, false) .addAccessConstraint(DEPLOYMENT_APPLICATION_CONSTRAINT) .addAccessConstraint(APPLICATION_CONSTRAINT) .build(); @Test public void testReadResourceDefinition() throws Exception { ModelNode op = Util.createOperation(READ_RESOURCE_DESCRIPTION_OPERATION, PathAddress.EMPTY_ADDRESS); op.get(RECURSIVE).set(true); op.get(OPERATIONS).set(true); op.get(INHERITED).set(false); ModelNode result = executeForResult(op); List<Property> rootOps = result.get(OPERATIONS).asPropertyList(); Assert.assertTrue(rootOps.size() > 0); //The root ops should not have any access constraints for (Property rootOp : rootOps) { Assert.assertFalse(rootOp.getValue().get(ACCESS_CONSTRAINTS).isDefined()); } //Get rid of the root ops to keep the output shorter before printing out result.get(OPERATIONS).set("-TRIMMED-"); System.out.println(result); ModelNode nonConstrained = result.get(CHILDREN, "nonconstrained-resource", MODEL_DESCRIPTION, "*"); Assert.assertFalse(nonConstrained.get(ACCESS_CONSTRAINTS).isDefined()); checkAttributesLength(nonConstrained, 1); ModelNode attr = getAndCheckDefinedAttribute(nonConstrained, STANDARD_ATTR.getName()); Assert.assertFalse(attr.get(ACCESS_CONSTRAINTS).isDefined()); List<Property> ops = checkOperationsSize(nonConstrained, 2); for (Property currentOp : ops) { Assert.assertFalse(currentOp.getValue().get(ACCESS_CONSTRAINTS).isDefined()); } ModelNode constrained = result.get(CHILDREN, "constrained-resource", MODEL_DESCRIPTION, "*"); ModelNode accessConstraints = constrained.get(ACCESS_CONSTRAINTS); Assert.assertFalse(accessConstraints.hasDefined(APPLICATION)); Assert.assertTrue(accessConstraints.hasDefined(SENSITIVE)); Assert.assertEquals(1, accessConstraints.get(SENSITIVE).keys().size()); checkSensitiveAccessConstraint(accessConstraints.get(SENSITIVE, SOCKET_CONFIG_NAME)); checkAttributesLength(constrained, 2); attr = getAndCheckDefinedAttribute(constrained, STANDARD_ATTR.getName()); Assert.assertFalse(attr.get(ACCESS_CONSTRAINTS).isDefined()); attr = getAndCheckDefinedAttribute(constrained, SENSITIVE_ATTR.getName()); Assert.assertFalse(attr.get(ACCESS_CONSTRAINTS, APPLICATION).isDefined()); Assert.assertEquals(2, attr.get(ACCESS_CONSTRAINTS, SENSITIVE).keys().size()); checkSensitiveAccessConstraint(attr.get(ACCESS_CONSTRAINTS, SENSITIVE, SOCKET_CONFIG_NAME)); checkSocketConfigSensitiveConstraint(attr.get(ACCESS_CONSTRAINTS, SENSITIVE, SENSITIVE_CONSTRAINT.getName())); ops = checkOperationsSize(constrained, 3); for (Property currentOp : ops) { if (currentOp.getName().equals(REMOVE) || currentOp.getName().equals(ADD)) { Assert.assertFalse(currentOp.getValue().get(ACCESS_CONSTRAINTS).isDefined()); } else { accessConstraints = currentOp.getValue().get(ACCESS_CONSTRAINTS); Assert.assertFalse(accessConstraints.hasDefined(APPLICATION)); Assert.assertTrue(accessConstraints.hasDefined(SENSITIVE)); Assert.assertEquals(1, accessConstraints.get(SENSITIVE).keys().size()); checkSensitiveAccessConstraint(accessConstraints.get(SENSITIVE, SOCKET_CONFIG_NAME)); } } ModelNode application = result.get(CHILDREN, "application-resource", MODEL_DESCRIPTION, "*"); accessConstraints = application.get(ACCESS_CONSTRAINTS); Assert.assertFalse(accessConstraints.hasDefined(SENSITIVE)); Assert.assertEquals(1, accessConstraints.get(APPLICATION).keys().size()); checkDeploymentApplicationConstraint(accessConstraints.get(APPLICATION, DEPLOYMENT_NAME)); checkAttributesLength(constrained, 2); attr = getAndCheckDefinedAttribute(application, STANDARD_ATTR.getName()); Assert.assertFalse(attr.get(ACCESS_CONSTRAINTS).isDefined()); attr = getAndCheckDefinedAttribute(application, APPLICATION_ATTR.getName()); Assert.assertFalse(attr.get(ACCESS_CONSTRAINTS, SENSITIVE).isDefined()); Assert.assertEquals(2, attr.get(ACCESS_CONSTRAINTS, APPLICATION).keys().size()); checkDeploymentApplicationConstraint(attr.get(ACCESS_CONSTRAINTS, APPLICATION, DEPLOYMENT_NAME)); checkApplicationConstraint(attr.get(ACCESS_CONSTRAINTS, APPLICATION, APPLICATION_CONSTRAINT.getName())); ops = checkOperationsSize(application, 2); for (Property currentOp : ops) { Assert.assertFalse(currentOp.getValue().get(ACCESS_CONSTRAINTS).isDefined()); } } private void checkSocketConfigSensitiveConstraint(ModelNode constraint){ checkAccessConstraint(constraint, "test", true, true, true); } private void checkSensitiveAccessConstraint(ModelNode constraint){ checkAccessConstraint(constraint, "core", false, false, true); } private void checkAccessConstraint(ModelNode constraint, String type, boolean access, boolean read, boolean write) { System.out.println(constraint); Assert.assertEquals(type, constraint.get("type").asString()); } private void checkDeploymentApplicationConstraint(ModelNode constraint) { checkApplicationConstraint(constraint, "core", false); } private void checkApplicationConstraint(ModelNode constraint) { checkApplicationConstraint(constraint, "test", true); } private void checkApplicationConstraint(ModelNode constraint, String type, boolean application) { Assert.assertEquals(type, constraint.get("type").asString()); } private List<Property> checkOperationsSize(ModelNode desc, int length) { Assert.assertEquals(length, desc.get(OPERATIONS).keys().size()); return desc.get(OPERATIONS).asPropertyList(); } private void checkAttributesLength(ModelNode desc, int length) { Assert.assertEquals(length, desc.get(ATTRIBUTES).keys().size()); } private ModelNode getAndCheckDefinedAttribute(ModelNode desc, String name) { ModelNode attr = desc.get(ATTRIBUTES, name); Assert.assertTrue(attr.isDefined()); return attr; } @Override protected AbstractControllerTestBase.ModelControllerService createModelControllerService(ProcessType processType) { return new AbstractControllerTestBase.ModelControllerService(processType, new RootResourceDefinition()); } @Override protected void initModel(ManagementModel managementModel) { } private static class RootResourceDefinition extends SimpleResourceDefinition { RootResourceDefinition() { super(new Parameters(PathElement.pathElement("root"), new NonResolvingResourceDescriptionResolver()) .setAddHandler(new AbstractAddStepHandler() {}) .setRemoveHandler(new AbstractRemoveStepHandler() {})); } @Override public void registerOperations(ManagementResourceRegistration resourceRegistration) { super.registerOperations(resourceRegistration); GlobalOperationHandlers.registerGlobalOperations(resourceRegistration, ProcessType.EMBEDDED_SERVER); } @Override public void registerAttributes(ManagementResourceRegistration resourceRegistration) { super.registerAttributes(resourceRegistration); } @Override public void registerChildren(ManagementResourceRegistration resourceRegistration) { resourceRegistration.registerSubModel(new NonConstrainedChildResourceDefinition()); resourceRegistration.registerSubModel(new ConstrainedChildResourceDefinition()); resourceRegistration.registerSubModel(new ApplicationChildResourceDefinition()); } } private static class ConstrainedChildResourceDefinition extends SimpleResourceDefinition implements ResourceDefinition { ConstrainedChildResourceDefinition(){ super(new Parameters(PathElement.pathElement("constrained-resource"), new NonResolvingResourceDescriptionResolver()) .setAddHandler(new AbstractAddStepHandler() {}) .setRemoveHandler(new AbstractRemoveStepHandler() {}) .setAccessConstraints(SOCKET_CONFIG_SENSITIVE_CONSTRAINT)); } @Override public void registerAttributes(ManagementResourceRegistration resourceRegistration) { resourceRegistration.registerReadWriteAttribute(STANDARD_ATTR, null, new TestWriteAttributeHandler(STANDARD_ATTR)); resourceRegistration.registerReadWriteAttribute(SENSITIVE_ATTR, null, new TestWriteAttributeHandler(SENSITIVE_ATTR)); } @Override public void registerOperations(ManagementResourceRegistration resourceRegistration) { super.registerOperations(resourceRegistration); resourceRegistration.registerOperationHandler(CUSTOM_OPERATION, new OperationStepHandler() { @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { // no-op } }); } } private static class NonConstrainedChildResourceDefinition extends SimpleResourceDefinition { NonConstrainedChildResourceDefinition(){ super(new Parameters(PathElement.pathElement("nonconstrained-resource"), new NonResolvingResourceDescriptionResolver()) .setAddHandler(new AbstractAddStepHandler() {}) .setRemoveHandler(new AbstractRemoveStepHandler() {})); } @Override public void registerAttributes(ManagementResourceRegistration resourceRegistration) { resourceRegistration.registerReadWriteAttribute(STANDARD_ATTR, null, new TestWriteAttributeHandler(STANDARD_ATTR)); } } private static class ApplicationChildResourceDefinition extends SimpleResourceDefinition implements ResourceDefinition { ApplicationChildResourceDefinition(){ super(new Parameters(PathElement.pathElement("application-resource"), new NonResolvingResourceDescriptionResolver()) .setAddHandler(new AbstractAddStepHandler() {}) .setRemoveHandler(new AbstractRemoveStepHandler() {}) .setAccessConstraints(DEPLOYMENT_APPLICATION_CONSTRAINT)); } @Override public void registerAttributes(ManagementResourceRegistration resourceRegistration) { resourceRegistration.registerReadWriteAttribute(STANDARD_ATTR, null, new TestWriteAttributeHandler(STANDARD_ATTR)); resourceRegistration.registerReadWriteAttribute(APPLICATION_ATTR, null, new TestWriteAttributeHandler(APPLICATION_ATTR)); } } private static class TestWriteAttributeHandler extends AbstractWriteAttributeHandler<Void> { public TestWriteAttributeHandler(AttributeDefinition... definitions) { super(definitions); } @Override protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode resolvedValue, ModelNode currentValue, org.jboss.as.controller.AbstractWriteAttributeHandler.HandbackHolder<Void> handbackHolder) throws OperationFailedException { return false; } @Override protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName, ModelNode valueToRestore, ModelNode valueToRevert, Void handback) throws OperationFailedException { } } }