inspec-core 5.17.4 → 5.18.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/etc/deprecations.json +4 -0
  4. data/inspec-core.gemspec +1 -1
  5. data/lib/inspec/base_cli.rb +5 -0
  6. data/lib/inspec/cli.rb +62 -9
  7. data/lib/inspec/dependencies/dependency_set.rb +6 -2
  8. data/lib/inspec/dsl.rb +18 -5
  9. data/lib/inspec/errors.rb +2 -0
  10. data/lib/inspec/exceptions.rb +2 -0
  11. data/lib/inspec/fetcher/url.rb +1 -1
  12. data/lib/inspec/file_provider.rb +36 -0
  13. data/lib/inspec/iaf_file.rb +127 -0
  14. data/lib/inspec/profile.rb +17 -7
  15. data/lib/inspec/resources/aide_conf.rb +4 -0
  16. data/lib/inspec/resources/apache.rb +4 -0
  17. data/lib/inspec/resources/apache_conf.rb +4 -0
  18. data/lib/inspec/resources/apt.rb +6 -1
  19. data/lib/inspec/resources/audit_policy.rb +5 -0
  20. data/lib/inspec/resources/auditd_conf.rb +4 -0
  21. data/lib/inspec/resources/bash.rb +4 -0
  22. data/lib/inspec/resources/bond.rb +4 -0
  23. data/lib/inspec/resources/bridge.rb +4 -0
  24. data/lib/inspec/resources/cassandradb_conf.rb +5 -0
  25. data/lib/inspec/resources/cassandradb_session.rb +8 -3
  26. data/lib/inspec/resources/chocolatey_package.rb +4 -0
  27. data/lib/inspec/resources/chrony_conf.rb +4 -0
  28. data/lib/inspec/resources/command.rb +5 -0
  29. data/lib/inspec/resources/cpan.rb +4 -0
  30. data/lib/inspec/resources/cran.rb +4 -0
  31. data/lib/inspec/resources/cron.rb +5 -0
  32. data/lib/inspec/resources/csv.rb +6 -1
  33. data/lib/inspec/resources/dh_params.rb +4 -0
  34. data/lib/inspec/resources/docker_container.rb +4 -0
  35. data/lib/inspec/resources/docker_image.rb +4 -0
  36. data/lib/inspec/resources/docker_plugin.rb +4 -0
  37. data/lib/inspec/resources/docker_service.rb +4 -0
  38. data/lib/inspec/resources/etc_group.rb +4 -0
  39. data/lib/inspec/resources/etc_hosts_allow_deny.rb +5 -0
  40. data/lib/inspec/resources/file.rb +6 -1
  41. data/lib/inspec/resources/filesystem.rb +4 -0
  42. data/lib/inspec/resources/gem.rb +4 -0
  43. data/lib/inspec/resources/groups.rb +4 -0
  44. data/lib/inspec/resources/grub_conf.rb +4 -0
  45. data/lib/inspec/resources/host.rb +4 -0
  46. data/lib/inspec/resources/http.rb +4 -0
  47. data/lib/inspec/resources/ibmdb2_conf.rb +8 -0
  48. data/lib/inspec/resources/ibmdb2_session.rb +12 -3
  49. data/lib/inspec/resources/iis_app.rb +4 -0
  50. data/lib/inspec/resources/iis_app_pool.rb +4 -0
  51. data/lib/inspec/resources/iis_site.rb +4 -0
  52. data/lib/inspec/resources/inetd_conf.rb +4 -0
  53. data/lib/inspec/resources/interface.rb +4 -0
  54. data/lib/inspec/resources/ip6tables.rb +4 -0
  55. data/lib/inspec/resources/ipfilter.rb +4 -0
  56. data/lib/inspec/resources/ipnat.rb +4 -0
  57. data/lib/inspec/resources/iptables.rb +4 -0
  58. data/lib/inspec/resources/json.rb +4 -0
  59. data/lib/inspec/resources/kernel_module.rb +4 -0
  60. data/lib/inspec/resources/kernel_parameter.rb +4 -0
  61. data/lib/inspec/resources/key_rsa.rb +4 -0
  62. data/lib/inspec/resources/ksh.rb +4 -0
  63. data/lib/inspec/resources/limits_conf.rb +4 -0
  64. data/lib/inspec/resources/login_defs.rb +4 -0
  65. data/lib/inspec/resources/mongodb.rb +4 -0
  66. data/lib/inspec/resources/mongodb_conf.rb +5 -0
  67. data/lib/inspec/resources/mongodb_session.rb +6 -1
  68. data/lib/inspec/resources/mount.rb +4 -0
  69. data/lib/inspec/resources/mssql_session.rb +4 -0
  70. data/lib/inspec/resources/mssql_sys_conf.rb +7 -0
  71. data/lib/inspec/resources/mysql_conf.rb +4 -0
  72. data/lib/inspec/resources/mysql_session.rb +8 -1
  73. data/lib/inspec/resources/nginx.rb +6 -1
  74. data/lib/inspec/resources/nginx_conf.rb +4 -0
  75. data/lib/inspec/resources/noop.rb +4 -0
  76. data/lib/inspec/resources/npm.rb +4 -0
  77. data/lib/inspec/resources/ntp_conf.rb +4 -0
  78. data/lib/inspec/resources/oneget.rb +4 -0
  79. data/lib/inspec/resources/opa_api.rb +10 -0
  80. data/lib/inspec/resources/opa_cli.rb +14 -0
  81. data/lib/inspec/resources/oracledb_conf.rb +5 -0
  82. data/lib/inspec/resources/oracledb_listener_conf.rb +4 -0
  83. data/lib/inspec/resources/oracledb_session.rb +10 -0
  84. data/lib/inspec/resources/os.rb +4 -0
  85. data/lib/inspec/resources/os_env.rb +4 -0
  86. data/lib/inspec/resources/package.rb +4 -0
  87. data/lib/inspec/resources/parse_config.rb +10 -1
  88. data/lib/inspec/resources/pip.rb +4 -0
  89. data/lib/inspec/resources/platform.rb +4 -0
  90. data/lib/inspec/resources/postfix_conf.rb +4 -0
  91. data/lib/inspec/resources/postgres_conf.rb +4 -0
  92. data/lib/inspec/resources/postgres_session.rb +8 -4
  93. data/lib/inspec/resources/powershell.rb +4 -0
  94. data/lib/inspec/resources/processes.rb +6 -4
  95. data/lib/inspec/resources/rabbitmq_config.rb +4 -0
  96. data/lib/inspec/resources/registry_key.rb +4 -0
  97. data/lib/inspec/resources/security_identifier.rb +4 -0
  98. data/lib/inspec/resources/security_policy.rb +4 -0
  99. data/lib/inspec/resources/service.rb +4 -0
  100. data/lib/inspec/resources/ssh_config.rb +4 -0
  101. data/lib/inspec/resources/sybase_conf.rb +4 -0
  102. data/lib/inspec/resources/sybase_session.rb +4 -0
  103. data/lib/inspec/resources/sys_info.rb +4 -0
  104. data/lib/inspec/resources/timezone.rb +4 -0
  105. data/lib/inspec/resources/users.rb +4 -0
  106. data/lib/inspec/resources/vbscript.rb +5 -0
  107. data/lib/inspec/resources/virtualization.rb +4 -0
  108. data/lib/inspec/resources/windows_feature.rb +5 -1
  109. data/lib/inspec/resources/windows_firewall.rb +4 -0
  110. data/lib/inspec/resources/windows_firewall_rule.rb +4 -0
  111. data/lib/inspec/resources/windows_hotfix.rb +4 -0
  112. data/lib/inspec/resources/windows_task.rb +4 -0
  113. data/lib/inspec/resources/wmi.rb +4 -0
  114. data/lib/inspec/resources/x509_certificate.rb +59 -0
  115. data/lib/inspec/resources/yum.rb +4 -0
  116. data/lib/inspec/resources/zfs_dataset.rb +4 -0
  117. data/lib/inspec/resources/zfs_pool.rb +4 -0
  118. data/lib/inspec/rule.rb +1 -1
  119. data/lib/inspec/secrets/yaml.rb +7 -1
  120. data/lib/inspec/ui.rb +1 -0
  121. data/lib/inspec/utils/yaml_profile_summary.rb +34 -0
  122. data/lib/inspec/version.rb +1 -1
  123. data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +4 -4
  124. data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +1 -1
  125. data/lib/plugins/inspec-reporter-html2/templates/profile.html.erb +1 -1
  126. data/lib/plugins/{inspec-artifact/inspec-artifact.gemspec → inspec-sign/inspec-sign.gemspec} +2 -2
  127. data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +161 -0
  128. data/lib/plugins/{inspec-artifact/lib/inspec-artifact → inspec-sign/lib/inspec-sign}/cli.rb +14 -23
  129. data/lib/plugins/inspec-sign/lib/inspec-sign.rb +12 -0
  130. data/lib/source_readers/inspec.rb +8 -2
  131. metadata +10 -8
  132. data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +0 -187
  133. data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +0 -12
@@ -83,6 +83,11 @@ module Inspec::Resources
83
83
  @parsed_subject = Hashie::Mash.new(Hash[@cert.subject.to_a.map { |k, v, _| [k, v] }])
84
84
  end
85
85
 
86
+ # This property is equivalent to subject.emailAddress
87
+ def email
88
+ subject.emailAddress
89
+ end
90
+
86
91
  def issuer_dn
87
92
  return if @cert.nil?
88
93
 
@@ -104,6 +109,8 @@ module Inspec::Resources
104
109
  @cert.public_key.n.num_bytes * 8
105
110
  end
106
111
 
112
+ alias :keylength :key_length
113
+
107
114
  def validity_in_days
108
115
  (not_after - Time.now.utc) / 86400
109
116
  end
@@ -138,6 +145,50 @@ module Inspec::Resources
138
145
  @extensions
139
146
  end
140
147
 
148
+ # check purpose of the certificate
149
+ def has_purpose?(purpose)
150
+ # If we have the filepath in our options we use the filepath to fetch the purposes.
151
+ # Else, we create a temporary file and write the content to that file.
152
+ # Then, use the temporary file to fetch the purposes.
153
+ # Todo: Check if this can be optimized or improved.
154
+
155
+ if @opts[:filepath]
156
+ cert_purpose = fetch_purpose(@opts[:filepath])
157
+ else
158
+ begin
159
+ f = File.open("temporary_certificate.pem", "w")
160
+ f.write(@cert.to_pem)
161
+ f.rewind
162
+ cert_purpose = fetch_purpose("temporary_certificate.pem")
163
+ ensure
164
+ f.close unless f.nil? || f.closed?
165
+ File.delete("temporary_certificate.pem") if File.exist? "temporary_certificate.pem"
166
+ end
167
+ end
168
+ cert_purpose =~ /purpose/ ? true : false
169
+ end
170
+
171
+ def fetch_purpose(cert_file_or_path)
172
+ openssl_utility = check_openssl_or_error
173
+
174
+ # The below command is used to view the Certificate purposes
175
+ # The -in argument expects a certificate file or path to certificate file.
176
+ cert_purpose_cmd = "#{openssl_utility} x509 -noout -purpose -in #{cert_file_or_path}"
177
+ cert_purpose = inspec.command(cert_purpose_cmd)
178
+
179
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{cert_purpose_cmd} failed: #{cert_purpose.stderr}" if cert_purpose.exit_status.to_i != 0
180
+
181
+ cert_purpose.stdout
182
+ end
183
+
184
+ def subject_alt_names
185
+ extensions["subjectAltName"]
186
+ end
187
+
188
+ def resource_id
189
+ @opts[:filepath] || subject.CN || "x509 Certificate"
190
+ end
191
+
141
192
  def to_s
142
193
  cert = @opts[:filepath]
143
194
  cert ||= subject.CN
@@ -153,5 +204,13 @@ module Inspec::Resources
153
204
  opts
154
205
  end
155
206
  end
207
+
208
+ def check_openssl_or_error
209
+ %w{/usr/sbin/openssl /usr/bin/openssl /sbin/openssl /bin/openssl openssl}.each do |cmd|
210
+ return cmd if inspec.command(cmd).exist?
211
+ end
212
+
213
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `openssl` on your system."
214
+ end
156
215
  end
157
216
  end
@@ -89,6 +89,10 @@ module Inspec::Resources
89
89
  repo(name.to_s) unless name.nil?
90
90
  end
91
91
 
92
+ def resource_id
93
+ "Yum repository"
94
+ end
95
+
92
96
  def to_s
93
97
  "Yum Repository"
94
98
  end
@@ -38,6 +38,10 @@ module Inspec::Resources
38
38
  inspec.mount(@params["mountpoint"]).mounted?
39
39
  end
40
40
 
41
+ def resource_id
42
+ @zfs_dataset || "ZFS Dataset"
43
+ end
44
+
41
45
  def to_s
42
46
  "ZFS Dataset #{@zfs_dataset}"
43
47
  end
@@ -31,6 +31,10 @@ module Inspec::Resources
31
31
  inspec.command("#{@zpool_cmd} get -Hp all #{@zfs_pool}").exit_status == 0
32
32
  end
33
33
 
34
+ def resource_id
35
+ @zfs_pool || "ZFS Pool"
36
+ end
37
+
34
38
  def to_s
35
39
  "ZFS Pool #{@zfs_pool}"
36
40
  end
data/lib/inspec/rule.rb CHANGED
@@ -358,7 +358,7 @@ module Inspec
358
358
  # YAML will automagically give us a Date or a Time.
359
359
  # If transcoding YAML between languages (e.g. Go) the date might have also ended up as a String.
360
360
  # A string that does not represent a valid time results in the date 0000-01-01.
361
- if [Date, Time].include?(expiry.class) || (expiry.is_a?(String) && Time.new(expiry).year != 0)
361
+ if [Date, Time].include?(expiry.class) || (expiry.is_a?(String) && Time.parse(expiry).year != 0)
362
362
  expiry = expiry.to_time if expiry.is_a? Date
363
363
  expiry = Time.parse(expiry) if expiry.is_a? String
364
364
  if expiry < Time.now # If the waiver expired, return - no skip applied
@@ -16,7 +16,13 @@ module Secrets
16
16
 
17
17
  # array of yaml file paths
18
18
  def initialize(target)
19
- @inputs = ::YAML.load_file(target)
19
+ # Ruby 3.1 treats YAML load as a dangerous operation by default, requiring us to declare date and time classes as permitted
20
+ # It's not a valid option in 3.0.x
21
+ if Gem.ruby_version >= Gem::Version.new("3.1.0")
22
+ @inputs = ::YAML.load_file(target, permitted_classes: [Date, Time])
23
+ else
24
+ @inputs = ::YAML.load_file(target)
25
+ end
20
26
 
21
27
  if @inputs == false || !@inputs.is_a?(Hash)
22
28
  Inspec::Log.warn("#{self.class} unable to parse #{target}: invalid YAML or contents is not a Hash")
data/lib/inspec/ui.rb CHANGED
@@ -31,6 +31,7 @@ module Inspec
31
31
  EXIT_PLUGIN_ERROR = 2
32
32
  EXIT_FATAL_DEPRECATION = 3
33
33
  EXIT_GEM_DEPENDENCY_LOAD_ERROR = 4
34
+ EXIT_BAD_SIGNATURE = 5
34
35
  EXIT_LICENSE_NOT_ACCEPTED = 172
35
36
  EXIT_FAILED_TESTS = 100
36
37
  EXIT_SKIPPED_TESTS = 101
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec
4
+ module Utils
5
+ #
6
+ # Inspec::Utils::YamlProfileSummary takes in certain information to identify a
7
+ # profile and then produces a YAML-formatted summary of that profile. It can
8
+ # return the results to STDOUT or a file.
9
+ #
10
+ #
11
+ module YamlProfileSummary
12
+ def self.produce_yaml(info:, write_path: "", suppress_output: false)
13
+ # add in inspec version
14
+ info[:generator] = {
15
+ name: "inspec",
16
+ version: Inspec::VERSION,
17
+ }
18
+ if write_path.empty?
19
+ puts info.to_yaml
20
+ else
21
+ unless suppress_output
22
+ if File.exist? write_path
23
+ Inspec::Log.info "----> updating #{write_path}"
24
+ else
25
+ Inspec::Log.info "----> creating #{write_path}"
26
+ end
27
+ end
28
+ full_write_path = File.expand_path(write_path)
29
+ File.write(full_write_path, info.to_yaml)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "5.17.4".freeze
2
+ VERSION = "5.18.14".freeze
3
3
  end
@@ -7,21 +7,21 @@
7
7
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
8
  <style type="text/css">
9
9
  /* Must inline all CSS files, this is a single-file output that may be airgapped */
10
- <%= ERB.new(File.read(css_path), nil, nil, "_css").result(binding) %>
10
+ <%= ERB.new(File.read(css_path), eoutvar: "_css").result(binding) %>
11
11
  </style>
12
12
  <script type="text/javascript">
13
13
  // <![CDATA[
14
14
  /* Must inline all JavaScript files, this is a single-file output that may be airgapped */
15
- <%= ERB.new(File.read(js_path), nil, nil, "_js").result(binding) %>
15
+ <%= ERB.new(File.read(js_path), eoutvar: "_js").result(binding) %>
16
16
  // ]]>
17
17
  </script>
18
18
  </head>
19
19
  <body onload="pageLoaded()">
20
- <%= ERB.new(File.read(template_path + "/selector.html.erb"), nil, nil, "_select").result(binding) %>
20
+ <%= ERB.new(File.read(template_path + "/selector.html.erb"), eoutvar: "_select").result(binding) %>
21
21
  <div class="inspec-report">
22
22
  <h1><%= Inspec::Dist::PRODUCT_NAME %> Report</h1>
23
23
  <% run_data.profiles.each do |profile| %>
24
- <%= ERB.new(File.read(template_path + "/profile.html.erb"), nil, nil, "_prof").result(binding) %>
24
+ <%= ERB.new(File.read(template_path + "/profile.html.erb"), eoutvar: "_prof").result(binding) %>
25
25
  <% end %>
26
26
 
27
27
  <div class="inspec-summary">
@@ -74,7 +74,7 @@
74
74
  </table>
75
75
 
76
76
  <% control.results.each do |result| %>
77
- <%= ERB.new(File.read(template_path + "/result.html.erb"), nil, nil, "_rslt").result(binding) %>
77
+ <%= ERB.new(File.read(template_path + "/result.html.erb"), eoutvar: "_rslt").result(binding) %>
78
78
  <% end %>
79
79
 
80
80
  </div>
@@ -18,7 +18,7 @@
18
18
 
19
19
  <% if profile.status == "loaded" %>
20
20
  <% profile.controls.each do |control| %>
21
- <%= ERB.new(File.read(template_path + "/control.html.erb"), nil, nil, "_ctl").result(binding) %>
21
+ <%= ERB.new(File.read(template_path + "/control.html.erb"), eoutvar: "_ctl").result(binding) %>
22
22
  <% end %>
23
23
  <% end %>
24
24
  </div>
@@ -2,8 +2,8 @@
2
2
  # These specs are used in plugin list and search command
3
3
 
4
4
  Gem::Specification.new do |spec|
5
- spec.name = "inspec-artifact"
5
+ spec.name = "inspec-sign"
6
6
  spec.summary = ""
7
7
  spec.description = "Plugin to generate asymmetrical keys that you can use to encrypt profiles"
8
8
  spec.license = "Apache-2.0"
9
- end
9
+ end
@@ -0,0 +1,161 @@
1
+ require "base64" unless defined?(Base64)
2
+ require "openssl" unless defined?(OpenSSL)
3
+ require "pathname" unless defined?(Pathname)
4
+ require "set" unless defined?(Set)
5
+ require "tempfile" unless defined?(Tempfile)
6
+ require "yaml"
7
+ require "inspec/dist"
8
+ require "inspec/utils/json_profile_summary"
9
+ require "inspec/iaf_file"
10
+
11
+ module InspecPlugins
12
+ module Sign
13
+ class Base
14
+ include Inspec::Dist
15
+
16
+ KEY_BITS = 2048
17
+ KEY_ALG = OpenSSL::PKey::RSA
18
+
19
+ INSPEC_PROFILE_VERSION_1 = "INSPEC-PROFILE-1".freeze
20
+ INSPEC_REPORT_VERSION_1 = "INSPEC-REPORT-1".freeze
21
+
22
+ INSPEC_PROFILE_VERSION_2 = "INSPEC-PROFILE-2".freeze
23
+ ARTIFACT_DIGEST = OpenSSL::Digest::SHA512
24
+ ARTIFACT_DIGEST_NAME = "SHA512".freeze
25
+
26
+ VALID_PROFILE_VERSIONS = Set.new [INSPEC_PROFILE_VERSION_1, INSPEC_PROFILE_VERSION_2]
27
+ VALID_PROFILE_DIGESTS = Set.new [ARTIFACT_DIGEST_NAME]
28
+
29
+ SIGNED_PROFILE_SUFFIX = "iaf".freeze
30
+ SIGNED_REPORT_SUFFIX = "iar".freeze
31
+
32
+ def self.keygen(options)
33
+ key = KEY_ALG.new KEY_BITS
34
+
35
+ path = File.join(Inspec.config_dir, "keys")
36
+ FileUtils.mkdir_p(path)
37
+
38
+ puts "Generating signing key in #{path}/#{options["keyname"]}.pem.key"
39
+ open "#{path}/#{options["keyname"]}.pem.key", "w" do |io|
40
+ io.write key.to_pem
41
+ end
42
+ puts "Generating validation key in #{path}/#{options["keyname"]}.pem.pub"
43
+ open "#{path}/#{options["keyname"]}.pem.pub", "w" do |io|
44
+ io.write key.public_key.to_pem
45
+ end
46
+ end
47
+
48
+ def self.profile_sign(profile_path, options)
49
+ artifact = new
50
+
51
+ # Writes the profile content id in the inspec.yml
52
+ if options[:profile_content_id] && !options[:profile_content_id].strip.empty?
53
+ artifact.write_profile_content_id(profile_path, options[:profile_content_id])
54
+ end
55
+
56
+ puts "Signing #{profile_path} with key #{options["keyname"]}"
57
+ keypath = Inspec::IafFile.find_signing_key(options["keyname"])
58
+
59
+ # Read name and version from metadata and use them to form the filename
60
+ profile_md = artifact.read_profile_metadata(profile_path)
61
+
62
+ artifact_filename = "#{profile_md["name"]}-#{profile_md["version"]}.#{SIGNED_PROFILE_SUFFIX}"
63
+
64
+ # Generating tar.gz file using archive method of Inspec Cli
65
+ Inspec::InspecCLI.new.archive(profile_path, "error")
66
+ tarfile = "#{profile_md["name"]}-#{profile_md["version"]}.tar.gz"
67
+ tar_content = IO.binread(tarfile)
68
+ FileUtils.rm(tarfile)
69
+
70
+ # Generate the signature
71
+ signing_key = KEY_ALG.new File.read keypath
72
+ sha = ARTIFACT_DIGEST.new
73
+ signature = signing_key.sign sha, tar_content
74
+ # convert the signature to Base64
75
+ signature_base64 = Base64.encode64(signature)
76
+
77
+ content = (format("%-100s", options[:keyname]) +
78
+ format("%-20s", ARTIFACT_DIGEST_NAME) +
79
+ format("%-370s", signature_base64)).gsub(" ", "\0").unpack("H*").pack("h*") + "#{tar_content}"
80
+
81
+ File.open(artifact_filename, "wb") do |f|
82
+ f.puts INSPEC_PROFILE_VERSION_2
83
+ f.puts "Use \"inspec export\" to view this file"
84
+ f.write(content)
85
+ end
86
+ puts "Successfully generated #{artifact_filename}"
87
+ rescue Inspec::Exceptions::ProfileValidationKeyNotFound => e
88
+ $stderr.puts e.message
89
+ Inspec::UI.new.exit(:usage_error)
90
+ end
91
+
92
+ def self.profile_verify(signed_profile_path)
93
+ file_to_verify = signed_profile_path
94
+ puts "Verifying #{file_to_verify}"
95
+
96
+ iaf_file = Inspec::IafFile.new(file_to_verify)
97
+ if iaf_file.valid?
98
+ puts "Detected format version '#{iaf_file.version}'"
99
+ puts "Attempting to verify using key '#{iaf_file.key_name}'"
100
+ puts "Profile is valid."
101
+ Inspec::UI.new.exit(:normal)
102
+ else
103
+ puts "Detected format version '#{iaf_file.version}'"
104
+ puts "Attempting to verify using key '#{iaf_file.key_name}'" if iaf_file.key_name
105
+ puts "Profile is invalid"
106
+ Inspec::UI.new.exit(:bad_signature)
107
+ end
108
+ rescue Inspec::Exceptions::ProfileValidationKeyNotFound => e
109
+ $stderr.puts e.message
110
+ Inspec::UI.new.exit(:usage_error)
111
+ end
112
+
113
+ def read_profile_metadata(profile_path)
114
+ begin
115
+ p = Pathname.new(profile_path)
116
+ p = p.join("inspec.yml")
117
+ unless p.exist?
118
+ raise "#{profile_path} doesn't appear to be a valid #{PRODUCT_NAME} profile"
119
+ end
120
+
121
+ yaml = YAML.load_file(p.to_s)
122
+ yaml = yaml.to_hash
123
+
124
+ unless yaml.key? "name"
125
+ raise "Profile is invalid, name is not defined"
126
+ end
127
+
128
+ unless yaml.key? "version"
129
+ raise "Profile is invalid, version is not defined"
130
+ end
131
+ rescue => e
132
+ # rewrap it and pass it up to the CLI
133
+ $stderr.puts "Error reading profile metadata file #{e.message}"
134
+ Inspec::UI.new.exit(:usage_error)
135
+ end
136
+
137
+ yaml
138
+ end
139
+
140
+ def write_profile_content_id(profile_path, profile_content_id)
141
+ p = Pathname.new(profile_path)
142
+ p = p.join("inspec.yml")
143
+ yaml = YAML.load_file(p.to_s)
144
+ existing_profile_content_id = yaml["profile_content_id"]
145
+
146
+ unless existing_profile_content_id.nil?
147
+ ui = Inspec::UI.new
148
+ ui.error("Cannot use --profile-content-id when profile_content_id already exists in metadata file.")
149
+ ui.exit(:usage_error)
150
+ end
151
+
152
+ lines = IO.readlines(p)
153
+ lines << "\nprofile_content_id: #{profile_content_id}\n"
154
+
155
+ File.open("#{p}", "w" ) do |f|
156
+ f.puts lines
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -70,46 +70,37 @@ require "inspec/dist"
70
70
  # To extract the raw content from a .iaf:
71
71
  # sed '1,/^$/d' foo.iaf
72
72
 
73
+ # inspec artifact is renamed to inspec sign
74
+
73
75
  module InspecPlugins
74
- module Artifact
76
+ module Sign
75
77
  class CLI < Inspec.plugin(2, :cli_command)
76
78
  include Inspec::Dist
77
79
 
78
- subcommand_desc "artifact SUBCOMMAND", "Manage #{PRODUCT_NAME} Artifacts"
80
+ subcommand_desc "sign SUBCOMMAND", "Manage #{PRODUCT_NAME} profile signing."
79
81
 
80
- desc "generate", "Generate a RSA key pair for signing and verification"
82
+ desc "generate-keys", "Generate a RSA key pair for signing and verification"
81
83
  option :keyname, type: :string, required: true,
82
84
  desc: "Desriptive name of key"
83
85
  option :keydir, type: :string, default: "./",
84
86
  desc: "Directory to search for keys"
85
87
  def generate_keys
86
88
  puts "Generating keys"
87
- InspecPlugins::Artifact::Base.keygen(options)
89
+ InspecPlugins::Sign::Base.keygen(options)
88
90
  end
89
91
 
90
- desc "sign-profile", "Create a signed .iaf artifact"
91
- option :profile, type: :string, required: true,
92
- desc: "Path to profile directory"
92
+ desc "profile PATH", "sign the profile in PATH and generate .iaf artifact."
93
93
  option :keyname, type: :string, required: true,
94
94
  desc: "Desriptive name of key"
95
- def sign_profile
96
- InspecPlugins::Artifact::Base.profile_sign(options)
97
- end
98
-
99
- desc "verify-profile", "Verify a signed .iaf artifact"
100
- option :infile, type: :string, required: true,
101
- desc: ".iaf file to verify"
102
- def verify_profile
103
- InspecPlugins::Artifact::Base.profile_verify(options)
95
+ option :profile_content_id, type: :string,
96
+ desc: "UUID of the profile. This will write the profile_content_id in the metadata file if it does not already exist in the metadata file."
97
+ def profile(profile_path)
98
+ InspecPlugins::Sign::Base.profile_sign(profile_path, options)
104
99
  end
105
100
 
106
- desc "install-profile", "Verify and install a signed .iaf artifact"
107
- option :infile, type: :string, required: true,
108
- desc: ".iaf file to install"
109
- option :destdir, type: :string, required: true,
110
- desc: "Installation directory"
111
- def install_profile
112
- InspecPlugins::Artifact::Base.profile_install(options)
101
+ desc "verify PATH", "Verify a signed profile .iaf artifact at given path."
102
+ def verify(signed_profile_path)
103
+ InspecPlugins::Sign::Base.profile_verify(signed_profile_path)
113
104
  end
114
105
  end
115
106
  end
@@ -0,0 +1,12 @@
1
+ module InspecPlugins
2
+ module Sign
3
+ class Plugin < Inspec.plugin(2)
4
+ plugin_name :'inspec-sign'
5
+
6
+ cli_command :sign do
7
+ require_relative "inspec-sign/cli"
8
+ InspecPlugins::Sign::CLI
9
+ end
10
+ end
11
+ end
12
+ end
@@ -12,7 +12,7 @@ module SourceReaders
12
12
  nil
13
13
  end
14
14
 
15
- attr_reader :metadata, :tests, :libraries, :data_files, :target
15
+ attr_reader :metadata, :metadata_src, :tests, :libraries, :data_files, :target, :readme
16
16
 
17
17
  # This create a new instance of an InSpec profile source reader
18
18
  #
@@ -24,14 +24,16 @@ module SourceReaders
24
24
  @tests = load_tests
25
25
  @libraries = load_libs
26
26
  @data_files = load_data_files
27
+ @readme = load_readme
27
28
  end
28
29
 
29
30
  private
30
31
 
31
32
  def load_metadata(metadata_source)
33
+ @metadata_src = @target.read(metadata_source)
32
34
  Inspec::Metadata.from_ref(
33
35
  metadata_source,
34
- @target.read(metadata_source),
36
+ @metadata_src,
35
37
  nil
36
38
  )
37
39
  rescue Psych::SyntaxError => e
@@ -62,5 +64,9 @@ module SourceReaders
62
64
  def load_data_files
63
65
  load_all(%r{^files/})
64
66
  end
67
+
68
+ def load_readme
69
+ load_all(/README.md/)
70
+ end
65
71
  end
66
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.17.4
4
+ version: 5.18.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-24 00:00:00.000000000 Z
11
+ date: 2022-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -370,14 +370,14 @@ dependencies:
370
370
  requirements:
371
371
  - - "~>"
372
372
  - !ruby/object:Gem::Version
373
- version: '3.0'
373
+ version: '3.10'
374
374
  type: :runtime
375
375
  prerelease: false
376
376
  version_requirements: !ruby/object:Gem::Requirement
377
377
  requirements:
378
378
  - - "~>"
379
379
  - !ruby/object:Gem::Version
380
- version: '3.0'
380
+ version: '3.10'
381
381
  description: InSpec provides a framework for creating end-to-end infrastructure tests.
382
382
  You can use it for integration or even compliance testing. Create fully portable
383
383
  test profiles and use them in your workflow to ensure stability and security. Integrate
@@ -444,6 +444,7 @@ files:
444
444
  - lib/inspec/formatters/json_rspec.rb
445
445
  - lib/inspec/formatters/show_progress.rb
446
446
  - lib/inspec/globals.rb
447
+ - lib/inspec/iaf_file.rb
447
448
  - lib/inspec/impact.rb
448
449
  - lib/inspec/input.rb
449
450
  - lib/inspec/input_dsl_helpers.rb
@@ -715,13 +716,10 @@ files:
715
716
  - lib/inspec/utils/telemetry/data_series.rb
716
717
  - lib/inspec/utils/telemetry/global_methods.rb
717
718
  - lib/inspec/utils/telemetry/run_context_probe.rb
719
+ - lib/inspec/utils/yaml_profile_summary.rb
718
720
  - lib/inspec/version.rb
719
721
  - lib/matchers/matchers.rb
720
722
  - lib/plugins/README.md
721
- - lib/plugins/inspec-artifact/inspec-artifact.gemspec
722
- - lib/plugins/inspec-artifact/lib/inspec-artifact.rb
723
- - lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb
724
- - lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb
725
723
  - lib/plugins/inspec-compliance/README.md
726
724
  - lib/plugins/inspec-compliance/inspec-compliance.gemspec
727
725
  - lib/plugins/inspec-compliance/lib/inspec-compliance.rb
@@ -805,6 +803,10 @@ files:
805
803
  - lib/plugins/inspec-reporter-junit/lib/inspec-reporter-junit.rb
806
804
  - lib/plugins/inspec-reporter-junit/lib/inspec-reporter-junit/reporter.rb
807
805
  - lib/plugins/inspec-reporter-junit/lib/inspec-reporter-junit/version.rb
806
+ - lib/plugins/inspec-sign/inspec-sign.gemspec
807
+ - lib/plugins/inspec-sign/lib/inspec-sign.rb
808
+ - lib/plugins/inspec-sign/lib/inspec-sign/base.rb
809
+ - lib/plugins/inspec-sign/lib/inspec-sign/cli.rb
808
810
  - lib/plugins/inspec-streaming-reporter-progress-bar/README.md
809
811
  - lib/plugins/inspec-streaming-reporter-progress-bar/inspec-streaming-reporter-progress-bar.gemspec
810
812
  - lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar.rb