opencontrol-linter 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +94 -0
  4. data/exe/opencontrol-linter +8 -0
  5. data/lib/opencontrol.rb +3 -0
  6. data/lib/opencontrol/cli.rb +231 -0
  7. data/lib/opencontrol/messages.rb +45 -0
  8. data/lib/opencontrol/version.rb +22 -0
  9. data/vendor/README.md +9 -0
  10. data/vendor/schemas/CONTRIBUTING.md +37 -0
  11. data/vendor/schemas/README.md +175 -0
  12. data/vendor/schemas/examples/component_v3.0.0.yaml +70 -0
  13. data/vendor/schemas/examples/component_v3.1.0.yaml +81 -0
  14. data/vendor/schemas/examples/opencontrol_v1.0.0.yaml +22 -0
  15. data/vendor/schemas/kwalify/README.md +31 -0
  16. data/vendor/schemas/kwalify/certification/v1.0.0.yaml +12 -0
  17. data/vendor/schemas/kwalify/component/test_data_validity.py +25 -0
  18. data/vendor/schemas/kwalify/component/v1.0.0.yaml +100 -0
  19. data/vendor/schemas/kwalify/component/v2.0.0.yaml +100 -0
  20. data/vendor/schemas/kwalify/component/v3.0.0.yaml +112 -0
  21. data/vendor/schemas/kwalify/component/v3.1.0.yaml +138 -0
  22. data/vendor/schemas/kwalify/opencontrol/v1.0.0.yaml +67 -0
  23. data/vendor/schemas/kwalify/requirements.txt +3 -0
  24. data/vendor/schemas/kwalify/standard/v1.0.0.yaml +14 -0
  25. data/vendor/schemas/transformation-scripts/utils.py +12 -0
  26. data/vendor/schemas/transformation-scripts/v1_example.yaml +40 -0
  27. data/vendor/schemas/transformation-scripts/v1_from_v2_example.yaml +41 -0
  28. data/vendor/schemas/transformation-scripts/v1_to_v2.py +75 -0
  29. data/vendor/schemas/transformation-scripts/v2_example.yaml +45 -0
  30. data/vendor/schemas/transformation-scripts/v2_from_v1_example.yaml +45 -0
  31. data/vendor/schemas/transformation-scripts/v2_to_v1.py +74 -0
  32. metadata +320 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5809df9b521e096796e994cacf885be8dd2d41b
4
+ data.tar.gz: 4b1b9250c44fbc75d3a2b941003de47a5f0def13
5
+ SHA512:
6
+ metadata.gz: 27353289411c6cf7bd42794274c6a134a89c51b3cf7555c6bafc047ec2bbfce4b743760c4719a58451f2e9d3b9c8495437e609c6687c41bef4448b91928f57ba
7
+ data.tar.gz: 722a2e65f5f4c6aaa2a8d7806f34669513e195cde7fd654927d3dd514427c0d88286de961abbbd73ac7813f29ea380136ca19796687601ca701fd3ada2fb1d4d
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2019 Center for Medicare Services
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ [![CircleCI](https://circleci.com/gh/huge-robot/opencontrol-linter.svg?style=svg&circle-token=7873c3440387ef3e3b04964f5c51a15f7e3f26de)](https://circleci.com/gh/huge-robot/opencontrol-linter)
2
+
3
+
4
+ **Open Control Linter** is a linter for the OpenControl standard of security controls.
5
+ Use it to check the correctness of opencontrols components, standards and certifications quickly.
6
+
7
+ To find out more about opencontrol see:
8
+ http://opencontrol.cfapps.io/
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ $ gem install opencontrol-linter
14
+ ```
15
+
16
+ If you'd rather install Open Control Linter using `bundler`, don't require it in your `Gemfile`:
17
+
18
+ ```rb
19
+ gem 'opencontrol-linter', require: false
20
+ ```
21
+
22
+ ## Quickstart
23
+
24
+ Just type `opencontrol-linter` in a control project root directory.
25
+
26
+ ```
27
+ $ cd awesome/opencontrols/
28
+ $ opencontrol-linter
29
+ ```
30
+
31
+ ## Documentation
32
+
33
+ Detailed command line arguments
34
+
35
+ ```
36
+ usage: opencontrol-linter
37
+
38
+ optional arguments:
39
+ -h, --help show this help message and exit
40
+ -c, --components
41
+ Specify component files should be checked. Defaults to
42
+ true. Searches ./**/component.yaml or the search you
43
+ optionally specify.
44
+ -n, --certifications
45
+ Specify certification (eg FISMA high)files should be
46
+ checked. Defaults to true. Searches
47
+ ./certifications/*.yaml or the search you optionally
48
+ specify.
49
+ -s, --standards
50
+ Specify standard files (eg NIST 800.53) should be
51
+ checked. Defaults to true. Searches ./standards/*.yaml
52
+ or the search you optionally specify.
53
+ -a, --all Run all types of validations (this is the default).
54
+ -v, --version Show the version of this utility.
55
+
56
+
57
+ ```
58
+
59
+ Usage examples
60
+
61
+ ```
62
+ # lint all components, standards and certifications in the current directory
63
+ opencontrol-linter
64
+
65
+ # lint all components subdir components
66
+ opencontrol-linter --components './components/**/component.yaml'
67
+
68
+ # lint all standards files found
69
+ opencontrol-linter --standards
70
+
71
+ # lint one component
72
+ opencontrol-linter --components './components/AU_policy/component.yaml'
73
+
74
+ ```
75
+
76
+ ## Compatibility
77
+
78
+ Open Control Linter supports the following Open Control schemas:
79
+
80
+ - Component: (all v1.0 through v3.1)
81
+ - Standard: (all v1.0 through v1.0)
82
+ - Certification: (all v1.0 through v1.0)
83
+
84
+ ## Related
85
+ http://opencontrol.cfapps.io/
86
+ https://github.com/opencontrol
87
+
88
+ ## Team
89
+
90
+ Here's a list of Open Control Linter's core developers:
91
+
92
+ * [Adrian Kierman](https://github.com/adriankierman)
93
+ * James Connor
94
+
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift("#{__dir__}/../lib")
5
+
6
+ require 'opencontrol'
7
+
8
+ Opencontrol::CLI.run_with_args(ARGV)
@@ -0,0 +1,3 @@
1
+ require_relative 'opencontrol/version'
2
+ require_relative 'opencontrol/messages'
3
+ require_relative 'opencontrol/cli'
@@ -0,0 +1,231 @@
1
+ require 'kwalify'
2
+ require 'yaml'
3
+ require 'opencontrol'
4
+ require 'rationalist'
5
+ require 'colorize'
6
+ require 'pp'
7
+
8
+ # frozen_string_literal: true
9
+
10
+ module Opencontrol
11
+ # This module holds the Opencontrol Linter Command Line Interface.
12
+ module CLI
13
+ USAGE_TEXT = <<USAGE_TEXT.freeze
14
+ usage: opencontrol-linter
15
+
16
+ optional arguments:
17
+ -h, --help show this help message and exit
18
+ -c, --components
19
+ Specify component files should be checked. Defaults to
20
+ true. Searches ./**/component.yaml or the search you
21
+ optionally specify.
22
+ -n, --certifications
23
+ Specify certification (eg FISMA high)files should be
24
+ checked. Defaults to true. Searches
25
+ ./certifications/*.yaml or the search you optionally
26
+ specify.
27
+ -s, --standards
28
+ Specify standard files (eg NIST 800.53) should be
29
+ checked. Defaults to true. Searches ./standards/*.yaml
30
+ or the search you optionally specify.
31
+ -a, --all Run all types of validations (this is the default).
32
+ -v, --version Show the version of this utility.
33
+
34
+ Usage examples:
35
+
36
+ # lint all components, standards and certifications in the current directory
37
+ opencontrol-linter
38
+
39
+ # lint all components subdir components
40
+ opencontrol-linter --components './components/**/component.yaml'
41
+
42
+ # lint all standards files found
43
+ opencontrol-linter --standards
44
+
45
+ # lint one component
46
+ opencontrol-linter --components './components/AU_policy/component.yaml'
47
+ USAGE_TEXT
48
+
49
+ DEFAULT_SPECIFICATION = {
50
+ action: :run,
51
+ targets: [
52
+ {
53
+ type: :components,
54
+ pattern: '**/component.yaml'
55
+ },
56
+ {
57
+ type: :standards,
58
+ pattern: './standards/*.yaml'
59
+ },
60
+ {
61
+ type: :certifications,
62
+ pattern: './certifications/*.yaml'
63
+ }
64
+ ]
65
+ }.freeze
66
+
67
+ def self.show_help
68
+ puts USAGE_TEXT
69
+ 0 # exit with no error
70
+ end
71
+
72
+ def self.show_version
73
+ puts 'Opencontrol linter version: v' + Opencontrol::Version.version
74
+ puts 'CMS 2019 Adrian Kierman '
75
+ 0 # exit with no error
76
+ end
77
+
78
+ # @param [String] version
79
+ def self.find_schema(type, version)
80
+ dir = __dir__
81
+ case type
82
+ when :components
83
+ "#{dir}/../../vendor/schemas/kwalify/component/v#{version}.yaml"
84
+ when :standards
85
+ "#{dir}/../../vendor/schemas/kwalify/standard/v#{version}.yaml"
86
+ when :certifications
87
+ "#{dir}/../../vendor/schemas/kwalify/certification/v#{version}.yaml"
88
+ else
89
+ throw "Unknown type of schema specified #{type} " \
90
+ "tried to get schema version #{version}"
91
+ end
92
+ end
93
+
94
+ def self.load_schema(schema_file)
95
+ ## load schema data
96
+ # Kwalify::Yaml.load_file(schema_file)
97
+ ## or
98
+ YAML.load_file(schema_file)
99
+ end
100
+
101
+ def self.show_issues(issues, filename)
102
+ if issues && !issues.empty?
103
+ puts "✗ #{filename}".red
104
+ issues.each do |issue|
105
+ puts Opencontrol::Messages.detail(issue).yellow
106
+ end
107
+ else
108
+ puts "✓ #{filename}".green
109
+ end
110
+ end
111
+
112
+ def self.schema_for_document(type, document)
113
+ version = document['schema_version'] || '1.0.0'
114
+ schema_file = find_schema(type, version)
115
+ load_schema(schema_file)
116
+ end
117
+
118
+ def self.targets_for_type(type, specification)
119
+ specification[:targets].select { |t| t[:type] == type }
120
+ end
121
+
122
+ def self.default_pattern_for_type(type)
123
+ targets_for_type(type, DEFAULT_SPECIFICATION).first[:pattern]
124
+ end
125
+
126
+ def self.add_target(type, opts, specification)
127
+ # pick a reasonable default
128
+ use_defaults = false
129
+ use_defaults = default_pattern_for_type(type) if opts[type] == true
130
+ specification[:targets].push(
131
+ type: type,
132
+ pattern: use_defaults || opts[type]
133
+ )
134
+ end
135
+
136
+ def self.validate(type, filename)
137
+ ## load document
138
+ # document = Kwalify::Yaml.load_file(filename)
139
+ ## or
140
+ document = YAML.load_file(filename)
141
+ schema = schema_for_document(type, document)
142
+
143
+ validator = Kwalify::Validator.new(schema)
144
+ validator.validate(document)
145
+ end
146
+
147
+ def self.files_not_found_issue
148
+ Kwalify::BaseError.new(
149
+ 'No validation files found for the pattern supplied. \
150
+ Adding an issue to avoid failing silently.',
151
+ nil,
152
+ nil,
153
+ nil,
154
+ :linter_files_not_found_issue
155
+ )
156
+ end
157
+
158
+ def self.validate_target(target)
159
+ filenames = Dir[target[:pattern]]
160
+ if filenames.empty?
161
+ issues = [files_not_found_issue]
162
+ show_issues(issues, target[:pattern])
163
+ return issues
164
+ end
165
+ filenames.collect do |filename|
166
+ issues = validate(target[:type], filename)
167
+ show_issues(issues, filename)
168
+ issues
169
+ end
170
+ end
171
+
172
+ def self.validate_all(specification)
173
+ specification[:targets].collect do |target|
174
+ validate_target(target)
175
+ end.flatten
176
+ end
177
+
178
+ def self.should_lint?(opts)
179
+ !(opts[:version] || opts[:help])
180
+ end
181
+
182
+ def self.all_targets_selected?(opts, specification)
183
+ opts[:all] || specification[:targets].empty?
184
+ end
185
+
186
+ def self.use_default?(opts, specification)
187
+ all_targets_selected?(opts, specification) && should_lint?(opts)
188
+ end
189
+
190
+ ALIASES = {
191
+ components: %w[component c],
192
+ standards: %w[standard s],
193
+ certifications: %w[certification n],
194
+ all: 'a',
195
+ help: 'h',
196
+ version: 'v'
197
+ }.freeze
198
+
199
+ def self.parse_args(arguments)
200
+ opts = Rationalist.parse(arguments, alias: ALIASES)
201
+ specification = {
202
+ action: :run,
203
+ targets: []
204
+ }
205
+ specification[:action] = :version if opts[:version]
206
+ specification[:action] = :help if opts[:help]
207
+ add_target(:components, opts, specification) if opts[:components]
208
+ add_target(:standards, opts, specification) if opts[:standards]
209
+ add_target(:certifications, opts, specification) if opts[:certifications]
210
+ specification = DEFAULT_SPECIFICATION if use_default?(opts, specification)
211
+ specification
212
+ end
213
+
214
+ def self.run(specification)
215
+ issues = validate_all(specification)
216
+ if !issues.empty?
217
+ puts "Complete. #{issues.length} issues found.".red
218
+ else
219
+ puts 'Complete. No problems found.'.green
220
+ end
221
+ issues.length
222
+ end
223
+
224
+ def self.run_with_args(args)
225
+ specification = parse_args(args)
226
+ exit(run(specification)) if specification[:action] == :run
227
+ show_version if specification[:action] == :version
228
+ show_help if specification[:action] == :help
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kwalify'
4
+
5
+ module Opencontrol
6
+ # This module holds the Opencontrol Linter detailed issue messages.
7
+ module Messages
8
+ def self.detail(issue)
9
+ case issue.error_symbol
10
+ when :enum_notexist
11
+ <<-MESSAGE
12
+ At: YAML path #{issue.path}.
13
+ Message: #{issue.message}
14
+ Expected: one of #{issue.rule.enum}.
15
+ Actual: The value '#{issue.value}' was found.
16
+ To fix this: Use one of #{issue.rule.enum}
17
+ instead of the value '#{issue.value}'
18
+ MESSAGE
19
+ when :key_undefined
20
+ <<-MESSAGE
21
+ At: YAML path #{issue.path}.
22
+ Expected: A key allowed by the schema.
23
+ Actual: A key was found that is not defined in the schema (#{issue.path}).
24
+ To fix this: Its possible the key found is a typo,
25
+ Remove #{issue.path} or correct the key.
26
+ MESSAGE
27
+ else
28
+ <<-MESSAGE
29
+ At: YAML path #{issue.path}.
30
+ Message: #{issue.message}
31
+ MESSAGE
32
+ end
33
+ end
34
+
35
+ def self.verbose(issue)
36
+ <<-MESSAGE
37
+ At: YAML path #{issue.path}.
38
+ Message: #{issue.message}
39
+ Rule: #{issue.rule.to_yaml}
40
+ Value: #{issue.value}
41
+ Symbol: #{issue.error_symbol}
42
+ MESSAGE
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Opencontrol
4
+ # This module holds the Opencontrol Linter version information.
5
+ module Version
6
+ STRING = '0.1'.freeze
7
+
8
+ MSG = '%<version>s (using Parser %<parser_version>s, running on ' \
9
+ '%<ruby_engine>s %<ruby_version>s %<ruby_platform>s)'.freeze
10
+
11
+ def self.version(debug = false)
12
+ if debug
13
+ require 'kwalify'
14
+ format(MSG, version: STRING, parser_version: Kwalify::VERSION,
15
+ ruby_engine: RUBY_ENGINE, ruby_version: RUBY_VERSION,
16
+ ruby_platform: RUBY_PLATFORM)
17
+ else
18
+ STRING
19
+ end
20
+ end
21
+ end
22
+ end
data/vendor/README.md ADDED
@@ -0,0 +1,9 @@
1
+ - Schemas
2
+
3
+ A project of 18F
4
+
5
+ General Services Administration of the United States
6
+
7
+ https://github.com/opencontrol/schemas
8
+
9
+ Included here in vendorized form to allow easy distribution.