001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; 004import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 005import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultilineAdapter; 006import gov.nist.secauto.metaschema.core.model.IBoundObject; 007import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 008import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; 009import gov.nist.secauto.metaschema.core.model.constraint.IConstraint; 010import gov.nist.secauto.metaschema.core.util.ObjectUtils; 011import gov.nist.secauto.metaschema.databind.model.annotations.AssemblyConstraints; 012import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly; 013import gov.nist.secauto.metaschema.databind.model.annotations.BoundField; 014import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 015import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs; 016import gov.nist.secauto.metaschema.databind.model.annotations.Index; 017import gov.nist.secauto.metaschema.databind.model.annotations.IsUnique; 018import gov.nist.secauto.metaschema.databind.model.annotations.KeyField; 019import gov.nist.secauto.metaschema.databind.model.annotations.Let; 020import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 021import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints; 022import java.lang.Override; 023import java.lang.String; 024import java.util.LinkedList; 025import java.util.List; 026import java.util.UUID; 027import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 028import org.apache.commons.lang3.builder.ToStringStyle; 029 030/** 031 * Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report. 032 */ 033@MetaschemaAssembly( 034 formalName = "Security Assessment Results (SAR)", 035 description = "Security assessment results, such as those provided by a FedRAMP assessor in the FedRAMP Security Assessment Report.", 036 name = "assessment-results", 037 moduleClass = OscalArModule.class, 038 rootName = "assessment-results", 039 valueConstraints = @ValueConstraints(lets = @Let(name = "all-imports", target = "recurse-depth('.[import-ap]/doc(resolve-uri(Q{http://csrc.nist.gov/ns/oscal/1.0}resolve-reference(import-ap/@href)))/assessment-plan|.[import-ssp]/doc(resolve-uri(Q{http://csrc.nist.gov/ns/oscal/1.0}resolve-reference(import-ssp/@href)))/system-security-plan|.[import-profile]/resolve-profile(doc(resolve-uri(Q{http://csrc.nist.gov/ns/oscal/1.0}resolve-reference(import-profile/@href))))/catalog')")), 040 modelConstraints = @AssemblyConstraints(index = {@Index(id = "oscal-ar-index-metadata-scoped-role-id", formalName = "In-Scope Role Identifiers", description = "An index of role identifiers that are in-scope for the assessment-result model. Roles are collected from imported assessment-plans, which in turn includes referenced system-securtity-plans, which in turn includes referenced profiles and catalogs. For a given role @id, a locally declared role takes precedence over a role that is imported, the role that was last imported.", level = IConstraint.Level.ERROR, target = "map:merge($all-imports/metadata/role ! map:entry(@id,.))?*", name = "index-imports-metadata-role-id", keyFields = @KeyField(target = "@id")), @Index(id = "oscal-ar-index-metadata-scoped-location-uuid", level = IConstraint.Level.ERROR, target = "map:merge($all-imports/metadata/location ! map:entry(@uuid,.))?*", name = "index-imports-metadata-location-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-ar-index-metadata-scoped-party-uuid", level = IConstraint.Level.ERROR, target = "map:merge($all-imports/metadata/party ! map:entry(@uuid,.))?*", name = "index-imports-metadata-party-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-ar-index-metadata-scoped-party-organization-uuid", level = IConstraint.Level.ERROR, target = "map:merge($all-imports/metadata/party[@type='organization'] ! map:entry(@uuid,.))?*", name = "index-imports-metadata-party-organization-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-ar-index-metadata-scoped-property-uuid", level = IConstraint.Level.ERROR, target = "map:merge($all-imports//prop[@uuid] ! map:entry(@uuid,.))?*", name = "index-imports-metadata-property-uuid", keyFields = @KeyField(target = "@uuid"))}, unique = {@IsUnique(id = "oscal-unique-document-id", formalName = "Unique Document Identifier", description = "Ensure all document identifiers have a unique combination of @scheme and value.", level = IConstraint.Level.ERROR, target = "document-id", keyFields = {@KeyField(target = "@scheme"), @KeyField}), @IsUnique(id = "oscal-unique-property-in-context-location", formalName = "Unique Properties", description = "Ensure all properties are unique for a given location using a unique combination of @ns, @name, @class. @group. and @value.", level = IConstraint.Level.ERROR, target = ".//prop", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@name"), @KeyField(target = "@ns"), @KeyField(target = "@class"), @KeyField(target = "@group"), @KeyField(target = "@value")}), @IsUnique(id = "oscal-unique-link-in-context-location", formalName = "Unique Links", description = "Ensure all links are unique for a given location using a unique combination of @href, @rel, and @media-type.", level = IConstraint.Level.ERROR, target = ".//link", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@href"), @KeyField(target = "@rel"), @KeyField(target = "@media-type")}), @IsUnique(id = "oscal-unique-responsibility-in-context-location", formalName = "Unique Responsibilities", description = "Ensure all responsible-roles and responsible-parties are unique for a given location using a unique combination of @role-id and the combination of @party-uuid values.", level = IConstraint.Level.ERROR, target = ".//(responsible-party|responsible-role)", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@role-id"), @KeyField(target = "@party-uuid")}, remarks = "Since `responsible-party` and `responsible-role` associate multiple `party-uuid` entries with a single `role-id`, each role-id must be referenced only once.")}) 041) 042public class AssessmentResults extends AbstractOscalInstance implements IBoundObject { 043 private final IMetaschemaData __metaschemaData; 044 045 /** 046 * "A <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented\">machine-oriented</a>, <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique\">globally unique</a> identifier with <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#cross-instance\">cross-instance</a> scope that can be used to reference this assessment results instance in <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#ar-identifiers\">this or other OSCAL instances</a>. The locally defined <em>UUID</em> of the <code>assessment result</code> can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency\">per-subject</a>, which means it should be consistently used to identify the same subject across revisions of the document." 047 */ 048 @BoundFlag( 049 formalName = "Assessment Results Universally Unique Identifier", 050 description = "A [machine-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented), [globally unique](https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique) identifier with [cross-instance](https://pages.nist.gov/OSCAL/concepts/identifier-use/#cross-instance) scope that can be used to reference this assessment results instance in [this or other OSCAL instances](https://pages.nist.gov/OSCAL/concepts/identifier-use/#ar-identifiers). The locally defined *UUID* of the `assessment result` can be used to reference the data item locally or globally (e.g., in an imported OSCAL instance). This UUID should be assigned [per-subject](https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency), which means it should be consistently used to identify the same subject across revisions of the document.", 051 name = "uuid", 052 required = true, 053 typeAdapter = UuidAdapter.class 054 ) 055 private UUID _uuid; 056 057 @BoundAssembly( 058 formalName = "Document Metadata", 059 description = "Provides information about the containing document, and defines concepts that are shared across the document.", 060 useName = "metadata", 061 minOccurs = 1 062 ) 063 private Metadata _metadata; 064 065 @BoundAssembly( 066 formalName = "Import Assessment Plan", 067 description = "Used by assessment-results to import information about the original plan for assessing the system.", 068 useName = "import-ap", 069 remarks = "Used by the SAR to import information about the original plan for assessing the system.", 070 minOccurs = 1 071 ) 072 private ImportAp _importAp; 073 074 @BoundAssembly( 075 formalName = "Local Definitions", 076 description = "Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.", 077 useName = "local-definitions" 078 ) 079 private LocalDefinitions _localDefinitions; 080 081 @BoundAssembly( 082 formalName = "Assessment Result", 083 description = "Used by the assessment results and POA\\&M. In the assessment results, this identifies all of the assessment observations and findings, initial and residual risks, deviations, and disposition. In the POA\\&M, this identifies initial and residual risks, deviations, and disposition.", 084 useName = "result", 085 minOccurs = 1, 086 maxOccurs = -1, 087 groupAs = @GroupAs(name = "results", inJson = JsonGroupAsBehavior.LIST) 088 ) 089 private List<Result> _results; 090 091 @BoundAssembly( 092 formalName = "Back matter", 093 description = "A collection of resources that may be referenced from within the OSCAL document instance.", 094 useName = "back-matter" 095 ) 096 private BackMatter _backMatter; 097 098 public AssessmentResults() { 099 this(null); 100 } 101 102 public AssessmentResults(IMetaschemaData data) { 103 this.__metaschemaData = data; 104 } 105 106 @Override 107 public IMetaschemaData getMetaschemaData() { 108 return __metaschemaData; 109 } 110 111 public UUID getUuid() { 112 return _uuid; 113 } 114 115 public void setUuid(UUID value) { 116 _uuid = value; 117 } 118 119 public Metadata getMetadata() { 120 return _metadata; 121 } 122 123 public void setMetadata(Metadata value) { 124 _metadata = value; 125 } 126 127 public ImportAp getImportAp() { 128 return _importAp; 129 } 130 131 public void setImportAp(ImportAp value) { 132 _importAp = value; 133 } 134 135 public LocalDefinitions getLocalDefinitions() { 136 return _localDefinitions; 137 } 138 139 public void setLocalDefinitions(LocalDefinitions value) { 140 _localDefinitions = value; 141 } 142 143 public List<Result> getResults() { 144 return _results; 145 } 146 147 public void setResults(List<Result> value) { 148 _results = value; 149 } 150 151 /** 152 * Add a new {@link Result} item to the underlying collection. 153 * @param item the item to add 154 * @return {@code true} 155 */ 156 public boolean addResult(Result item) { 157 Result value = ObjectUtils.requireNonNull(item,"item cannot be null"); 158 if (_results == null) { 159 _results = new LinkedList<>(); 160 } 161 return _results.add(value); 162 } 163 164 /** 165 * Remove the first matching {@link Result} item from the underlying collection. 166 * @param item the item to remove 167 * @return {@code true} if the item was removed or {@code false} otherwise 168 */ 169 public boolean removeResult(Result item) { 170 Result value = ObjectUtils.requireNonNull(item,"item cannot be null"); 171 return _results != null && _results.remove(value); 172 } 173 174 public BackMatter getBackMatter() { 175 return _backMatter; 176 } 177 178 public void setBackMatter(BackMatter value) { 179 _backMatter = value; 180 } 181 182 @Override 183 public String toString() { 184 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 185 } 186 187 /** 188 * Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP. 189 */ 190 @MetaschemaAssembly( 191 formalName = "Local Definitions", 192 description = "Used to define data objects that are used in the assessment plan, that do not appear in the referenced SSP.", 193 name = "local-definitions", 194 moduleClass = OscalArModule.class 195 ) 196 public static class LocalDefinitions implements IBoundObject { 197 private final IMetaschemaData __metaschemaData; 198 199 @BoundAssembly( 200 formalName = "Assessment-Specific Control Objective", 201 description = "A local definition of a control objective for this assessment. Uses catalog syntax for control objective and assessment actions.", 202 useName = "objectives-and-methods", 203 maxOccurs = -1, 204 groupAs = @GroupAs(name = "objectives-and-methods", inJson = JsonGroupAsBehavior.LIST) 205 ) 206 private List<LocalObjective> _objectivesAndMethods; 207 208 @BoundAssembly( 209 formalName = "Activity", 210 description = "Identifies an assessment or related process that can be performed. In the assessment plan, this is an intended activity which may be associated with an assessment task. In the assessment results, this an activity that was actually performed as part of an assessment.", 211 useName = "activity", 212 maxOccurs = -1, 213 groupAs = @GroupAs(name = "activities", inJson = JsonGroupAsBehavior.LIST) 214 ) 215 private List<Activity> _activities; 216 217 @BoundField( 218 formalName = "Remarks", 219 description = "Additional commentary about the containing object.", 220 useName = "remarks", 221 typeAdapter = MarkupMultilineAdapter.class 222 ) 223 private MarkupMultiline _remarks; 224 225 public LocalDefinitions() { 226 this(null); 227 } 228 229 public LocalDefinitions(IMetaschemaData data) { 230 this.__metaschemaData = data; 231 } 232 233 @Override 234 public IMetaschemaData getMetaschemaData() { 235 return __metaschemaData; 236 } 237 238 public List<LocalObjective> getObjectivesAndMethods() { 239 return _objectivesAndMethods; 240 } 241 242 public void setObjectivesAndMethods(List<LocalObjective> value) { 243 _objectivesAndMethods = value; 244 } 245 246 /** 247 * Add a new {@link LocalObjective} item to the underlying collection. 248 * @param item the item to add 249 * @return {@code true} 250 */ 251 public boolean addObjectivesAndMethods(LocalObjective item) { 252 LocalObjective value = ObjectUtils.requireNonNull(item,"item cannot be null"); 253 if (_objectivesAndMethods == null) { 254 _objectivesAndMethods = new LinkedList<>(); 255 } 256 return _objectivesAndMethods.add(value); 257 } 258 259 /** 260 * Remove the first matching {@link LocalObjective} item from the underlying collection. 261 * @param item the item to remove 262 * @return {@code true} if the item was removed or {@code false} otherwise 263 */ 264 public boolean removeObjectivesAndMethods(LocalObjective item) { 265 LocalObjective value = ObjectUtils.requireNonNull(item,"item cannot be null"); 266 return _objectivesAndMethods != null && _objectivesAndMethods.remove(value); 267 } 268 269 public List<Activity> getActivities() { 270 return _activities; 271 } 272 273 public void setActivities(List<Activity> value) { 274 _activities = value; 275 } 276 277 /** 278 * Add a new {@link Activity} item to the underlying collection. 279 * @param item the item to add 280 * @return {@code true} 281 */ 282 public boolean addActivity(Activity item) { 283 Activity value = ObjectUtils.requireNonNull(item,"item cannot be null"); 284 if (_activities == null) { 285 _activities = new LinkedList<>(); 286 } 287 return _activities.add(value); 288 } 289 290 /** 291 * Remove the first matching {@link Activity} item from the underlying collection. 292 * @param item the item to remove 293 * @return {@code true} if the item was removed or {@code false} otherwise 294 */ 295 public boolean removeActivity(Activity item) { 296 Activity value = ObjectUtils.requireNonNull(item,"item cannot be null"); 297 return _activities != null && _activities.remove(value); 298 } 299 300 public MarkupMultiline getRemarks() { 301 return _remarks; 302 } 303 304 public void setRemarks(MarkupMultiline value) { 305 _remarks = value; 306 } 307 308 @Override 309 public String toString() { 310 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 311 } 312 } 313}