oscal 0.1.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.docker/Dockerfile +19 -0
  3. data/.docker/Makefile +43 -0
  4. data/.docker/docker-compose.yml +14 -0
  5. data/.docker/readme.md +61 -0
  6. data/.gitignore +2 -0
  7. data/.rspec +0 -1
  8. data/.rubocop.yml +1 -1
  9. data/.ruby-version +1 -0
  10. data/Gemfile +2 -0
  11. data/LICENSE +25 -0
  12. data/Makefile +1 -0
  13. data/README.adoc +3 -0
  14. data/Rakefile +13 -6
  15. data/bin/console +2 -2
  16. data/bin/rspec +27 -0
  17. data/docker-compose.yml +1 -0
  18. data/lib/oscal/add.rb +5 -4
  19. data/lib/oscal/address.rb +3 -2
  20. data/lib/oscal/address_line.rb +1 -0
  21. data/lib/oscal/alter.rb +3 -2
  22. data/lib/oscal/assembly.rb +119 -0
  23. data/lib/oscal/assessment_plan.rb +28 -0
  24. data/lib/oscal/assessment_result.rb +230 -0
  25. data/lib/oscal/attribute_type_hash.rb +81 -0
  26. data/lib/oscal/back_matter.rb +2 -1
  27. data/lib/oscal/base64_object.rb +1 -0
  28. data/lib/oscal/base_class.rb +5 -4
  29. data/lib/oscal/catalog.rb +8 -7
  30. data/lib/oscal/choice.rb +1 -0
  31. data/lib/oscal/citation.rb +3 -2
  32. data/lib/oscal/combine.rb +1 -0
  33. data/lib/oscal/common_utils.rb +1 -1
  34. data/lib/oscal/constraint.rb +2 -1
  35. data/lib/oscal/control.rb +6 -5
  36. data/lib/oscal/custom.rb +3 -2
  37. data/lib/oscal/datatypes.rb +50 -0
  38. data/lib/oscal/document_id.rb +1 -0
  39. data/lib/oscal/email_address.rb +1 -0
  40. data/lib/oscal/exclude_control.rb +3 -2
  41. data/lib/oscal/external_id.rb +1 -0
  42. data/lib/oscal/group.rb +9 -8
  43. data/lib/oscal/guideline.rb +1 -0
  44. data/lib/oscal/hash_object.rb +1 -0
  45. data/lib/oscal/import_object.rb +3 -2
  46. data/lib/oscal/include_control.rb +3 -2
  47. data/lib/oscal/insert_control.rb +3 -2
  48. data/lib/oscal/link.rb +1 -0
  49. data/lib/oscal/list.rb +160 -0
  50. data/lib/oscal/location.rb +8 -7
  51. data/lib/oscal/location_uuid.rb +1 -0
  52. data/lib/oscal/logger.rb +12 -0
  53. data/lib/oscal/matching.rb +1 -0
  54. data/lib/oscal/member_of_organization.rb +1 -0
  55. data/lib/oscal/merge.rb +2 -1
  56. data/lib/oscal/metadata_block.rb +11 -10
  57. data/lib/oscal/modify.rb +3 -2
  58. data/lib/oscal/parameter.rb +8 -7
  59. data/lib/oscal/parsing_functions.rb +19 -0
  60. data/lib/oscal/part.rb +4 -3
  61. data/lib/oscal/party.rb +11 -10
  62. data/lib/oscal/party_uuid.rb +1 -0
  63. data/lib/oscal/profile.rb +7 -6
  64. data/lib/oscal/property.rb +1 -0
  65. data/lib/oscal/remove.rb +1 -0
  66. data/lib/oscal/resource.rb +7 -6
  67. data/lib/oscal/responsible_party.rb +11 -10
  68. data/lib/oscal/revision.rb +4 -3
  69. data/lib/oscal/rlink.rb +2 -1
  70. data/lib/oscal/role.rb +3 -2
  71. data/lib/oscal/select.rb +2 -1
  72. data/lib/oscal/set_parameter.rb +8 -7
  73. data/lib/oscal/telephone_number.rb +1 -0
  74. data/lib/oscal/test.rb +1 -0
  75. data/lib/oscal/url.rb +1 -0
  76. data/lib/oscal/value.rb +5 -4
  77. data/lib/oscal/version.rb +1 -1
  78. data/lib/oscal/with_id.rb +2 -1
  79. data/lib/oscal.rb +1 -1
  80. data/spec/oscal/catalog_spec.rb +5 -4
  81. data/spec/oscal_spec.rb +11 -0
  82. data/spec/sample_inputs/import-ap.json +4 -0
  83. metadata +24 -6
@@ -0,0 +1,230 @@
1
+ require_relative "assembly"
2
+ require_relative "metadata_block"
3
+ require_relative "datatypes"
4
+
5
+ module Oscal
6
+ module AssessmentResult
7
+ class Activity < Assembly
8
+ attr_accessor(*(MANDATORY = %i(uuid).freeze),
9
+ *(OPTIONAL = %i(title description props links steps
10
+ related_controls responsible_roles
11
+ remarks).freeze))
12
+ end
13
+
14
+ class Attestations < Assembly
15
+ # TODO: Define this. Punting for the time being
16
+ end
17
+
18
+ class AssessmentAssets < Assembly
19
+ attr_accessor(*(MANDATORY = %i(assessment_platforms).freeze),
20
+ *(OPTIONAL = %i(components).freeze))
21
+ end
22
+
23
+ class AssessmentLog
24
+ attr_accessor(*(MANDATORY = %i(entries).freeze))
25
+ end
26
+
27
+ class AssessmentPlatform < Assembly
28
+ # TODO: Define this. Punting for the time being
29
+ end
30
+
31
+ class AssessmentTask < Assembly
32
+ attr_accessor(*(MANDATORY = %i(uuid type title).freeze),
33
+ *(OPTIONAL = %i(description props links timing dependencies
34
+ tasks associated_activities subjects
35
+ responsible_roles remarks).freeze))
36
+ end
37
+
38
+ class AssociatedActivity < Assembly
39
+ attr_accessor(*(MANDATORY = %i(activity_uuid subjects).freeze),
40
+ *(OPTIONAL = %i(props links responsible_roles
41
+ remarks).freeze))
42
+ end
43
+
44
+ class AssociatedRisk < Assembly
45
+ attr_accessor(*(MANDATORY = %i(risk_uuid).freeze))
46
+ end
47
+
48
+ class Attestation < Assembly
49
+ # TODO: Define this. Punting for the time being
50
+ end
51
+
52
+ class Component < Assembly
53
+ # TODO: Define this. Punting for the time being
54
+ end
55
+
56
+ class ControlObjectiveSelection < Assembly
57
+ attr_accessor(*(OPTIONAL = %i(description props links include_all
58
+ include_objectives exclude_objectives
59
+ remarks).freeze))
60
+ end
61
+
62
+ class ControlSelection < Assembly
63
+ attr_accessor(*(OPTIONAL = %i(description props links include_all
64
+ include_controls exclude_controls
65
+ remarks).freeze))
66
+ end
67
+
68
+ class Entry < Assembly
69
+ # TODO: Define this. Punting for the time being
70
+ end
71
+
72
+ class ExcludeControl
73
+ # TODO: Define this. Punting for the time being
74
+ # NOTE: This has the same name as profile/exclude-control, but a different
75
+ # definition!
76
+ end
77
+
78
+ class ExcludeObjective < Assembly
79
+ attr_accessor(*(MANDATORY = %i(objective_id).freeze))
80
+ end
81
+
82
+ class Finding < Assembly
83
+ attr_accessor(*(MANDATORY = %i(uuid title description target).freeze),
84
+ *(OPTIONAL = %i(implementation_statement_uuid
85
+ related_observations related_risks
86
+ remarks).freeze))
87
+ end
88
+
89
+ class ImportAP < Assembly
90
+ attr_accessor(*(MANDATORY = %i(href).freeze),
91
+ *(OPTIONAL = %i(remarks).freeze))
92
+ end
93
+
94
+ class IncludeAll < Assembly
95
+ # This is an Assembly that acts like a flag - it has no no contents
96
+ end
97
+
98
+ class IncludeControl < Assembly
99
+ attr_accessor(*(MANDATORY = %i(control_id).freeze),
100
+ *(OPTIONAL = %i(statement_ids).freeze))
101
+ end
102
+
103
+ class IncludeObjective < Assembly
104
+ attr_accessor(*(MANDATORY = %i(objective_id).freeze))
105
+ end
106
+
107
+ class InventoryItem < Assembly
108
+ # TODO: Define this. Punting for the time being
109
+ end
110
+
111
+ class LocalDefinitions < Assembly
112
+ # NOTE we deviate fromt the spec here! local-definitions is defined twice
113
+ # with different attributes. All attributes are optional, so we merge it
114
+ # into one big back of optional attributes
115
+ attr_accessor(*(OPTIONAL = %i(objectives_and_methods activities
116
+ remarks components inventory_items users
117
+ assesssment_assets tasks).freeze))
118
+ end
119
+
120
+ class ObjectivesAndMethods < Assembly
121
+ attr_accessor(*(MANDATORY = %i(control_id parts).freeze),
122
+ *(OPTIONAL = %i(description props links remarks).freeze))
123
+ end
124
+
125
+ class Observation < Assembly
126
+ attr_accessor(*(MANDATORY = %i(uuid description methods collected).freeze),
127
+ *(OPTIONAL = %i(title props links methods types origins
128
+ subjects relevent_evidence expires
129
+ remarks).freeze))
130
+ end
131
+
132
+ class RelatedControls < Assembly
133
+ attr_accessor(*(MANDATORY = %i(control_selections).freeze),
134
+ *(OPTIONAL = %i(description props links
135
+ control_objective_selections
136
+ remarks).freeze))
137
+ end
138
+
139
+ class RelatedObservation < Assembly
140
+ attr_accessor(*(MANDATORY = %i(observation_uuid).freeze),
141
+ *(OPTIONAL = %i().freeze))
142
+ end
143
+
144
+ class ResponsibleRole < Assembly
145
+ attr_accessor(*(MANDATORY = %i(role_id).freeze),
146
+ *(OPTIONAL = %i(props links party_uuids remarks).freeze))
147
+ end
148
+
149
+ class Result < Assembly
150
+ attr_accessor(*(MANDATORY = %i(uuid title description start).freeze),
151
+ *(OPTIONAL = %i(end props links local_definitions
152
+ reviewed_controls attestations
153
+ assessment_log observations risks findings
154
+ remarks).freeze))
155
+ end
156
+
157
+ class ReviewedControls < Assembly
158
+ attr_accessor(*(MANDATORY = %i(control_selections).freeze),
159
+ *(OPTIONAL = %i(description props links
160
+ control_objective_selections
161
+ remarks).freeze))
162
+ end
163
+
164
+ class Risk < Assembly
165
+ attr_accessor(*(MANDATORY = %i(uuid title description statement
166
+ status).freeze),
167
+ *(OPTIONAL = %i(propse links origins threat_ids
168
+ characterizations mitigating_factors
169
+ deadline remediations risk_log
170
+ related_observations).freeze))
171
+ end
172
+
173
+ class Status
174
+ # Status is defined twice, once as a datatype, once as an assembly
175
+ # this class figures out which is which
176
+ def initialize(input)
177
+ if input.instance_of? String
178
+ StatusString.new(input)
179
+ elsif input.instance_of? Hash
180
+ StatusAssembly.new(input)
181
+ else
182
+ raise Oscal::InvalidTypeError, "status must be a string or assembly"
183
+ end
184
+ end
185
+ end
186
+
187
+ class StatusString < TokenDataType
188
+ end
189
+
190
+ class StatusAssembly < Assembly
191
+ attr_accessor(*(MANDATORY = %i(state).freeze),
192
+ *(OPTIONAL = %i(reason remarks).freeze))
193
+ end
194
+
195
+ class Step < Assembly
196
+ attr_accessor(*(MANDATORY = %i(uuid).freeze),
197
+ *(OPTIONAL = %i(title description props links
198
+ reviewed_controls responsible_roles
199
+ remarks).freeze))
200
+ end
201
+
202
+ class Subject < Assembly
203
+ attr_accessor(*(OPTIONAL = %i(subject_uuid type
204
+ description props links include_all
205
+ include_subjects exclude_subjects
206
+ remarks).freeze))
207
+ end
208
+
209
+ class Target < Assembly
210
+ attr_accessor(*(MANDATORY = %i(type target_id status).freeze),
211
+ *(OPTIONAL = %i(title description props links
212
+ implementation_status remarks).freeze))
213
+ end
214
+
215
+ class Task < Assembly
216
+ # TODO: Define this. Punting for the time being
217
+ end
218
+
219
+ class User < Assembly
220
+ # TODO: Define this. Punting for the time being
221
+ end
222
+
223
+ ##########################################
224
+
225
+ class AssessmentResult < Assembly
226
+ attr_accessor(*(MANDATORY = %i(uuid metadata import_ap results).freeze),
227
+ *(OPTIONAL = %i(local_definitions back_matter).freeze))
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,81 @@
1
+ require_relative("datatypes")
2
+ require_relative("list")
3
+
4
+ module Oscal
5
+ ATTRIBUTE_TYPE_HASH = {
6
+ activities: AssessmentResult::ActivityArray,
7
+ activity_uuid: Uuid,
8
+ assessment_plan: AssessmentPlan::AssessmentPlan,
9
+ assessment_platforms: AssessmentResult::AssessmentPlatformArray,
10
+ assessment_results: AssessmentResult::AssessmentResult,
11
+ assessment_log: AssessmentResult::AssessmentLog,
12
+ associated_activities: AssessmentResult::AssociatedActivityArray,
13
+ attestations: AssessmentResult::AttestationArray,
14
+ collected: DateTimeWithTimezoneDataType,
15
+ components: AssessmentResult::ComponentArray,
16
+ control_id: TokenDataType,
17
+ control_objective_selections: AssessmentResult::ControlObjectiveSelectionArray,
18
+ control_selections: AssessmentResult::ControlSelectionArray,
19
+ description: MarkupMultilineDataType,
20
+ end: DateTimeWithTimezoneDataType,
21
+ entries: AssessmentResult::EntryArray,
22
+ exclude_controls: AssessmentResult::ExcludeControlArray,
23
+ exclude_objectives: AssessmentResult::ExcludeObjectiveArray,
24
+ expires: DateTimeWithTimezoneDataType,
25
+ findings: AssessmentResult::FindingArray,
26
+ href: UriReference,
27
+ implementation_statement_uuid: Uuid,
28
+ import_ap: AssessmentResult::ImportAP,
29
+ import_ssp: AssessmentPlan::ImportSSP,
30
+ include_all: AssessmentResult::IncludeAll,
31
+ include_controls: AssessmentResult::IncludeControlArray,
32
+ inventory_items: AssessmentResult::InventoryItemArray,
33
+ links: AssessmentResult::LinkArray,
34
+ local_definitions: AssessmentResult::LocalDefinitions,
35
+ metadata: MetadataBlockWrapper,
36
+ methods: AssessmentResult::MethodArray,
37
+ objective_id: TokenDataType,
38
+ objectives_and_methods: AssessmentResult::ObjectivesAndMethodsArray,
39
+ observations: AssessmentResult::ObservationArray,
40
+ observation_uuid: Uuid,
41
+ parts: AssessmentResult::PartArray,
42
+ party_uuids: AssessmentResult::PartyUuidArray,
43
+ props: AssessmentResult::PropArray,
44
+ reason: TokenDataType,
45
+ related_controls: AssessmentResult::RelatedControls,
46
+ related_observations: AssessmentResult::RelatedObservationArray,
47
+ related_risks: AssessmentResult::RelatedRiskArray,
48
+ remarks: MarkupMultilineDataType,
49
+ responsible_roles: AssessmentResult::ResponsibleRoleArray,
50
+ results: AssessmentResult::ResultArray,
51
+ reviewed_controls: AssessmentResult::ReviewedControls,
52
+ risks: AssessmentResult::RiskArray,
53
+ risk_uuid: Uuid,
54
+ role_id: TokenDataType,
55
+ start: DateTimeWithTimezoneDataType,
56
+ state: TokenDataType,
57
+ status: AssessmentResult::Status,
58
+ statement: MarkupMultilineDataType,
59
+ statement_ids: AssessmentResult::StatementIdArray,
60
+ steps: AssessmentResult::StepArray,
61
+ subjects: AssessmentResult::SubjectArray,
62
+ subject_uuid: Uuid,
63
+ target: AssessmentResult::Target,
64
+ target_id: TokenDataType,
65
+ tasks: AssessmentResult::AssessmentTaskArray,
66
+ title: MarkupMultilineDataType,
67
+ type: TokenDataType,
68
+ types: AssessmentResult::TypeArray,
69
+ uuid: Uuid,
70
+ users: AssessmentResult::UserArray,
71
+ }.freeze
72
+
73
+ def self.get_type_of_attribute(attribute_name)
74
+ klass = Oscal::ATTRIBUTE_TYPE_HASH[attribute_name.to_sym]
75
+ if klass == nil
76
+ raise InvalidTypeError, "No type found for #{attribute_name}"
77
+ else
78
+ klass
79
+ end
80
+ end
81
+ end
@@ -5,11 +5,12 @@ module Oscal
5
5
  KEY = %i(resources)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'resources'
13
+ when "resources"
13
14
  Resource.wrap(val)
14
15
  else
15
16
  val
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(filename media_type value)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -7,6 +7,7 @@ module Oscal
7
7
  KEY = %i(val)
8
8
 
9
9
  attr_accessor *KEY
10
+
10
11
  attr_serializable *KEY
11
12
 
12
13
  def self.wrap(obj)
@@ -23,16 +24,16 @@ module Oscal
23
24
  klass = self.class
24
25
 
25
26
  unless options.is_a? Hash
26
- options = {klass::KEY.first.to_s => options}
27
+ options = { klass::KEY.first.to_s => options }
27
28
  end
28
29
 
29
30
  options.each_pair.each do |key, val|
30
31
  key_name = key.gsub("-", "_")
31
- key_name = 'klass' if key == 'class'
32
+ key_name = "klass" if key == "class"
32
33
 
33
34
  unless klass::KEY.include?(key_name.to_sym)
34
35
  raise UnknownAttributeError.new(
35
- "Unknown key `#{key}` in #{klass.name}"
36
+ "Unknown key `#{key}` in #{klass.name}",
36
37
  )
37
38
  end
38
39
 
@@ -42,7 +43,7 @@ module Oscal
42
43
  end
43
44
  end
44
45
 
45
- def set_value(key_name, val)
46
+ def set_value(_key_name, val)
46
47
  val
47
48
  end
48
49
  end
data/lib/oscal/catalog.rb CHANGED
@@ -9,6 +9,7 @@ module Oscal
9
9
 
10
10
  KEY = %i(uuid metadata params controls groups back_matter)
11
11
  attr_accessor *KEY
12
+
12
13
  attr_serializable *KEY
13
14
 
14
15
  def initialize(uuid, metadata, params, controls, groups, back_matter)
@@ -26,12 +27,12 @@ module Oscal
26
27
  yaml_data = safe_load_yaml(path)
27
28
  yaml_catalog = yaml_data["catalog"]
28
29
 
29
- uuid = yaml_catalog['uuid']
30
- metadata = yaml_catalog['metadata']
31
- params = yaml_catalog['params']
32
- controls = yaml_catalog['controls']
33
- groups = yaml_catalog['groups']
34
- back_matter = yaml_catalog['back-matter']
30
+ uuid = yaml_catalog["uuid"]
31
+ metadata = yaml_catalog["metadata"]
32
+ params = yaml_catalog["params"]
33
+ controls = yaml_catalog["controls"]
34
+ groups = yaml_catalog["groups"]
35
+ back_matter = yaml_catalog["back-matter"]
35
36
 
36
37
  Catalog.new(uuid, metadata, params, controls, groups, back_matter)
37
38
  end
@@ -42,7 +43,7 @@ module Oscal
42
43
  end
43
44
 
44
45
  def append_all_control_group(obj)
45
- if obj.to_s.match(/Oscal::Control/)
46
+ if /Oscal::Control/.match?(obj.to_s)
46
47
  @all_controls << obj
47
48
  end
48
49
 
data/lib/oscal/choice.rb CHANGED
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(val)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -5,13 +5,14 @@ module Oscal
5
5
  KEY = %i(text props links)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'props'
13
+ when "props"
13
14
  Property.wrap(val)
14
- when 'links'
15
+ when "links"
15
16
  Link.wrap(val)
16
17
  else
17
18
  val
data/lib/oscal/combine.rb CHANGED
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(method)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -8,7 +8,7 @@ module Oscal
8
8
  res = nil
9
9
 
10
10
  obj.instance_variables.each do |ins_var|
11
- val = obj.send(ins_var.to_s.delete('@').to_sym)
11
+ val = obj.send(ins_var.to_s.delete("@").to_sym)
12
12
 
13
13
  if val.is_a? Array
14
14
  val.each do |v|
@@ -5,11 +5,12 @@ module Oscal
5
5
  KEY = %i(description tests)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'test'
13
+ when "test"
13
14
  Test.wrap(val)
14
15
  else
15
16
  val
data/lib/oscal/control.rb CHANGED
@@ -5,19 +5,20 @@ module Oscal
5
5
  KEY = %i(id klass title params props links parts controls)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'params'
13
+ when "params"
13
14
  Parameter.wrap(val)
14
- when 'props'
15
+ when "props"
15
16
  Property.wrap(val)
16
- when 'links'
17
+ when "links"
17
18
  Link.wrap(val)
18
- when 'parts'
19
+ when "parts"
19
20
  Part.wrap(val)
20
- when 'controls'
21
+ when "controls"
21
22
  Control.wrap(val)
22
23
  else
23
24
  val
data/lib/oscal/custom.rb CHANGED
@@ -5,13 +5,14 @@ module Oscal
5
5
  KEY = %i(groups insert_controls)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'groups'
13
+ when "groups"
13
14
  Group.wrap(val)
14
- when 'insert_controls'
15
+ when "insert_controls"
15
16
  InsertControl.wrap(val)
16
17
  else
17
18
  val
@@ -0,0 +1,50 @@
1
+ module Oscal
2
+ class OscalDatatype < String
3
+ include ParsingLogger
4
+
5
+ def validate(value)
6
+ @logger.debug("validating against pattern #{self.class::PATTERN}")
7
+ unless self.class::PATTERN.match?(value)
8
+ raise Oscal::InvalidTypeError,
9
+ "#{value.to_s[0, 25]} does not match Pattern for #{self.class}"
10
+ end
11
+ end
12
+
13
+ def initialize(input)
14
+ super
15
+ @logger = get_logger
16
+ @logger.debug("#{self.class}.new called with #{input.to_s[0, 25]}")
17
+ validate(input) # Will raise an Error if invalid
18
+ @logger.debug("validation successful.")
19
+ end
20
+
21
+ def to_s
22
+ @value
23
+ end
24
+ end
25
+
26
+ class DateTimeWithTimezoneDataType < OscalDatatype
27
+ PATTERN = /(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|(-((0[0-9]|1[0-2]):00|0[39]:30)|\+((0[0-9]|1[0-4]):00|(0[34569]|10):30|(0[58]|12):45)))/
28
+ end
29
+
30
+ class MarkupMultilineDataType < OscalDatatype
31
+ # Note that there are complex rules for MarkupMultilineDataType that we are ignoring
32
+ PATTERN = /.*/
33
+ end
34
+
35
+ class StringDataType < OscalDatatype
36
+ PATTERN = /\S(.*\S)?/
37
+ end
38
+
39
+ class TokenDataType < OscalDatatype
40
+ PATTERN = /(\p{L}|_)(\p{L}|\p{N}|[.\-_])*/
41
+ end
42
+
43
+ class UriReference < OscalDatatype
44
+ PATTERN = %r{^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?}
45
+ end
46
+
47
+ class Uuid < OscalDatatype
48
+ PATTERN = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$/
49
+ end
50
+ end
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(schema identifier)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(val)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -5,13 +5,14 @@ module Oscal
5
5
  KEY = %i(with_child_controls with_ids matching)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'with_ids'
13
+ when "with_ids"
13
14
  WithId.wrap(val)
14
- when 'matching'
15
+ when "matching"
15
16
  Matching.wrap(val)
16
17
  else
17
18
  val
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(schema id)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
data/lib/oscal/group.rb CHANGED
@@ -3,26 +3,27 @@ require_relative "base_class"
3
3
  module Oscal
4
4
  class Group < Oscal::BaseClass
5
5
  KEY = %i(id klass title params props links parts groups
6
- controls insert_controls)
6
+ controls insert_controls)
7
7
 
8
8
  attr_accessor *KEY
9
+
9
10
  attr_serializable *KEY
10
11
 
11
12
  def set_value(key_name, val)
12
13
  case key_name
13
- when 'params'
14
+ when "params"
14
15
  Parameter.wrap(val)
15
- when 'props'
16
+ when "props"
16
17
  Property.wrap(val)
17
- when 'links'
18
+ when "links"
18
19
  Link.wrap(val)
19
- when 'parts'
20
+ when "parts"
20
21
  Part.wrap(val)
21
- when 'groups'
22
+ when "groups"
22
23
  Group.wrap(val)
23
- when 'controls'
24
+ when "controls"
24
25
  Control.wrap(val)
25
- when 'insert_controls'
26
+ when "insert_controls"
26
27
  InsertControl.wrap(val)
27
28
  else
28
29
  val
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(prose)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -5,6 +5,7 @@ module Oscal
5
5
  KEY = %i(algorithm value)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
  end
10
11
  end
@@ -5,13 +5,14 @@ module Oscal
5
5
  KEY = %i(href include_all include_controls exclude_controls)
6
6
 
7
7
  attr_accessor *KEY
8
+
8
9
  attr_serializable *KEY
9
10
 
10
11
  def set_value(key_name, val)
11
12
  case key_name
12
- when 'include_controls'
13
+ when "include_controls"
13
14
  IncludeControl.wrap(val)
14
- when 'exclude_controls'
15
+ when "exclude_controls"
15
16
  ExcludeControl.wrap(val)
16
17
  else
17
18
  val