Skip to content

Commit

Permalink
Metadata tests and way of determining top UUID
Browse files Browse the repository at this point in the history
- Remove global parameter assign-uuid (note backward incompatibility - is it OK?)
- Instead, support global parameters uuid-method and top-uuid, in uuid-method-choice.xsl
- Support global parameter hide-source-profile-uri
- Stub of opr:oscal-version function
- Stub of message handler template, using xsl:message for now
- Add XSpec tests
  • Loading branch information
galtm committed Mar 15, 2022
1 parent f416fd5 commit b997f8e
Show file tree
Hide file tree
Showing 8 changed files with 589 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
stylesheet="../../../utils/util/resolver-pipeline/oscal-profile-RESOLVE.xsl"
run-as="external">
<!--<x:param name="assign-uuid">00000000-0000-4000-A000-000000000000</x:param>-->
<!--<x:param name="top-uuid">00000000-0000-4000-A000-000000000000</x:param>
<x:param name="uuid-method" select="'user-provided'"/>-->

<!-- x:description/@run-as='external' permits the context item to be determined dynamically per scenario
cf https://github.com/xspec/xspec/wiki/External-Transformation#global-context-item
Expand Down
19 changes: 19 additions & 0 deletions src/utils/util/resolver-pipeline/message-handler.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:mh="http://csrc.nist.gov/ns/message"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">

<xsl:template name="mh:message-handler">
<xsl:param name="text" as="xs:string"/>
<xsl:param name="message-type" as="xs:string?"/><!-- e.g., 'Error', 'Warning' -->
<xsl:param name="error-code" as="xs:string?"/>
<xsl:param name="terminate" as="xs:boolean" select="false()"/>
<xsl:message expand-text="yes" terminate="{$terminate}">{
string-join(($message-type, $error-code, $text),': ')
}</xsl:message>
</xsl:template>

</xsl:stylesheet>
49 changes: 14 additions & 35 deletions src/utils/util/resolver-pipeline/oscal-profile-RESOLVE.xsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
xmlns:u="http://csrc.nist.gov/ns/uuid"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
xmlns:javaUUID="java.util.UUID"
xmlns:r="http://csrc.nist.gov/ns/random"
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/1.0">

<!--
Expand All @@ -22,8 +21,10 @@

<xsl:output method="xml" indent="yes"/>

<xsl:import href="random-util.xsl"/>

<!-- uuid-method-choice.xsl has global parameters
$uuid-method, $top-uuid, and $uuid-service. -->
<xsl:import href="uuid-method-choice.xsl"/>

<xsl:strip-space
elements="catalog group control param guideline select part
metadata back-matter annotation party person org rlink address resource role responsible-party citation
Expand All @@ -35,36 +36,8 @@

<xsl:param name="trace" as="xs:string">off</xsl:param>

<!-- Provide a top-level UUID for the result catalog as $assign-uuid,
or assign-uuid=make-uuid for a native (XSLT 3.0) function call. -->
<xsl:param name="assign-uuid" as="xs:string?"/>
<!-- Alternatively, call a web site if the processor supports it -->
<xsl:param name="uuid-service" select="'https://www.uuidgenerator.net/api/version4'"/>

<!-- For checking a UUID before assigning it. -->
<xsl:variable name="uuid-v4-regex" as="xs:string">^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$</xsl:variable>

<xsl:param name="uri-stack" as="xs:anyURI*" select="()"/>

<xsl:variable name="use-uuid" as="xs:string">
<xsl:choose>
<xsl:when test="matches($assign-uuid,$uuid-v4-regex)">
<xsl:sequence select="$assign-uuid"/>
</xsl:when>
<xsl:when use-when="function-available('random-number-generator')" test="$assign-uuid = 'make-uuid'">
<!-- seed splices a timestamp with a given @uuid -->
<xsl:sequence select="r:make-uuid( /*/@uuid || '-' || replace( string(current-dateTime()),'\D','') )"/>
</xsl:when>
<xsl:when use-when="function-available('javaUUID:randomUUID')" test="function-available('javaUUID:randomUUID')">
<xsl:sequence select="javaUUID:randomUUID()"/>
</xsl:when>
<xsl:when test="unparsed-text-available($uuid-service)">
<xsl:sequence select="unparsed-text($uuid-service)"/>
</xsl:when>
<xsl:otherwise>00000000-0000-4000-B000-000000000000</xsl:otherwise>
</xsl:choose>
</xsl:variable>


<!-- $path-to-source should point back to the location of the source catalog (or profile) from its result,
so '..' is appropriate when writing results down a directory. -->
<xsl:param name="path-to-source" as="xs:string?"/>
Expand All @@ -73,6 +46,10 @@

<xsl:param name="home" select="/"/>

<!-- If true, do not record profile URI in output catalog's source-profile
metadata, due to privacy or security concerns. -->
<xsl:param name="hide-source-profile-uri" as="xs:boolean" select="false()"/>

<!-- The $transformation-sequence declares transformations to be applied in order. -->
<xsl:variable name="transformation-sequence">
<opr:transform version="2.0">oscal-profile-resolve-select.xsl</opr:transform>
Expand Down Expand Up @@ -109,8 +86,10 @@
<xsl:template mode="opr:provide-parameters" match="opr:transform"/>

<xsl:template mode="opr:provide-parameters" match="opr:transform[.='oscal-profile-resolve-metadata.xsl']">
<!-- Since the fallback is not a valid URI the processor will try Java -->
<xsl:map-entry key="QName('','assign-uuid')" select="$use-uuid"/>
<xsl:map-entry key="QName('','top-uuid-computed')">
<xsl:call-template name="u:determine-uuid"/>
</xsl:map-entry>
<xsl:map-entry key="QName('','hide-source-profile-uri')" select="$hide-source-profile-uri"/>
</xsl:template>

<!-- for opr:transformation, the semantics are "apply this XSLT" -->
Expand Down
76 changes: 61 additions & 15 deletions src/utils/util/resolver-pipeline/oscal-profile-resolve-metadata.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,53 @@
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
exclude-result-prefixes="xs math o opr"
xmlns:u="http://csrc.nist.gov/ns/uuid"
exclude-result-prefixes="xs math o opr u"
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/1.0" >

<!-- XSLT 2.0 so as to validate against XSLT 3.0 constructs -->

<!-- How to specify top-level UUID for result catalog:
a) When oscal-profile-RESOLVE.xsl invokes this transform,
it passes in a precomputed value for $top-uuid-computed.
b) Any other caller of this transform should pass in
$uuid-method and, if applicable, $top-uuid and $uuid-service,
but not $top-uuid-computed. As a result, this transform
will compute $top-uuid-computed.
-->

<!-- uuid-method-choice.xsl has global parameters
$uuid-method, $top-uuid, and $uuid-service. -->
<xsl:import href="uuid-method-choice.xsl"/>

<!-- Top-level UUID for result catalog. -->
<xsl:param name="top-uuid-computed" as="xs:string">
<xsl:call-template name="u:determine-uuid"/>
</xsl:param>

<xsl:param name="profile-origin-uri">urn:UNKNOWN</xsl:param>

<!-- Accepts a uuid as $assign-uuid, or provides a dummy UUID. A calling application can provide a 'random' UUID. -->
<xsl:param name="assign-uuid" as="xs:string?"/>

<xsl:variable name="uuid-v4-regex" as="xs:string">^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$</xsl:variable>
<!-- If true, do not record profile URI in output catalog's source-profile
metadata, due to privacy or security concerns. This parameter is
passed from oscal-profile-RESOLVE.xsl and the end user can override it. -->
<xsl:param name="hide-source-profile-uri" as="xs:boolean" select="false()"/>

<xsl:variable name="use-uuid" as="xs:string"
select="( $assign-uuid[matches(.,$uuid-v4-regex)], '00000000-0000-4000-B000-000000000000' )[1]"/>

<xsl:template match="* | @*" mode="#all">
<!-- Version of this resolution tool -->
<xsl:variable name="tool-oscal-version" as="xs:string" select="'1.1.0'"/>

<xsl:variable name="source-profile" as="xs:string"
select="if ($hide-source-profile-uri) then 'profile' else $profile-origin-uri"/>

<xsl:template match="/ | * | @*" mode="#all">
<xsl:copy>
<xsl:apply-templates mode="#current" select="node() | @*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="profile" priority="1">
<catalog uuid="{ $use-uuid }">
<catalog uuid="{ $top-uuid-computed }">
<!-- Rewriting top-level @id -->
<!--<xsl:if test="function-available('uuid:randomUUID')" xmlns:uuid="java:java.util.UUID">
<xsl:attribute name="uuid" select="uuid:randomUUID()"/>
Expand All @@ -38,12 +62,13 @@
</xsl:template>

<xsl:template match="profile/metadata">
<xsl:variable name="leaders" select="(title | published | last-modified | version | oscal-version | doc-id)"/>
<xsl:variable name="leaders" select="(title | published | last-modified | version | oscal-version | document-id)"/>
<xsl:copy>
<xsl:apply-templates mode="#current" select="@*"/>
<xsl:apply-templates mode="#current" select="$leaders"/>
<xsl:apply-templates mode="#current" select="prop"/>
<link href="{$profile-origin-uri}" rel="resolution-source"/>
<prop name="resolution-tool" value="OSCAL Profile Resolver XSLT Pipeline OPRXP"/>
<link href="{$source-profile}" rel="source-profile"/>
<xsl:apply-templates mode="#current" select="* except ($leaders | prop)"/>
<!--<xsl:apply-templates select="../selection" mode="imported-metadata"/>-->
</xsl:copy>
Expand All @@ -55,13 +80,34 @@
</xsl:copy>
</xsl:template>

<xsl:template match="profile/metadata/oscal-version">
<xsl:copy>
<xsl:sequence select="opr:oscal-version(
.,
ancestor::profile/selection/metadata/oscal-version/normalize-space(),
$tool-oscal-version
)"/>
</xsl:copy>
</xsl:template>

<!-- If there is a common major version among all inputs,
return the most recent minor version or the tool version,
whichever is earlier.
If there is no common major version, return fatal error. -->
<xsl:function name="opr:oscal-version" as="xs:string">
<xsl:param name="source" as="xs:string"/>
<xsl:param name="imported" as="xs:string*"/>
<xsl:param name="tool" as="xs:string"/>
<xsl:value-of select="'TODO: Not implemented yet'"/>
</xsl:function>

<!--<xsl:template match="selection" mode="imported-metadata">
<resource id="{@id}-RESOURCE" rel="imported">
<xsl:copy-of select="metadata/title" copy-namespaces="no"/>
<rlink href="{@opr:src}"/>
</resource>
</xsl:template>-->

<xsl:template match="selection/metadata"/>

</xsl:stylesheet>
Loading

0 comments on commit b997f8e

Please sign in to comment.