inspec 4.10.4 → 4.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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")