Skip to content

Commit e88369d

Browse files
galtmaj-stein-nist
authored andcommitted
Profile resolver: Metadata tests and way of determining top UUID (#1175)
- Metadata tests and way of determining top UUID - 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 - Add table of parameters and clarify testing folder content - Change "home" from global param to global variable; does not need to be set from outside
1 parent 48af7dc commit e88369d

File tree

9 files changed

+621
-187
lines changed

9 files changed

+621
-187
lines changed

src/specifications/profile-resolution/profile-resolution-examples/example-set.xspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
44
stylesheet="../../../utils/util/resolver-pipeline/oscal-profile-RESOLVE.xsl"
55
run-as="external">
6-
<!--<x:param name="assign-uuid">00000000-0000-4000-A000-000000000000</x:param>-->
6+
<!--<x:param name="top-uuid">00000000-0000-4000-A000-000000000000</x:param>
7+
<x:param name="uuid-method" select="'user-provided'"/>-->
78

89
<!-- x:description/@run-as='external' permits the context item to be determined dynamically per scenario
910
cf https://github.com/xspec/xspec/wiki/External-Transformation#global-context-item
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet
3+
xmlns:mh="http://csrc.nist.gov/ns/message"
4+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
6+
exclude-result-prefixes="#all"
7+
version="3.0">
8+
9+
<xsl:template name="mh:message-handler">
10+
<xsl:param name="text" as="xs:string"/>
11+
<xsl:param name="message-type" as="xs:string?"/><!-- e.g., 'Error', 'Warning' -->
12+
<xsl:param name="error-code" as="xs:string?"/>
13+
<xsl:param name="terminate" as="xs:boolean" select="false()"/>
14+
<xsl:message expand-text="yes" terminate="{$terminate}">{
15+
string-join(($message-type, $error-code, $text),': ')
16+
}</xsl:message>
17+
</xsl:template>
18+
19+
</xsl:stylesheet>

src/utils/util/resolver-pipeline/oscal-profile-RESOLVE.xsl

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
33
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
4+
xmlns:u="http://csrc.nist.gov/ns/uuid"
45
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
56
xmlns:xs="http://www.w3.org/2001/XMLSchema"
67
exclude-result-prefixes="#all"
7-
xmlns:javaUUID="java.util.UUID"
8-
xmlns:r="http://csrc.nist.gov/ns/random"
98
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/1.0">
109

1110
<!--
@@ -22,8 +21,10 @@
2221

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

25-
<xsl:import href="random-util.xsl"/>
26-
24+
<!-- uuid-method-choice.xsl has global parameters
25+
$uuid-method, $top-uuid, and $uuid-service. -->
26+
<xsl:import href="uuid-method-choice.xsl"/>
27+
2728
<xsl:strip-space
2829
elements="catalog group control param guideline select part
2930
metadata back-matter annotation party person org rlink address resource role responsible-party citation
@@ -35,43 +36,19 @@
3536

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

38-
<!-- Provide a top-level UUID for the result catalog as $assign-uuid,
39-
or assign-uuid=make-uuid for a native (XSLT 3.0) function call. -->
40-
<xsl:param name="assign-uuid" as="xs:string?"/>
41-
<!-- Alternatively, call a web site if the processor supports it -->
42-
<xsl:param name="uuid-service" select="'https://www.uuidgenerator.net/api/version4'"/>
43-
44-
<!-- For checking a UUID before assigning it. -->
45-
<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>
46-
4739
<xsl:param name="uri-stack" as="xs:anyURI*" select="()"/>
48-
49-
<xsl:variable name="use-uuid" as="xs:string">
50-
<xsl:choose>
51-
<xsl:when test="matches($assign-uuid,$uuid-v4-regex)">
52-
<xsl:sequence select="$assign-uuid"/>
53-
</xsl:when>
54-
<xsl:when use-when="function-available('random-number-generator')" test="$assign-uuid = 'make-uuid'">
55-
<!-- seed splices a timestamp with a given @uuid -->
56-
<xsl:sequence select="r:make-uuid( /*/@uuid || '-' || replace( string(current-dateTime()),'\D','') )"/>
57-
</xsl:when>
58-
<xsl:when use-when="function-available('javaUUID:randomUUID')" test="function-available('javaUUID:randomUUID')">
59-
<xsl:sequence select="javaUUID:randomUUID()"/>
60-
</xsl:when>
61-
<xsl:when test="unparsed-text-available($uuid-service)">
62-
<xsl:sequence select="unparsed-text($uuid-service)"/>
63-
</xsl:when>
64-
<xsl:otherwise>00000000-0000-4000-B000-000000000000</xsl:otherwise>
65-
</xsl:choose>
66-
</xsl:variable>
67-
40+
6841
<!-- $path-to-source should point back to the location of the source catalog (or profile) from its result,
6942
so '..' is appropriate when writing results down a directory. -->
7043
<xsl:param name="path-to-source" as="xs:string?"/>
7144

7245
<xsl:variable name="louder" select="$trace = 'on'"/>
7346

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

7653
<!-- The $transformation-sequence declares transformations to be applied in order. -->
7754
<xsl:variable name="transformation-sequence">
@@ -109,8 +86,10 @@
10986
<xsl:template mode="opr:provide-parameters" match="opr:transform"/>
11087

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

11695
<!-- for opr:transformation, the semantics are "apply this XSLT" -->

src/utils/util/resolver-pipeline/oscal-profile-resolve-metadata.xsl

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,53 @@
66
xmlns:xs="http://www.w3.org/2001/XMLSchema"
77
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
88
xmlns:opr="http://csrc.nist.gov/ns/oscal/profile-resolution"
9-
exclude-result-prefixes="xs math o opr"
9+
xmlns:u="http://csrc.nist.gov/ns/uuid"
10+
exclude-result-prefixes="xs math o opr u"
1011
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/1.0" >
11-
12+
1213
<!-- XSLT 2.0 so as to validate against XSLT 3.0 constructs -->
14+
15+
<!-- How to specify top-level UUID for result catalog:
16+
17+
a) When oscal-profile-RESOLVE.xsl invokes this transform,
18+
it passes in a precomputed value for $top-uuid-computed.
19+
20+
b) Any other caller of this transform should pass in
21+
$uuid-method and, if applicable, $top-uuid and $uuid-service,
22+
but not $top-uuid-computed. As a result, this transform
23+
will compute $top-uuid-computed.
24+
-->
25+
26+
<!-- uuid-method-choice.xsl has global parameters
27+
$uuid-method, $top-uuid, and $uuid-service. -->
28+
<xsl:import href="uuid-method-choice.xsl"/>
29+
30+
<!-- Top-level UUID for result catalog. -->
31+
<xsl:param name="top-uuid-computed" as="xs:string">
32+
<xsl:call-template name="u:determine-uuid"/>
33+
</xsl:param>
1334

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

16-
<!-- Accepts a uuid as $assign-uuid, or provides a dummy UUID. A calling application can provide a 'random' UUID. -->
17-
<xsl:param name="assign-uuid" as="xs:string?"/>
18-
19-
<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>
37+
<!-- If true, do not record profile URI in output catalog's source-profile
38+
metadata, due to privacy or security concerns. This parameter is
39+
passed from oscal-profile-RESOLVE.xsl and the end user can override it. -->
40+
<xsl:param name="hide-source-profile-uri" as="xs:boolean" select="false()"/>
2041

21-
<xsl:variable name="use-uuid" as="xs:string"
22-
select="( $assign-uuid[matches(.,$uuid-v4-regex)], '00000000-0000-4000-B000-000000000000' )[1]"/>
23-
24-
<xsl:template match="* | @*" mode="#all">
42+
<!-- Version of this resolution tool -->
43+
<xsl:variable name="tool-oscal-version" as="xs:string" select="'1.1.0'"/>
44+
45+
<xsl:variable name="source-profile" as="xs:string"
46+
select="if ($hide-source-profile-uri) then 'profile' else $profile-origin-uri"/>
47+
48+
<xsl:template match="/ | * | @*" mode="#all">
2549
<xsl:copy>
2650
<xsl:apply-templates mode="#current" select="node() | @*"/>
2751
</xsl:copy>
2852
</xsl:template>
2953

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

4064
<xsl:template match="profile/metadata">
41-
<xsl:variable name="leaders" select="(title | published | last-modified | version | oscal-version | doc-id)"/>
65+
<xsl:variable name="leaders" select="(title | published | last-modified | version | oscal-version | document-id)"/>
4266
<xsl:copy>
4367
<xsl:apply-templates mode="#current" select="@*"/>
4468
<xsl:apply-templates mode="#current" select="$leaders"/>
4569
<xsl:apply-templates mode="#current" select="prop"/>
46-
<link href="{$profile-origin-uri}" rel="resolution-source"/>
70+
<prop name="resolution-tool" value="OSCAL Profile Resolver XSLT Pipeline OPRXP"/>
71+
<link href="{$source-profile}" rel="source-profile"/>
4772
<xsl:apply-templates mode="#current" select="* except ($leaders | prop)"/>
4873
<!--<xsl:apply-templates select="../selection" mode="imported-metadata"/>-->
4974
</xsl:copy>
@@ -55,13 +80,34 @@
5580
</xsl:copy>
5681
</xsl:template>
5782

83+
<xsl:template match="profile/metadata/oscal-version">
84+
<xsl:copy>
85+
<xsl:sequence select="opr:oscal-version(
86+
.,
87+
ancestor::profile/selection/metadata/oscal-version/normalize-space(),
88+
$tool-oscal-version
89+
)"/>
90+
</xsl:copy>
91+
</xsl:template>
92+
93+
<!-- If there is a common major version among all inputs,
94+
return the most recent minor version or the tool version,
95+
whichever is earlier.
96+
If there is no common major version, return fatal error. -->
97+
<xsl:function name="opr:oscal-version" as="xs:string">
98+
<xsl:param name="source" as="xs:string"/>
99+
<xsl:param name="imported" as="xs:string*"/>
100+
<xsl:param name="tool" as="xs:string"/>
101+
<xsl:value-of select="'TODO: Not implemented yet'"/>
102+
</xsl:function>
103+
58104
<!--<xsl:template match="selection" mode="imported-metadata">
59105
<resource id="{@id}-RESOURCE" rel="imported">
60106
<xsl:copy-of select="metadata/title" copy-namespaces="no"/>
61107
<rlink href="{@opr:src}"/>
62108
</resource>
63109
</xsl:template>-->
64-
110+
65111
<xsl:template match="selection/metadata"/>
66-
112+
67113
</xsl:stylesheet>
Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,49 @@
1-
## Resolver pipeline
1+
## Profile Resolver Pipeline
22

3-
Profile resolution is implemented here as a set of XSLT transformations to be performed in sequence, applied to defined inputs (a **source profile** with imported **catalog** sources) to produce defined outputs (a **profile resolution result** in the form of a catalog). The word **baseline** is also used to refer to a particular profile in application, whether in its unprocessed form or its resolved, serialized form.
3+
Profile resolution is implemented here as a sequence of XSLT transformations. The sequence applies to defined inputs (a **source profile** with imported **catalog** sources) and produces defined outputs (a **profile resolution result** in the form of a catalog). The word **baseline** also refers to a particular profile in application, whether in its unprocessed form or its resolved, serialized form.
44

5-
The sequence reflects and roughly corresponds to the three steps in profile resolution described for OSCAL in the [Profile Resolution Specification](https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/):
5+
The sequence of XSLT transformations reflects and roughly corresponds to the steps in profile resolution described for OSCAL in the [Profile Resolution Specification](https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/):
66

7-
- **selection** (importing catalogs or profiles and selecting controls from them)
7+
- **selection**: importing catalogs or profiles, and selecting controls from them
88

9-
- **organization (merging)** i.e. specifying how selected controls are to be organized in representation
9+
- **organization (merging)**: organizing the selected controls for the output representation
1010

11-
- **modification** - setting parameters and potentially supplementing, amending or editing control text
11+
- **modification**: setting parameters and potentially supplementing, amending or editing control text
1212

13-
For demonstration, the expected interim results for test files are kept in the testing/\* folders
13+
### Tests for this Implementation
1414

15-
Note that these interim results are *not always valid to any OSCAL schema* while at the same time they are quite close to OSCAL profile and catalog syntax.
15+
The `testing/*` folders contain XSpec tests that indicate expected interim results of each XSLT transformation in the sequence.
1616

17-
Testing files for profile resolution in general are kept [with the specification](../../../specifications/profile-resolution). The testing files in this subdirectory are only for this implementation.
17+
Note that these interim results are *not necessarily valid to any OSCAL schema*, although they are quite close to OSCAL profile and catalog syntax.
1818

19-
### Invoking the XSLT:
19+
The files in `testing/*` are only for this implementation. Implementation-independent tests and sample files for profile resolution are [with the specification](../../../specifications/profile-resolution).
2020

21-
Use a recent version of Saxon for best results -- although we would also be *very interested* to hear from users of other XSLT engines conformant to the 3.1 family of XML standards (XSLT/XPath/XDM/XQuery).
21+
### Invoking the XSLT
2222

23-
The main entry point for the transformation pipeline is the dynamic build XSLT called `oscal-profile-RESOLVE.xsl`, which invokes the core transformation steps in sequence, taking the source profile document as primary input. Load Saxon with your document and this stylesheet as follows (for example):
23+
Use a recent version of Saxon for best results &#8212; although we would also be *very interested* to hear from users of other XSLT engines conformant to the 3.1 family of XML standards (XSLT/XPath/XDM/XQuery).
24+
25+
The entry point for the transformation pipeline is `oscal-profile-RESOLVE.xsl`, which invokes the transformation steps in sequence, taking the source profile document as primary input. Load Saxon with your document and this stylesheet as follows (for example):
2426

2527
```bash
2628
> java -cp saxon-he-10.0.jar net.sf.saxon.Transform -t -s:YOUR_PROFILE_DOCUMENT.xml -xsl:path/to/oscal-profile-RESOLVE.xsl -o:YOUR_RESULT_BASELINE.xml
2729
```
2830

29-
Alternatively, set up the bindings in an IDE or programmed environment that has XSLT 3.1 support.
31+
You can optionally set one or more of the parameters listed in the following table, using syntax `name=value` at the end of the command above. The sequence of parameters is not significant.
32+
33+
For example,
34+
```bash
35+
> java -cp saxon-he-10.0.jar net.sf.saxon.Transform -t -s:YOUR_PROFILE_DOCUMENT.xml -xsl:path/to/oscal-profile-RESOLVE.xsl -o:YOUR_RESULT_BASELINE.xml uuid-method=random-xslt hide-source-profile-uri=true
36+
```
37+
| Name | Description | Default |
38+
|---|---|---|
39+
| `hide-source-profile-uri` | If `true`, the output catalog's metadata does not record the source profile's URI. | `false` |
40+
| `path-to-source` | Path from output catalog to location of source profile. | None |
41+
| `top-uuid` | UUID value for top-level element in output catalog, if `uuid-method` is `user-provided`. | None |
42+
| `uuid-method` | Method for computing UUID of top-level element in output catalog. Valid values are: `random-xslt`, in which case the `random-number-generator` XPath function must be available; `random-java`, in which case the `java.util.UUID.randomUUID()` Java method must be available; `user-provided`, in which case you must specify the `top-uuid` parameter; `web-service`, referring to the `uuid-service` parameter value; and `fixed`. | `fixed`|
43+
| `uuid-service` | URI for a web service that produces a UUID, if `uuid-method` is `web-service`.| `https://www.uuidgenerator.net/api/version4`|
44+
45+
Alternatively, set up the bindings in an IDE or programming environment that has XSLT 3.1 support.
3046

31-
Note that URIs (addresses) given in a profile document must link correctly as absolute or relative paths to their imported catalogs, as demonstrated in examples.
47+
Note that URIs (addresses) given in a profile document must link correctly as absolute or relative paths to their imported catalogs, as demonstrated in [examples](../../../specifications/profile-resolution/profile-resolution-examples).
3248

33-
A captured and serialized profile resolution will take the form of an OSCAL catalog, and be valid to the catalog schema for correctly formed inputs.
49+
A serialized output of profile resolution takes the form of an OSCAL catalog. Assuming inputs are correctly formed, the output is valid to the catalog schema.

0 commit comments

Comments
 (0)