liboscal-java
liboscal-java copied to clipboard
Metaschema Validation Has Findings For Valid Component
Describe the bug
Valid XML component-definitions are returning findings.
Add the following to src/test/resources/content/component-def.xml
<?xml version="1.0" encoding="UTF-8"?>
<component-definition xmlns="http://csrc.nist.gov/ns/oscal/1.0"
uuid="6c5149e8-f3a6-437c-8035-025e9b5fc0bc">
<metadata>
<title>Test Component Definition</title>
<last-modified>2023-11-30T01:01:01Z</last-modified>
<version>1.0</version>
<oscal-version>1.1.1</oscal-version>
</metadata>
<component uuid="849e5b94-5ccb-49c4-97ab-56ac391a8b37" type="service">
<title>Test Service</title>
<description></description>
<protocol uuid="d25e47d8-b5da-475f-854b-6ce292fefaa7" name="http">
<port-range start="80" end="80" transport="TCP"/>
</protocol>
</component>
</component-definition>
Add the following test function to src/test/java/gov/nist/secauto/oscal/java/ExamplesTest.java
:
@Test
void testComponentDefinition() throws IOException {
OscalBindingContext bindingContext = OscalBindingContext.instance();
IBoundLoader loader = bindingContext.newBoundLoader();
IDocumentNodeItem nodeItem = loader.loadAsNodeItem(ObjectUtils.notNull(Paths.get("src/test/resources/content/component-def.xml")));
DynamicContext dynamicContext = new StaticContext().newDynamicContext();
dynamicContext.setDocumentLoader(loader);
FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
DefaultConstraintValidator validator = new DefaultConstraintValidator(dynamicContext, handler);
validator.validate(nodeItem);
validator.finalizeValidation();
assertTrue(handler.isPassing());
assertTrue(handler.getFindings().isEmpty());
}
The following log output is shown:
16:38:41.827 [main] WARN gov.nist.secauto.metaschema.model.common.constraint.LoggingConstraintValidationHandler.logConstraint(LoggingConstraintValidationHandler.java:121) - WARNING: (/component-definition/component[1]/protocol[1]/port-range[1]) A start port exists, but an end point does not. To define a single port, the start and end should be the same value.
16:38:41.831 [main] WARN gov.nist.secauto.metaschema.model.common.constraint.LoggingConstraintValidationHandler.logConstraint(LoggingConstraintValidationHandler.java:121) - WARNING: (/component-definition/component[1]/protocol[1]/port-range[1]) An end point exists, but a start port does not. To define a single port, the start and end should be the same value.
Who is the bug affecting?
Anyone trying to validate component-definitions. Presumably this applies to other OSCAL types too.
What is affected by this bug?
Findings are returned despite valid input. Doesn't matter if the input is JSON, YAML, or XML.
When does this occur?
See example
How do we replicate the issue?
Please see detailed unit test above.
Expected behavior (i.e. solution)
This particular example should return no findings, as it meets all the metaschema requirements.
Other Comments
This appears to relate to the port range constraint in OSCAL. The <
entity used might be causing the issue. We need to investigate this.
It's actually these two tests that fail:
exists(@start) and not(exists(@end))
not(exists(@start)) and exists(@end)
I've tested both of these, and they work as expected:
exists(@start) and exists(@end)
@start <= @end
Question: if @start
or @end
is not given or not given correctly (so as to be comparable), is that an error? One might say yes, but it is failing for a different reason; one could also test for that separately.
Indeed since the (non-negative) integer form is already validated separately, one might argue this rule should pass if @start
or @end
is not formed correctly, since that aspect of conformance is already tested with the data type. So:
not((@start castable as xs:integer) and (@end castable as xs:integer)) or (@end >= @start)
fails only if the numbers are given 'correctly' (as integers), but wrong (as out of order). But if either is missing or not comparable, we get a failure on its value, not this error.
nb >
does not typically need to be escaped in XML (although it often is).
I will review the underlying metaschema-java code, but I do not believe Metapath (as implemented in the Java version; the spec is very underdefined in this bit 😆) has castable
yet but I will have to check. I told Dave I would look into the root cause, so more to follow.
Cool. @start castable as xs:integer
might be replaced (XPath 1.0-style) with
number(@start) != number(@start)
which tests true only if number(@start)
is NaN, which is the only thing that comes back true as 'not-equal' !=
with itself. (Of course that is XPath not Metapath or this engine, so I can't speak for what will happen here either.) This is decimal-format not integer checking but to a similar effect.
Not advancing a position on whether to prefer such a thing if castable as
is not in the library, only noting there are (more) options.