inspec-core 5.17.4 → 5.21.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +20 -17
  3. data/etc/deprecations.json +4 -0
  4. data/inspec-core.gemspec +23 -23
  5. data/lib/inspec/base_cli.rb +7 -0
  6. data/lib/inspec/cli.rb +68 -11
  7. data/lib/inspec/dependencies/dependency_set.rb +6 -2
  8. data/lib/inspec/dsl.rb +24 -5
  9. data/lib/inspec/enhanced_outcomes.rb +19 -0
  10. data/lib/inspec/env_printer.rb +1 -1
  11. data/lib/inspec/errors.rb +2 -0
  12. data/lib/inspec/exceptions.rb +4 -0
  13. data/lib/inspec/fetcher/url.rb +1 -1
  14. data/lib/inspec/file_provider.rb +36 -0
  15. data/lib/inspec/formatters/base.rb +69 -16
  16. data/lib/inspec/iaf_file.rb +127 -0
  17. data/lib/inspec/plugin/v2/loader.rb +19 -8
  18. data/lib/inspec/plugin/v2/plugin_types/reporter.rb +1 -0
  19. data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +54 -0
  20. data/lib/inspec/profile.rb +17 -7
  21. data/lib/inspec/reporters/base.rb +1 -0
  22. data/lib/inspec/reporters/cli.rb +94 -3
  23. data/lib/inspec/reporters/json.rb +3 -1
  24. data/lib/inspec/reporters/yaml.rb +3 -1
  25. data/lib/inspec/reporters.rb +2 -1
  26. data/lib/inspec/resources/aide_conf.rb +4 -0
  27. data/lib/inspec/resources/apache.rb +4 -0
  28. data/lib/inspec/resources/apache_conf.rb +4 -0
  29. data/lib/inspec/resources/apt.rb +6 -1
  30. data/lib/inspec/resources/audit_policy.rb +5 -0
  31. data/lib/inspec/resources/auditd_conf.rb +4 -0
  32. data/lib/inspec/resources/bash.rb +4 -0
  33. data/lib/inspec/resources/bond.rb +4 -0
  34. data/lib/inspec/resources/bridge.rb +4 -0
  35. data/lib/inspec/resources/cassandradb_conf.rb +5 -0
  36. data/lib/inspec/resources/cassandradb_session.rb +8 -3
  37. data/lib/inspec/resources/chocolatey_package.rb +4 -0
  38. data/lib/inspec/resources/chrony_conf.rb +4 -0
  39. data/lib/inspec/resources/command.rb +5 -0
  40. data/lib/inspec/resources/cpan.rb +4 -0
  41. data/lib/inspec/resources/cran.rb +4 -0
  42. data/lib/inspec/resources/cron.rb +5 -0
  43. data/lib/inspec/resources/csv.rb +6 -1
  44. data/lib/inspec/resources/dh_params.rb +4 -0
  45. data/lib/inspec/resources/docker_container.rb +4 -0
  46. data/lib/inspec/resources/docker_image.rb +4 -0
  47. data/lib/inspec/resources/docker_plugin.rb +4 -0
  48. data/lib/inspec/resources/docker_service.rb +4 -0
  49. data/lib/inspec/resources/etc_group.rb +4 -0
  50. data/lib/inspec/resources/etc_hosts_allow_deny.rb +5 -0
  51. data/lib/inspec/resources/file.rb +7 -2
  52. data/lib/inspec/resources/filesystem.rb +4 -0
  53. data/lib/inspec/resources/gem.rb +4 -0
  54. data/lib/inspec/resources/groups.rb +4 -0
  55. data/lib/inspec/resources/grub_conf.rb +4 -0
  56. data/lib/inspec/resources/host.rb +4 -0
  57. data/lib/inspec/resources/http.rb +6 -2
  58. data/lib/inspec/resources/ibmdb2_conf.rb +8 -0
  59. data/lib/inspec/resources/ibmdb2_session.rb +12 -3
  60. data/lib/inspec/resources/iis_app.rb +4 -0
  61. data/lib/inspec/resources/iis_app_pool.rb +4 -0
  62. data/lib/inspec/resources/iis_site.rb +4 -0
  63. data/lib/inspec/resources/inetd_conf.rb +4 -0
  64. data/lib/inspec/resources/interface.rb +4 -0
  65. data/lib/inspec/resources/ip6tables.rb +4 -0
  66. data/lib/inspec/resources/ipfilter.rb +4 -0
  67. data/lib/inspec/resources/ipnat.rb +4 -0
  68. data/lib/inspec/resources/iptables.rb +4 -0
  69. data/lib/inspec/resources/json.rb +4 -0
  70. data/lib/inspec/resources/kernel_module.rb +4 -0
  71. data/lib/inspec/resources/kernel_parameter.rb +4 -0
  72. data/lib/inspec/resources/key_rsa.rb +4 -0
  73. data/lib/inspec/resources/ksh.rb +4 -0
  74. data/lib/inspec/resources/limits_conf.rb +4 -0
  75. data/lib/inspec/resources/login_defs.rb +4 -0
  76. data/lib/inspec/resources/lxc.rb +65 -9
  77. data/lib/inspec/resources/mongodb.rb +4 -0
  78. data/lib/inspec/resources/mongodb_conf.rb +5 -0
  79. data/lib/inspec/resources/mongodb_session.rb +6 -1
  80. data/lib/inspec/resources/mount.rb +4 -0
  81. data/lib/inspec/resources/mssql_session.rb +4 -0
  82. data/lib/inspec/resources/mssql_sys_conf.rb +7 -0
  83. data/lib/inspec/resources/mysql_conf.rb +4 -0
  84. data/lib/inspec/resources/mysql_session.rb +8 -1
  85. data/lib/inspec/resources/nginx.rb +6 -1
  86. data/lib/inspec/resources/nginx_conf.rb +4 -0
  87. data/lib/inspec/resources/noop.rb +4 -0
  88. data/lib/inspec/resources/npm.rb +4 -0
  89. data/lib/inspec/resources/ntp_conf.rb +4 -0
  90. data/lib/inspec/resources/oneget.rb +4 -0
  91. data/lib/inspec/resources/opa_api.rb +10 -0
  92. data/lib/inspec/resources/opa_cli.rb +14 -0
  93. data/lib/inspec/resources/oracledb_conf.rb +5 -0
  94. data/lib/inspec/resources/oracledb_listener_conf.rb +4 -0
  95. data/lib/inspec/resources/oracledb_session.rb +23 -4
  96. data/lib/inspec/resources/os.rb +4 -0
  97. data/lib/inspec/resources/os_env.rb +4 -0
  98. data/lib/inspec/resources/package.rb +4 -0
  99. data/lib/inspec/resources/parse_config.rb +10 -1
  100. data/lib/inspec/resources/pip.rb +4 -0
  101. data/lib/inspec/resources/platform.rb +4 -0
  102. data/lib/inspec/resources/podman.rb +353 -0
  103. data/lib/inspec/resources/podman_container.rb +84 -0
  104. data/lib/inspec/resources/podman_image.rb +108 -0
  105. data/lib/inspec/resources/podman_network.rb +81 -0
  106. data/lib/inspec/resources/podman_pod.rb +101 -0
  107. data/lib/inspec/resources/podman_volume.rb +87 -0
  108. data/lib/inspec/resources/postfix_conf.rb +4 -0
  109. data/lib/inspec/resources/postgres_conf.rb +4 -0
  110. data/lib/inspec/resources/postgres_session.rb +8 -4
  111. data/lib/inspec/resources/powershell.rb +4 -0
  112. data/lib/inspec/resources/processes.rb +6 -4
  113. data/lib/inspec/resources/rabbitmq_config.rb +4 -0
  114. data/lib/inspec/resources/registry_key.rb +4 -0
  115. data/lib/inspec/resources/security_identifier.rb +4 -0
  116. data/lib/inspec/resources/security_policy.rb +4 -0
  117. data/lib/inspec/resources/service.rb +5 -1
  118. data/lib/inspec/resources/ssh_config.rb +4 -0
  119. data/lib/inspec/resources/sybase_conf.rb +4 -0
  120. data/lib/inspec/resources/sybase_session.rb +4 -0
  121. data/lib/inspec/resources/sys_info.rb +4 -0
  122. data/lib/inspec/resources/timezone.rb +4 -0
  123. data/lib/inspec/resources/users.rb +4 -0
  124. data/lib/inspec/resources/vbscript.rb +5 -0
  125. data/lib/inspec/resources/virtualization.rb +4 -0
  126. data/lib/inspec/resources/windows_feature.rb +5 -1
  127. data/lib/inspec/resources/windows_firewall.rb +4 -0
  128. data/lib/inspec/resources/windows_firewall_rule.rb +4 -0
  129. data/lib/inspec/resources/windows_hotfix.rb +4 -0
  130. data/lib/inspec/resources/windows_task.rb +4 -0
  131. data/lib/inspec/resources/wmi.rb +4 -0
  132. data/lib/inspec/resources/x509_certificate.rb +59 -0
  133. data/lib/inspec/resources/yum.rb +4 -0
  134. data/lib/inspec/resources/zfs_dataset.rb +4 -0
  135. data/lib/inspec/resources/zfs_pool.rb +4 -0
  136. data/lib/inspec/rule.rb +55 -18
  137. data/lib/inspec/run_data/control.rb +6 -0
  138. data/lib/inspec/run_data/statistics.rb +8 -2
  139. data/lib/inspec/runner.rb +18 -8
  140. data/lib/inspec/runner_rspec.rb +3 -2
  141. data/lib/inspec/schema/exec_json.rb +78 -2
  142. data/lib/inspec/schema/output_schema.rb +4 -1
  143. data/lib/inspec/schema/profile_json.rb +46 -0
  144. data/lib/inspec/schema.rb +91 -0
  145. data/lib/inspec/secrets/yaml.rb +7 -1
  146. data/lib/inspec/ui.rb +1 -0
  147. data/lib/inspec/utils/convert.rb +8 -0
  148. data/lib/inspec/utils/podman.rb +24 -0
  149. data/lib/inspec/utils/waivers/csv_file_reader.rb +34 -0
  150. data/lib/inspec/utils/waivers/excel_file_reader.rb +39 -0
  151. data/lib/inspec/utils/waivers/json_file_reader.rb +15 -0
  152. data/lib/inspec/utils/yaml_profile_summary.rb +34 -0
  153. data/lib/inspec/version.rb +1 -1
  154. data/lib/inspec/waiver_file_reader.rb +61 -0
  155. data/lib/matchers/matchers.rb +7 -1
  156. data/lib/plugins/inspec-init/templates/profiles/alicloud/README.md +27 -0
  157. data/lib/plugins/inspec-init/templates/profiles/alicloud/controls/example.rb +10 -0
  158. data/lib/plugins/inspec-init/templates/profiles/alicloud/inputs.yml +1 -0
  159. data/lib/plugins/inspec-init/templates/profiles/alicloud/inspec.yml +14 -0
  160. data/lib/plugins/inspec-reporter-html2/README.md +1 -1
  161. data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +11 -5
  162. data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +11 -7
  163. data/lib/plugins/inspec-reporter-html2/templates/default.css +12 -0
  164. data/lib/plugins/inspec-reporter-html2/templates/profile.html.erb +1 -1
  165. data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +7 -1
  166. data/lib/plugins/{inspec-artifact/inspec-artifact.gemspec → inspec-sign/inspec-sign.gemspec} +2 -2
  167. data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +164 -0
  168. data/lib/plugins/{inspec-artifact/lib/inspec-artifact → inspec-sign/lib/inspec-sign}/cli.rb +14 -23
  169. data/lib/plugins/inspec-sign/lib/inspec-sign.rb +12 -0
  170. data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +39 -13
  171. data/lib/source_readers/inspec.rb +8 -2
  172. metadata +33 -15
  173. data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +0 -187
  174. data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +0 -12
@@ -0,0 +1,353 @@
1
+ require "inspec/resources/command"
2
+ require "inspec/utils/filter"
3
+ require "hashie/mash"
4
+
5
+ module Inspec::Resources
6
+ class Podman < Inspec.resource(1)
7
+ # Resource requires an internal name.
8
+ name "podman"
9
+
10
+ # Restrict to only run on the below platforms (if none were given,
11
+ # all OS's and cloud API's supported)
12
+ supports platform: "unix"
13
+
14
+ desc "A resource to retrieve information about podman"
15
+
16
+ example <<~EXAMPLE
17
+ describe podman.containers do
18
+ its('images') { should include "docker.io/library/ubuntu:latest" }
19
+ end
20
+
21
+ describe podman.images do
22
+ its('names') { should_not include "docker.io/library/ubuntu:latest" }
23
+ end
24
+
25
+ describe podman.pods do
26
+ its("ids") { should include "95cadbb84df71e6374fceb3fd89ee3b8f2c7e1a831062cd9cea7d0e3e4b1dbcc" }
27
+ end
28
+
29
+ describe podman.info.host do
30
+ its("os") { should eq "linux"}
31
+ end
32
+
33
+ describe podman.version do
34
+ its("Client.Version") { should eq "4.1.0"}
35
+ end
36
+
37
+ podman.containers.ids.each do |id|
38
+ # call podman inspect for a specific container id
39
+ describe podman.object(id) do
40
+ its("State.OciVersion") { should eq "1.0.2-dev" }
41
+ its("State.Running") { should eq true}
42
+ end
43
+ end
44
+ EXAMPLE
45
+
46
+ def containers
47
+ PodmanContainerFilter.new(parse_containers)
48
+ end
49
+
50
+ def images
51
+ PodmanImageFilter.new(parse_images)
52
+ end
53
+
54
+ def networks
55
+ PodmanNetworkFilter.new(parse_networks)
56
+ end
57
+
58
+ def pods
59
+ PodmanPodFilter.new(parse_pods)
60
+ end
61
+
62
+ def volumes
63
+ PodmanVolumeFilter.new(parse_volumes)
64
+ end
65
+
66
+ def version
67
+ return @version if defined?(@version)
68
+
69
+ sub_cmd = "version --format json"
70
+ output = run_command(sub_cmd)
71
+ @version = Hashie::Mash.new(JSON.parse(output))
72
+ rescue JSON::ParserError => _e
73
+ Hashie::Mash.new({})
74
+ end
75
+
76
+ def info
77
+ return @info if defined?(@info)
78
+
79
+ sub_cmd = "info --format json"
80
+ output = run_command(sub_cmd)
81
+ @info = Hashie::Mash.new(JSON.parse(output))
82
+ rescue JSON::ParserError => _e
83
+ Hashie::Mash.new({})
84
+ end
85
+
86
+ # returns information about podman objects
87
+ def object(id)
88
+ return @inspect if defined?(@inspect)
89
+
90
+ output = run_command("inspect #{id} --format json")
91
+ data = JSON.parse(output)
92
+ data = data[0] if data.is_a?(Array)
93
+ @inspect = Hashie::Mash.new(data)
94
+ rescue JSON::ParserError => _e
95
+ Hashie::Mash.new({})
96
+ end
97
+
98
+ def to_s
99
+ "Podman"
100
+ end
101
+
102
+ private
103
+
104
+ # Calls the run_command method to get all podman containers and parse the command output.
105
+ # Returns the parsed command output.
106
+ def parse_containers
107
+ labels = %w{ID Image ImageID Command CreatedAt RunningFor Status Pod Ports Size Names Networks Labels Mounts}
108
+ parse_json_command(labels, "ps -a --no-trunc --size")
109
+ end
110
+
111
+ # Calls the run_command method to get all podman images and parse the command output.
112
+ # Returns the parsed command output.
113
+ def parse_images
114
+ labels = %w{ID Repository Tag Size Digest CreatedAt CreatedSince History}
115
+ parse_json_command(labels, "images -a --no-trunc")
116
+ end
117
+
118
+ # Calls the run_command method to get all podman network list and parse the command output.
119
+ # Returns the parsed command output.
120
+ def parse_networks
121
+ labels = %w{ID Name Driver Labels Options IPAMOptions Created Internal IPv6Enabled DNSEnabled NetworkInterface Subnets}
122
+ parse_json_command(labels, "network ls --no-trunc")
123
+ end
124
+
125
+ # Calls the run_command method to get all podman pod list and parse the command output.
126
+ # Returns the parsed command output.
127
+ def parse_pods
128
+ sub_cmd = "pod ps --no-trunc --format json"
129
+ output = run_command(sub_cmd)
130
+ parse(output)
131
+ end
132
+
133
+ # Calls the run_command method to get all podman volume list and parse the command output.
134
+ # Returns the parsed command output.
135
+ def parse_volumes
136
+ sub_cmd = "volume ls --format json"
137
+ output = run_command(sub_cmd)
138
+ parse(output)
139
+ end
140
+
141
+ # Runs the given podman command on the host machine on which podman is installed
142
+ # Returns the command output or raises the command execution error.
143
+ def run_command(subcommand)
144
+ result = inspec.command("podman #{subcommand}")
145
+ if result.stderr.empty?
146
+ result.stdout
147
+ else
148
+ raise "Error while running command \'podman #{subcommand}\' : #{result.stderr}"
149
+ end
150
+ end
151
+
152
+ def parse_json_command(labels, subcommand)
153
+ # build command
154
+ format = labels.map { |label| "\"#{label}\": {{json .#{label}}}" }
155
+ raw = inspec.command("podman #{subcommand} --format '{#{format.join(", ")}}'").stdout
156
+ output = []
157
+
158
+ raw.each_line do |entry|
159
+ # convert all keys to lower_case to work well with ruby and filter table
160
+ row = JSON.parse(entry).map do |key, value|
161
+ [key.downcase, value]
162
+ end.to_h
163
+
164
+ # ensure all keys are there
165
+ row = ensure_keys(row, labels)
166
+ output.push(row)
167
+ end
168
+
169
+ output
170
+ rescue JSON::ParserError => _e
171
+ warn "Could not parse `podman #{subcommand}` output"
172
+ []
173
+ end
174
+
175
+ def ensure_keys(entry, labels)
176
+ labels.each do |key|
177
+ entry[key.downcase] = nil unless entry.key?(key.downcase)
178
+ end
179
+ entry
180
+ end
181
+
182
+ # Method to parse JDON content.
183
+ # Returns: Parsed data.
184
+ def parse(content)
185
+ require "json" unless defined?(JSON)
186
+ output = JSON.parse(content)
187
+ parsed_output = []
188
+ output.each do |entry|
189
+ entry = entry.map do |k, v|
190
+ [k.downcase, v]
191
+ end.to_h
192
+ parsed_output << entry
193
+ end
194
+ parsed_output
195
+ rescue => e
196
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse command JSON output: #{e.message}"
197
+ end
198
+ end
199
+
200
+ # class for podman.containers plural resource
201
+ class PodmanContainerFilter
202
+ filter = FilterTable.create
203
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
204
+ filter.register_column(:commands, field: "command")
205
+ .register_column(:ids, field: "id")
206
+ .register_column(:created_at, field: "createdat")
207
+ .register_column(:images, field: "image")
208
+ .register_column(:names, field: "names")
209
+ .register_column(:status, field: "status")
210
+ .register_column(:image_ids, field: "image_id")
211
+ .register_column(:labels, field: "labels", style: :simple)
212
+ .register_column(:mounts, field: "mounts")
213
+ .register_column(:networks, field: "networks")
214
+ .register_column(:pods, field: "pod")
215
+ .register_column(:ports, field: "ports")
216
+ .register_column(:sizes, field: "size")
217
+ .register_column(:running_for, field: "running_for")
218
+ .register_custom_matcher(:running?) do |x|
219
+ x.where { status.downcase.start_with?("up") }
220
+ end
221
+ filter.install_filter_methods_on_resource(self, :containers)
222
+
223
+ attr_reader :containers
224
+ def initialize(containers)
225
+ @containers = containers
226
+ end
227
+
228
+ def to_s
229
+ "Podman Containers"
230
+ end
231
+
232
+ def resource_id
233
+ "Podman Containers"
234
+ end
235
+ end
236
+
237
+ # class for podman.images plural resource
238
+ class PodmanImageFilter
239
+ filter = FilterTable.create
240
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
241
+ filter.register_column(:ids, field: "id")
242
+ .register_column(:repositories, field: "repository")
243
+ .register_column(:tags, field: "tag")
244
+ .register_column(:sizes, field: "size")
245
+ .register_column(:digests, field: "digest")
246
+ .register_column(:created_at, field: "createdat")
247
+ .register_column(:created_since, field: "createdsince")
248
+ .register_column(:history, field: "history")
249
+ filter.install_filter_methods_on_resource(self, :images)
250
+
251
+ attr_reader :images
252
+ def initialize(images)
253
+ @images = images
254
+ end
255
+
256
+ def to_s
257
+ "Podman Images"
258
+ end
259
+
260
+ def resource_id
261
+ "Podman Images"
262
+ end
263
+ end
264
+
265
+ class PodmanNetworkFilter
266
+ filter = FilterTable.create
267
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
268
+ .register_column(:ids, field: "id")
269
+ .register_column(:names, field: "name")
270
+ .register_column(:drivers, field: "driver")
271
+ .register_column(:network_interfaces, field: "networkinterface")
272
+ .register_column(:created, field: "created")
273
+ .register_column(:subnets, field: "subnets")
274
+ .register_column(:ipv6_enabled, field: "ipv6enabled")
275
+ .register_column(:internal, field: "internal")
276
+ .register_column(:dns_enabled, field: "dnsenabled")
277
+ .register_column(:ipam_options, field: "ipamoptions")
278
+ .register_column(:options, field: "options")
279
+ .register_column(:labels, field: "labels")
280
+ filter.install_filter_methods_on_resource(self, :networks)
281
+
282
+ attr_reader :networks
283
+ def initialize(networks)
284
+ @networks = networks
285
+ end
286
+
287
+ def to_s
288
+ "Podman Networks"
289
+ end
290
+
291
+ def resource_id
292
+ "Podman Networks"
293
+ end
294
+ end
295
+
296
+ class PodmanPodFilter
297
+ filter = FilterTable.create
298
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
299
+ .register_column(:ids, field: "id")
300
+ .register_column(:cgroups, field: "cgroup")
301
+ .register_column(:containers, field: "containers")
302
+ .register_column(:created, field: "created")
303
+ .register_column(:infraids, field: "infraid")
304
+ .register_column(:names, field: "name")
305
+ .register_column(:namespaces, field: "namespace")
306
+ .register_column(:networks, field: "networks")
307
+ .register_column(:status, field: "status")
308
+ .register_column(:labels, field: "labels")
309
+ filter.install_filter_methods_on_resource(self, :pods)
310
+
311
+ attr_reader :pods
312
+ def initialize(pods)
313
+ @pods = pods
314
+ end
315
+
316
+ def to_s
317
+ "Podman Pods"
318
+ end
319
+
320
+ def resource_id
321
+ "Podman Pods"
322
+ end
323
+ end
324
+
325
+ class PodmanVolumeFilter
326
+ filter = FilterTable.create
327
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
328
+ .register_column(:names, field: "name")
329
+ .register_column(:drivers, field: "driver")
330
+ .register_column(:mountpoints, field: "mountpoint")
331
+ .register_column(:createdat, field: "createdat")
332
+ .register_column(:labels, field: "labels")
333
+ .register_column(:scopes, field: "scope")
334
+ .register_column(:options, field: "options")
335
+ .register_column(:mountcount, field: "mountcount")
336
+ .register_column(:needscopyup, field: "needscopyup")
337
+ .register_column(:needschown, field: "needschown")
338
+ filter.install_filter_methods_on_resource(self, :volumes)
339
+
340
+ attr_reader :volumes
341
+ def initialize(volumes)
342
+ @volumes = volumes
343
+ end
344
+
345
+ def to_s
346
+ "Podman Volumes"
347
+ end
348
+
349
+ def resource_id
350
+ "Podman Volumes"
351
+ end
352
+ end
353
+ end
@@ -0,0 +1,84 @@
1
+ require "inspec/resources/podman"
2
+ require_relative "docker_object"
3
+
4
+ # Change module if required
5
+ module Inspec::Resources
6
+ class PodmanContainer < Inspec.resource(1)
7
+ include Inspec::Resources::DockerObject
8
+ name "podman_container"
9
+ supports platform: "unix"
10
+
11
+ desc "Inspec core resource to retrieve information about podman container"
12
+
13
+ example <<~EXAMPLE
14
+ describe podman_container("sweet_mendeleev") do
15
+ it { should exist }
16
+ it { should be_running }
17
+ its("id") { should eq "591270d8d80d26671fd6ed622f367fbe19004d16e3b519c292313feb5f22e7f7" }
18
+ its("image") { should eq "docker.io/library/nginx:latest" }
19
+ its("labels") { should include "maintainer"=>"NGINX Docker Maintainers <docker-maint@nginx.com>" }
20
+ its("ports") { should eq nil }
21
+ end
22
+
23
+ describe podman_container(id: "591270d8d80d2667") do
24
+ it { should exist }
25
+ it { should be_running }
26
+ end
27
+ EXAMPLE
28
+
29
+ def initialize(opts = {})
30
+ skip_resource "The `podman_container` resource is not yet available on your OS." unless inspec.os.unix?
31
+
32
+ # if a string is provided, we expect it is the name
33
+ if opts.is_a?(String)
34
+ @opts = { name: opts }
35
+ else
36
+ @opts = opts
37
+ end
38
+ end
39
+
40
+ def running?
41
+ status.downcase.start_with?("up") if object_info.entries.length == 1
42
+ end
43
+
44
+ def status
45
+ object_info.status[0] if object_info.entries.length == 1
46
+ end
47
+
48
+ def labels
49
+ object_info.labels
50
+ end
51
+
52
+ def ports
53
+ object_info.ports[0] if object_info.entries.length == 1
54
+ end
55
+
56
+ def command
57
+ return unless object_info.entries.length == 1
58
+
59
+ object_info.commands[0]
60
+ end
61
+
62
+ def image
63
+ object_info.images[0] if object_info.entries.length == 1
64
+ end
65
+
66
+ def resource_id
67
+ object_info.ids[0] || @opts[:id] || @opts[:name] || ""
68
+ end
69
+
70
+ def to_s
71
+ name = @opts[:name] || @opts[:id]
72
+ "Podman Container #{name}"
73
+ end
74
+
75
+ private
76
+
77
+ def object_info
78
+ return @info if defined?(@info)
79
+
80
+ opts = @opts
81
+ @info = inspec.podman.containers.where { names == opts[:name] || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id]))) }
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,108 @@
1
+ require "inspec/resources/command"
2
+ require_relative "docker_object"
3
+ require "inspec/utils/podman"
4
+
5
+ module Inspec::Resources
6
+ class PodmanImage < Inspec.resource(1)
7
+ include Inspec::Resources::DockerObject
8
+ include Inspec::Utils::Podman
9
+
10
+ name "podman_image"
11
+ supports platform: "unix"
12
+
13
+ desc "InSpec core resource to retrieve information about podman image"
14
+
15
+ example <<~EXAMPLE
16
+ describe podman_image("docker.io/library/busybox") do
17
+ it { should exist }
18
+ its("repo_tags") { should include "docker.io/library/busybox:latest" }
19
+ its("size") { should eq 1636053 }
20
+ its("resource_id") { should eq "docker.io/library/busybox:latest" }
21
+ end
22
+
23
+ describe podman_image("docker.io/library/busybox:latest") do
24
+ it { should exist }
25
+ end
26
+
27
+ describe podman_image(repo: "docker.io/library/busybox", tag: "latest") do
28
+ it { should exist }
29
+ end
30
+
31
+ describe podman_image(id: "3c19bafed223") do
32
+ it { should exist }
33
+ end
34
+ EXAMPLE
35
+
36
+ attr_reader :opts, :image_info
37
+
38
+ def initialize(opts)
39
+ skip_resource "The `podman_image` resource is not yet available on your OS." unless inspec.os.unix?
40
+ opts = { image: opts } if opts.is_a?(String)
41
+ @opts = sanitize_options(opts)
42
+ raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
43
+
44
+ @image_info = get_image_info
45
+ end
46
+
47
+ LABELS = {
48
+ "id" => "ID",
49
+ "repo_tags" => "RepoTags",
50
+ "size" => "Size",
51
+ "digest" => "Digest",
52
+ "created_at" => "Created",
53
+ "version" => "Version",
54
+ "names_history" => "NamesHistory",
55
+ "repo_digests" => "RepoDigests",
56
+ "architecture" => "Architecture",
57
+ "os" => "Os",
58
+ "virtual_size" => "VirtualSize",
59
+ }.freeze
60
+
61
+ ## This creates all the required properties methods dynamically.
62
+ LABELS.each do |k, v|
63
+ define_method(k) do
64
+ image_info[k.to_s]
65
+ end
66
+ end
67
+
68
+ def exist?
69
+ ! image_info.empty?
70
+ end
71
+
72
+ def resource_id
73
+ opts[:id] || opts[:image] || ""
74
+ end
75
+
76
+ def to_s
77
+ "podman_image #{resource_id}"
78
+ end
79
+
80
+ private
81
+
82
+ def sanitize_options(opts)
83
+ opts.merge!(parse_components_from_image(opts[:image]))
84
+
85
+ # assume a "latest" tag if we don't have one
86
+ opts[:tag] ||= "latest"
87
+
88
+ # Assemble/reassemble the image from the repo and tag
89
+ opts[:image] = "#{opts[:repo]}:#{opts[:tag]}" unless opts[:repo].nil?
90
+
91
+ opts
92
+ end
93
+
94
+ def get_image_info
95
+ current_image = opts[:id] || opts[:image] || opts[:repo] + ":" + opts[:tag]
96
+ json_key_label = generate_go_template(LABELS)
97
+ podman_inspect_cmd = inspec.command("podman image inspect #{current_image} --format '{#{json_key_label}}'")
98
+
99
+ if podman_inspect_cmd.exit_status == 0
100
+ parse_command_output(podman_inspect_cmd.stdout)
101
+ elsif podman_inspect_cmd.stderr =~ /failed to find image/
102
+ {}
103
+ else
104
+ raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman image information for #{current_image}.\nError message: #{podman_inspect_cmd.stderr}"
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,81 @@
1
+ require "inspec/resources/command"
2
+ require "inspec/utils/podman"
3
+ module Inspec::Resources
4
+ class PodmanNetwork < Inspec.resource(1)
5
+ include Inspec::Utils::Podman
6
+
7
+ name "podman_network"
8
+
9
+ supports platform: "unix"
10
+
11
+ desc "InSpec core resource to retrive information about the given Podman network"
12
+
13
+ example <<~EXAMPLE
14
+ describe podman_network("podman") do
15
+ it { should exist }
16
+ end
17
+ describe podman_network("3a7c94d937d5f3a0f1a9b1610589945aedfbe56207fd5d32fc8154aa1a8b007f") do
18
+ its("driver") { should eq bridge }
19
+ end
20
+ EXAMPLE
21
+
22
+ LABELS = {
23
+ id: "ID",
24
+ name: "Name",
25
+ driver: "Driver",
26
+ labels: "Labels",
27
+ options: "Options",
28
+ ipam_options: "IPAMOptions",
29
+ internal: "Internal",
30
+ created: "Created",
31
+ ipv6_enabled: "IPv6Enabled",
32
+ dns_enabled: "DNSEnabled",
33
+ network_interface: "NetworkInterface",
34
+ subnets: "Subnets",
35
+ }.freeze
36
+
37
+ attr_reader :param, :network_info
38
+ def initialize(param)
39
+ skip_resource "The `podman_network` resource is not yet available on your OS." unless inspec.os.unix?
40
+
41
+ @param = param
42
+ raise Inspec::Exceptions::ResourceFailed, "Podman is not running. Please make sure it is installed and running." unless podman_running?
43
+
44
+ @network_info = get_network_info
45
+ end
46
+
47
+ ## This creates all the required properties methods dynamically.
48
+ LABELS.each do |k, v|
49
+ define_method(k) do
50
+ network_info[k.to_s]
51
+ end
52
+ end
53
+
54
+ def exist?
55
+ !network_info.empty?
56
+ end
57
+
58
+ def resource_id
59
+ id || param || ""
60
+ end
61
+
62
+ def to_s
63
+ "podman_network #{resource_id}"
64
+ end
65
+
66
+ private
67
+
68
+ def get_network_info
69
+ go_template_format = generate_go_template(LABELS)
70
+ result = inspec.command("podman network inspect #{param} --format '{#{go_template_format}}'")
71
+
72
+ if result.exit_status == 0
73
+ parse_command_output(result.stdout)
74
+ elsif result.stderr =~ /network not found/
75
+ {}
76
+ else
77
+ raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve podman network information for #{param}.\nError message: #{result.stderr}"
78
+ end
79
+ end
80
+ end
81
+ end