-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Describe the bug
In recent versions of the liboscal-java, the dependent oscal-cli's list-allowed-values subcommand to dump values fails with any external constraint set defined in a file with a let/@var and its @expression. They are bound to the model but processed without validating constraints against an instance, so most such constraints evaluate to an empty sequence and are missing from the dynamic context.
Who is the bug affecting
Developers using the existing liboscal-java functionality or extending it to dump information about inline or external constraints an inventory for documentation or further analysis.
How do we replicate this issue
Run the following unit test (cross-referenced in a branch by issue number below as well).
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/
package gov.nist.secauto.oscal.lib.model.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import edu.umd.cs.findbugs.annotations.NonNull;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
import gov.nist.secauto.metaschema.core.model.MetaschemaException;
import gov.nist.secauto.metaschema.core.model.constraint.ExternalConstraintsModulePostProcessor;
import gov.nist.secauto.metaschema.core.model.constraint.IAllowedValue;
import gov.nist.secauto.metaschema.core.model.constraint.IAllowedValuesConstraint;
import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
import gov.nist.secauto.metaschema.core.model.xml.IXmlMetaschemaModule;
import gov.nist.secauto.metaschema.core.model.xml.ModuleLoader;
import gov.nist.secauto.metaschema.core.model.xml.XmlMetaConstraintLoader;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.model.IBoundModule;
import gov.nist.secauto.oscal.lib.OscalBindingContext;
import gov.nist.secauto.oscal.lib.model.OscalCompleteModule;
import gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.AllowedValuesRecord;
import gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.NodeItemRecord;
class AbstractNodeItemVisitorTest {
@Test
void testAllowedValuesMissingVariableBindings() throws MetaschemaException, IOException {
List<IConstraintSet> constraintSet = new XmlMetaConstraintLoader().load(ObjectUtils.requireNonNull(ObjectUtils.notNull(Paths.get("src/test/resources/content/computer-metaschema-meta-constraints.xml").toUri())));
ExternalConstraintsModulePostProcessor postProcessor = new ExternalConstraintsModulePostProcessor(constraintSet);
ModuleLoader loader = new ModuleLoader(CollectionUtil.singletonList(postProcessor));
IXmlMetaschemaModule module = loader.load(ObjectUtils.notNull(Paths.get("src/test/resources/content/computer-example.xml").toUri()));
AllowedValueCollectingNodeItemVisitor walker = new AllowedValueCollectingNodeItemVisitor();
walker.visit(module);
Collection<NodeItemRecord> allowedValuesByTarget = ObjectUtils.notNull(walker.getAllowedValueLocations());
assertEquals(1, allowedValuesByTarget.size());
}
}computer-example.xml:
<?xml version="1.0" encoding="UTF-8"?>
<METASCHEMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://csrc.nist.gov/ns/oscal/metaschema/1.0 ../schema/xml/metaschema.xsd"
xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0">
<schema-name>Minimak Computer Model</schema-name>
<schema-version>0.0.5</schema-version>
<short-name>computer</short-name>
<namespace>http://example.com/ns/computer</namespace>
<json-base-uri>http://example.com/ns/computer</json-base-uri>
<define-assembly name="computer">
<formal-name>Computer Assembly</formal-name>
<description>A minimal computer model to test let var usage with external constraints.</description>
<root-name>computer</root-name>
<define-flag name="id" required="yes"/>
</define-assembly>
</METASCHEMA>computer-metaschema-meta-constraints.xml:
<?xml version="1.0" encoding="UTF-8"?>
<metaschema-meta-constraints xmlns="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://csrc.nist.gov/ns/oscal/metaschema/1.0 ../../../../core/metaschema/schema/xml/metaschema-meta-constraints.xsd">
<context>
<metapath target="/computer"/>
<constraints>
<let var="computer-id" expression="@id"/>
<allowed-values id="example-constraint-using-let-var" target="$computer-id">
<enum value="model1"/>
<enum value="model2"/>
<enum value="model3"/>
</allowed-values>
</constraints>
</context>
</metaschema-meta-constraints>Resulting exception:
gov.nist.secauto.metaschema.core.metapath.MetapathException: An error occurred while evaluating the expression '$computer-id'. MPST0008: Variable 'computer-id' not defined in the dynamic context.
at gov.nist.secauto.metaschema.core.metapath.MetapathExpression.evaluate(MetapathExpression.java:192)
at gov.nist.secauto.metaschema.core.metapath.impl.LazyCompilationMetapathExpression.evaluate(LazyCompilationMetapathExpression.java:66)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.lambda$0(AllowedValueCollectingNodeItemVisitor.java:60)
at java.base/java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1249)
at java.base/java.util.stream.ReferencePipeline$Head.forEachOrdered(ReferencePipeline.java:772)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.handleAllowedValuesAtLocation(AllowedValueCollectingNodeItemVisitor.java:58)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.visitAssembly(AllowedValueCollectingNodeItemVisitor.java:99)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.visitAssembly(AllowedValueCollectingNodeItemVisitor.java:1)
at gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem.accept(IAssemblyNodeItem.java:76)
at gov.nist.secauto.metaschema.core.metapath.item.node.AbstractNodeItemVisitor.visitModelChildren(AbstractNodeItemVisitor.java:73)
at gov.nist.secauto.metaschema.core.metapath.item.node.AbstractNodeItemVisitor.visitMetaschema(AbstractNodeItemVisitor.java:185)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.visit(AllowedValueCollectingNodeItemVisitor.java:51)
at gov.nist.secauto.oscal.lib.model.util.AllowedValueCollectingNodeItemVisitor.visit(AllowedValueCollectingNodeItemVisitor.java:46)
at gov.nist.secauto.oscal.lib.model.util.AbstractNodeItemVisitorTest.testAllowedValuesMissingVariableBindings(AbstractNodeItemVisitorTest.java:93)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: gov.nist.secauto.metaschema.core.metapath.StaticMetapathException: MPST0008: Variable 'computer-id' not defined in the dynamic context.
at gov.nist.secauto.metaschema.core.metapath.DynamicContext.getVariableValue(DynamicContext.java:284)
at gov.nist.secauto.metaschema.core.metapath.cst.VariableReference.evaluate(VariableReference.java:71)
at gov.nist.secauto.metaschema.core.metapath.cst.AbstractExpression.accept(AbstractExpression.java:47)
at gov.nist.secauto.metaschema.core.metapath.MetapathExpression.evaluate(MetapathExpression.java:190)
... 16 moreExpected behavior (i.e. solution)
Variables bindings are evaluated to empty expressions and do not throw exceptions.
Other comments
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status