Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCORE-1932 validate resource subset-match in interface definition #1901

Merged
merged 1 commit into from
Mar 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
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);
}
Original file line number Diff line number Diff line change
@@ -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 + "]");
}
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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.
}
}
}