usnistgov / liboscal-java

A Java library to support processing OSCAL content
Other
30 stars 14 forks source link

Profile resolution with catalog with ungrouped controls throws exception #200

Open aj-stein-nist opened 1 year ago

aj-stein-nist commented 1 year ago

Describe the bug

While writing tests for usnistgov/oscal-cli#178, I have been unable to resolve a profile with a catalog with a "flat" catalog that has only two controls. This is using a development version using liboscal-java v3.0.2 as a dependency.

Catalog that throws stack trace:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://github.com/usnistgov/OSCAL/releases/download/v1.1.1/oscal_complete_schema.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<catalog xmlns="http://csrc.nist.gov/ns/oscal/1.0" uuid="1296032c-f0a7-4e00-84f0-c09b9b1c81b5">
    <metadata>
        <title>Valid OSCAL Document</title>
        <last-modified>2023-10-24T00:00:00.000000-00:00</last-modified>
        <version>1.0</version>
        <oscal-version>1.1.1</oscal-version>
        <role id="maintainer">
            <title>Maintainer of oscal-cli</title>
        </role>
        <party uuid="4ba3f2b7-e894-48d7-b940-91c68661df55" type="person">
            <name>NIST ITL CSD Developer</name>
        </party>
        <responsible-party role-id="maintainer">
            <party-uuid>4ba3f2b7-e894-48d7-b940-91c68661df55</party-uuid>
        </responsible-party>
    </metadata>
    <group id="eg1">
        <title>Example Group 1</title>
        <control id="control-1">
            <title>Control 1</title>
            <part name="statement">
                <p>This statement is a requirement for Control 1.</p>
            </part>
        </control>
        <control id="control-2">
            <title>Control 2</title>
            <part name="statement">
                <p>This statement is a requirement for Control 2.</p>
            </part>
        </control>
    </group>
</catalog>

Catalog that does not throw stack trace:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://github.com/usnistgov/OSCAL/releases/download/v1.1.1/oscal_complete_schema.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<catalog xmlns="http://csrc.nist.gov/ns/oscal/1.0" uuid="1296032c-f0a7-4e00-84f0-c09b9b1c81b5">
    <metadata>
        <title>Valid OSCAL Document</title>
        <last-modified>2023-10-24T00:00:00.000000-00:00</last-modified>
        <version>1.0</version>
        <oscal-version>1.1.1</oscal-version>
        <role id="maintainer">
            <title>Maintainer of oscal-cli</title>
        </role>
        <party uuid="4ba3f2b7-e894-48d7-b940-91c68661df55" type="person">
            <name>NIST ITL CSD Developer</name>
        </party>
        <responsible-party role-id="maintainer">
            <party-uuid>4ba3f2b7-e894-48d7-b940-91c68661df55</party-uuid>
        </responsible-party>
    </metadata>
    <group id="eg1">
        <title>Example Group 1</title>
        <control id="control-1">
            <title>Control 1</title>
            <part name="statement">
                <p>This statement is a requirement for Control 1.</p>
            </part>
        </control>
        <control id="control-2">
            <title>Control 2</title>
            <part name="statement">
                <p>This statement is a requirement for Control 2.</p>
            </part>
        </control>
    </group>
</catalog>

Profile:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://github.com/usnistgov/OSCAL/releases/download/v1.1.1/oscal_complete_schema.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?>
<profile xmlns="http://csrc.nist.gov/ns/oscal/1.0" uuid="46a67f43-6dd0-4231-b7d0-28e900fcbbe0">
    <metadata>
        <title>Valid OSCAL Document</title>
        <last-modified>2023-10-24T00:00:00.000000-00:00</last-modified>
        <version>1.0</version>
        <oscal-version>1.1.1</oscal-version>
        <role id="maintainer">
            <title>Maintainer of oscal-cli</title>
        </role>
        <party uuid="4ba3f2b7-e894-48d7-b940-91c68661df55" type="person">
            <name>NIST ITL CSD Developer</name>
        </party>
        <responsible-party role-id="maintainer">
            <party-uuid>4ba3f2b7-e894-48d7-b940-91c68661df55</party-uuid>
        </responsible-party>
    </metadata>
    <import href="example_catalog_valid.xml">
        <include-controls>
            <with-id>control-1</with-id>
        </include-controls>
    </import>
    <back-matter>
        <resource uuid="1ac08f59-cafa-4a71-a63b-5f4a0f3cf1f2">
            <rlink href="example_catalog_valid.xml"/>
        </resource>
    </back-matter>
</profile>

Stack trace:

java.lang.AssertionError
 at gov.nist.secauto.oscal.lib.profile.resolver.merge.FlatteningStructuringVisitor.visitControl(FlatteningStructuringVisitor.java:121)
 at gov.nist.secauto.oscal.lib.profile.resolver.merge.FlatteningStructuringVisitor.visitControl(FlatteningStructuringVisitor.java:55)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogEntityVisitor.visitControlInternal(AbstractCatalogEntityVisitor.java:168)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogVisitor.visitControlItem(AbstractCatalogVisitor.java:145)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogVisitor.lambda$visitControlContainer$2(AbstractCatalogVisitor.java:127)
 at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
 at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
 at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
 at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
 at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
 at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
 at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:553)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogVisitor.visitControlContainer(AbstractCatalogVisitor.java:129)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogEntityVisitor.visitControlContainer(AbstractCatalogEntityVisitor.java:122)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogVisitor.visitGroupContainer(AbstractCatalogVisitor.java:73)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogEntityVisitor.visitGroupContainer(AbstractCatalogEntityVisitor.java:110)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogVisitor.visitCatalog(AbstractCatalogVisitor.java:50)
 at gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogEntityVisitor.visitCatalog(AbstractCatalogEntityVisitor.java:96)
 at gov.nist.secauto.oscal.lib.profile.resolver.merge.FlatteningStructuringVisitor.visitCatalog(FlatteningStructuringVisitor.java:84)
 at gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver.structureFlat(ProfileResolver.java:489)
 at gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver.handleMerge(ProfileResolver.java:453)
 at gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver.resolveProfile(ProfileResolver.java:205)
 at gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver.resolve(ProfileResolver.java:234)
 at gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver.resolve(ProfileResolver.java:219)
 at gov.nist.secauto.oscal.tools.cli.core.commands.profile.ResolveSubcommand.executeCommand(ResolveSubcommand.java:287)
 at gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor$1.execute(ICommandExecutor.java:48)
 at gov.nist.secauto.metaschema.cli.processor.CLIProcessor$CallingContext.invokeCommand(CLIProcessor.java:403)
 at gov.nist.secauto.metaschema.cli.processor.CLIProcessor$CallingContext.processCommand(CLIProcessor.java:374)
 at gov.nist.secauto.metaschema.cli.processor.CLIProcessor.parseCommand(CLIProcessor.java:192)
 at gov.nist.secauto.metaschema.cli.processor.CLIProcessor.process(CLIProcessor.java:176)
 at gov.nist.secauto.oscal.tools.cli.core.CLI.runCli(CLI.java:78)
 at gov.nist.secauto.oscal.tools.cli.core.CLITest.testResolveSubCommandValidFile(CLITest.java:127)
 at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
 at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)

Who is the bug affecting?

  1. Developers writing software with liboscal-java or engineers using software based on liboscal-java, such as oscal-cli.

What is affected by this bug?

Profile resolution with catalogs that do not have groups.

When does this occur?

Consistently.

How do we replicate the issue?

Review the examples or use the integration tests in in the 178-add-integration-tests branch.

See the above stack trace for further details.

Expected behavior (i.e. solution)

The catalog resolves correctly if it does not have groups.

Other Comments

N/A

aj-stein-nist commented 1 year ago

So it appears the assertion that a control lookup in the index during flattening is the cause of the exception. When stepping through with a debugger, the control in question is control-2 because it is not included from the profile and dropped, so it is not included within the index.