Skip to content

Commit

Permalink
WFCORE-1932 validate resource subset-match in interface definition
Browse files Browse the repository at this point in the history
  • Loading branch information
soul2zimate committed Mar 13, 2017
1 parent 637ce5f commit 6e5c5ad
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
Expand Up @@ -3510,4 +3510,7 @@ OperationFailedRuntimeException capabilityAlreadyRegisteredInContext(String capa

@Message(id = 438, value = "Couldn't convert '%s' into proper warning level, threshold falling back to 'ALL'. Possible values: SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST,ALL,OFF")
String couldntConvertWarningLevel(String level);

@Message(id = 439, value = "Value %s for attribute %s is not a valid subnet format")
OperationFailedException invalidSubnetFormat(String value, String name);
}
@@ -0,0 +1,99 @@
/*
* Copyright 2016 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.as.controller.operations.validation;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.logging.ControllerLogger;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;

/**
*
* Validates that a String value can resolve to a subnet format based on class SubnetUtils in Apache Commons Net
*
* @author wangc based on work of @author rwinston@apache.org
*
*/
public class SubnetValidator extends StringLengthValidator {

private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";
private static final String SLASH_FORMAT = IP_ADDRESS + "/(\\d{1,3})";
private static final Pattern cidrPattern = Pattern.compile(SLASH_FORMAT);
private static final int NBITS = 32;

public SubnetValidator(final boolean allowNull, final boolean allowExpressions) {
super(1, allowNull, allowExpressions);
}

@Override
public void validateParameter(String parameterName, ModelNode value) throws OperationFailedException {
super.validateParameter(parameterName, value);

if (value.isDefined() && value.getType() != ModelType.EXPRESSION) {
String subnet = value.asString();
try {
calculate(subnet);
} catch (IllegalArgumentException e) {
throw ControllerLogger.ROOT_LOGGER.invalidSubnetFormat(subnet, parameterName);
}

}
}

/*
* Initialize the internal fields from the supplied CIDR mask
*/
private void calculate(String mask) {
Matcher matcher = cidrPattern.matcher(mask);

if (matcher.matches()) {
matchAddress(matcher);

/* Create a binary netmask from the number of bits specification /x */
rangeCheck(Integer.parseInt(matcher.group(5)), 0, NBITS);
} else {
throw new IllegalArgumentException("Could not parse [" + mask + "]");
}
}

/*
* Convenience method to extract the components of a dotted decimal address and pack into an integer using a regex match
*/
private int matchAddress(Matcher matcher) {
int addr = 0;
for (int i = 1; i <= 4; ++i) {
int n = (rangeCheck(Integer.parseInt(matcher.group(i)), 0, 255));
addr |= ((n & 0xff) << 8 * (4 - i));
}
return addr;
}

/*
* Convenience function to check integer boundaries. Checks if a value x is in the range [begin,end]. Returns x if it is in
* range, throws an exception otherwise.
*/
private int rangeCheck(int value, int begin, int end) {
if (value >= begin && value <= end) { // (begin,end]
return value;
}

throw new IllegalArgumentException("Value [" + value + "] not in range [" + begin + "," + end + "]");
}
}
Expand Up @@ -56,6 +56,7 @@
import org.jboss.as.controller.operations.common.InterfaceRemoveHandler;
import org.jboss.as.controller.operations.validation.ModelTypeValidator;
import org.jboss.as.controller.operations.validation.ParameterValidator;
import org.jboss.as.controller.operations.validation.SubnetValidator;
import org.jboss.as.controller.parsing.Element;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
Expand Down Expand Up @@ -122,6 +123,7 @@ public class InterfaceDefinition extends SimpleResourceDefinition {
.build();
public static final AttributeDefinition SUBNET_MATCH = SimpleAttributeDefinitionBuilder.create(localName(Element.SUBNET_MATCH), ModelType.STRING)
.setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices()
.setValidator(new SubnetValidator(true, true))
.build();
public static final AttributeDefinition UP = SimpleAttributeDefinitionBuilder.create(localName(Element.UP), ModelType.BOOLEAN)
.setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices()
Expand Down
@@ -0,0 +1,61 @@
/*
* Copyright 2017 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.as.controller;

import static org.junit.Assert.fail;

import org.jboss.as.controller.operations.validation.ModelTypeValidator;
import org.jboss.as.controller.operations.validation.SubnetValidator;
import org.jboss.dmr.ModelNode;
import org.junit.Test;

/**
* Unit Tests of Interface resource
*
* @author wangc
*/
public class InterfaceAttributeDefinitionUnitTestCase {

private static final String INVALID_STRING = "bad value";
private static final String VALID_SUBSET = "192.168.1.1/16";
private static final String INVALID_SUBSET = "192.168.1.1/";

@Test
public void testSubset() {
SubnetValidator testee = new SubnetValidator(true, true);
assertOk(testee, new ModelNode().set(VALID_SUBSET));
assertFail(testee, new ModelNode().set(INVALID_STRING));
assertFail(testee, new ModelNode().set(INVALID_SUBSET));
}

private static void assertOk(ModelTypeValidator validator, ModelNode toTest) {
try {
validator.validateParameter("test", toTest);
} catch (OperationFailedException e) {
fail("Validation should have passed but received " + e.getFailureDescription().toString());
}
}

private static void assertFail(ModelTypeValidator validator, ModelNode toTest) {
try {
validator.validateParameter("test", toTest);
fail("Validation should have failed ");
} catch (OperationFailedException e) {
// This is OK, expected exception.
}
}
}

0 comments on commit 6e5c5ad

Please sign in to comment.