/* * Copyright (C) 2014 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 library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ package org.jboss.as.controller.access.management; import java.util.EnumSet; import java.util.Objects; import java.util.Set; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.access.Action; import org.jboss.as.controller.access.AuthorizationResult; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; 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_RESOURCE_OPERATION; /** * * @author <a href="mailto:ehugonne@redhat.com">Emmanuel Hugonnet</a> (c) 2014 Red Hat, inc. */ public class AuthorizedAddress { private static final String HIDDEN = "<hidden>"; private static final Set<Action.ActionEffect> ADDRESS_EFFECT = EnumSet.of(Action.ActionEffect.ADDRESS); private final ModelNode address; private final boolean elided; AuthorizedAddress(ModelNode address, boolean elided) { this.address = address; this.elided = elided; } @Override public int hashCode() { int hash = 5; hash = 37 * hash + Objects.hashCode(this.address); hash = 37 * hash + (this.elided ? 1 : 0); return hash; } @Override public String toString() { return "AuthorizedAddress{" + "address=" + address + ", elided=" + elided + '}'; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final AuthorizedAddress other = (AuthorizedAddress) obj; if (!Objects.equals(this.address, other.address)) { return false; } if (this.elided != other.elided) { return false; } return true; } public ModelNode getAddress() { return address; } public boolean isElided() { return elided; } public static AuthorizedAddress authorizeAddress(OperationContext context, ModelNode operation) { ModelNode address = operation.get(ModelDescriptionConstants.OP_ADDR); ModelNode testOp = new ModelNode(); testOp.get(OP).set(READ_RESOURCE_OPERATION); testOp.get(OP_ADDR).set(address); AuthorizationResult authResult = context.authorize(testOp, ADDRESS_EFFECT); if (authResult.getDecision() == AuthorizationResult.Decision.PERMIT) { return new AuthorizedAddress(address, false); } // Failed. Now we need to see how far we can go ModelNode partialAddress = new ModelNode().setEmptyList(); ModelNode elidedAddress = new ModelNode().setEmptyList(); for (Property prop : address.asPropertyList()) { partialAddress.add(prop); testOp.get(OP_ADDR).set(partialAddress); authResult = context.authorize(testOp, ADDRESS_EFFECT); if (authResult.getDecision() == AuthorizationResult.Decision.DENY) { elidedAddress.add(prop.getName(), HIDDEN); return new AuthorizedAddress(elidedAddress, true); } else { elidedAddress.add(prop); } } // Should not be reachable, but in case of a bug, be conservative and hide data ModelNode strange = new ModelNode(); strange.add(HIDDEN, HIDDEN); return new AuthorizedAddress(strange, true); } }