├── .gitattributes ├── .gitignore ├── 3.1 ├── generic │ ├── 3.1.yml │ └── ARS_3-1_Excel_Export 2021.xlsx └── oscal │ ├── CMS_ARS_3_1_catalog.json │ └── json │ ├── CMS_ARS_3_1_HIGH-baseline_catalog.json │ ├── CMS_ARS_3_1_LOW-baseline_catalog.json │ ├── CMS_ARS_3_1_MODERATE-baseline_catalog.json │ └── CMS_ARS_3_1_catalog.json ├── 5.0 ├── generic │ └── 5.0.yml └── oscal │ └── json │ ├── CMS_ARS_5_0_catalog.json │ ├── cms_ars_50_high.json │ ├── cms_ars_50_low.json │ ├── cms_ars_50_moderate.json │ └── cms_ars_50_supplemental.json ├── ODP-extract ├── .gitignore ├── ARS-5.01-01.xml ├── ARS-5.01.xml ├── CMS ARS 5.0 control catalog 2022-08-19.xlsx ├── CMS ARS 5.0 control catalog 2022-08-19.xml ├── ODP-extract-cleanup.xsl ├── ODP-extract-edited.xml ├── ODP-extract-modified.xlsx ├── ODP-extract.css ├── ODP-extract.xlsx ├── ODP-extract.xml ├── ODP-extract.xsl ├── README.md ├── UTC.xsl ├── ars-5.0-catalog.xml ├── ars-5.0-catalog.xsl ├── ars-5.0-high-catalog.xml ├── ars-5.0-high-control-profile.xml ├── ars-5.0-high-profile.xml ├── ars-5.0-hva-catalog.xml ├── ars-5.0-hva-control-profile.xml ├── ars-5.0-hva-profile.xml ├── ars-5.0-low-catalog.xml ├── ars-5.0-low-control-profile.xml ├── ars-5.0-low-profile.xml ├── ars-5.0-moderate-catalog.xml ├── ars-5.0-moderate-control-profile.xml ├── ars-5.0-moderate-profile.xml ├── ars-5.0-odp-profile.xml ├── catalog2html.css ├── catalog2html.xsl ├── generate-profiles.xsl ├── miscellaneous-reports.css ├── miscellaneous-reports.xsl ├── profile.sch └── random-util.xsl ├── README.md └── ars-xlsx-oscal-json ├── README.md ├── catalog31.py ├── catalog50.py ├── header31_map.json ├── header50_map.json ├── poetry.lock └── pyproject.toml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | *.json text 5 | *.yaml text -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS noise 2 | *.DS_Store 3 | 4 | # OxygenXML project files 5 | *.xpl 6 | -------------------------------------------------------------------------------- /3.1/generic/ARS_3-1_Excel_Export 2021.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMSgov/ars-machine-readable/e15e2183310b455f40c6c459cfd0b4d5ab50317d/3.1/generic/ARS_3-1_Excel_Export 2021.xlsx -------------------------------------------------------------------------------- /5.0/generic/5.0.yml: -------------------------------------------------------------------------------- 1 | # this is a yaml file yo. 2 | -------------------------------------------------------------------------------- /ODP-extract/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /ODP-extract/CMS ARS 5.0 control catalog 2022-08-19.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMSgov/ars-machine-readable/e15e2183310b455f40c6c459cfd0b4d5ab50317d/ODP-extract/CMS ARS 5.0 control catalog 2022-08-19.xlsx -------------------------------------------------------------------------------- /ODP-extract/ODP-extract-cleanup.xsl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ODP-extract/ODP-extract-modified.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMSgov/ars-machine-readable/e15e2183310b455f40c6c459cfd0b4d5ab50317d/ODP-extract/ODP-extract-modified.xlsx -------------------------------------------------------------------------------- /ODP-extract/ODP-extract.css: -------------------------------------------------------------------------------- 1 | 2 | thead tr { 3 | background-color: #e0e0e0; 4 | color: inherit; 5 | } 6 | 7 | thead th { 8 | vertical-align: bottom; 9 | text-align: left; 10 | white-space: normal; 11 | } 12 | 13 | thead td { 14 | } 15 | 16 | tbody tr { 17 | vertical-align: top; 18 | } 19 | 20 | tbody th { 21 | text-align: left; 22 | background-color: #e8e8e8; 23 | color: inherit; 24 | } 25 | 26 | tbody tr { 27 | background-color: #f0f0f0; 28 | color: inherit; 29 | } 30 | tbody tr.odd-row { 31 | background-color: #f0f0ff; 32 | color: inherit; 33 | } 34 | 35 | tbody td { 36 | } 37 | 38 | table.template { 39 | border: thin solid black; 40 | border-collapse: collapse; 41 | } 42 | table.template th { 43 | border: thin solid black; 44 | } 45 | table.template td { 46 | border: thin solid black; 47 | } 48 | 49 | tbody td.fillin { 50 | background-color: white; 51 | } 52 | 53 | tr.prior-revision { 54 | color: grey; 55 | } 56 | 57 | table.tr-hover tbody tr:hover { 58 | background-color: #f8f8f8; 59 | border-color: black; 60 | } 61 | 62 | 63 | tbody tr.prior-revision:hover { 64 | color: inherit; 65 | } 66 | 67 | .multirow { 68 | vertical-align: middle; 69 | } 70 | 71 | 72 | td.centered { 73 | vertical-align: middle; 74 | text-align: center; 75 | } 76 | 77 | .LMHP 78 | { 79 | /*font-weight: bold;*/ 80 | } 81 | 82 | .fr 83 | { 84 | float: right; 85 | } 86 | 87 | .revision { 88 | } 89 | 90 | .different { 91 | background-color: cornsilk; 92 | } 93 | 94 | .label { 95 | } 96 | .select { 97 | } 98 | .label, 99 | .select { 100 | /*font-variant: small-caps;*/ 101 | font-style: italic; 102 | background-color: powderblue; 103 | /*text-decoration: underline;*/ 104 | } 105 | 106 | .select > .label { 107 | text-decoration:underline; 108 | } 109 | 110 | 111 | div > div.statement { 112 | margin-left: 1em; 113 | } 114 | div > div.item { 115 | margin-left: 1em; 116 | } 117 | div.item > div.item { 118 | margin-left: 1em; 119 | } 120 | 121 | .anomaly { 122 | font-style: italic; 123 | background-color: yellow; 124 | } 125 | 126 | .withdrawn { 127 | text-decoration: line-through; 128 | } 129 | .withdrawn2 { 130 | color: grey; 131 | text-decoration: line-through; 132 | } 133 | 134 | *[title] { 135 | cursor: help; 136 | } 137 | 138 | details.ODPs { 139 | display: inline-table; 140 | vertical-align: text-top; 141 | 142 | } 143 | details[open] { 144 | /*font-size: smaller;*/ 145 | } 146 | summary { 147 | list-style: none; 148 | cursor: pointer; 149 | } 150 | 151 | details summary:after { 152 | /*content: "☟";*/ 153 | content: "⬇"; 154 | font-size: smaller; 155 | } 156 | 157 | span.TBS { 158 | font-variant: small-caps; 159 | font-style: italic; 160 | font-weight: bold; 161 | } 162 | 163 | span.match { 164 | background-color: lightgreen; 165 | } 166 | span.nomatch { 167 | background-color: lightyellow; 168 | } 169 | span.textmatch { 170 | background-color: lightskyblue; 171 | } 172 | span.partialmatch { 173 | background-color: lightyellow; 174 | } 175 | 176 | span.superscript-identifier { 177 | /*font-variant: small-caps;*/ 178 | vertical-align: super; 179 | font-family: courier, fixed, monospace; 180 | font-size: xx-small; 181 | hyphens: none; 182 | } 183 | 184 | span.boolean { 185 | font-variant: small-caps; 186 | font-family: courier, fixed, monospace; 187 | font-weight: bold; 188 | } 189 | 190 | span.guideline { 191 | font-size: smaller; 192 | } 193 | 194 | div.ars-statement { 195 | /*white-space: pre;*/ 196 | } 197 | 198 | span.ODP { 199 | background-color: powderblue; 200 | } 201 | 202 | span.insert { 203 | font-size: smaller; 204 | font-family: courier, fixed, monospace; 205 | } 206 | 207 | ul.statement-odp-list { 208 | margin-top: 0; 209 | } 210 | 211 | span.regex-group, 212 | span.analysis-string { 213 | font-family: courier, fixed, monospace; 214 | font-size: smaller; 215 | } 216 | table.analysis { 217 | margin-left: 1em; 218 | } 219 | .missing { 220 | background-color: orange; 221 | } 222 | .novel { 223 | background-color: orange; 224 | } 225 | 226 | .novel-ODP { 227 | text-decoration: underline; 228 | text-decoration-color: orange; 229 | } 230 | .established-ODP { 231 | text-decoration: none; 232 | } 233 | .comparison { 234 | text-align: right; 235 | } 236 | 237 | .param_id { 238 | font-family: courier, fixed, monospace; 239 | font-size: smaller; 240 | } 241 | 242 | .id { 243 | font-family: monospace; 244 | } 245 | 246 | .center { 247 | text-align: center; 248 | } 249 | 250 | caption { 251 | font-weight: bold; 252 | } 253 | 254 | blockquote { 255 | background: #f9f9f9; 256 | border-left: 10px solid #ccc; 257 | margin: 1.5em 10px; 258 | padding: 0.5em 10px; 259 | quotes: "\201C" "\201D" "\2018" "\2019"; 260 | width: 50%; 261 | } 262 | blockquote:before { 263 | color: #ccc; 264 | content: open-quote; 265 | font-size: 4em; 266 | line-height: 0.1em; 267 | margin-right: 0.25em; 268 | vertical-align: -0.4em; 269 | } 270 | blockquote p { 271 | display: inline; 272 | } 273 | 274 | div.comparison-example { 275 | margin-left: 5%; 276 | margin-right: 5%; 277 | } 278 | 279 | .semantic-error { 280 | text-decoration: underline; 281 | text-decoration-color: sandybrown; 282 | } 283 | .semantic-error::before { 284 | background-color: sandybrown; 285 | content: "faux pas ☛ "; 286 | } 287 | 288 | div.trailer > p { 289 | font-size: xx-small; 290 | max-width: 85ex; 291 | text-align: center; 292 | text-transform: uppercase; 293 | margin-left: auto; 294 | margin-right: auto; 295 | font-family: monospace; 296 | color: #888; 297 | background-color: inherit; 298 | line-height: 120% 299 | } -------------------------------------------------------------------------------- /ODP-extract/ODP-extract.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMSgov/ars-machine-readable/e15e2183310b455f40c6c459cfd0b4d5ab50317d/ODP-extract/ODP-extract.xlsx -------------------------------------------------------------------------------- /ODP-extract/README.md: -------------------------------------------------------------------------------- 1 | # ARS ODP extract 2 | 3 | This directory contains data and transforms to create ARS 5.0 OSCAL catalog and profiles. 4 | 5 | ## ODP extract 6 | 7 | `ARS-5.0.xml` was created by converting the 8 | [ARS 5.0 spreadsheet](https://dkanreserve.prod.acquia-sites.com/sites/default/files/Main%20Library%20Documents/ARS%20Full%20Element%20Principle_Single_Assessment_Current%20V5.01.xlsx) to XML. 9 | This was a manual process: remove the first row and then invoke an MS Excel to XML import in OxygenXML Editor. 10 | 11 | The XML import was then manually edited to remove a few errors resulting in `ARS-5.01-01.xml`. 12 | 13 | `ODP-example.xsl` can be used to produce the ODP extract as an OSCAL profile using `ARS-5.01-01.xml` as input. (The profile cannot be created and used in the same transformation.) 14 | 15 | There are two parameters which should be used in three sequential transforms: 16 | 1. `generate-odp-profile` set to boolean true to produce the ODP profile.. 17 | 1. `generate-ars-profiles` set to boolean true to produce the baseline profiles. 18 | 1. Transform with the above set to boolean false (the default) to produce the report. 19 | 20 | ## ARS OSCAL profile generation 21 | 22 | `ODP-extract.xlsx` was received 2022-07-26 and contains values for all ODPs in baselined controls. It was copied and modified to become `ODP-extract (modified).xlsx` which was then imported to become `ODP-extract.xml`. A manual process was used to alter the received file (using LibreOffice) and converting the result to XML using the XML import in OxygenXML Editor. 23 | 24 | After finding 49 ODP values ending in a period, a small transform `ODP-extract-cleanup.xsl` was created to produce `ODP-extract-edited.xml` using `ODP-extract.xml` as input. 25 | 26 | `java -cp ~/saxon/saxon-he-11.3.jar net.sf.saxon.Transform -xsl:ODP-extract-cleanup.xsl -s:ODP-extract.xml -o:ODP-extract-edited.xml` 27 | 28 | To create the ARS OSCAL profiles using `generate-profiles.xsl` as the transform and `ODP-extract-edited.xml` as input, the following command would be used: 29 | 30 | `java -cp ~/saxon/saxon-he-11.3.jar net.sf.saxon.Transform -xsl:generate-profiles.xsl -s:ODP-extract-edited.xml`. 31 | 32 | ## ARS OSCAL catalog generation 33 | 34 | The XSL transform `ars-5.0-catalog.xsl` creates the catalog `ars-5.0-catalog.xml` using `https://raw.githubusercontent.com/usnistgov/oscal-content/main/nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_catalog.xml` as input. 35 | 36 | This catalog is quite preliminary; SP 800-53A information is deliberately omitted. 37 | 38 | ## ARS OSCAL catalog rendition 39 | 40 | The XSL transform `catalog2html.xsl` (with a companion `catalog2html.css`) produces an HTML rendition of the ARS OSCAL catalog and profiles. 41 | 42 | ## Running XSL Transformations (XSLT) 43 | 44 | The supplied transforms (`.xsl` documents) require the use of an XSLT 3.0/XPath 3.1 implementation. 45 | 46 | The use of [SaxonJ-HE](https://www.saxonica.com/html/documentation11/about/gettingstarted/gettingstartedjava.html) is one method. This can be used on any platform which accommodates Java. 47 | 48 | SaxonJ-HE is typically employed in the operating system terminal application. 49 | Using an alias such as `alias xslt='java -cp ~/saxon/saxon-he-11.3.jar net.sf.saxon.Transform'` simplifies command specification. 50 | 51 | As an exaample, when creating the ARS OSCAL profiles using `generate-profiles.xsl` as the transform and `ODP-extract.xml` as input, the following command would be used: 52 | 53 | `xslt -xsl:generate-profiles.xsl -s:ODP-extract.xml` (no output file need be identified - the transform generates three). 54 | 55 | The command without the alias would be 56 | 57 | `java -cp ~/saxon/saxon-he-11.3.jar net.sf.saxon.Transform -xsl:generate-profiles.xsl -s:ODP-extract.xml`. -------------------------------------------------------------------------------- /ODP-extract/UTC.xsl: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ODP-extract/ars-5.0-catalog.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | href="https://github.com/usnistgov/OSCAL/raw/v1.0.4/xml/schema/oscal_complete_schema.xsd" schematypens="http://www.w3.org/2001/XMLSchema" title="OSCAL complete schema" 28 | 29 | 30 | Input document was {document-uri()} 31 | 32 | Input document version was {//metadata/version} 33 | 34 | Input document last-modified was {//metadata/last-modified} 35 | 36 | Transform document was {static-base-uri()} 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | >CMS ARS 5.0 Catalog 51 | {$UTC-datetime} 52 | {$UTC-datetime} 53 | 1.0.4 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | {@id} 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /ODP-extract/ars-5.0-high-control-profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CMS ARS 5.0 High Control Profile 6 | 2022-08-26T14:49:07.559731Z 7 | 2022-08-26T14:49:07.559731Z 8 | 1.0.4 9 | 10 | 11 | 12 | 13 | ac-1 14 | ac-2 15 | ac-2.1 16 | ac-2.2 17 | ac-2.3 18 | ac-2.4 19 | ac-2.5 20 | ac-2.11 21 | ac-2.12 22 | ac-2.13 23 | ac-3 24 | ac-3.14 25 | ac-4 26 | ac-4.4 27 | ac-5 28 | ac-6 29 | ac-6.1 30 | ac-6.2 31 | ac-6.3 32 | ac-6.5 33 | ac-6.7 34 | ac-6.9 35 | ac-6.10 36 | ac-7 37 | ac-8 38 | ac-10 39 | ac-11 40 | ac-11.1 41 | ac-12 42 | ac-14 43 | ac-17 44 | ac-17.1 45 | ac-17.2 46 | ac-17.3 47 | ac-17.4 48 | ac-18 49 | ac-18.1 50 | ac-18.3 51 | ac-18.4 52 | ac-18.5 53 | ac-19 54 | ac-19.5 55 | ac-20 56 | ac-20.1 57 | ac-20.2 58 | ac-21 59 | ac-22 60 | at-1 61 | at-2 62 | at-2.2 63 | at-2.3 64 | at-3 65 | at-3.5 66 | at-4 67 | au-1 68 | au-2 69 | au-3 70 | au-3.1 71 | au-3.3 72 | au-4 73 | au-5 74 | au-5.1 75 | au-5.2 76 | au-6 77 | au-6.1 78 | au-6.3 79 | au-6.5 80 | au-6.6 81 | au-7 82 | au-7.1 83 | au-8 84 | au-9 85 | au-9.2 86 | au-9.3 87 | au-9.4 88 | au-10 89 | au-11 90 | au-12 91 | au-12.1 92 | au-12.3 93 | ca-1 94 | ca-2 95 | ca-2.1 96 | ca-2.2 97 | ca-2.3 98 | ca-3 99 | ca-3.6 100 | ca-5 101 | ca-6 102 | ca-7 103 | ca-7.1 104 | ca-7.4 105 | ca-8 106 | ca-8.1 107 | ca-9 108 | cm-1 109 | cm-2 110 | cm-2.2 111 | cm-2.3 112 | cm-2.7 113 | cm-3 114 | cm-3.1 115 | cm-3.2 116 | cm-3.4 117 | cm-3.6 118 | cm-4 119 | cm-4.1 120 | cm-4.2 121 | cm-5 122 | cm-5.1 123 | cm-6 124 | cm-6.1 125 | cm-6.2 126 | cm-7 127 | cm-7.1 128 | cm-7.2 129 | cm-7.5 130 | cm-8 131 | cm-8.1 132 | cm-8.2 133 | cm-8.3 134 | cm-8.4 135 | cm-9 136 | cm-10 137 | cm-11 138 | cm-12 139 | cm-12.1 140 | cp-1 141 | cp-2 142 | cp-2.1 143 | cp-2.2 144 | cp-2.3 145 | cp-2.5 146 | cp-2.8 147 | cp-3 148 | cp-3.1 149 | cp-4 150 | cp-4.1 151 | cp-4.2 152 | cp-6 153 | cp-6.1 154 | cp-6.2 155 | cp-6.3 156 | cp-7 157 | cp-7.1 158 | cp-7.2 159 | cp-7.3 160 | cp-7.4 161 | cp-8 162 | cp-8.1 163 | cp-8.2 164 | cp-8.3 165 | cp-8.4 166 | cp-9 167 | cp-9.1 168 | cp-9.2 169 | cp-9.3 170 | cp-9.5 171 | cp-9.8 172 | cp-10 173 | cp-10.2 174 | cp-10.4 175 | ia-1 176 | ia-2 177 | ia-2.1 178 | ia-2.2 179 | ia-2.5 180 | ia-2.8 181 | ia-2.12 182 | ia-3 183 | ia-4 184 | ia-4.4 185 | ia-5 186 | ia-5.1 187 | ia-5.2 188 | ia-5.6 189 | ia-6 190 | ia-7 191 | ia-8 192 | ia-8.1 193 | ia-8.2 194 | ia-8.4 195 | ia-11 196 | ia-12 197 | ia-12.2 198 | ia-12.3 199 | ia-12.4 200 | ia-12.5 201 | ir-1 202 | ir-2 203 | ir-2.3 204 | ir-3 205 | ir-3.2 206 | ir-4 207 | ir-4.1 208 | ir-4.4 209 | ir-4.11 210 | ir-5 211 | ir-5.1 212 | ir-6 213 | ir-6.1 214 | ir-6.3 215 | ir-7 216 | ir-7.1 217 | ir-8 218 | ir-8.1 219 | ma-1 220 | ma-2 221 | ma-2.2 222 | ma-3 223 | ma-3.1 224 | ma-3.2 225 | ma-3.3 226 | ma-4 227 | ma-4.3 228 | ma-5 229 | ma-5.1 230 | ma-6 231 | mp-1 232 | mp-2 233 | mp-3 234 | mp-4 235 | mp-5 236 | mp-6 237 | mp-6.1 238 | mp-6.2 239 | mp-6.3 240 | mp-7 241 | pe-1 242 | pe-2 243 | pe-3 244 | pe-3.1 245 | pe-4 246 | pe-5 247 | pe-6 248 | pe-6.1 249 | pe-6.4 250 | pe-8 251 | pe-8.1 252 | pe-9 253 | pe-10 254 | pe-11 255 | pe-11.1 256 | pe-12 257 | pe-13 258 | pe-13.1 259 | pe-13.2 260 | pe-14 261 | pe-15 262 | pe-15.1 263 | pe-16 264 | pe-17 265 | pe-18 266 | pl-1 267 | pl-2 268 | pl-4 269 | pl-4.1 270 | pl-8 271 | pl-9 272 | pl-10 273 | pl-11 274 | pm-1 275 | pm-2 276 | pm-3 277 | pm-4 278 | pm-5 279 | pm-5.1 280 | pm-6 281 | pm-7 282 | pm-7.1 283 | pm-8 284 | pm-9 285 | pm-10 286 | pm-11 287 | pm-12 288 | pm-13 289 | pm-14 290 | pm-15 291 | pm-16 292 | pm-16.1 293 | pm-17 294 | pm-18 295 | pm-19 296 | pm-20 297 | pm-20.1 298 | pm-21 299 | pm-22 300 | pm-23 301 | pm-24 302 | pm-25 303 | pm-26 304 | pm-27 305 | pm-28 306 | pm-29 307 | pm-30 308 | pm-30.1 309 | pm-31 310 | pm-32 311 | ps-1 312 | ps-2 313 | ps-3 314 | ps-4 315 | ps-4.2 316 | ps-5 317 | ps-6 318 | ps-7 319 | ps-8 320 | ps-9 321 | pt-1 322 | pt-2 323 | pt-3 324 | pt-4 325 | pt-5 326 | pt-5.2 327 | pt-6 328 | pt-6.1 329 | pt-6.2 330 | pt-7 331 | pt-7.1 332 | pt-7.2 333 | pt-8 334 | ra-1 335 | ra-2 336 | ra-3 337 | ra-3.1 338 | ra-5 339 | ra-5.2 340 | ra-5.4 341 | ra-5.5 342 | ra-5.11 343 | ra-7 344 | ra-8 345 | ra-9 346 | sa-1 347 | sa-2 348 | sa-3 349 | sa-4 350 | sa-4.1 351 | sa-4.2 352 | sa-4.5 353 | sa-4.9 354 | sa-4.10 355 | sa-5 356 | sa-8 357 | sa-8.33 358 | sa-9 359 | sa-9.2 360 | sa-10 361 | sa-11 362 | sa-15 363 | sa-15.3 364 | sa-16 365 | sa-17 366 | sa-21 367 | sa-22 368 | sc-1 369 | sc-2 370 | sc-3 371 | sc-4 372 | sc-5 373 | sc-7 374 | sc-7.3 375 | sc-7.4 376 | sc-7.5 377 | sc-7.7 378 | sc-7.8 379 | sc-7.24 380 | sc-8 381 | sc-8.1 382 | sc-10 383 | sc-12 384 | sc-12.1 385 | sc-13 386 | sc-15 387 | sc-17 388 | sc-18 389 | sc-20 390 | sc-21 391 | sc-22 392 | sc-23 393 | sc-24 394 | sc-28 395 | sc-28.1 396 | sc-39 397 | si-1 398 | si-2 399 | si-2.2 400 | si-3 401 | si-4 402 | si-4.2 403 | si-4.4 404 | si-4.5 405 | si-4.10 406 | si-4.12 407 | si-4.14 408 | si-4.20 409 | si-4.22 410 | si-5 411 | si-5.1 412 | si-6 413 | si-7 414 | si-7.1 415 | si-7.2 416 | si-7.5 417 | si-7.7 418 | si-7.15 419 | si-8 420 | si-8.2 421 | si-10 422 | si-11 423 | si-12 424 | si-12.1 425 | si-12.2 426 | si-12.3 427 | si-16 428 | si-18 429 | si-18.4 430 | si-19 431 | sr-1 432 | sr-2 433 | sr-2.1 434 | sr-3 435 | sr-5 436 | sr-6 437 | sr-8 438 | sr-9 439 | sr-9.1 440 | sr-10 441 | sr-11 442 | sr-11.1 443 | sr-11.2 444 | sr-12 445 | 446 | 447 | 448 | -------------------------------------------------------------------------------- /ODP-extract/ars-5.0-hva-control-profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CMS ARS 5.0 HVA Control Profile 6 | 2022-08-11T17:22:22Z 7 | 2022-08-11T17:22:22Z 8 | 1.0.4 9 | 10 | 11 | 12 | ac-1 13 | ac-2 14 | ac-2.1 15 | ac-2.2 16 | ac-2.3 17 | ac-2.4 18 | ac-2.5 19 | ac-2.11 20 | ac-2.12 21 | ac-2.13 22 | ac-3 23 | ac-3.9 24 | ac-3.14 25 | ac-4 26 | ac-4.4 27 | ac-5 28 | ac-6 29 | ac-6.1 30 | ac-6.2 31 | ac-6.3 32 | ac-6.5 33 | ac-6.7 34 | ac-6.9 35 | ac-6.10 36 | ac-7 37 | ac-8 38 | ac-10 39 | ac-11 40 | ac-11.1 41 | ac-12 42 | ac-14 43 | ac-17 44 | ac-17.1 45 | ac-17.2 46 | ac-17.3 47 | ac-17.4 48 | ac-18 49 | ac-18.1 50 | ac-18.3 51 | ac-18.4 52 | ac-18.5 53 | ac-19 54 | ac-19.5 55 | ac-20 56 | ac-20.1 57 | ac-20.2 58 | ac-21 59 | ac-22 60 | at-1 61 | at-2 62 | at-2.1 63 | at-2.2 64 | at-2.3 65 | at-3 66 | at-3.5 67 | at-4 68 | au-1 69 | au-2 70 | au-3 71 | au-3.1 72 | au-3.3 73 | au-4 74 | au-5 75 | au-5.1 76 | au-5.2 77 | au-6 78 | au-6.1 79 | au-6.3 80 | au-6.5 81 | au-6.6 82 | au-7 83 | au-7.1 84 | au-8 85 | au-9 86 | au-9.2 87 | au-9.3 88 | au-9.4 89 | au-9.5 90 | au-10 91 | au-11 92 | au-12 93 | au-12.1 94 | au-12.3 95 | au-16 96 | ca-1 97 | ca-2 98 | ca-2.1 99 | ca-2.2 100 | ca-2.3 101 | ca-3 102 | ca-3.6 103 | ca-5 104 | ca-6 105 | ca-6.1 106 | ca-7 107 | ca-7.1 108 | ca-7.3 109 | ca-7.4 110 | ca-8 111 | ca-8.1 112 | ca-9 113 | cm-1 114 | cm-2 115 | cm-2.2 116 | cm-2.3 117 | cm-2.7 118 | cm-3 119 | cm-3.1 120 | cm-3.2 121 | cm-3.4 122 | cm-3.6 123 | cm-3.7 124 | cm-4 125 | cm-4.1 126 | cm-4.2 127 | cm-5 128 | cm-5.1 129 | cm-6 130 | cm-6.1 131 | cm-6.2 132 | cm-7 133 | cm-7.1 134 | cm-7.2 135 | cm-7.5 136 | cm-8 137 | cm-8.1 138 | cm-8.2 139 | cm-8.3 140 | cm-8.4 141 | cm-9 142 | cm-10 143 | cm-11 144 | cm-12 145 | cm-12.1 146 | cp-1 147 | cp-2 148 | cp-2.1 149 | cp-2.2 150 | cp-2.3 151 | cp-2.5 152 | cp-2.8 153 | cp-3 154 | cp-3.1 155 | cp-4 156 | cp-4.1 157 | cp-4.2 158 | cp-6 159 | cp-6.1 160 | cp-6.2 161 | cp-6.3 162 | cp-7 163 | cp-7.1 164 | cp-7.2 165 | cp-7.3 166 | cp-7.4 167 | cp-8 168 | cp-8.1 169 | cp-8.2 170 | cp-8.3 171 | cp-8.4 172 | cp-8.5 173 | cp-9 174 | cp-9.1 175 | cp-9.2 176 | cp-9.3 177 | cp-9.5 178 | cp-9.8 179 | cp-10 180 | cp-10.2 181 | cp-10.4 182 | ia-1 183 | ia-2 184 | ia-2.1 185 | ia-2.2 186 | ia-2.5 187 | ia-2.8 188 | ia-2.12 189 | ia-3 190 | ia-4 191 | ia-4.4 192 | ia-5 193 | ia-5.1 194 | ia-5.2 195 | ia-5.6 196 | ia-6 197 | ia-7 198 | ia-8 199 | ia-8.1 200 | ia-8.2 201 | ia-8.4 202 | ia-11 203 | ia-12 204 | ia-12.2 205 | ia-12.3 206 | ia-12.4 207 | ia-12.5 208 | ir-1 209 | ir-2 210 | ir-2.3 211 | ir-3 212 | ir-3.2 213 | ir-4 214 | ir-4.1 215 | ir-4.2 216 | ir-4.4 217 | ir-4.8 218 | ir-4.10 219 | ir-4.11 220 | ir-5 221 | ir-5.1 222 | ir-6 223 | ir-6.1 224 | ir-6.3 225 | ir-7 226 | ir-7.1 227 | ir-8 228 | ir-8.1 229 | ma-1 230 | ma-2 231 | ma-2.2 232 | ma-3 233 | ma-3.1 234 | ma-3.2 235 | ma-3.3 236 | ma-4 237 | ma-4.3 238 | ma-5 239 | ma-5.1 240 | ma-6 241 | mp-1 242 | mp-2 243 | mp-3 244 | mp-4 245 | mp-5 246 | mp-6 247 | mp-6.1 248 | mp-6.2 249 | mp-6.3 250 | mp-6.8 251 | mp-7 252 | pe-1 253 | pe-2 254 | pe-3 255 | pe-3.1 256 | pe-4 257 | pe-5 258 | pe-6 259 | pe-6.1 260 | pe-6.4 261 | pe-8 262 | pe-8.1 263 | pe-9 264 | pe-10 265 | pe-11 266 | pe-11.1 267 | pe-12 268 | pe-13 269 | pe-13.1 270 | pe-13.2 271 | pe-14 272 | pe-15 273 | pe-15.1 274 | pe-16 275 | pe-17 276 | pe-18 277 | pl-1 278 | pl-2 279 | pl-4 280 | pl-4.1 281 | pl-8 282 | pl-8.1 283 | pl-9 284 | pl-10 285 | pl-11 286 | pm-1 287 | pm-2 288 | pm-3 289 | pm-4 290 | pm-5 291 | pm-5.1 292 | pm-6 293 | pm-7 294 | pm-7.1 295 | pm-8 296 | pm-9 297 | pm-10 298 | pm-11 299 | pm-12 300 | pm-13 301 | pm-14 302 | pm-15 303 | pm-16 304 | pm-16.1 305 | pm-17 306 | pm-18 307 | pm-19 308 | pm-20 309 | pm-20.1 310 | pm-21 311 | pm-22 312 | pm-23 313 | pm-24 314 | pm-25 315 | pm-26 316 | pm-27 317 | pm-28 318 | pm-29 319 | pm-30 320 | pm-30.1 321 | pm-31 322 | pm-32 323 | ps-1 324 | ps-2 325 | ps-3 326 | ps-4 327 | ps-4.2 328 | ps-5 329 | ps-6 330 | ps-7 331 | ps-8 332 | ps-9 333 | pt-1 334 | pt-2 335 | pt-3 336 | pt-4 337 | pt-5 338 | pt-5.2 339 | pt-6 340 | pt-6.1 341 | pt-6.2 342 | pt-7 343 | pt-7.1 344 | pt-7.2 345 | pt-8 346 | ra-1 347 | ra-2 348 | ra-3 349 | ra-3.1 350 | ra-5 351 | ra-5.2 352 | ra-5.4 353 | ra-5.5 354 | ra-5.6 355 | ra-5.10 356 | ra-5.11 357 | ra-7 358 | ra-8 359 | ra-9 360 | sa-1 361 | sa-2 362 | sa-3 363 | sa-4 364 | sa-4.1 365 | sa-4.2 366 | sa-4.5 367 | sa-4.9 368 | sa-4.10 369 | sa-5 370 | sa-8 371 | sa-8.33 372 | sa-9 373 | sa-9.2 374 | sa-10 375 | sa-11 376 | sa-11.1 377 | sa-15 378 | sa-15.3 379 | sa-16 380 | sa-17 381 | sa-21 382 | sa-22 383 | sc-1 384 | sc-2 385 | sc-3 386 | sc-3.2 387 | sc-4 388 | sc-5 389 | sc-5.2 390 | sc-5.3 391 | sc-7 392 | sc-7.3 393 | sc-7.4 394 | sc-7.5 395 | sc-7.7 396 | sc-7.8 397 | sc-7.10 398 | sc-7.11 399 | sc-7.12 400 | sc-7.14 401 | sc-7.17 402 | sc-7.22 403 | sc-7.24 404 | sc-8 405 | sc-8.1 406 | sc-10 407 | sc-12 408 | sc-12.1 409 | sc-13 410 | sc-15 411 | sc-17 412 | sc-18 413 | sc-18.4 414 | sc-20 415 | sc-21 416 | sc-22 417 | sc-23 418 | sc-24 419 | sc-28 420 | sc-28.1 421 | sc-39 422 | si-1 423 | si-2 424 | si-2.2 425 | si-3 426 | si-4 427 | si-4.1 428 | si-4.2 429 | si-4.4 430 | si-4.5 431 | si-4.10 432 | si-4.11 433 | si-4.12 434 | si-4.13 435 | si-4.14 436 | si-4.16 437 | si-4.18 438 | si-4.20 439 | si-4.22 440 | si-4.23 441 | si-5 442 | si-5.1 443 | si-6 444 | si-7 445 | si-7.1 446 | si-7.2 447 | si-7.5 448 | si-7.7 449 | si-7.15 450 | si-8 451 | si-8.2 452 | si-10 453 | si-11 454 | si-12 455 | si-12.1 456 | si-12.2 457 | si-12.3 458 | si-16 459 | si-18 460 | si-18.4 461 | si-19 462 | sr-1 463 | sr-2 464 | sr-2.1 465 | sr-3 466 | sr-4 467 | sr-4.2 468 | sr-5 469 | sr-5.2 470 | sr-6 471 | sr-8 472 | sr-9 473 | sr-9.1 474 | sr-10 475 | sr-11 476 | sr-11.1 477 | sr-11.2 478 | sr-12 479 | 480 | 481 | 482 | -------------------------------------------------------------------------------- /ODP-extract/ars-5.0-low-control-profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CMS ARS 5.0 Low Control Profile 6 | 2022-08-26T14:49:07.559731Z 7 | 2022-08-26T14:49:07.559731Z 8 | 1.0.4 9 | 10 | 11 | 12 | 13 | ac-1 14 | ac-2 15 | ac-3 16 | ac-7 17 | ac-8 18 | ac-14 19 | ac-17 20 | ac-18 21 | ac-19 22 | ac-20 23 | ac-22 24 | at-1 25 | at-2 26 | at-2.2 27 | at-3 28 | at-4 29 | au-1 30 | au-2 31 | au-3 32 | au-4 33 | au-5 34 | au-6 35 | au-8 36 | au-9 37 | au-11 38 | au-12 39 | ca-1 40 | ca-2 41 | ca-3 42 | ca-5 43 | ca-6 44 | ca-7 45 | ca-7.4 46 | ca-9 47 | cm-1 48 | cm-2 49 | cm-4 50 | cm-5 51 | cm-6 52 | cm-7 53 | cm-8 54 | cm-10 55 | cm-11 56 | cp-1 57 | cp-2 58 | cp-3 59 | cp-4 60 | cp-9 61 | cp-10 62 | ia-1 63 | ia-2 64 | ia-2.1 65 | ia-2.2 66 | ia-2.8 67 | ia-2.12 68 | ia-4 69 | ia-5 70 | ia-5.1 71 | ia-6 72 | ia-7 73 | ia-8 74 | ia-8.1 75 | ia-8.2 76 | ia-8.4 77 | ia-11 78 | ir-1 79 | ir-2 80 | ir-4 81 | ir-5 82 | ir-6 83 | ir-7 84 | ir-8 85 | ma-1 86 | ma-2 87 | ma-4 88 | ma-5 89 | mp-1 90 | mp-2 91 | mp-6 92 | mp-7 93 | pe-1 94 | pe-2 95 | pe-3 96 | pe-6 97 | pe-8 98 | pe-12 99 | pe-13 100 | pe-14 101 | pe-15 102 | pe-16 103 | pl-1 104 | pl-2 105 | pl-4 106 | pl-4.1 107 | pl-10 108 | pl-11 109 | pm-1 110 | pm-2 111 | pm-3 112 | pm-4 113 | pm-5 114 | pm-5.1 115 | pm-6 116 | pm-7 117 | pm-7.1 118 | pm-8 119 | pm-9 120 | pm-10 121 | pm-11 122 | pm-12 123 | pm-13 124 | pm-14 125 | pm-15 126 | pm-16 127 | pm-16.1 128 | pm-17 129 | pm-18 130 | pm-19 131 | pm-20 132 | pm-20.1 133 | pm-21 134 | pm-22 135 | pm-23 136 | pm-24 137 | pm-25 138 | pm-26 139 | pm-27 140 | pm-28 141 | pm-29 142 | pm-30 143 | pm-30.1 144 | pm-31 145 | pm-32 146 | ps-1 147 | ps-2 148 | ps-3 149 | ps-4 150 | ps-5 151 | ps-6 152 | ps-7 153 | ps-8 154 | ps-9 155 | ra-1 156 | ra-2 157 | ra-3 158 | ra-3.1 159 | ra-5 160 | ra-5.2 161 | ra-5.11 162 | ra-7 163 | sa-1 164 | sa-2 165 | sa-3 166 | sa-4 167 | sa-4.10 168 | sa-5 169 | sa-8 170 | sa-9 171 | sa-22 172 | sc-1 173 | sc-5 174 | sc-7 175 | sc-12 176 | sc-13 177 | sc-15 178 | sc-20 179 | sc-21 180 | sc-22 181 | sc-39 182 | si-1 183 | si-2 184 | si-3 185 | si-4 186 | si-5 187 | si-12 188 | sr-1 189 | sr-2 190 | sr-2.1 191 | sr-3 192 | sr-5 193 | sr-8 194 | sr-10 195 | sr-11 196 | sr-11.1 197 | sr-11.2 198 | sr-12 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /ODP-extract/ars-5.0-moderate-control-profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CMS ARS 5.0 Moderate Control Profile 6 | 2022-08-26T14:49:07.559731Z 7 | 2022-08-26T14:49:07.559731Z 8 | 1.0.4 9 | 10 | 11 | 12 | 13 | ac-1 14 | ac-2 15 | ac-2.1 16 | ac-2.2 17 | ac-2.3 18 | ac-2.4 19 | ac-2.5 20 | ac-2.13 21 | ac-3 22 | ac-3.14 23 | ac-4 24 | ac-5 25 | ac-6 26 | ac-6.1 27 | ac-6.2 28 | ac-6.5 29 | ac-6.7 30 | ac-6.9 31 | ac-6.10 32 | ac-7 33 | ac-8 34 | ac-11 35 | ac-11.1 36 | ac-12 37 | ac-14 38 | ac-17 39 | ac-17.1 40 | ac-17.2 41 | ac-17.3 42 | ac-17.4 43 | ac-18 44 | ac-18.1 45 | ac-18.3 46 | ac-19 47 | ac-19.5 48 | ac-20 49 | ac-20.1 50 | ac-20.2 51 | ac-21 52 | ac-22 53 | at-1 54 | at-2 55 | at-2.2 56 | at-2.3 57 | at-3 58 | at-3.5 59 | at-4 60 | au-1 61 | au-2 62 | au-3 63 | au-3.1 64 | au-3.3 65 | au-4 66 | au-5 67 | au-6 68 | au-6.1 69 | au-6.3 70 | au-7 71 | au-7.1 72 | au-8 73 | au-9 74 | au-9.4 75 | au-11 76 | au-12 77 | ca-1 78 | ca-2 79 | ca-2.1 80 | ca-3 81 | ca-5 82 | ca-6 83 | ca-7 84 | ca-7.1 85 | ca-7.4 86 | ca-9 87 | cm-1 88 | cm-2 89 | cm-2.2 90 | cm-2.3 91 | cm-2.7 92 | cm-3 93 | cm-3.2 94 | cm-3.4 95 | cm-4 96 | cm-4.2 97 | cm-5 98 | cm-6 99 | cm-7 100 | cm-7.1 101 | cm-7.2 102 | cm-7.5 103 | cm-8 104 | cm-8.1 105 | cm-8.3 106 | cm-9 107 | cm-10 108 | cm-11 109 | cm-12 110 | cm-12.1 111 | cp-1 112 | cp-2 113 | cp-2.1 114 | cp-2.3 115 | cp-2.8 116 | cp-3 117 | cp-4 118 | cp-4.1 119 | cp-6 120 | cp-6.1 121 | cp-6.3 122 | cp-7 123 | cp-7.1 124 | cp-7.2 125 | cp-7.3 126 | cp-8 127 | cp-8.1 128 | cp-8.2 129 | cp-9 130 | cp-9.1 131 | cp-9.8 132 | cp-10 133 | cp-10.2 134 | ia-1 135 | ia-2 136 | ia-2.1 137 | ia-2.2 138 | ia-2.8 139 | ia-2.12 140 | ia-3 141 | ia-4 142 | ia-4.4 143 | ia-5 144 | ia-5.1 145 | ia-5.2 146 | ia-5.6 147 | ia-6 148 | ia-7 149 | ia-8 150 | ia-8.1 151 | ia-8.2 152 | ia-8.4 153 | ia-11 154 | ia-12 155 | ia-12.2 156 | ia-12.3 157 | ia-12.5 158 | ir-1 159 | ir-2 160 | ir-2.3 161 | ir-3 162 | ir-3.2 163 | ir-4 164 | ir-4.1 165 | ir-5 166 | ir-6 167 | ir-6.1 168 | ir-6.3 169 | ir-7 170 | ir-7.1 171 | ir-8 172 | ir-8.1 173 | ma-1 174 | ma-2 175 | ma-3 176 | ma-3.1 177 | ma-3.2 178 | ma-3.3 179 | ma-4 180 | ma-5 181 | ma-6 182 | mp-1 183 | mp-2 184 | mp-3 185 | mp-4 186 | mp-5 187 | mp-6 188 | mp-7 189 | pe-1 190 | pe-2 191 | pe-3 192 | pe-4 193 | pe-5 194 | pe-6 195 | pe-6.1 196 | pe-8 197 | pe-9 198 | pe-10 199 | pe-11 200 | pe-12 201 | pe-13 202 | pe-13.1 203 | pe-14 204 | pe-15 205 | pe-16 206 | pe-17 207 | pl-1 208 | pl-2 209 | pl-4 210 | pl-4.1 211 | pl-8 212 | pl-9 213 | pl-10 214 | pl-11 215 | pm-1 216 | pm-2 217 | pm-3 218 | pm-4 219 | pm-5 220 | pm-5.1 221 | pm-6 222 | pm-7 223 | pm-7.1 224 | pm-8 225 | pm-9 226 | pm-10 227 | pm-11 228 | pm-12 229 | pm-13 230 | pm-14 231 | pm-15 232 | pm-16 233 | pm-16.1 234 | pm-17 235 | pm-18 236 | pm-19 237 | pm-20 238 | pm-20.1 239 | pm-21 240 | pm-22 241 | pm-23 242 | pm-24 243 | pm-25 244 | pm-26 245 | pm-27 246 | pm-28 247 | pm-29 248 | pm-30 249 | pm-30.1 250 | pm-31 251 | pm-32 252 | ps-1 253 | ps-2 254 | ps-3 255 | ps-4 256 | ps-5 257 | ps-6 258 | ps-7 259 | ps-8 260 | ps-9 261 | pt-1 262 | pt-2 263 | pt-3 264 | pt-4 265 | pt-5 266 | pt-5.2 267 | pt-6 268 | pt-6.1 269 | pt-6.2 270 | pt-7 271 | pt-7.1 272 | pt-7.2 273 | pt-8 274 | ra-1 275 | ra-2 276 | ra-3 277 | ra-3.1 278 | ra-5 279 | ra-5.2 280 | ra-5.5 281 | ra-5.11 282 | ra-7 283 | ra-8 284 | ra-9 285 | sa-1 286 | sa-2 287 | sa-3 288 | sa-4 289 | sa-4.1 290 | sa-4.2 291 | sa-4.9 292 | sa-4.10 293 | sa-5 294 | sa-8 295 | sa-8.33 296 | sa-9 297 | sa-9.2 298 | sa-10 299 | sa-11 300 | sa-15 301 | sa-15.3 302 | sa-22 303 | sc-1 304 | sc-2 305 | sc-4 306 | sc-5 307 | sc-7 308 | sc-7.3 309 | sc-7.4 310 | sc-7.5 311 | sc-7.7 312 | sc-7.8 313 | sc-7.24 314 | sc-8 315 | sc-8.1 316 | sc-10 317 | sc-12 318 | sc-13 319 | sc-15 320 | sc-17 321 | sc-18 322 | sc-20 323 | sc-21 324 | sc-22 325 | sc-23 326 | sc-28 327 | sc-28.1 328 | sc-39 329 | si-1 330 | si-2 331 | si-2.2 332 | si-3 333 | si-4 334 | si-4.2 335 | si-4.4 336 | si-4.5 337 | si-5 338 | si-7 339 | si-7.1 340 | si-7.7 341 | si-8 342 | si-8.2 343 | si-10 344 | si-11 345 | si-12 346 | si-12.1 347 | si-12.2 348 | si-12.3 349 | si-16 350 | si-18 351 | si-18.4 352 | si-19 353 | sr-1 354 | sr-2 355 | sr-2.1 356 | sr-3 357 | sr-5 358 | sr-6 359 | sr-8 360 | sr-10 361 | sr-11 362 | sr-11.1 363 | sr-11.2 364 | sr-12 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /ODP-extract/catalog2html.css: -------------------------------------------------------------------------------- 1 | 2 | thead tr { 3 | background-color: #e0e0e0; 4 | color: inherit; 5 | } 6 | 7 | thead th { 8 | vertical-align: bottom; 9 | text-align: left; 10 | white-space: normal; 11 | } 12 | 13 | thead td { 14 | } 15 | 16 | tbody tr { 17 | vertical-align: top; 18 | } 19 | 20 | tbody th { 21 | text-align: left; 22 | background-color: #e8e8e8; 23 | color: inherit; 24 | } 25 | 26 | tbody tr { 27 | background-color: #f0f0f0; 28 | color: inherit; 29 | } 30 | tbody tr.odd-row { 31 | background-color: #f0f0ff; 32 | color: inherit; 33 | } 34 | 35 | tbody td { 36 | } 37 | 38 | table.template { 39 | border: thin solid black; 40 | border-collapse: collapse; 41 | } 42 | table.template th { 43 | border: thin solid black; 44 | } 45 | table.template td { 46 | border: thin solid black; 47 | } 48 | 49 | tbody td.fillin { 50 | background-color: white; 51 | } 52 | 53 | tr.prior-revision { 54 | color: grey; 55 | } 56 | 57 | table.tr-hover tbody tr:hover { 58 | background-color: #f8f8f8; 59 | border-color: black; 60 | } 61 | 62 | 63 | tbody tr.prior-revision:hover { 64 | color: inherit; 65 | } 66 | 67 | .multirow { 68 | vertical-align: middle; 69 | } 70 | 71 | 72 | td.centered { 73 | vertical-align: middle; 74 | text-align: center; 75 | } 76 | 77 | .LMHP 78 | { 79 | /*font-weight: bold;*/ 80 | } 81 | 82 | .fr 83 | { 84 | float: right; 85 | } 86 | 87 | .revision { 88 | } 89 | 90 | .different { 91 | background-color: cornsilk; 92 | } 93 | 94 | .label { 95 | } 96 | .select { 97 | } 98 | .label, 99 | .select { 100 | /*font-variant: small-caps;*/ 101 | font-style: italic; 102 | background-color: powderblue; 103 | /*text-decoration: underline;*/ 104 | } 105 | 106 | .select > .label { 107 | text-decoration: underline; 108 | } 109 | 110 | 111 | div > div.statement { 112 | margin-left: 1em; 113 | } 114 | div > div.item { 115 | margin-left: 1em; 116 | } 117 | div.item > div.item { 118 | margin-left: 1em; 119 | } 120 | 121 | .anomaly { 122 | font-style: italic; 123 | background-color: yellow; 124 | } 125 | 126 | .withdrawn { 127 | text-decoration: line-through; 128 | } 129 | .withdrawn2 { 130 | color: grey; 131 | text-decoration: line-through; 132 | } 133 | 134 | *[title] { 135 | cursor: help; 136 | } 137 | 138 | details.ODPs { 139 | display: inline-table; 140 | vertical-align: text-top; 141 | 142 | } 143 | details[open] { 144 | /*font-size: smaller;*/ 145 | } 146 | summary { 147 | list-style: none; 148 | cursor: pointer; 149 | } 150 | 151 | details summary:after { 152 | /*content: "☟";*/ 153 | content: "⬇"; 154 | font-size: smaller; 155 | } 156 | 157 | span.TBS { 158 | font-variant: small-caps; 159 | font-style: italic; 160 | font-weight: bold; 161 | } 162 | 163 | span.match { 164 | background-color: lightgreen; 165 | } 166 | span.nomatch { 167 | background-color: lightyellow; 168 | } 169 | span.textmatch { 170 | background-color: lightskyblue; 171 | } 172 | span.partialmatch { 173 | background-color: lightyellow; 174 | } 175 | 176 | span.superscript-identifier { 177 | /*font-variant: small-caps;*/ 178 | vertical-align: super; 179 | font-family: courier, fixed, monospace; 180 | font-size: xx-small; 181 | hyphens: none; 182 | } 183 | 184 | span.boolean { 185 | font-variant: small-caps; 186 | font-family: courier, fixed, monospace; 187 | font-weight: bold; 188 | } 189 | 190 | span.guideline { 191 | font-size: smaller; 192 | } 193 | 194 | div.ars-statement { 195 | /*white-space: pre;*/ 196 | } 197 | 198 | div.element::before { 199 | position: relative; 200 | left: -1em; 201 | content: "➤"; 202 | font-size: small; 203 | } 204 | 205 | span.ODP { 206 | background-color: powderblue; 207 | } 208 | 209 | span.insert { 210 | font-size: smaller; 211 | font-family: courier, fixed, monospace; 212 | } 213 | 214 | ul.statement-odp-list { 215 | margin-top: 0; 216 | } 217 | 218 | span.regex-group, 219 | span.analysis-string { 220 | font-family: courier, fixed, monospace; 221 | font-size: smaller; 222 | } 223 | table.analysis { 224 | margin-left: 1em; 225 | } 226 | .missing { 227 | background-color: orange; 228 | } 229 | .novel { 230 | background-color: orange; 231 | } 232 | 233 | .novel-ODP { 234 | text-decoration: underline; 235 | text-decoration-color: orange; 236 | } 237 | .established-ODP { 238 | text-decoration: none; 239 | } 240 | .comparison { 241 | text-align: right; 242 | } 243 | 244 | .param_id { 245 | font-family: courier, fixed, monospace; 246 | font-size: smaller; 247 | } 248 | 249 | .id { 250 | font-family: monospace; 251 | } 252 | 253 | .center { 254 | text-align: center; 255 | } 256 | 257 | caption { 258 | font-weight: bold; 259 | } 260 | 261 | blockquote { 262 | background: #f9f9f9; 263 | border-left: 10px solid #ccc; 264 | margin: 1.5em 10px; 265 | padding: 0.5em 10px; 266 | quotes: "\201C" "\201D" "\2018" "\2019"; 267 | width: 50%; 268 | } 269 | blockquote:before { 270 | color: #ccc; 271 | content: open-quote; 272 | font-size: 4em; 273 | line-height: 0.1em; 274 | margin-right: 0.25em; 275 | vertical-align: -0.4em; 276 | } 277 | blockquote p { 278 | display: inline; 279 | } 280 | 281 | div.comparison-example { 282 | margin-left: 5%; 283 | margin-right: 5%; 284 | } 285 | 286 | .semantic-error { 287 | text-decoration: underline; 288 | text-decoration-color: sandybrown; 289 | } 290 | .semantic-error::before { 291 | background-color: sandybrown; 292 | content: "faux pas ☛ "; 293 | } 294 | 295 | div.trailer > p { 296 | font-size: xx-small; 297 | max-width: 85ex; 298 | text-align: center; 299 | text-transform: uppercase; 300 | margin-left: auto; 301 | margin-right: auto; 302 | font-family: monospace; 303 | color: #888; 304 | background-color: inherit; 305 | line-height: 120% 306 | } -------------------------------------------------------------------------------- /ODP-extract/catalog2html.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | CMS ARS 5.0 control catalog 40 | 41 | 42 | 43 | 44 | 45 | 46 | {$document-title} 47 | 48 | 49 | 50 | 51 | 52 | 53 |

{$document-title}

54 | 55 |

This document will be frequently updated. This update was produced {format-dateTime($UTC-datetime, '[F] [MNn] [D1] [Y] at 56 | [H01]:[m01]:[s01]Z')}. The transform used to produce the report was {static-base-uri() ! tokenize(., 57 | '/')[last()]}.

58 | 59 |

The version of the ARS OSCAL catalog used is {//metadata/version}.

60 |

The version of the {$ODP-low//metadata/title} used is {$ODP-low//metadata/version}.

61 |

The version of the {$ODP-moderate//metadata/title} used is {$ODP-moderate//metadata/version}.

62 |

The version of the {$ODP-high//metadata/title} used is {$ODP-high//metadata/version}.

63 |

The version of the {$ODP-hva//metadata/title} used is {$ODP-hva//metadata/version}.

64 | 65 | 66 | 67 | 68 | 69 |
70 |
71 |

Revised

72 |
73 | 74 | 75 | 76 | 77 |
78 | 79 | 80 | 81 |

ODP Template

82 | 83 |

The following table shows ODP values for Low {$BL}, Moderate {$BM}, High {$BH}, and HVA {$BV} baselines.

84 | 85 |

ODPs with missing values appear as ❓.

86 | 87 |

Control details are here.

88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 136 | 144 | 147 | 150 | 151 | 152 | 153 | 154 | 155 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 182 | 185 | 186 | 187 | 188 | 189 | 190 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 |
ODPs from ARS profiles
NIST SP 800-53rev5 OSCAL Catalog OriginDefined Baseline Values
Control
Label
BaselinesODP IDODP "Label"LowModerateHighHVA
134 | {$control/prop[@name eq 'label'][not(@class)]/@value} 135 | 137 |
138 | {$BL} 139 | {$BM} 140 | {$BH} 141 | {$BV} 142 |
143 |
145 | {@id} 146 | 148 | 149 | 156 | 159 | 160 | 163 | {$baseline//set-parameter[@param-id eq $param/@id]/value} 164 | 165 | 166 | center 167 | 168 | 169 | 170 | 171 |
180 | {@id} 181 | 183 | 184 | 191 | 194 | 195 | 198 | {$baseline//set-parameter[@param-id eq $param/@id]/value} 199 | 200 | 201 | center 202 | 203 | 204 | 205 | 206 |
221 | 222 |
223 | 224 | 225 | 226 |

ARS ODPs in situ

227 | 228 |

The following table shows ARS OSCAL catalog controls which appear in baselines (there are {count(//control[@id = $ODP-hva//with-id])} 229 | controls and control enhancements).

230 | 231 |

The Low {$BL}, Moderate {$BM}, High {$BH}, and HVA {$BV} baselines have {count(//control[@id = $ODP-low//with-id])}, {count(//control[@id = 232 | $ODP-moderate//with-id])}, {count(//control[@id = $ODP-high//with-id])}, and {count(//control[@id = $ODP-hva//with-id])} controls 233 | respectively.

234 | 235 |

The ⬇ symbol appears when ODPs lack definition or vary by baseline. Click on the ODP too see the baseline values.

236 | 237 |

A single value is displayed when all baseline values are 238 | identical.

239 | 240 |

➤ denotes a top-level control statement (element) - one for which an individual control implementation response is required. The Low 241 | {$BL}, Moderate {$BM}, High {$BH}, and HVA {$BV} baselines have {count(//control[@id = $ODP-low//with-id]/part[@name eq 242 | 'statement']//prop[@class eq 'ARS' and @name eq 'label'])}, {count(//control[@id = $ODP-moderate//with-id]/part[@name eq 243 | 'statement']//prop[@class eq 'ARS' and @name eq 'label'])}, {count(//control[@id = $ODP-high//with-id]/part[@name eq 244 | 'statement']//prop[@class eq 'ARS' and @name eq 'label'])}, and {count(//control[@id = $ODP-hva//with-id]/part[@name eq 245 | 'statement']//prop[@class eq 'ARS' and @name eq 'label'])} elements respectively.

246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 285 | 286 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 |
ODPs in situ
ControlNIST 800-53 Statements
275 |
276 | 277 |
278 |
279 | {$BL} 280 | {$BM} 281 | {$BH} 282 | {$BV} 283 |
284 |
287 | 288 |
289 | 290 | 291 | | 292 | 293 | 294 |
295 | 296 |
297 | 298 | 299 | 300 |
301 | 302 |
311 | 312 |
313 | 314 | 315 | 316 | 317 |
318 | 319 | 320 | 321 | 322 |
323 |
324 | 325 |
326 | 327 | 328 | 329 |
330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 |
338 |
339 | 340 | 341 | {@value} 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | oscal-{local-name()} 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | {$vl} 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | {$vm} 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | {$vh} 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | {$vv} 418 | 419 | 420 |
421 | 422 | true 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | {$BL}: {$ODP-low//set-parameter[@param-id eq $id]/value} 431 | 432 | 433 | {$BL}: (Not defined) 434 | 435 | 436 | 437 | 438 | {$BM}: {$ODP-moderate//set-parameter[@param-id eq $id]/value} 439 | 440 | 441 | {$BM}: (Not defined) 442 | 443 | 444 | 445 | 446 | {$BH}: {$ODP-high//set-parameter[@param-id eq $id]/value} 447 | 448 | 449 | {$BH}: (Not defined) 450 | 451 | 452 | 453 | 454 | {$BV}: {$ODP-hva//set-parameter[@param-id eq $id]/value} 455 | 456 | 457 | {$BV}: (Not defined) 458 | 459 | 460 | 461 | 462 | 463 |
464 |
465 | 466 |
467 |
468 |
469 |
470 | 471 | 472 |
473 | 474 | 475 | 476 | 477 | 478 |
479 | 480 |
481 | 482 | 483 | Unsupported insert type {@type}. 484 | 485 | 486 |
487 | 488 |
489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | Unsupported insert type {@typoe}. 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | label 511 | 512 | 513 | select 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | [ 522 | 523 | ] 524 | 525 | 526 | 527 | 528 | Assignment: {.} 529 | 530 | 531 | 532 | 533 | 534 | Selection (one or more): 535 | 536 | 537 | Selection: 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | ; 548 | 549 | 550 | or 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 |
570 | -------------------------------------------------------------------------------- /ODP-extract/generate-profiles.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | href="https://github.com/usnistgov/OSCAL/raw/v1.0.4/xml/schema/oscal_complete_schema.xsd" schematypens="http://www.w3.org/2001/XMLSchema" title="OSCAL complete schema" 44 | 45 | 46 | 47 | 48 | CMS ARS 5.0 {current()} Profile 49 | {$UTC-datetime} 50 | {$UTC-datetime} 51 | 1.0.4 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | {normalize-space(Low)} 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {normalize-space(Moderate)} 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | {normalize-space(High)} 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | {normalize-space(HVA)} 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /ODP-extract/miscellaneous-reports.css: -------------------------------------------------------------------------------- 1 | 2 | thead tr { 3 | background-color: #e0e0e0; 4 | color: inherit; 5 | } 6 | 7 | thead th { 8 | vertical-align: bottom; 9 | text-align: left; 10 | white-space: normal; 11 | } 12 | 13 | thead td { 14 | } 15 | 16 | tbody tr { 17 | vertical-align: top; 18 | } 19 | 20 | tbody th { 21 | text-align: left; 22 | background-color: #e8e8e8; 23 | color: inherit; 24 | } 25 | 26 | tbody tr { 27 | background-color: #f0f0f0; 28 | color: inherit; 29 | } 30 | tbody tr.odd-row { 31 | background-color: #f0f0ff; 32 | color: inherit; 33 | } 34 | 35 | tbody td { 36 | } 37 | 38 | tr.prior-revision { 39 | color: grey; 40 | } 41 | 42 | table.tr-hover tbody tr:hover { 43 | background-color: #f8f8f8; 44 | border-color: black; 45 | } 46 | 47 | 48 | tbody tr.prior-revision:hover { 49 | color: inherit; 50 | } 51 | 52 | .multirow { 53 | vertical-align: middle; 54 | } 55 | 56 | 57 | td.centered { 58 | vertical-align: middle; 59 | text-align: center; 60 | } 61 | 62 | .LMHP 63 | { 64 | /*font-weight: bold;*/ 65 | } 66 | 67 | .fr 68 | { 69 | float: right; 70 | } 71 | 72 | .revision { 73 | } 74 | 75 | .different { 76 | background-color: cornsilk; 77 | } 78 | 79 | .label { 80 | } 81 | .select { 82 | } 83 | .label, 84 | .select { 85 | /*font-variant: small-caps;*/ 86 | font-style: italic; 87 | background-color: powderblue; 88 | /*text-decoration: underline;*/ 89 | } 90 | 91 | 92 | div > div.statement { 93 | margin-left: 1em; 94 | } 95 | div > div.item { 96 | margin-left: 1em; 97 | } 98 | div.item > div.item { 99 | margin-left: 1em; 100 | } 101 | 102 | .anomaly { 103 | font-style: italic; 104 | background-color: yellow; 105 | } 106 | 107 | .withdrawn { 108 | text-decoration: line-through; 109 | } 110 | .withdrawn2 { 111 | color: grey; 112 | text-decoration: line-through; 113 | } 114 | 115 | *[title] { 116 | cursor: help; 117 | } 118 | 119 | details.ODPs { 120 | display: inline-table; 121 | vertical-align: text-top; 122 | 123 | } 124 | details[open] { 125 | /*font-size: smaller;*/ 126 | } 127 | summary { 128 | list-style: none; 129 | cursor: pointer; 130 | } 131 | 132 | details summary:after { 133 | /*content: "☟";*/ 134 | content: "⬇"; 135 | font-size: smaller; 136 | } 137 | 138 | span.TBS { 139 | font-variant: small-caps; 140 | font-style: italic; 141 | font-weight: bold; 142 | } 143 | 144 | span.match { 145 | background-color: lightgreen; 146 | } 147 | span.nomatch { 148 | background-color: lightyellow; 149 | } 150 | span.textmatch { 151 | background-color: lightskyblue; 152 | } 153 | span.partialmatch { 154 | background-color: lightyellow; 155 | } 156 | 157 | .title-mismatch { 158 | background-color: yellow; 159 | } 160 | 161 | span.superscript-identifier { 162 | /*font-variant: small-caps;*/ 163 | vertical-align: super; 164 | font-family: courier, fixed, monospace; 165 | font-size: xx-small; 166 | hyphens: none; 167 | } 168 | 169 | 170 | span.subscript-identifier { 171 | /*font-variant: small-caps;*/ 172 | vertical-align: middle; 173 | font-family: courier, fixed, monospace; 174 | font-size: x-small; 175 | hyphens: none; 176 | } 177 | 178 | span.boolean { 179 | font-variant: small-caps; 180 | font-family: courier, fixed, monospace; 181 | font-weight: bold; 182 | } 183 | 184 | span.guideline { 185 | font-size: smaller; 186 | } 187 | 188 | div.ars-statement { 189 | /*white-space: pre;*/ 190 | } 191 | 192 | span.ODP { 193 | background-color: powderblue; 194 | } 195 | 196 | span.insert { 197 | font-size: smaller; 198 | font-family: courier, fixed, monospace; 199 | } 200 | 201 | ul.statement-odp-list { 202 | margin-top: 0; 203 | } 204 | 205 | span.regex-group, 206 | span.analysis-string { 207 | font-family: courier, fixed, monospace; 208 | font-size: smaller; 209 | } 210 | table.analysis { 211 | margin-left: 1em; 212 | } 213 | .missing { 214 | background-color: orange; 215 | } 216 | .novel { 217 | background-color: orange; 218 | } 219 | 220 | .novel-ODP { 221 | text-decoration: underline; 222 | text-decoration-color: orange; 223 | } 224 | .established-ODP { 225 | text-decoration: none; 226 | } 227 | .comparison { 228 | text-align: right; 229 | } 230 | 231 | .param_id { 232 | font-family: courier, fixed, monospace; 233 | font-size: smaller; 234 | } 235 | 236 | .id { 237 | font-family: monospace; 238 | } 239 | 240 | .center { 241 | text-align: center; 242 | } 243 | 244 | caption { 245 | font-weight: bold; 246 | } 247 | 248 | blockquote { 249 | background: #f9f9f9; 250 | border-left: 10px solid #ccc; 251 | margin: 1.5em 10px; 252 | padding: 0.5em 10px; 253 | quotes: "\201C" "\201D" "\2018" "\2019"; 254 | width: 50%; 255 | } 256 | blockquote:before { 257 | color: #ccc; 258 | content: open-quote; 259 | font-size: 4em; 260 | line-height: 0.1em; 261 | margin-right: 0.25em; 262 | vertical-align: -0.4em; 263 | } 264 | blockquote p { 265 | display: inline; 266 | } 267 | 268 | div.comparison-example { 269 | margin-left: 5%; 270 | margin-right: 5%; 271 | } 272 | 273 | .semantic-error { 274 | text-decoration: underline; 275 | text-decoration-color: sandybrown; 276 | } 277 | .semantic-error::before { 278 | background-color: sandybrown; 279 | content: "faux pas ☛ "; 280 | } 281 | 282 | div.trailer > p { 283 | font-size: xx-small; 284 | max-width: 85ex; 285 | text-align: center; 286 | text-transform: uppercase; 287 | margin-left: auto; 288 | margin-right: auto; 289 | font-family: monospace; 290 | color: #888; 291 | background-color: inherit; 292 | line-height: 120% 293 | } -------------------------------------------------------------------------------- /ODP-extract/miscellaneous-reports.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 33 | 35 | 37 | 38 | 39 | 40 | NIST SP 800-53r5 Controls 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {$document-title} 49 | 50 | 51 | 52 | 53 | 54 |

This document was produced {format-dateTime($UTC-datetime, '[F] [MNn] [D1] [Y] at [H01]:[m01]:[s01]Z')}.

55 |

The transform used to produce the report was {static-base-uri() ! tokenize(., '/')[last()]}.

56 |

Input to the transform was {base-uri()}.

57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
65 | 66 | 67 | 68 | 69 | 70 |

800-53 rev5 Control Title Mismatches

71 |

This is a comparison of control and control enhancement titles found in

72 |
    73 |
  • NIST SP 800-53 revision 5 OSCAL control catalog (found here) version {//metadata/version}
  • 76 |
  • NIST SP 800-53 revision 5 control catalog spreadsheet (found here)
  • 78 |
  • NIST SP 800-53b (revision 5) control baselines spreadsheet (found here)
  • 80 |
81 |

The OSCAL control enhancement titles are synthesized to match those found in the spreadsheets.

82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | {parent::control/title} | {title} 95 | 96 | 97 | {title} 98 | 99 | 100 | 101 | 104 | 107 | 108 | 109 | 110 | 111 | 132 | 133 | 134 | 135 | 136 |
ControlVarious 800-53 Titles
{prop[@name eq 'label' and not(@class)]/@value} 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
Mismatch
OSCAL catalog{$o}
800-53 spreadsheet{$c}
800-53b spreadsheet{$b}
131 |
137 | 138 |
139 | 140 | 141 |

ARS Control "Spreadsheet"

142 |

The following table shows ARS controls in "spreadsheet" fashion. Row numbers correspond to those in the ARS 5.01 xlsx document.

143 |

Control titles which do not match those in NIST SP 800-53 rev5 OSCAL catalog are highlighted thus.

144 |

There is no need to apply manual corrections to the ARS 5.01 spreadsheet! Such errors will be removed during ARS OSCAL 145 | content generation.

146 |

NB: There are some NIST OSCAL catalog which are patently incorrect. SR-2(1) is an example. These errors have been reported 147 | here.

148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 202 | 203 | 204 | 205 | 206 |
ARS ControlNIST
RowFamilyNumberNameTitle
{2 + position()}{Control_Family}{Control_Number} 178 | 179 | 180 | 181 |
{Control_Name}
182 |
183 | 184 |
185 | {Control_Name} 186 | 187 | 188 | (upper-lower case mismatch) 189 | 190 | 191 | (trailing space in title) 192 | 193 | 194 | (trailing non-breaking space in title) 195 | 196 | 197 | 198 |
199 |
200 |
201 |
{$nc/*:title}
207 |
208 | 209 | 210 |

Control title mismatches are highlighted thus.

211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 223 | 224 | 225 | 226 | 227 | 229 | 230 | 231 | 254 | 262 | 278 | 290 | 291 | 292 | 293 |
800-53
Control
ID
TitleARS
Control
ID
ResponsibilityStatement
IDs
{@id} 232 |
{title}
233 | 234 | 235 |
236 | ARS mismatch « 237 | {$ars-xref/*:Control_Name} 238 | » 239 | 240 | 241 | (trailing space in title) 242 | 243 | 244 | (trailing non-breaking space in title) 245 | 246 | 247 | (upper-lower case mismatch) 248 | 249 | 250 |
251 |
252 |
253 |
255 | 256 | {prop[@name eq 'label' and @class]/@value} 257 | 258 | missing 259 | 260 | 261 | 263 | 264 | {@id} {$ars-xref/Control_Number} 265 | 266 | 267 | 268 | 269 | 270 |
{.}
271 |
272 |
273 | 274 | missing 275 | 276 |
277 |
279 | 280 | 281 | {part[@name eq 'statement']/@id} 282 | 283 | 284 | 285 |
{@id}
286 |
287 |
288 |
289 |
294 |
295 | 296 | 297 | 298 |

Control, Statement, and ODP identifiers

299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 |
Control
ID
800-53
Label
800-53A
Label
TitleBaselines
314 | 315 |
316 | 317 | 318 | 319 | 320 | {@id} 321 | {prop[@name eq 'label' and not(@class)]/@value} 322 | {prop[@name eq 'label' and @class]/@value} 323 | 324 | 325 | 326 | {parent::control/title} | {title} 327 | 328 | 329 | {title} 330 | 331 | 332 | 333 | 334 |
335 | 800-53B: 336 | 337 | 338 | 339 | Low 340 | 341 | 342 | Moderate 343 | 344 | 345 | High 346 | 347 | 348 | 349 | not specified 350 | 351 | 352 |
353 |
354 | ARS: 355 | 356 | 357 | {$ars-xref/*:CMS_Baseline} 358 | 359 | 360 | 361 | not specified 362 | 363 | 364 | 365 |
366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 |
375 | 376 | 377 | 378 | 379 | 380 | 381 |
382 | 383 | 384 | 385 | {@id} 386 | 387 |
388 |
389 | 390 |
391 | 392 | 393 | 394 |
395 | 396 | 397 | 398 | {@id} 399 | 400 | 401 | 402 | 403 |
404 |
405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | semantic-error 413 | The input catalog contained a faux HTML <{local-name()}> element 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | {@value} 426 | 427 | 428 | 429 | 430 | 431 | {@id-ref} 432 | 433 | 434 | 435 | 436 | {@id-ref} 437 | 438 | 439 | {$p/label} 440 | 441 | 444 | {normalize-space($p/guideline)} 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | Life must end 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | [ 479 | 480 | Assignment: 481 | 482 | 483 | ] 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | [ 503 | 504 | 505 | 506 | Selection (one or more): 507 | 508 | 509 | ; 510 | 511 | 512 | 513 | 514 | 515 | Selection: 516 | 517 | 518 | or 519 | 520 | 521 | 522 | 523 | 524 | 525 | ] 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 |
537 | -------------------------------------------------------------------------------- /ODP-extract/profile.sch: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | with-id target 23 | control exists in catalog. 24 | 25 | 26 | 27 | 28 | 29 | set-parameter target param exists in 30 | catalog. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Control does not exist in the catalog. (). 40 | 41 | 42 | set-parameter target does not exist in the catalog. 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /ODP-extract/random-util.xsl: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | { r:make-uuid(current-dateTime()) } 40 | { r:make-uuid($germ) } 41 | { r:make-uuid('a') } 42 | { r:make-uuid('a') } 43 | { r:make-uuid('b') } 44 | 45 | 46 | { . } 47 | 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 64 | 65 | 66 | ________-____-4___-=___-____________ 67 | 68 | 69 | 70 | 71 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Acceptable Risk Safeguards # 2 | 3 | ## About ## 4 | 5 | This is the Centers for Medicare & Medicaid Services repository that provides the Acceptable Risk Safeguards (ARS) in machine-readable format to support compliance as code initiatives. 6 | 7 | We believe compliance activity at the scale of CMS requires automation to be successful and repeatable. Compliance as Code standards like OSCAL allow teams to bridge between the "Governance" layer and operational tools. With this repository, CMS aims to support innovative teams in leveraging automation to improve the CMS security posture and reduce the burden of compliance. 8 | 9 | ## What are ARS? ## 10 | ARS are the Acceptable Risk Safeguards used to define a baseline of minimum information security and privacy assurance controls at CMS. These controls are based on both internal CMS governance documents and laws, regulations, and other authorities created by institutions external to CMS. Protecting and ensuring the confidentiality, integrity, and availability for all of CMS’ information and information systems is the primary purpose of the information security and privacy assurance program. The ARS complies with the CMS guidelines by providing a defense-in-depth security structure along with a least-privilege, need-to-know basis for all information access. CMS updates ARS to keep up with the latest risk safeguards and these come in the form or 11 | 12 | ## ARS Versions ## 13 | As ARS are updated, are numbered, with the highest number being the latest release. We provide formats 14 | CMS has adopted NIST's OSCAL standard for Compliance as Code. 15 | 16 | ## Using this ## 17 | If you're looking to ship software to production at CMS, your system will need to comply with ARS controls. Product teams looking to automate compliance (including but not limited to automatically generating their System Security Plans) can use these machine-readable ARS controls to support their efforts. 18 | 19 | ## Contribution ## 20 | This repository is updated in an automated fashion. CMS is not actively monitoring this repository for pull requests or issues at this time. For inquiries, please refer to the contact section of this document. 21 | 22 | ## Contact ## 23 | CISO@cms.hhs.gov 24 | -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/README.md: -------------------------------------------------------------------------------- 1 | # Convert ARS Spreadsheets to OSCAL (JSON) 2 | 3 | Parse an ARS spreadsheet and output JSON formatted OSCAL Catalog. 4 | 5 | ## Source files 6 | 7 | From: https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 8 | 9 | * ARS_3-1_Excel_Export.xlsx (deprecated) 10 | * [ARS Full Element Principle_Single_Assessment_Current V5.01.xlsx](https://dkanreserve.prod.acquia-sites.com/sites/default/files/Main%20Library%20Documents/ARS%20Full%20Element%20Principle_Single_Assessment_Current%20V5.01.xlsx) 11 | 12 | ## Signature 13 | 14 | ```bash 15 | $ poetry run python catalog50.py --help 16 | Usage: catalog50.py [OPTIONS] SOURCE 17 | 18 | Create an OSCAL Catalog from Excel (.xlsx) spreadsheet. Source: 19 | https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 20 | 21 | Options: 22 | -t, --title TEXT [required] 23 | -a, --ars_version TEXT ARS version [default: 5.01] 24 | -o, --oscal_version TEXT OSCAL version [default: 1.0.2] 25 | -m, --minimize Minimize output: no PII or HVA overlays. 26 | --help Show this message and exit. 27 | ``` 28 | 29 | ## Example run 30 | 31 | ```bash 32 | $ poetry run python catalog50.py -t CMS_ARS_5_01_catalog ../../ARS\ Full\ Element\ Principle_Single_Assessment_Current\ V5.01.xlsx > ../5.0/oscal/CMS_ARS_5_01_catalog.json 33 | ``` 34 | 35 | ## To do 36 | 37 | * Some errors in the spreadsheet can't be automatically corrected: 38 | * line 332 : column J should be blank (now contains "HVA") 39 | * line 833 : `CP-09(07)` should be `CP-09(08)` 40 | * _There may be others..._ 41 | * May need to manually add a `T` separator to the `"last-modified"` value on line 6 of the output JSON catalog. 42 | -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/catalog31.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | from datetime import datetime, timezone 4 | from pathlib import Path 5 | from uuid import uuid4 6 | 7 | import click 8 | import openpyxl 9 | from trestle.oscal.catalog import Catalog, Control, Group, Model 10 | from trestle.oscal.common import Link, Metadata, Part, Property, Role 11 | 12 | from complianceio.oscal.oscal import control_to_statement_id 13 | 14 | import logging 15 | import sys 16 | 17 | # set to INFO or DEBUG for more verbose logging (ERROR for none) 18 | logging.basicConfig(stream=sys.stdout, level=logging.ERROR) 19 | 20 | ''' 21 | Convert ARS 3.1 spreadsheet into OSCAL code 22 | SOURCE: https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 23 | ARS_3-1_Excel_Export.xlsx 24 | 25 | Todo: 26 | * fix isoformat() -- missing sep='T' 27 | * add debug arguments 28 | * handle Redacted links 29 | * add Organization Defined Parameters (ODPs) 30 | ''' 31 | 32 | 33 | def create_groups(p, impact_level, supplemental): 34 | """ 35 | Parse the spreadsheet to get groups by family. 36 | """ 37 | with open(Path.cwd().joinpath('header31_map.json'), 'r') as f: 38 | c_map = json.load(f) 39 | wb = openpyxl.load_workbook(filename=p, data_only=True) 40 | if "Sheet1" not in wb.sheetnames: 41 | print(f"Sheetname 'Sheet1' not found in: {wb.sheetnames}") 42 | quit() 43 | ws = wb["Sheet1"] 44 | # header = [cell for cell in ws['A2:XFD2'][0] 45 | # if cell.value is not None and cell.value.strip() != ''] 46 | groups = [] 47 | family_id = None 48 | group = None 49 | controls = [] 50 | for row in ws.iter_rows(min_row=2, max_col=19, max_row=1890): 51 | if row[0].value is not None: 52 | family = row[c_map.get('family')].value 53 | control_id = row[c_map.get('control_id')].value 54 | group = control_id[:2].lower() 55 | name = row[c_map.get('name')].value.strip() 56 | control_text = row[c_map.get('control')].value 57 | # responsibility = row[c_map.get('responsiblity')].value 58 | related = row[c_map.get('related')].value 59 | # reference = row[c_map.get('reference')].value 60 | baseline = row[c_map.get('baseline')].value 61 | priority = row[c_map.get('priority')].value 62 | 63 | # Non-mandatory controls 64 | if baseline is None: 65 | if supplemental: 66 | baseline = "Supplemental" 67 | else: 68 | continue 69 | if impact_level not in baseline: 70 | continue 71 | 72 | # check for ac--09(02) 73 | control_id = control_id.replace('--', '-') 74 | # check for AU14-(01) 75 | control_id = re.sub(r'([A-Z][A-Z])([0-9][0-9])\-', r"\1-\2", control_id) 76 | 77 | if family_id is not None and family != family_id: 78 | g = add_group(group_id, family_id, controls) 79 | groups.append(g) 80 | controls = [] 81 | 82 | if control_text is not None: 83 | cid = control_to_statement_id(control_id) 84 | parts = [] 85 | part = parse_parts(control_text, cid) 86 | parts.append(part) 87 | 88 | imp = row[c_map.get('implementation')].value 89 | if imp and imp.strip(): 90 | pid = cid.replace('_smt', '_imp') 91 | part = add_additional(pid, 'implementation', imp.strip()) 92 | parts.append(part) 93 | 94 | gdn = row[c_map.get('discussion')].value 95 | if gdn and gdn.strip(): 96 | pid = cid.replace('_smt', '_gdn') 97 | part = add_additional(pid, 'guidance', gdn.strip()) 98 | parts.append(part) 99 | 100 | links = [] 101 | related = row[c_map.get('related')].value 102 | if related and related.strip(): 103 | rlt = related.strip().replace(' ', ',').split(',') 104 | for r in rlt: 105 | if r[:4] != 'None': 106 | link = r.strip() 107 | if link: 108 | # clean up Redacted links 109 | if "Redacted" in link: 110 | continue 111 | links.append(Link( 112 | href=f'#{link}', 113 | rel='related' 114 | )) 115 | l = links if len(links) > 0 else None 116 | 117 | props = [ 118 | Property( 119 | name='label', 120 | value=control_id 121 | ), 122 | Property( 123 | name='sort-id', 124 | value=control_id.lower() 125 | ) 126 | ] 127 | if "Supplemental" in baseline: 128 | control_class = "ARS-3.1-Non-Mandatory" 129 | else: 130 | control_class = "ARS-3.1-Mandatory" 131 | props.append( 132 | Property( 133 | name='baseline', 134 | value=str(baseline.replace('\n', ',').rstrip(',')) 135 | ) 136 | ) 137 | if priority and priority.strip(): 138 | props.append( 139 | Property( 140 | name='priority', 141 | value=priority.strip() 142 | ) 143 | ) 144 | controls.append(Control( 145 | id=cid.split('_')[0], 146 | class_=control_class, 147 | title=name, 148 | props=props, 149 | links=l, 150 | parts=parts, 151 | )) 152 | family_id = family 153 | group_id = group 154 | 155 | g = add_group(group_id, family, controls) 156 | groups.append(g) 157 | return groups 158 | 159 | 160 | def add_group(group_id, family, controls): 161 | return Group( 162 | id=group_id, 163 | class_='family', 164 | title=family, 165 | controls=controls 166 | ) 167 | 168 | 169 | def parse_parts(text, cid): 170 | """ 171 | This is very specific to the CMS spreadsheet. 172 | """ 173 | pt = parse_control(text, cid) 174 | parts = [] 175 | if pt: 176 | parts = create_parts(pt) 177 | 178 | part = Part( 179 | id=cid, 180 | name='statement', 181 | parts=parts, 182 | ) 183 | 184 | return part 185 | 186 | 187 | def parse_control(text, cid): 188 | """ 189 | This is looking for a very specifically formatted control statement. 190 | Top level parts should start with (LETTER), for instance (a) or a. 191 | Secondary level should start with NUMBER. for instance 1. or i. 192 | Tertiary level should start with LETTER. for instance a. 193 | As an example: 194 | (a) This is the top level 195 | a. Could also be top-level 196 | a. Could also be top-level 197 | 1. Could also be top-level 198 | 1. Some secondary text 199 | (1) Also some secondary text 200 | a. And tertiary text. 201 | """ 202 | lines = text.splitlines() 203 | parts = {cid.strip(): {'prose': None, 'children': {}}} 204 | pr = None 205 | fid = '' 206 | sid = '' 207 | for text in lines: 208 | firstdot = '' 209 | second = '' 210 | secondparen = '' 211 | third = '' 212 | first = re.search(r'^\s*\(([a-z])\)', text) # |*(a) 213 | if not first: 214 | firstdot = re.search(r'^[a-z]\.', text) # |a. 215 | if not first and not firstdot: 216 | second = re.search(r'^\s+[0-9i]+\.', text) # |(a) 1. 217 | if second and not fid: 218 | firstdot = second # | 1. 219 | if not first and not firstdot and not second: 220 | secondparen = re.search(r'^\s+\(([0-9]+)\)', text) # |(a) (1) 221 | if secondparen and not fid: 222 | first = secondparen # | (1) 223 | if not first and not firstdot and not second and not secondparen: 224 | third = re.search(r'^\s+[a-z]\.', text) # |(a) 1. a. 225 | if third and not sid: 226 | firstdot = third # | a. 227 | text = text.strip() 228 | if first: 229 | f = first.group() 230 | logging.debug(f'1-"{f}"') 231 | fid = f.replace('(', '').replace(')', '') 232 | prose = text.strip(f'({f})').strip() 233 | parts[cid.strip()]['children'][fid.strip()] = { 234 | 'prose': prose, 235 | 'children': {}, 236 | } 237 | elif firstdot: 238 | f = firstdot.group() 239 | logging.debug(f'1-"{f}"') 240 | fid = f.replace('.', '') 241 | prose = text.strip(f'{f}').strip() 242 | parts[cid.strip()]['children'][fid.strip()] = { 243 | 'prose': prose, 244 | 'children': {}, 245 | } 246 | elif second: 247 | s = second.group() 248 | logging.debug(f'2-"{s}"') 249 | sid = s.replace('.', '') 250 | prose = text.strip(f'{s}').strip() 251 | parts[cid.strip()]['children'][fid.strip()]['children'][sid.strip()] = { 252 | 'prose': prose, 253 | 'children': {}, 254 | } 255 | elif secondparen: 256 | s = secondparen.group() 257 | logging.debug(f'2-"{s}"') 258 | sid = s.replace('(', '').replace(')', '') 259 | prose = text.strip(f'{s}').strip() 260 | parts[cid.strip()]['children'][fid.strip()]['children'][sid.strip()] = { 261 | 'prose': prose, 262 | 'children': {}, 263 | } 264 | elif third: 265 | t = third.group() 266 | logging.debug(f'3-"{t}"') 267 | tid = t.replace('.', '') 268 | prose = text.strip(f'{t}').strip() 269 | parts[cid.strip()]['children'][fid.strip()]\ 270 | ['children'][sid.strip()]['children'][tid.strip()] = {'prose': prose} 271 | else: 272 | pr = f'{pr}\n{text}' if pr else text 273 | parts[cid.strip()]['prose'] = pr 274 | 275 | return parts 276 | 277 | 278 | def create_parts(parts): 279 | part = [] 280 | first = None 281 | secondary = None 282 | tertiary = None 283 | for k, pv in parts.items(): 284 | if 'children' in pv: 285 | first = [] 286 | for f, fv in pv.get('children').items(): 287 | if 'children' in fv: 288 | secondary = [] 289 | for s, sv in fv.get('children').items(): 290 | if 'children' in sv: 291 | tertiary = [] 292 | for t, tv in sv.get('children').items(): 293 | logging.info(f'{k}.{f}.{s}.{t}') 294 | tertiary.append(Part( 295 | id=f'{k}.{f}.{s}.{t}', 296 | name='item', 297 | props=[Property( 298 | name='label', 299 | value=t, 300 | )], 301 | prose=tv.get('prose') 302 | )) 303 | tp = tertiary if len(tertiary) > 0 else None 304 | logging.info(f'{k}.{f}.{s}') 305 | secondary.append(Part( 306 | id=f'{k}.{f}.{s}', 307 | name='item', 308 | props=[Property( 309 | name='label', 310 | value=s, 311 | )], 312 | parts=tp, 313 | prose=sv.get('prose'), 314 | )) 315 | sp = secondary if len(secondary) > 0 else None 316 | logging.info(f'{k}.{f}') 317 | first.append(Part( 318 | id=f'{k}.{f}', 319 | name='item', 320 | props=[Property( 321 | name='label', 322 | value=f, 323 | )], 324 | parts=sp, 325 | prose=fv.get('prose'), 326 | )) 327 | fp = first if len(first) > 0 else None 328 | logging.info(f'{k}') 329 | part.append(Part( 330 | id=f'{k}', 331 | name='item', 332 | props=[Property( 333 | name='label', 334 | value=k, 335 | )], 336 | parts=fp, 337 | prose=pv.get('prose'), 338 | )) 339 | return part 340 | 341 | 342 | def add_additional(pid, name, prose): 343 | return Part( 344 | id=pid, 345 | name=name, 346 | prose=prose, 347 | ) 348 | 349 | 350 | roles = [ 351 | Role( 352 | id="creator", 353 | title="Document creator" 354 | ), 355 | Role( 356 | id="contact", 357 | title="Contact" 358 | ) 359 | ] 360 | parties = [ 361 | { 362 | "id": "CMS-ISPG", 363 | "org": { 364 | "org-name": "Centers for Medicare & Medicaid Services Office of Information Technology (OIT)", 365 | "addresses": [ 366 | { 367 | "postal-address": [ 368 | "Information Security and Privacy Group 7500 Security Boulevard" 369 | ], 370 | "city": "Baltimore", 371 | "state": "MD", 372 | "postal-code": "21244-1850" 373 | } 374 | ], 375 | "email-addresses": [ 376 | "ciso@cms.hhs.gov" 377 | ] 378 | } 379 | } 380 | ] 381 | responsible_parties = { 382 | "creator": { 383 | "party-ids": [ 384 | "CMS-ISPG" 385 | ] 386 | }, 387 | "contact": { 388 | "party-ids": [ 389 | "CMS-ISPG" 390 | ] 391 | } 392 | } 393 | 394 | 395 | @click.command() 396 | @click.option('-t', '--title', required=True) 397 | @click.argument( 398 | 'source', 399 | type=click.Path(exists=True, dir_okay=False, file_okay=True, resolve_path=True) 400 | ) 401 | @click.option( 402 | "-a", 403 | "--ars_version", 404 | default="3.1", 405 | show_default=True, 406 | help="ARS version ", 407 | ) 408 | @click.option( 409 | "-o", 410 | "--oscal_version", 411 | default="1.0.2", 412 | show_default=True, 413 | help="OSCAL version ", 414 | ) 415 | @click.option( 416 | "-i", 417 | "--impact_level", 418 | default="Moderate", 419 | show_default=True, 420 | help="FISMA impact level " 421 | ) 422 | @click.option( 423 | "-s", 424 | "--supplemental", 425 | is_flag=True, 426 | help="Include supplemental (non-mandatory) controls.", 427 | ) 428 | def main(title, source, ars_version, oscal_version, impact_level, supplemental): 429 | """ 430 | Create an OSCAL Catalog from Excel (.xlsx) spreadsheet. 431 | Source: https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 432 | """ 433 | p = Path(source) 434 | groups = create_groups(p, impact_level, supplemental) 435 | uuid = uuid4().urn 436 | 437 | 438 | # today = datetime.now(timezone(timedelta(hours=-6))).isoformat(sep='T') 439 | today = datetime.now().astimezone(timezone.utc).isoformat(sep='T') 440 | 441 | # FIXME: missing 'T' separator in last-modified 442 | md = Metadata( 443 | title=title, 444 | last_modified=today, 445 | version=ars_version, 446 | oscal_version=oscal_version, 447 | roles=roles 448 | # parties=parties 449 | # responsible_parties=responsible_parties 450 | ) 451 | 452 | catalog = Catalog( 453 | uuid=uuid[9:], 454 | metadata=md, 455 | groups=groups, 456 | ) 457 | root = Model(catalog=catalog).dict(by_alias=True, exclude_unset=True, exclude_none=True) 458 | print(json.dumps(root, indent=2, default=str)) 459 | 460 | 461 | if __name__ == "__main__": 462 | main() 463 | -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/catalog50.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | from datetime import datetime, timezone 4 | from pathlib import Path 5 | from uuid import uuid4 6 | 7 | import click 8 | import openpyxl 9 | from trestle.oscal.catalog import Catalog, Control, Group, Model 10 | from trestle.oscal.common import Link, Metadata, Part, Property 11 | 12 | from complianceio.oscal.oscal import control_to_statement_id 13 | 14 | import logging 15 | import sys 16 | 17 | # set to INFO or DEBUG for more verbose logging (ERROR for none) 18 | logging.basicConfig(stream=sys.stdout, level=logging.ERROR) 19 | 20 | ''' 21 | Convert ARS 5.0 spreadsheet into OSCAL code 22 | SOURCE: https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 23 | ARS Full Element Principle_Single_Assessment_Current V5.01.xlsx 24 | 25 | Todo: 26 | * fix isoformat() -- missing sep='T' 27 | * add debug arguments 28 | * handle Redacted links 29 | * add Organization Defined Parameters (ODPs) 30 | ''' 31 | 32 | 33 | def create_groups(p, minimize): 34 | """ 35 | Parse the spreadsheet to get groups by family. 36 | """ 37 | with open(Path.cwd().joinpath('header50_map.json'), 'r') as f: 38 | c_map = json.load(f) 39 | wb = openpyxl.load_workbook(filename=p, data_only=True) 40 | if "Full" not in wb.sheetnames: 41 | print(f"Sheetname 'Full' not found in: {wb.sheetnames}") 42 | quit() 43 | ws = wb["Full"] 44 | # header = [cell for cell in ws['A2:XFD2'][0] 45 | # if cell.value is not None and cell.value.strip() != ''] 46 | groups = [] 47 | family_id = None 48 | group = None 49 | controls = [] 50 | for row in ws.iter_rows(min_row=3, max_col=19, max_row=2600): 51 | if row[0].value is not None: 52 | family = row[c_map.get('family')].value 53 | control_id = row[c_map.get('control_id')].value 54 | group = control_id[:2].lower() 55 | name = row[c_map.get('name')].value.strip() 56 | control_text = row[c_map.get('control')].value 57 | responsibility = row[c_map.get('responsiblity')].value 58 | related = row[c_map.get('responsiblity')].value 59 | reference = row[c_map.get('reference')].value 60 | baseline = row[c_map.get('baseline')].value 61 | priority = row[c_map.get('priority')].value 62 | 63 | # ignore duplicated parts (elements) 64 | if baseline is None: 65 | continue 66 | # check for HVA in element (line 332) 67 | if control_id == 'AT-02(01)a': 68 | continue 69 | # check for ac--09(02) 70 | control_id = control_id.replace('--', '-') 71 | # check for AU14-(01) 72 | control_id = re.sub(r'([A-Z][A-Z])([0-9][0-9])\-', r"\1-\2", control_id) 73 | 74 | if family_id is not None and family != family_id: 75 | g = add_group(group_id, family_id, controls) 76 | groups.append(g) 77 | controls = [] 78 | 79 | if control_text is not None: 80 | cid = control_to_statement_id(control_id) 81 | parts = [] 82 | part = parse_parts(control_text, cid) 83 | parts.append(part) 84 | 85 | imp = row[c_map.get('implementation')].value 86 | if imp and imp.strip(): 87 | pid = cid.replace('_smt', '_imp') 88 | part = add_additional(pid, 'implementation', imp.strip()) 89 | parts.append(part) 90 | 91 | if not minimize: 92 | hva = row[c_map.get('hva_standards')].value 93 | if hva and hva.strip(): 94 | pid = cid.replace('_smt', '_hva') 95 | part = add_additional(pid, 'hva', hva.strip()) 96 | parts.append(part) 97 | 98 | prv = row[c_map.get('privacy_standards')].value 99 | if prv and prv.strip(): 100 | pid = cid.replace('_smt', '_prv') 101 | part = add_additional(pid, 'privacy', prv.strip()) 102 | parts.append(part) 103 | 104 | gdn = row[c_map.get('discussion')].value 105 | if gdn and gdn.strip(): 106 | pid = cid.replace('_smt', '_gdn') 107 | part = add_additional(pid, 'guidance', gdn.strip()) 108 | parts.append(part) 109 | 110 | links = [] 111 | related = row[c_map.get('related')].value 112 | if related and related.strip(): 113 | rlt = related.strip().replace(' ', ',').split(',') 114 | for r in rlt: 115 | if r[:4] != 'None': 116 | link = r.strip() 117 | if link: 118 | # clean up Redacted links 119 | if "Redacted" in link: 120 | continue 121 | links.append(Link( 122 | href=f'#{link}', 123 | rel='related' 124 | )) 125 | l = links if len(links) > 0 else None 126 | 127 | props = [ 128 | Property( 129 | name='label', 130 | value=control_id 131 | ), 132 | Property( 133 | name='sort-id', 134 | value=control_id.lower() 135 | ), 136 | Property( 137 | name='responsibility', 138 | value=str(responsibility.replace('\n', ',').strip().rstrip(',')) 139 | ) 140 | ] 141 | if "Supplemental" in baseline: 142 | control_class = "ARS-5.0-Supplemental" 143 | else: 144 | control_class = "ARS-5.0-Mandatory" 145 | props.append( 146 | Property( 147 | name='baseline', 148 | value=str(baseline.replace('\n', ',').rstrip(',')) 149 | ) 150 | ) 151 | if priority and priority.strip(): 152 | props.append( 153 | Property( 154 | name='priority', 155 | value=priority.strip() 156 | ) 157 | ) 158 | controls.append(Control( 159 | id=cid.split('_')[0], 160 | class_=control_class, 161 | title=name, 162 | props=props, 163 | links=l, 164 | parts=parts, 165 | )) 166 | family_id = family 167 | group_id = group 168 | 169 | g = add_group(group_id, family, controls) 170 | groups.append(g) 171 | return groups 172 | 173 | 174 | def add_group(group_id, family, controls): 175 | return Group( 176 | id=group_id, 177 | class_='family', 178 | title=family, 179 | controls=controls 180 | ) 181 | 182 | 183 | def parse_parts(text, cid): 184 | """ 185 | This is very specific to the CMS spreadsheet. 186 | """ 187 | pt = parse_control(text, cid) 188 | parts = [] 189 | if pt: 190 | parts = create_parts(pt) 191 | 192 | part = Part( 193 | id=cid, 194 | name='statement', 195 | parts=parts, 196 | ) 197 | 198 | return part 199 | 200 | 201 | def parse_control(text, cid): 202 | """ 203 | This is looking for a very specifically formatted control statement. 204 | Top level parts should start with (LETTER), for instance (a) or a. 205 | Secondary level should start with NUMBER. for instance 1. or i. 206 | Tertiary level should start with LETTER. for instance a. 207 | As an example: 208 | (a) This is the top level 209 | a. Could also be top-level 210 | a. Could also be top-level 211 | 1. Could also be top-level 212 | 1. Some secondary text 213 | (1) Also some secondary text 214 | a. And tertiary text. 215 | """ 216 | lines = text.splitlines() 217 | parts = {cid.strip(): {'prose': None, 'children': {}}} 218 | pr = None 219 | fid = '' 220 | sid = '' 221 | for text in lines: 222 | firstdot = '' 223 | second = '' 224 | secondparen = '' 225 | third = '' 226 | first = re.search(r'^\s*\(([a-z])\)', text) # |*(a) 227 | if not first: 228 | firstdot = re.search(r'^[a-z]\.', text) # |a. 229 | if not first and not firstdot: 230 | second = re.search(r'^\s+[0-9i]+\.', text) # |(a) 1. 231 | if second and not fid: 232 | firstdot = second # | 1. 233 | if not first and not firstdot and not second: 234 | secondparen = re.search(r'^\s+\(([0-9]+)\)', text) # |(a) (1) 235 | if secondparen and not fid: 236 | first = secondparen # | (1) 237 | if not first and not firstdot and not second and not secondparen: 238 | third = re.search(r'^\s+[a-z]\.', text) # |(a) 1. a. 239 | if third and not sid: 240 | firstdot = third # | a. 241 | text = text.strip() 242 | if first: 243 | f = first.group() 244 | logging.debug(f'1-"{f}"') 245 | fid = f.replace('(', '').replace(')', '') 246 | prose = text.strip(f'({f})').strip() 247 | parts[cid.strip()]['children'][fid.strip()] = { 248 | 'prose': prose, 249 | 'children': {}, 250 | } 251 | elif firstdot: 252 | f = firstdot.group() 253 | logging.debug(f'1-"{f}"') 254 | fid = f.replace('.', '') 255 | prose = text.strip(f'{f}').strip() 256 | parts[cid.strip()]['children'][fid.strip()] = { 257 | 'prose': prose, 258 | 'children': {}, 259 | } 260 | elif second: 261 | s = second.group() 262 | logging.debug(f'2-"{s}"') 263 | sid = s.replace('.', '') 264 | prose = text.strip(f'{s}').strip() 265 | parts[cid.strip()]['children'][fid.strip()]['children'][sid.strip()] = { 266 | 'prose': prose, 267 | 'children': {}, 268 | } 269 | elif secondparen: 270 | s = secondparen.group() 271 | logging.debug(f'2-"{s}"') 272 | sid = s.replace('(', '').replace(')', '') 273 | prose = text.strip(f'{s}').strip() 274 | parts[cid.strip()]['children'][fid.strip()]['children'][sid.strip()] = { 275 | 'prose': prose, 276 | 'children': {}, 277 | } 278 | elif third: 279 | t = third.group() 280 | logging.debug(f'3-"{t}"') 281 | tid = t.replace('.', '') 282 | prose = text.strip(f'{t}').strip() 283 | parts[cid.strip()]['children'][fid.strip()]\ 284 | ['children'][sid.strip()]['children'][tid.strip()] = {'prose': prose} 285 | else: 286 | pr = f'{pr}\n{text}' if pr else text 287 | parts[cid.strip()]['prose'] = pr 288 | 289 | return parts 290 | 291 | 292 | def create_parts(parts): 293 | part = [] 294 | first = None 295 | secondary = None 296 | tertiary = None 297 | for k, pv in parts.items(): 298 | if 'children' in pv: 299 | first = [] 300 | for f, fv in pv.get('children').items(): 301 | if 'children' in fv: 302 | secondary = [] 303 | for s, sv in fv.get('children').items(): 304 | if 'children' in sv: 305 | tertiary = [] 306 | for t, tv in sv.get('children').items(): 307 | logging.info(f'{k}.{f}.{s}.{t}') 308 | tertiary.append(Part( 309 | id=f'{k}.{f}.{s}.{t}', 310 | name='item', 311 | props=[Property( 312 | name='label', 313 | value=t, 314 | )], 315 | prose=tv.get('prose') 316 | )) 317 | tp = tertiary if len(tertiary) > 0 else None 318 | logging.info(f'{k}.{f}.{s}') 319 | secondary.append(Part( 320 | id=f'{k}.{f}.{s}', 321 | name='item', 322 | props=[Property( 323 | name='label', 324 | value=s, 325 | )], 326 | parts=tp, 327 | prose=sv.get('prose'), 328 | )) 329 | sp = secondary if len(secondary) > 0 else None 330 | logging.info(f'{k}.{f}') 331 | first.append(Part( 332 | id=f'{k}.{f}', 333 | name='item', 334 | props=[Property( 335 | name='label', 336 | value=f, 337 | )], 338 | parts=sp, 339 | prose=fv.get('prose'), 340 | )) 341 | fp = first if len(first) > 0 else None 342 | logging.info(f'{k}') 343 | part.append(Part( 344 | id=f'{k}', 345 | name='item', 346 | props=[Property( 347 | name='label', 348 | value=k, 349 | )], 350 | parts=fp, 351 | prose=pv.get('prose'), 352 | )) 353 | return part 354 | 355 | 356 | def add_additional(pid, name, prose): 357 | return Part( 358 | id=pid, 359 | name=name, 360 | prose=prose, 361 | ) 362 | 363 | 364 | @click.command() 365 | @click.option('-t', '--title', required=True) 366 | @click.argument( 367 | 'source', 368 | type=click.Path(exists=True, dir_okay=False, file_okay=True, resolve_path=True) 369 | 370 | ) 371 | @click.option( 372 | "-a", 373 | "--ars_version", 374 | default="5.01", 375 | show_default=True, 376 | help="ARS version ", 377 | ) 378 | @click.option( 379 | "-o", 380 | "--oscal_version", 381 | default="1.0.2", 382 | show_default=True, 383 | help="OSCAL version ", 384 | ) 385 | @click.option( 386 | "-m", 387 | "--minimize", 388 | is_flag=True, 389 | help="Minimize output: no PII or HVA overlays.", 390 | ) 391 | def main(title, source, ars_version, oscal_version, minimize): 392 | """ 393 | Create an OSCAL Catalog from Excel (.xlsx) spreadsheet. 394 | Source: https://security.cms.gov/library/cms-acceptable-risk-safeguards-ars 395 | """ 396 | p = Path(source) 397 | groups = create_groups(p, minimize) 398 | uuid = uuid4().urn 399 | 400 | 401 | # today = datetime.now(timezone(timedelta(hours=-6))).isoformat(sep='T') 402 | today = datetime.now().astimezone(timezone.utc).isoformat(sep='T') 403 | 404 | # FIXME: missing 'T' separator in last-modified 405 | md = Metadata( 406 | title=title, 407 | last_modified=today, 408 | version=ars_version, 409 | oscal_version=oscal_version 410 | ) 411 | 412 | catalog = Catalog( 413 | uuid=uuid[9:], 414 | metadata=md, 415 | groups=groups, 416 | ) 417 | root = Model(catalog=catalog).dict(by_alias=True, exclude_unset=True, exclude_none=True) 418 | print(json.dumps(root, indent=2, default=str)) 419 | 420 | 421 | if __name__ == "__main__": 422 | main() 423 | -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/header31_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "family": 0, 3 | "control_id": 2, 4 | "name": 3, 5 | "baseline": 4, 6 | "priority": 6, 7 | "control": 7, 8 | "implementation": 8, 9 | "discussion": 9, 10 | "reference": 10, 11 | "related": 11, 12 | "responsiblity": 999, 13 | "review_frequency": 999, 14 | "assessment_frequency": 999, 15 | "privacy_standards": 999, 16 | "privacy_discussion": 999, 17 | "hva_statement": 999, 18 | "hva_standards": 999, 19 | "hva_discussion": 999 20 | } 21 | -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/header50_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "family": 0, 3 | "control_id": 1, 4 | "name": 2, 5 | "control": 3, 6 | "implementation": 5, 7 | "responsiblity": 6, 8 | "review_frequency": 7, 9 | "assessment_frequency": 8, 10 | "baseline": 9, 11 | "discussion": 10, 12 | "priority": 11, 13 | "related": 12, 14 | "reference": 13, 15 | "privacy_standards": 14, 16 | "privacy_discussion": 15, 17 | "hva_statement": 16, 18 | "hva_standards": 17, 19 | "hva_discussion": 18 20 | } -------------------------------------------------------------------------------- /ars-xlsx-oscal-json/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ars-xlsx-oscal-json" 3 | version = "0.1.0" 4 | description = "Convert ARS .xlsx spreadsheet into OSCAL JSON" 5 | authors = ["Fen Labalme "] 6 | license = "GNU General Public Licence v3" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | click = ">=7.1.2" 11 | openpyxl = "^3.0.10" 12 | compliance-trestle = "^1.1.0" 13 | complianceio = {git = "https://github.com/CivicActions/compliance-io.git", rev = "main"} 14 | 15 | [tool.poetry.dev-dependencies] 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.0.0"] 19 | build-backend = "poetry.core.masonry.api" 20 | --------------------------------------------------------------------------------