inspec 4.10.4 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,125 +5,127 @@ require "inspec/resources/powershell"
5
5
  # check for web applications in IIS
6
6
  # Note: this is only supported in windows 2012 and later
7
7
 
8
- class IisAppPool < Inspec.resource(1)
9
- name "iis_app_pool"
10
- desc "Tests IIS application pool configuration on windows."
11
- supports platform: "windows"
12
- example <<~EXAMPLE
13
- describe iis_app_pool('DefaultAppPool') do
14
- it { should exist }
15
- its('enable32bit') { should cmp 'True' }
16
- its('runtime_version') { should eq 'v4.0' }
17
- its('pipeline_mode') { should eq 'Integrated' }
18
- end
19
- EXAMPLE
20
-
21
- def initialize(pool_name)
22
- @pool_name = pool_name
23
- @pool_path = "IIS:\\AppPools\\#{@pool_name}"
24
- @cache = nil
25
-
26
- # verify that this resource is only supported on Windows
27
- return skip_resource "The `iis_app_pool` resource is not supported on your OS." unless inspec.os.windows?
28
- end
29
-
30
- def pool_name
31
- iis_app_pool[:pool_name]
32
- end
33
-
34
- def runtime_version
35
- iis_app_pool[:version]
36
- end
8
+ module Inspec::Resources
9
+ class IisAppPool < Inspec.resource(1)
10
+ name "iis_app_pool"
11
+ desc "Tests IIS application pool configuration on windows."
12
+ supports platform: "windows"
13
+ example <<~EXAMPLE
14
+ describe iis_app_pool('DefaultAppPool') do
15
+ it { should exist }
16
+ its('enable32bit') { should cmp 'True' }
17
+ its('runtime_version') { should eq 'v4.0' }
18
+ its('pipeline_mode') { should eq 'Integrated' }
19
+ end
20
+ EXAMPLE
21
+
22
+ def initialize(pool_name)
23
+ @pool_name = pool_name
24
+ @pool_path = "IIS:\\AppPools\\#{@pool_name}"
25
+ @cache = nil
26
+
27
+ # verify that this resource is only supported on Windows
28
+ return skip_resource "The `iis_app_pool` resource is not supported on your OS." unless inspec.os.windows?
29
+ end
37
30
 
38
- def enable32bit
39
- iis_app_pool[:e32b]
40
- end
31
+ def pool_name
32
+ iis_app_pool[:pool_name]
33
+ end
41
34
 
42
- def pipeline_mode
43
- iis_app_pool[:mode]
44
- end
35
+ def runtime_version
36
+ iis_app_pool[:version]
37
+ end
45
38
 
46
- def max_processes
47
- iis_app_pool[:processes]
48
- end
39
+ def enable32bit
40
+ iis_app_pool[:e32b]
41
+ end
49
42
 
50
- def timeout
51
- iis_app_pool[:timeout]
52
- end
43
+ def pipeline_mode
44
+ iis_app_pool[:mode]
45
+ end
53
46
 
54
- def timeout_days
55
- iis_app_pool[:timeout_days]
56
- end
47
+ def max_processes
48
+ iis_app_pool[:processes]
49
+ end
57
50
 
58
- def timeout_hours
59
- iis_app_pool[:timeout_hours]
60
- end
51
+ def timeout
52
+ iis_app_pool[:timeout]
53
+ end
61
54
 
62
- def timeout_minutes
63
- iis_app_pool[:timeout_minutes]
64
- end
55
+ def timeout_days
56
+ iis_app_pool[:timeout_days]
57
+ end
65
58
 
66
- def timeout_seconds
67
- iis_app_pool[:timeout_seconds]
68
- end
59
+ def timeout_hours
60
+ iis_app_pool[:timeout_hours]
61
+ end
69
62
 
70
- def user_identity_type
71
- iis_app_pool[:user_identity_type]
72
- end
63
+ def timeout_minutes
64
+ iis_app_pool[:timeout_minutes]
65
+ end
73
66
 
74
- def username
75
- iis_app_pool[:username]
76
- end
67
+ def timeout_seconds
68
+ iis_app_pool[:timeout_seconds]
69
+ end
77
70
 
78
- def exists?
79
- !iis_app_pool[:pool_name].empty?
80
- end
71
+ def user_identity_type
72
+ iis_app_pool[:user_identity_type]
73
+ end
81
74
 
82
- def to_s
83
- "IIS App Pool '#{@pool_name}'"
84
- end
75
+ def username
76
+ iis_app_pool[:username]
77
+ end
85
78
 
86
- private
79
+ def exists?
80
+ !iis_app_pool[:pool_name].empty?
81
+ end
87
82
 
88
- def iis_app_pool
89
- return @cache unless @cache.nil?
83
+ def to_s
84
+ "IIS App Pool '#{@pool_name}'"
85
+ end
90
86
 
91
- # We use `-Compress` here to avoid a bug in PowerShell
92
- # It does not affect validity of the output, only the representation
93
- # See: https://github.com/inspec/inspec/pull/3842
94
- script = <<~EOH
95
- Import-Module WebAdministration
96
- If (Test-Path '#{@pool_path}') {
97
- Get-Item '#{@pool_path}' | Select-Object * | ConvertTo-Json -Compress
98
- } Else {
99
- Write-Host '{}'
87
+ private
88
+
89
+ def iis_app_pool
90
+ return @cache unless @cache.nil?
91
+
92
+ # We use `-Compress` here to avoid a bug in PowerShell
93
+ # It does not affect validity of the output, only the representation
94
+ # See: https://github.com/inspec/inspec/pull/3842
95
+ script = <<~EOH
96
+ Import-Module WebAdministration
97
+ If (Test-Path '#{@pool_path}') {
98
+ Get-Item '#{@pool_path}' | Select-Object * | ConvertTo-Json -Compress
99
+ } Else {
100
+ Write-Host '{}'
101
+ }
102
+ EOH
103
+ cmd = inspec.powershell(script)
104
+
105
+ begin
106
+ pool = JSON.parse(cmd.stdout)
107
+ rescue JSON::ParserError => _e
108
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse app pool JSON"
109
+ end
110
+
111
+ process_model = pool.fetch("processModel", {})
112
+ idle_timeout = process_model.fetch("idleTimeout", {})
113
+
114
+ # map our values to a hash table
115
+ @cache = {
116
+ pool_name: pool["name"],
117
+ version: pool["managedRuntimeVersion"],
118
+ e32b: pool["enable32BitAppOnWin64"],
119
+ mode: pool["managedPipelineMode"],
120
+ processes: process_model["maxProcesses"],
121
+ timeout: "#{idle_timeout["Hours"]}:#{idle_timeout["Minutes"]}:#{idle_timeout["Seconds"]}",
122
+ timeout_days: idle_timeout["Days"],
123
+ timeout_hours: idle_timeout["Hours"],
124
+ timeout_minutes: idle_timeout["Minutes"],
125
+ timeout_seconds: idle_timeout["Seconds"],
126
+ user_identity_type: process_model["identityType"],
127
+ username: process_model["userName"],
100
128
  }
101
- EOH
102
- cmd = inspec.powershell(script)
103
-
104
- begin
105
- pool = JSON.parse(cmd.stdout)
106
- rescue JSON::ParserError => _e
107
- raise Inspec::Exceptions::ResourceFailed, "Unable to parse app pool JSON"
108
- end
109
-
110
- process_model = pool.fetch("processModel", {})
111
- idle_timeout = process_model.fetch("idleTimeout", {})
112
-
113
- # map our values to a hash table
114
- @cache = {
115
- pool_name: pool["name"],
116
- version: pool["managedRuntimeVersion"],
117
- e32b: pool["enable32BitAppOnWin64"],
118
- mode: pool["managedPipelineMode"],
119
- processes: process_model["maxProcesses"],
120
- timeout: "#{idle_timeout["Hours"]}:#{idle_timeout["Minutes"]}:#{idle_timeout["Seconds"]}",
121
- timeout_days: idle_timeout["Days"],
122
- timeout_hours: idle_timeout["Hours"],
123
- timeout_minutes: idle_timeout["Minutes"],
124
- timeout_seconds: idle_timeout["Seconds"],
125
- user_identity_type: process_model["identityType"],
126
- username: process_model["userName"],
127
- }
129
+ end
128
130
  end
129
131
  end
@@ -243,6 +243,13 @@ module Inspec::Resources
243
243
  info[:startmode]
244
244
  end
245
245
 
246
+ # returns the service's user from info
247
+ def startname
248
+ return nil if info.nil?
249
+
250
+ info[:startname]
251
+ end
252
+
246
253
  def to_s
247
254
  "Service #{@service_name}"
248
255
  end
@@ -575,12 +582,13 @@ module Inspec::Resources
575
582
  # Also see: https://msdn.microsoft.com/en-us/library/aa384896(v=vs.85).aspx
576
583
  # Use the following powershell to determine the start mode
577
584
  # PS: Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $name -or $_.DisplayName -eq $name} | Select-Object -Prop
578
- # erty Name, StartMode, State, Status | ConvertTo-Json
585
+ # erty Name, StartMode, State, Status, StartName | ConvertTo-Json
579
586
  # {
580
587
  # "Name": "Dhcp",
581
588
  # "StartMode": "Auto",
582
589
  # "State": "Running",
583
- # "Status": "OK"
590
+ # "Status": "OK",
591
+ # "StartName": "LocalSystem"
584
592
  # }
585
593
  #
586
594
  # Windows Services have the following status code:
@@ -593,7 +601,7 @@ module Inspec::Resources
593
601
  # - 6: Pause Pending
594
602
  # - 7: Paused
595
603
  def info(service_name)
596
- cmd = inspec.command("New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name '#{service_name}'| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq '#{service_name}' -or $_.DisplayName -eq '#{service_name}'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json")
604
+ cmd = inspec.command("New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name '#{service_name}'| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq '#{service_name}' -or $_.DisplayName -eq '#{service_name}'} | Select-Object -Property StartMode, StartName) -PassThru | ConvertTo-Json")
597
605
 
598
606
  # cannot rely on exit code for now, successful command returns exit code 1
599
607
  # return nil if cmd.exit_status != 0
@@ -614,6 +622,7 @@ module Inspec::Resources
614
622
  running: service_running?(service),
615
623
  enabled: service_enabled?(service),
616
624
  startmode: service["WMI"]["StartMode"],
625
+ startname: service["WMI"]["StartName"],
617
626
  type: "windows",
618
627
  }
619
628
  end
@@ -6,92 +6,94 @@ require "uri"
6
6
  require "parallel"
7
7
 
8
8
  # Custom resource based on the InSpec resource DSL
9
- class SSL < Inspec.resource(1)
10
- name "ssl"
11
- supports platform: "unix"
12
- supports platform: "windows"
9
+ module Inspec::Resources
10
+ class SSL < Inspec.resource(1)
11
+ name "ssl"
12
+ supports platform: "unix"
13
+ supports platform: "windows"
13
14
 
14
- desc "
15
- SSL test resource
16
- "
15
+ desc "
16
+ SSL test resource
17
+ "
17
18
 
18
- example <<~EXAMPLE
19
- describe ssl(port: 443) do
20
- it { should be_enabled }
21
- end
19
+ example <<~EXAMPLE
20
+ describe ssl(port: 443) do
21
+ it { should be_enabled }
22
+ end
22
23
 
23
- # protocols: ssl2, ssl3, tls1.0, tls1.1, tls1.2
24
- describe ssl(port: 443).protocols('ssl2') do
25
- it { should_not be_enabled }
26
- end
24
+ # protocols: ssl2, ssl3, tls1.0, tls1.1, tls1.2
25
+ describe ssl(port: 443).protocols('ssl2') do
26
+ it { should_not be_enabled }
27
+ end
27
28
 
28
- # any ciphers, filter by name or regex
29
- describe ssl(port: 443).ciphers(/rc4/i) do
30
- it { should_not be_enabled }
31
- end
32
- EXAMPLE
29
+ # any ciphers, filter by name or regex
30
+ describe ssl(port: 443).ciphers(/rc4/i) do
31
+ it { should_not be_enabled }
32
+ end
33
+ EXAMPLE
33
34
 
34
- VERSIONS = [
35
- "ssl2",
36
- "ssl3",
37
- "tls1.0",
38
- "tls1.1",
39
- "tls1.2",
40
- ].freeze
35
+ VERSIONS = [
36
+ "ssl2",
37
+ "ssl3",
38
+ "tls1.0",
39
+ "tls1.1",
40
+ "tls1.2",
41
+ ].freeze
41
42
 
42
- attr_reader :host, :port, :timeout, :retries
43
+ attr_reader :host, :port, :timeout, :retries
43
44
 
44
- def initialize(opts = {})
45
- @host = opts[:host]
46
- if @host.nil?
47
- # Transports like SSH and WinRM will provide a hostname
48
- if inspec.backend.respond_to?("hostname")
49
- @host = inspec.backend.hostname
50
- elsif inspec.backend.class.to_s == "Train::Transports::Local::Connection"
51
- @host = "localhost"
45
+ def initialize(opts = {})
46
+ @host = opts[:host]
47
+ if @host.nil?
48
+ # Transports like SSH and WinRM will provide a hostname
49
+ if inspec.backend.respond_to?("hostname")
50
+ @host = inspec.backend.hostname
51
+ elsif inspec.backend.class.to_s == "Train::Transports::Local::Connection"
52
+ @host = "localhost"
53
+ end
52
54
  end
55
+ @port = opts[:port] || 443
56
+ @timeout = opts[:timeout]
57
+ @retries = opts[:retries]
53
58
  end
54
- @port = opts[:port] || 443
55
- @timeout = opts[:timeout]
56
- @retries = opts[:retries]
57
- end
58
59
 
59
- filter = FilterTable.create
60
- filter.register_custom_matcher(:enabled?) do |x|
61
- raise "Cannot determine host for SSL test. Please specify it or use a different target." if x.resource.host.nil?
60
+ filter = FilterTable.create
61
+ filter.register_custom_matcher(:enabled?) do |x|
62
+ raise "Cannot determine host for SSL test. Please specify it or use a different target." if x.resource.host.nil?
62
63
 
63
- x.handshake.values.any? { |i| i["success"] }
64
- end
65
- filter.register_column(:ciphers, field: "cipher")
66
- .register_column(:protocols, field: "protocol")
67
- .register_custom_property(:handshake) do |x|
68
- groups = x.entries.group_by(&:protocol)
69
- res = Parallel.map(groups, in_threads: 8) do |proto, e|
70
- [proto, SSLShake.hello(x.resource.host, port: x.resource.port,
71
- protocol: proto, ciphers: e.map(&:cipher),
72
- timeout: x.resource.timeout, retries: x.resource.retries, servername: x.resource.host)]
73
- end
74
- Hash[res]
64
+ x.handshake.values.any? { |i| i["success"] }
75
65
  end
76
- .install_filter_methods_on_resource(self, :scan_config)
66
+ filter.register_column(:ciphers, field: "cipher")
67
+ .register_column(:protocols, field: "protocol")
68
+ .register_custom_property(:handshake) do |x|
69
+ groups = x.entries.group_by(&:protocol)
70
+ res = Parallel.map(groups, in_threads: 8) do |proto, e|
71
+ [proto, SSLShake.hello(x.resource.host, port: x.resource.port,
72
+ protocol: proto, ciphers: e.map(&:cipher),
73
+ timeout: x.resource.timeout, retries: x.resource.retries, servername: x.resource.host)]
74
+ end
75
+ Hash[res]
76
+ end
77
+ .install_filter_methods_on_resource(self, :scan_config)
77
78
 
78
- def to_s
79
- "SSL/TLS on #{@host}:#{@port}"
80
- end
79
+ def to_s
80
+ "SSL/TLS on #{@host}:#{@port}"
81
+ end
81
82
 
82
- private
83
+ private
83
84
 
84
- def scan_config
85
- [
86
- { "protocol" => "ssl2", "ciphers" => SSLShake::SSLv2::CIPHERS.keys },
87
- { "protocol" => "ssl3", "ciphers" => SSLShake::TLS::SSL3_CIPHERS.keys },
88
- { "protocol" => "tls1.0", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
89
- { "protocol" => "tls1.1", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
90
- { "protocol" => "tls1.2", "ciphers" => SSLShake::TLS::TLS_CIPHERS.keys },
91
- ].map do |line|
92
- line["ciphers"].map do |cipher|
93
- { "protocol" => line["protocol"], "cipher" => cipher }
94
- end
95
- end.flatten
85
+ def scan_config
86
+ [
87
+ { "protocol" => "ssl2", "ciphers" => SSLShake::SSLv2::CIPHERS.keys },
88
+ { "protocol" => "ssl3", "ciphers" => SSLShake::TLS::SSL3_CIPHERS.keys },
89
+ { "protocol" => "tls1.0", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
90
+ { "protocol" => "tls1.1", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
91
+ { "protocol" => "tls1.2", "ciphers" => SSLShake::TLS::TLS_CIPHERS.keys },
92
+ ].map do |line|
93
+ line["ciphers"].map do |cipher|
94
+ { "protocol" => line["protocol"], "cipher" => cipher }
95
+ end
96
+ end.flatten
97
+ end
96
98
  end
97
99
  end
@@ -33,6 +33,7 @@ module Inspec
33
33
  extend Forwardable
34
34
 
35
35
  attr_reader :backend, :rules
36
+ attr_accessor :target_profiles
36
37
 
37
38
  def attributes
38
39
  Inspec.deprecate(:rename_attributes_to_inputs, "Don't call runner.attributes, call runner.inputs")