abide_dev_utils 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf0d6affedd8f13f06af7f1f0db11666b9df2707d87a7685a4bd39ecd3e1519d
4
- data.tar.gz: 0f20af443ff1e13f9e854daa5e7cf5ec45213dfe9a2f0390c250dac92a8cc8d3
3
+ metadata.gz: 3978f655b9053e54d4fd63d456d3d65b9079c7684c6fcc88a3f764ead1aa012a
4
+ data.tar.gz: 746265daf86c8095a0f4ddbf9909d85a30ba2495b2b449e19896584c6e88da2b
5
5
  SHA512:
6
- metadata.gz: '097e88fb6b19170c2b727fd8873fa3dbb766ace25a7538ab8cfbd0a35083cb11654b58fb7f45ee7130d7c4f4cb48b8b241de4849b0cb406de8f7eb62cf09ce68'
7
- data.tar.gz: 4c0bc197da434b0ee25c9854b4b2af98a6ad9600733b734f9be21022ce312d7e8f0aea4f27c2217c3f56f7d2df26fedfe228f80b60fcd04da4ec08877a86bc54
6
+ metadata.gz: a6bbb36782aff2d06e4fd55ea66582cf64c4414c2e13f1c3cca76c8b1c33c420f76474b058c2e2ce49bb294efc01b677588957fa8f745d3b2fa022683253281f
7
+ data.tar.gz: 78f92a917f547ba04f17610e0bca9cc5816efaadf7b066645cc75e40c303173a9b0d3e27ea0d7a741219f88c5e479810e14f180fc813cd5a31e3d6f0ee4bf65e
data/.gitignore CHANGED
@@ -6,7 +6,8 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
9
+ w10_20h2.xml
10
+ w10_2004.xml
10
11
  # rspec failure tracking
11
12
  .rspec_status
12
13
  Gemfile.lock
data/.rubocop.yml CHANGED
@@ -12,7 +12,7 @@ AllCops:
12
12
  - 'tmp/**/*'
13
13
  - '.git/**/*'
14
14
  - 'bin/*'
15
- TargetRubyVersion: 2.5
15
+ TargetRubyVersion: 2.7
16
16
  SuggestExtensions: false
17
17
 
18
18
  Naming/PredicateName:
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @puppetlabs/abide-team
@@ -7,14 +7,14 @@ require "abide_dev_utils/version"
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = "abide_dev_utils"
9
9
  spec.version = AbideDevUtils::VERSION
10
- spec.authors = ["Heston Snodgrass"]
11
- spec.email = ["hsnodgrass3@gmail.com"]
10
+ spec.authors = ["abide-team"]
11
+ spec.email = ["abide-team@puppet.com"]
12
12
 
13
- spec.summary = "Helper utilities for developing Abide"
14
- spec.description = "Provides a CLI with helpful utilities for developing Abide"
15
- spec.homepage = "https://github.com/hsnodgrass/abide_dev_utils"
13
+ spec.summary = "Helper utilities for developing compliance Puppet code"
14
+ spec.description = "Provides a CLI with helpful utilities for developing compliance Puppet code"
15
+ spec.homepage = "https://github.com/puppetlabs/abide_dev_utils"
16
16
  spec.license = "MIT"
17
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
17
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
18
18
 
19
19
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
20
20
 
@@ -39,6 +39,7 @@ Gem::Specification.new do |spec|
39
39
  spec.add_dependency 'ruby-progressbar', '~> 1.11'
40
40
  spec.add_dependency 'selenium-webdriver', '~> 4.0.0.beta4'
41
41
  spec.add_dependency 'google-cloud-storage', '~> 1.34'
42
+ spec.add_dependency 'hashdiff', '~> 1.0'
42
43
 
43
44
  # Dev dependencies
44
45
  spec.add_development_dependency 'bundler'
data/itests.rb ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'abide_dev_utils/comply'
7
+ require 'abide_dev_utils/ppt/api'
8
+
9
+ OS_BENCHMARK_MAP = {
10
+ 'centos-7' => 'CIS_CentOS_Linux_7_Benchmark_v3.1.1-xccdf.xml',
11
+ 'centos-8' => 'CIS_CentOS_Linux_8_Benchmark_v1.0.1-xccdf.xml',
12
+ 'rhel-7' => 'CIS_Red_Hat_Enterprise_Linux_7_Benchmark_v3.1.1-xccdf.xml',
13
+ 'rhel-8' => 'CIS_Red_Hat_Enterprise_Linux_8_Benchmark_v1.0.1-xccdf.xml',
14
+ 'serv-2016' => 'CIS_Microsoft_Windows_Server_2016_RTM_(Release_1607)_Benchmark_v1.3.0-xccdf.xml',
15
+ 'serv-2019' => 'CIS_Microsoft_Windows_Server_2019_Benchmark_v1.2.1-xccdf.xml'
16
+ }
17
+ EL_PROFILE_1_SERVER = 'xccdf_org.cisecurity.benchmarks_profile_Level_1_-_Server'
18
+ WIN_PROFILE_1_MS = 'xccdf_org.cisecurity.benchmarks_profile_Level_1_-_Member_Server'
19
+ NIX_SCAN_HASH = {
20
+ 'nix-centos-7.c.team-sse.internal' => {
21
+ 'benchmark' => OS_BENCHMARK_MAP['centos-7'],
22
+ 'profile' => EL_PROFILE_1_SERVER
23
+ },
24
+ 'nix-centos-8.c.team-sse.internal' => {
25
+ 'benchmark' => OS_BENCHMARK_MAP['centos-8'],
26
+ 'profile' => EL_PROFILE_1_SERVER
27
+ },
28
+ 'nix-rhel-7.c.team-sse.internal' => {
29
+ 'benchmark' => OS_BENCHMARK_MAP['rhel-7'],
30
+ 'profile' => EL_PROFILE_1_SERVER
31
+ },
32
+ 'nix-rhel-8.c.team-sse.internal' => {
33
+ 'benchmark' => OS_BENCHMARK_MAP['rhel-8'],
34
+ 'profile' => EL_PROFILE_1_SERVER
35
+ }
36
+ }.freeze
37
+ WIN_SCAN_HASH = {
38
+ 'win-server-2016.c.team-sse.internal' => {
39
+ 'benchmark' => OS_BENCHMARK_MAP['serv-2016'],
40
+ 'profile' => EL_PROFILE_1_SERVER
41
+ },
42
+ 'win-serv-2019.c.team-sse.internal' => {
43
+ 'benchmark' => OS_BENCHMARK_MAP['serv-2019'],
44
+ 'profile' => WIN_PROFILE_1_MS
45
+ }
46
+ }.freeze
47
+
48
+ scan_hash = ENV['ABIDE_OS'] == 'nix' ? NIX_SCAN_HASH : WIN_SCAN_HASH
49
+ node_group_name = ENV['ABIDE_OS'] == 'nix' ? 'CEM Linux Nodes' : 'CEM Windows Nodes'
50
+
51
+ puts 'Creating client...'
52
+ client = AbideDevUtils::Ppt::ApiClient.new(ENV['PUPPET_HOST'], auth_token: ENV['PE_ACCESS_TOKEN'])
53
+ puts 'Starting code deploy...'
54
+ code_manager_deploy = client.post_codemanager_deploys('environments' => ['production'], 'wait' => true)
55
+ raise 'Code manager deployment failed!' unless code_manager_deploy['status'] == 'complete'
56
+
57
+ puts 'Code deploy successful...'
58
+ puts 'Gathering node group ID...'
59
+ node_groups = client.get_classifier1_groups
60
+ node_group_id = nil
61
+ node_groups.each { |x| node_group_id = x['id'] if x['name'] == node_group_name }
62
+ raise 'Failed to find requested node group!' if node_group_id.nil?
63
+
64
+ puts 'Running Puppet on nodes...'
65
+ puppet_run = client.post_orchestrator_command_deploy('environment' => 'production', 'scope' => { 'node_group' => node_group_id })
66
+ puts "Started job #{puppet_run['job']['name']}..."
67
+ timeout = 0
68
+ run_complete = false
69
+ until run_complete || timeout >= 30
70
+ puts "Waiting on job #{puppet_run['job']['name']} to complete..."
71
+ status = client.get_orchestrator_jobs(puppet_run['job']['name'])
72
+ case status['state']
73
+ when 'failed'
74
+ raise "Job #{puppet_run['job']['name']} finished with failures!"
75
+ when 'finished'
76
+ run_complete = true
77
+ break
78
+ else
79
+ timeout += 1
80
+ sleep(10)
81
+ end
82
+ end
83
+ raise 'Job timed out waiting for completion' unless run_complete
84
+
85
+ puts 'Starting node scans...'
86
+ scan_job = client.post_orchestrator_command_task(
87
+ 'environment' => 'production',
88
+ 'task' => 'comply::ciscat_scan',
89
+ 'params' => {
90
+ 'comply_port' => '443',
91
+ 'comply_server' => ENV['COMPLY_FQDN'],
92
+ 'ssl_verify_mode' => 'none',
93
+ 'scan_type' => 'desired',
94
+ 'scan_hash' => JSON.generate(scan_hash)
95
+ },
96
+ 'scope' => {
97
+ 'node_group' => node_group_id
98
+ }
99
+ )
100
+ puts "Started scan #{scan_job['job']['name']}..."
101
+ timeout = 0
102
+ scan_complete = false
103
+ until scan_complete || timeout >= 30
104
+ puts "Waiting on scan #{scan_job['job']['name']} to complete..."
105
+ status = client.get_orchestrator_jobs(scan_job['job']['name'])
106
+ case status['state']
107
+ when 'failed'
108
+ raise "Task #{scan_job['job']['name']} finished with failures!"
109
+ when 'finished'
110
+ scan_complete = true
111
+ break
112
+ else
113
+ timeout += 1
114
+ sleep(10)
115
+ end
116
+ end
117
+ raise 'Job timed out waiting for completion' unless scan_complete
118
+
119
+ puts 'Collecting scan report from Comply...'
120
+ onlylist = scan_hash.keys
121
+ scan_report = AbideDevUtils::Comply.build_report("https://#{ENV['COMPLY_FQDN']}", ENV['COMPLY_PASSWORD'], nil, onlylist: onlylist)
122
+ puts 'Saving report to nix_report.yaml...'
123
+ File.open('nix_report.yaml', 'w') { |f| f.write(scan_report.to_yaml) }
124
+
125
+ puts 'Comparing current report to last report...'
126
+ opts = {
127
+ report_name: 'nix_report.yaml',
128
+ remote_storage: 'gcloud',
129
+ upload: true
130
+ }
131
+ result = AbideDevUtils::Comply.compare_reports(File.expand_path('./nix_report.yaml'), 'nix_report.yaml', opts)
132
+ if result
133
+ puts 'Success!'
134
+ exit(0)
135
+ else
136
+ puts 'Failure!'
137
+ exit(1)
138
+ end
@@ -12,6 +12,7 @@ module Abide
12
12
  def initialize
13
13
  super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: true)
14
14
  add_command(ComplyReportCommand.new)
15
+ add_command(ComplyCompareReportCommand.new)
15
16
  end
16
17
  end
17
18
 
@@ -57,23 +58,19 @@ module Abide
57
58
  options.on('-t [SECONDS]', '--timeout [SECONDS]', OPT_TIMEOUT_DESC) do |t|
58
59
  @data[:timeout] = t
59
60
  end
60
- options.on('-s x,y,z', '--status x,y,x',
61
+ options.on('-s [X,Y,Z]', '--status [X,Y,Z]',
61
62
  %w[pass fail error notapplicable notchecked unknown informational],
62
63
  Array,
63
64
  OPT_STATUS_DESC) do |s|
64
65
  s&.map! { |i| i == 'notchecked' ? 'not checked' : i }
65
66
  @data[:status] = s
66
67
  end
67
- options.on('--only x,y,z', Array, OPT_ONLY_NODES) do |o|
68
+ options.on('--only [X,Y,Z]', Array, OPT_ONLY_NODES) do |o|
68
69
  @data[:onlylist] = o
69
70
  end
70
- options.on('--ignore x,y,z', Array, OPT_IGNORE_NODES) do |i|
71
+ options.on('--ignore [X,Y,Z]', Array, OPT_IGNORE_NODES) do |i|
71
72
  @data[:ignorelist] = i
72
73
  end
73
- # options.on('-R', '--[no-]regression-test', OPT_REGRESSION_TEST) do |r|
74
- # @data[:regression] = r
75
- # end
76
- # options.on('--')
77
74
  end
78
75
 
79
76
  def help_arguments
@@ -95,5 +92,24 @@ module Abide
95
92
  Abide::CLI::OUTPUT.yaml(report, file: outfile)
96
93
  end
97
94
  end
95
+
96
+ class ComplyCompareReportCommand < AbideCommand
97
+ CMD_NAME = 'compare-report'
98
+ CMD_SHORT = 'Compare two Comply reports and get the differences.'
99
+ CMD_LONG = 'Compare two Comply reports and get the differences. Report A is compared to report B, showing what changes it would take for A to equal B.'
100
+ CMD_REPORT_A = 'The current Comply report yaml file'
101
+ CMD_REPORT_B = 'The old Comply report yaml file name or full path'
102
+ def initialize
103
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
104
+ argument_desc(REPORT_A: CMD_REPORT_A, REPORT_B: CMD_REPORT_B)
105
+ options.on('-u', '--upload-new', 'If you want to upload the new scan report') { @data[:upload] = true }
106
+ options.on('-s [STORAGE]', '--remote-storage [STORAGE]', 'Remote storage to upload the report to. (Only supports "gcloud")') { |x| @data[:remote_storage] = x }
107
+ options.on('-r [NAME]', '--name [NAME]', 'The name to upload the report as') { |x| @data[:report_name] = x }
108
+ end
109
+
110
+ def execute(report_a, report_b)
111
+ AbideDevUtils::Comply.compare_reports(report_a, report_b, @data)
112
+ end
113
+ end
98
114
  end
99
115
  end
@@ -217,5 +217,23 @@ module Abide
217
217
  AbideDevUtils::Ppt.add_cis_comment(path, xccdf, number_format: @data.fetch(:number_format, false))
218
218
  end
219
219
  end
220
+
221
+ class PuppetScoreModuleCommand < AbideCommand
222
+ CMD_NAME = 'score'
223
+ CMD_SHORT = 'Scores a Puppet module just like Puppet Forge'
224
+ CMD_LONG = 'Scores a Puppet module just like Puppet Forge. This is a useful quality-check before publishing a module.'
225
+ def initialize
226
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
227
+ options.on('-o [PATH]', '--outfile [PATH]', 'Save results to a file') { |x| @data[:outfile] = x }
228
+ options.on('-q', '--quiet', FalseClass, 'Do not print results to console') { |x| @data[:quiet] = x }
229
+ options.on('-c', '--checks', Array, 'Comma-separated list of individual checks to run. Defaults to running all checks.') { |x| @data[:check] = x }
230
+ options.on('-m [PATH]', '--module [PATH]', 'Path to a Puppet module to score. Defaults to using the current directory.') { |x| @data[:module] = x }
231
+ end
232
+
233
+ def execute
234
+ module_path = @data.fetch(:module, nil)
235
+ AbideDevUtils::Ppt.score_module(module_path, **@data)
236
+ end
237
+ end
220
238
  end
221
239
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'abide_dev_utils/cli/abstract'
3
4
  require 'abide_dev_utils/xccdf'
4
5
 
5
6
  module Abide
@@ -14,11 +15,12 @@ module Abide
14
15
  long_desc(CMD_LONG)
15
16
  add_command(CmdParse::HelpCommand.new, default: true)
16
17
  add_command(XccdfToHieraCommand.new)
18
+ add_command(XccdfDiffCommand.new)
17
19
  end
18
20
  end
19
21
 
20
22
  class XccdfToHieraCommand < CmdParse::Command
21
- CMD_NAME = 'to_hiera'
23
+ CMD_NAME = 'to-hiera'
22
24
  CMD_SHORT = 'Generates control coverage report'
23
25
  CMD_LONG = 'Generates report of valid Puppet classes that match with Hiera controls'
24
26
  def initialize
@@ -37,15 +39,32 @@ module Abide
37
39
 
38
40
  def execute(xccdf_file)
39
41
  @data[:type] = 'cis' if @data[:type].nil?
40
-
41
- to_hiera(xccdf_file)
42
+ hfile = AbideDevUtils::XCCDF.to_hiera(xccdf_file, @data)
43
+ AbideDevUtils::Output.yaml(hfile, console: @data[:file].nil?, file: @data[:file])
42
44
  end
45
+ end
43
46
 
44
- private
47
+ class XccdfDiffCommand < AbideCommand
48
+ CMD_NAME = 'diff'
49
+ CMD_SHORT = 'Generates a diff report between two XCCDF files'
50
+ CMD_LONG = 'Generates a diff report between two XCCDF files'
51
+ CMD_FILE1_ARG = 'path to first XCCDF file'
52
+ CMD_FILE2_ARG = 'path to second XCCDF file'
53
+ def initialize
54
+ super(CMD_NAME, CMD_SHORT, CMD_LONG, takes_commands: false)
55
+ argument_desc(FILE1: CMD_FILE1_ARG, FILE2: CMD_FILE2_ARG)
56
+ options.on('-o [PATH]', '--out-file', 'Save the report as a yaml file') { |x| @data[:outfile] = x }
57
+ options.on('-p [PROFILE]', '--profile', 'Only diff and specific profile in the benchmarks') do |x|
58
+ @data[:profile] = x
59
+ end
60
+ options.on('-q', '--quiet', 'Show no output in the terminal') { @data[:quiet] = false }
61
+ options.on('--no-diff-profiles', 'Do not diff the profiles in the XCCDF files') { @data[:diff_profiles] = false }
62
+ options.on('--no-diff-controls', 'Do not diff the controls in the XCCDF files') { @data[:diff_controls] = false }
63
+ end
45
64
 
46
- def to_hiera(xccdf_file)
47
- xfile = AbideDevUtils::XCCDF.to_hiera(xccdf_file, @data)
48
- Abide::CLI::OUTPUT.yaml(xfile, console: @data[:file].nil?, file: @data[:file])
65
+ def execute(file1, file2)
66
+ diffreport = AbideDevUtils::XCCDF.diff(file1, file2, @data)
67
+ AbideDevUtils::Output.yaml(diffreport, console: @data.fetch(:quiet, true), file: @data.fetch(:outfile, nil))
49
68
  end
50
69
  end
51
70
  end