oscal 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) 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 +80 -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 +8 -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/sample_inputs/import-ap.json +4 -0
  82. metadata +21 -3
@@ -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,80 @@
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
+ related_controls: AssessmentResult::RelatedControls,
45
+ related_observations: AssessmentResult::RelatedObservationArray,
46
+ related_risks: AssessmentResult::RelatedRiskArray,
47
+ remarks: MarkupMultilineDataType,
48
+ responsible_roles: AssessmentResult::ResponsibleRoleArray,
49
+ results: AssessmentResult::ResultArray,
50
+ reviewed_controls: AssessmentResult::ReviewedControls,
51
+ risks: AssessmentResult::RiskArray,
52
+ risk_uuid: Uuid,
53
+ role_id: TokenDataType,
54
+ start: DateTimeWithTimezoneDataType,
55
+ state: TokenDataType,
56
+ status: AssessmentResult::Status,
57
+ statement: MarkupMultilineDataType,
58
+ statement_ids: AssessmentResult::StatementIdArray,
59
+ steps: AssessmentResult::StepArray,
60
+ subjects: AssessmentResult::SubjectArray,
61
+ subject_uuid: Uuid,
62
+ target: AssessmentResult::Target,
63
+ target_id: TokenDataType,
64
+ tasks: AssessmentResult::AssessmentTaskArray,
65
+ title: MarkupMultilineDataType,
66
+ type: TokenDataType,
67
+ types: AssessmentResult::TypeArray,
68
+ uuid: Uuid,
69
+ users: AssessmentResult::UserArray,
70
+ }.freeze
71
+
72
+ def self.get_type_of_attribute(attribute_name)
73
+ klass = Oscal::ATTRIBUTE_TYPE_HASH[attribute_name.to_sym]
74
+ if klass == nil
75
+ raise InvalidTypeError, "No type found for #{attribute_name}"
76
+ else
77
+ klass
78
+ end
79
+ end
80
+ 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