inspec 0.9.2 → 0.9.3

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +272 -49
  3. data/Gemfile +1 -0
  4. data/README.md +9 -0
  5. data/Rakefile +12 -0
  6. data/docs/resources.rst +56 -56
  7. data/examples/test-kitchen/test/integration/default/web_spec.rb +1 -1
  8. data/inspec.gemspec +8 -3
  9. data/lib/inspec/profile_context.rb +2 -1
  10. data/lib/inspec/runner.rb +8 -0
  11. data/lib/inspec/shell.rb +2 -2
  12. data/lib/inspec/version.rb +1 -1
  13. data/lib/resources/command.rb +2 -0
  14. data/lib/resources/os_env.rb +38 -6
  15. data/lib/resources/port.rb +16 -4
  16. data/lib/resources/registry_key.rb +113 -17
  17. data/lib/resources/script.rb +1 -3
  18. data/lib/resources/security_policy.rb +1 -1
  19. data/lib/resources/service.rb +21 -15
  20. data/lib/utils/simpleconfig.rb +1 -1
  21. data/test/helper.rb +4 -2
  22. data/test/integration/cookbooks/os_prepare/recipes/default.rb +2 -0
  23. data/test/integration/cookbooks/os_prepare/recipes/file.rb +16 -12
  24. data/test/integration/cookbooks/os_prepare/recipes/registry_key.rb +69 -0
  25. data/test/integration/cookbooks/os_prepare/recipes/service.rb +12 -0
  26. data/test/integration/{default → test/integration/default}/_debug_spec.rb +0 -0
  27. data/test/integration/{default → test/integration/default}/apt_spec.rb +0 -0
  28. data/test/integration/{default → test/integration/default}/file_spec.rb +0 -0
  29. data/test/integration/{default → test/integration/default}/group_spec.rb +0 -0
  30. data/test/integration/{default → test/integration/default}/kernel_module_spec.rb +0 -0
  31. data/test/integration/{default → test/integration/default}/kernel_parameter_spec.rb +0 -0
  32. data/test/integration/{default → test/integration/default}/package_spec.rb +0 -0
  33. data/test/integration/test/integration/default/port_spec.rb +9 -0
  34. data/test/integration/test/integration/default/registry_key_spec.rb +53 -0
  35. data/test/integration/{default → test/integration/default}/service_spec.rb +14 -1
  36. data/test/integration/test/integration/default/user_spec.rb +62 -0
  37. data/test/unit/mock/cmd/$env-PATH +1 -0
  38. data/test/unit/mock/cmd/env +1 -0
  39. data/test/unit/mock/cmd/reg_schedule +6 -1
  40. data/test/unit/profile_context_test.rb +14 -3
  41. data/test/unit/resources/os_env_test.rb +6 -1
  42. data/test/unit/resources/registry_key_test.rb +2 -3
  43. metadata +32 -22
  44. data/test/integration/default/user_spec.rb +0 -44
  45. data/test/unit/mock/cmd/PATH +0 -1
@@ -42,7 +42,7 @@ class SimpleConfig
42
42
  start_idx = 2
43
43
  i = 0
44
44
  count = values - 1
45
- return match[start_idx] if (values == 1)
45
+ return match[start_idx] if values == 1
46
46
 
47
47
  # iterate over expected parameters
48
48
  values = []
data/test/helper.rb CHANGED
@@ -108,8 +108,10 @@ class MockLoader
108
108
  'type win_secpol.cfg' => cmd.call('secedit-export'),
109
109
  'secedit /export /cfg win_secpol.cfg' => cmd.call('success'),
110
110
  'del win_secpol.cfg' => cmd.call('success'),
111
- 'su - root -c \'echo $PATH\'' => cmd.call('PATH'),
112
- '(Get-Item \'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule\').GetValue(\'Start\')' => cmd.call('reg_schedule'),
111
+ 'env' => cmd.call('env'),
112
+ '$Env:PATH' => cmd.call('$env-PATH'),
113
+ # registry key test
114
+ '2790db1e88204a073ed7fd3493f5445e5ce531afd0d2724a0e36c17110c535e6' => cmd.call('reg_schedule'),
113
115
  'Auditpol /get /subcategory:\'User Account Management\' /r' => cmd.call('auditpol'),
114
116
  '/sbin/auditctl -l' => cmd.call('auditctl'),
115
117
  'yum -v repolist all' => cmd.call('yum-repolist-all'),
@@ -7,3 +7,5 @@
7
7
  include_recipe('os_prepare::apt')
8
8
  include_recipe('os_prepare::file')
9
9
  include_recipe('os_prepare::package')
10
+ include_recipe('os_prepare::registry_key')
11
+ include_recipe('os_prepare::service')
@@ -4,18 +4,22 @@
4
4
  #
5
5
  # prepares a sample file for verification
6
6
 
7
- gid = 'root'
8
- gid = 'wheel' if node['platform_family'] == 'freebsd'
7
+ if node['platform_family'] != 'windows'
9
8
 
10
- file '/tmp/file' do
11
- mode '0765'
12
- owner 'root'
13
- group gid
14
- content 'hello world'
15
- end
9
+ gid = 'root'
10
+ gid = 'wheel' if node['platform_family'] == 'freebsd'
11
+
12
+ file '/tmp/file' do
13
+ mode '0765'
14
+ owner 'root'
15
+ group gid
16
+ content 'hello world'
17
+ end
18
+
19
+ directory '/tmp/folder' do
20
+ mode '0567'
21
+ owner 'root'
22
+ group gid
23
+ end
16
24
 
17
- directory '/tmp/folder' do
18
- mode '0567'
19
- owner 'root'
20
- group gid
21
25
  end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+ # author: Alex Pop
3
+ # author: Christoph Hartmann
4
+ #
5
+ # change a few Windows registry keys for testing purposes
6
+
7
+ if node['platform_family'] == 'windows'
8
+
9
+ registry_key 'HKLM\System\Test' do
10
+ values [{
11
+ :name => '',
12
+ :type => :string,
13
+ :data => 'test'
14
+ },{
15
+ :name => 'string value',
16
+ :type => :string,
17
+ :data => nil
18
+ },{
19
+ :name => 'binary value',
20
+ :type => :binary,
21
+ :data => 'dfa0f066'
22
+ },{
23
+ :name => 'dword value',
24
+ :type => :dword,
25
+ :data => 0
26
+ },{
27
+ :name => 'qword value',
28
+ :type => :qword,
29
+ :data => 0
30
+ },{
31
+ :name => 'multistring value',
32
+ :type => :multi_string,
33
+ :data => ['test', 'multi','string','data']
34
+ }]
35
+ recursive true
36
+ action :create
37
+ end
38
+
39
+ registry_key 'HKLM\Software\Policies\Microsoft\Windows\EventLog\System' do
40
+ values [{ name: 'MaxSize', type: :dword, data: 67_108_864 }]
41
+ recursive true
42
+ action :create
43
+ end
44
+
45
+ registry_key 'HKLM\System\CurrentControlSet\Control\Session Manager' do
46
+ values [{ name: 'SafeDllSearchMode', type: :dword, data: 1 }]
47
+ recursive true
48
+ action :create
49
+ end
50
+
51
+ registry_key 'HKLM\System\CurrentControlSet\Services\LanManServer\Parameters' do
52
+ values [{ name: 'NullSessionShares', type: :multi_string, data: [] }]
53
+ recursive true
54
+ action :create
55
+ end
56
+
57
+ registry_key 'HKLM\Software\Policies\Microsoft\Internet Explorer\Main' do
58
+ values [{ name: 'Isolation64Bit', type: :dword, data: 1 }]
59
+ recursive true
60
+ action :create
61
+ end
62
+
63
+ registry_key 'HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' do
64
+ values [{ name: 'MinEncryptionLevel', type: :dword, data: 3 }]
65
+ recursive true
66
+ action :create
67
+ end
68
+
69
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+ #
5
+ # prepares services
6
+
7
+ # install ntp as a service on ubuntu
8
+ case node['platform']
9
+ when 'ubuntu'
10
+ include_recipe('apt')
11
+ package 'ntp'
12
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ if os.unix?
4
+ # check that ssh runs
5
+ describe port(22) do
6
+ it { should be_listening }
7
+ its('protocol') { should include('tcp') }
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ if os.windows?
4
+
5
+ describe registry_key('HKLM\System\Test') do
6
+ it { should exist }
7
+ it { should have_value('test') }
8
+ it { should have_property('binary value', :binary) }
9
+ it { should have_property('string value') }
10
+ it { should have_property('dword value', :dword) }
11
+ it { should have_property_value('multistring value', :multi_string, ['test', 'multi','string','data']) }
12
+ it { should have_property_value('qword value', :qword, 0) }
13
+ it { should have_property_value('binary value', :binary, 'dfa0f066') }
14
+ end
15
+
16
+ # serverspec compatability
17
+ describe windows_registry_key('HKLM\System\Test') do
18
+ it { should exist }
19
+ it { should have_value('test') }
20
+ it { should have_property('string value') }
21
+ it { should have_property('binary value', :type_binary) }
22
+ it { should have_property('dword value', :type_dword) }
23
+ it { should have_property_value('multistring value', :type_multistring, ['test', 'multi','string','data']) }
24
+ it { should have_property_value('qword value', :type_qword, 0) }
25
+ it { should have_property_value('binary value', :type_binary, 'dfa0f066') }
26
+ end
27
+
28
+ describe registry_key('HKLM\Software\Policies\Microsoft\Windows\EventLog\System') do
29
+ it { should exist }
30
+ its('MaxSize') { should_not eq nil }
31
+ end
32
+
33
+ describe registry_key('HKLM\System\CurrentControlSet\Control\Session Manager') do
34
+ it { should exist }
35
+ it { should_not have_property_value('SafeDllSearchMode', :type_dword, 0) }
36
+ end
37
+
38
+ describe registry_key('HKLM\System\CurrentControlSet\Services\LanManServer\Parameters') do
39
+ it { should exist }
40
+ its('NullSessionShares') { should eq [''] }
41
+ end
42
+
43
+ describe registry_key('HKLM\Software\Policies\Microsoft\Internet Explorer\Main') do
44
+ it { should exist }
45
+ its('Isolation64Bit') { should eq 1 }
46
+ end
47
+
48
+ describe registry_key('HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services') do
49
+ it { should exist }
50
+ its('MinEncryptionLevel') { should eq 3 }
51
+ end
52
+
53
+ end
@@ -9,10 +9,14 @@ elsif ['debian'].include?(os[:family])
9
9
  # Debian
10
10
  unavailable_service = 'clamav'
11
11
  available_service = 'ssh'
12
- else
12
+ elsif ['ubuntu'].include?(os[:family])
13
13
  # Ubuntu
14
14
  unavailable_service = 'sshd'
15
15
  available_service = 'ssh'
16
+ elsif ['windows'].include?(os[:family])
17
+ # Ubuntu
18
+ unavailable_service = 'sshd'
19
+ available_service = 'dhcp'
16
20
  end
17
21
 
18
22
  describe service(unavailable_service) do
@@ -26,3 +30,12 @@ describe service(available_service) do
26
30
  it { should be_installed }
27
31
  it { should be_running }
28
32
  end
33
+
34
+ # extra test for ubuntu upstart with systemv service
35
+ if os[:family] == 'ubuntu'
36
+ describe service('ntp') do
37
+ it { should be_enabled }
38
+ it { should be_installed }
39
+ it { should be_running }
40
+ end
41
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ # root test
4
+ if ['centos', 'fedora', 'opensuse', 'debian', 'ubuntu'].include?(os[:family])
5
+
6
+ userinfo = {
7
+ name: 'root',
8
+ group: 'root',
9
+ uid: 0,
10
+ gid: 0,
11
+ groups: ["root"],
12
+ home: '/root',
13
+ shell: '/bin/bash',
14
+ }
15
+
16
+ # different groupset for centos 5
17
+ userinfo[:groups] = ["root", "bin", "daemon", "sys", "adm", "disk", "wheel"] if os[:release].to_i == 5
18
+
19
+ elsif ['freebsd'].include?(os[:family])
20
+
21
+ userinfo = {
22
+ name: 'root',
23
+ group: 'wheel',
24
+ uid: 0,
25
+ gid: 0,
26
+ groups: ["wheel", "operator"],
27
+ home: '/root',
28
+ shell: '/bin/csh',
29
+ }
30
+
31
+ elsif ['windows'].include?(os[:family])
32
+
33
+ userinfo = {
34
+ name: 'Administrator',
35
+ group: nil,
36
+ uid: nil,
37
+ gid: nil,
38
+ groups: nil,
39
+ home: nil,
40
+ shell: nil,
41
+ }
42
+
43
+ else
44
+ userinfo = {}
45
+ end
46
+
47
+ if !os.windows?
48
+ describe user(userinfo[:name]) do
49
+ it { should exist }
50
+ it { should belong_to_group userinfo[:group] }
51
+ its('uid') { should eq userinfo[:uid] }
52
+ its('gid') { should eq userinfo[:gid] }
53
+ its('group') { should eq userinfo[:group] }
54
+ its('groups') { should eq userinfo[:groups] }
55
+ its('home') { should eq userinfo[:home] }
56
+ its('shell') { should eq userinfo[:shell] }
57
+ end
58
+ else
59
+ describe user(userinfo[:name]) do
60
+ it { should exist }
61
+ end
62
+ end
@@ -0,0 +1 @@
1
+ C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\opscode\chef\bin\
@@ -0,0 +1 @@
1
+ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
@@ -1 +1,6 @@
1
- 2
1
+ {
2
+ "Start": {
3
+ "value": 2,
4
+ "type": 4
5
+ }
6
+ }
@@ -22,21 +22,32 @@ describe Inspec::ProfileContext do
22
22
  load('print os[:family]').must_output 'ubuntu'
23
23
  end
24
24
 
25
- it 'must profide file resource' do
25
+ it 'must provide file resource' do
26
26
  load('print file("").type').must_output 'unknown'
27
27
  end
28
28
 
29
- it 'must profide command resource' do
29
+ it 'must provide command resource' do
30
30
  load('print command("").stdout').must_output ''
31
31
  end
32
32
 
33
33
  it 'provides the describe keyword in the global DSL' do
34
34
  load('describe true do; it { should_eq true }; end')
35
35
  .must_output ''
36
- profile.rules.keys.must_equal ['unknown:1']
36
+ profile.rules.keys.length.must_equal 1
37
+ profile.rules.keys[0].must_match /^unknown:1 [0-9a-f]+$/
37
38
  profile.rules.values[0].must_be_kind_of Inspec::Rule
38
39
  end
39
40
 
41
+ it 'loads multiple computed calls to describe correctly' do
42
+ load("%w{1 2 3}.each do\ndescribe true do; it { should_eq true }; end\nend")
43
+ .must_output ''
44
+ profile.rules.keys.length.must_equal 3
45
+ [0, 1, 2].each do |i|
46
+ profile.rules.keys[i].must_match /^unknown:2 [0-9a-f]+$/
47
+ profile.rules.values[i].must_be_kind_of Inspec::Rule
48
+ end
49
+ end
50
+
40
51
  it 'does not provide the expect keyword in the global DLS' do
41
52
  load('expect(true).to_eq true').must_raise NoMethodError
42
53
  end
@@ -6,8 +6,13 @@ require 'helper'
6
6
  require 'inspec/resource'
7
7
 
8
8
  describe 'Inspec::Resources::OsEnv' do
9
- it 'verify ntp config parsing' do
9
+ it 'verify env parsing' do
10
10
  resource = load_resource('os_env', 'PATH')
11
11
  _(resource.split).must_equal %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin}
12
12
  end
13
+
14
+ it 'read env variable on Windows' do
15
+ resource = MockLoader.new(:windows).load_resource('os_env', 'PATH')
16
+ _(resource.split).must_equal ['C:\Windows\system32', 'C:\Windows', 'C:\Windows\System32\Wbem', 'C:\Windows\System32\WindowsPowerShell\v1.0\\', 'C:\opscode\chef\bin\\']
17
+ end
13
18
  end
@@ -6,14 +6,13 @@ require 'helper'
6
6
  require 'inspec/resource'
7
7
 
8
8
  describe 'Inspec::Resources::RegistryKey' do
9
- let(:resource) { load_resource('registry_key', 'Task Scheduler', 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule') }
10
- let(:resource_without_name) { load_resource('registry_key', 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule') }
11
-
12
9
  it 'read reg key with human readable name' do
10
+ resource = MockLoader.new(:windows).load_resource('registry_key', 'Task Scheduler', 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule')
13
11
  _(resource.Start).must_equal 2
14
12
  end
15
13
 
16
14
  it 'read reg key without human readable name' do
15
+ resource_without_name = MockLoader.new(:windows).load_resource('registry_key', 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Schedule')
17
16
  _(resource_without_name.Start).must_equal 2
18
17
  end
19
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-06 00:00:00.000000000 Z
11
+ date: 2015-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: r-train
@@ -262,15 +262,19 @@ files:
262
262
  - test/integration/cookbooks/os_prepare/recipes/default.rb
263
263
  - test/integration/cookbooks/os_prepare/recipes/file.rb
264
264
  - test/integration/cookbooks/os_prepare/recipes/package.rb
265
- - test/integration/default/_debug_spec.rb
266
- - test/integration/default/apt_spec.rb
267
- - test/integration/default/file_spec.rb
268
- - test/integration/default/group_spec.rb
269
- - test/integration/default/kernel_module_spec.rb
270
- - test/integration/default/kernel_parameter_spec.rb
271
- - test/integration/default/package_spec.rb
272
- - test/integration/default/service_spec.rb
273
- - test/integration/default/user_spec.rb
265
+ - test/integration/cookbooks/os_prepare/recipes/registry_key.rb
266
+ - test/integration/cookbooks/os_prepare/recipes/service.rb
267
+ - test/integration/test/integration/default/_debug_spec.rb
268
+ - test/integration/test/integration/default/apt_spec.rb
269
+ - test/integration/test/integration/default/file_spec.rb
270
+ - test/integration/test/integration/default/group_spec.rb
271
+ - test/integration/test/integration/default/kernel_module_spec.rb
272
+ - test/integration/test/integration/default/kernel_parameter_spec.rb
273
+ - test/integration/test/integration/default/package_spec.rb
274
+ - test/integration/test/integration/default/port_spec.rb
275
+ - test/integration/test/integration/default/registry_key_spec.rb
276
+ - test/integration/test/integration/default/service_spec.rb
277
+ - test/integration/test/integration/default/user_spec.rb
274
278
  - test/resource/command_test.rb
275
279
  - test/resource/dsl_test.rb
276
280
  - test/resource/file_test.rb
@@ -278,10 +282,10 @@ files:
278
282
  - test/resource/sshd_config.rb
279
283
  - test/test-extra.yaml
280
284
  - test/test.yaml
285
+ - test/unit/mock/cmd/$env-PATH
281
286
  - test/unit/mock/cmd/Get-NetAdapter
282
287
  - test/unit/mock/cmd/GetUserAccount
283
288
  - test/unit/mock/cmd/GetWin32Group
284
- - test/unit/mock/cmd/PATH
285
289
  - test/unit/mock/cmd/Resolve-DnsName
286
290
  - test/unit/mock/cmd/Test-NetConnection
287
291
  - test/unit/mock/cmd/auditctl
@@ -290,6 +294,7 @@ files:
290
294
  - test/unit/mock/cmd/chage-l-root
291
295
  - test/unit/mock/cmd/dpkg-s-curl
292
296
  - test/unit/mock/cmd/dscl
297
+ - test/unit/mock/cmd/env
293
298
  - test/unit/mock/cmd/etc-apt
294
299
  - test/unit/mock/cmd/find-etc-rc-d-name-S
295
300
  - test/unit/mock/cmd/find-net-interface
@@ -427,15 +432,19 @@ test_files:
427
432
  - test/integration/cookbooks/os_prepare/recipes/default.rb
428
433
  - test/integration/cookbooks/os_prepare/recipes/file.rb
429
434
  - test/integration/cookbooks/os_prepare/recipes/package.rb
430
- - test/integration/default/_debug_spec.rb
431
- - test/integration/default/apt_spec.rb
432
- - test/integration/default/file_spec.rb
433
- - test/integration/default/group_spec.rb
434
- - test/integration/default/kernel_module_spec.rb
435
- - test/integration/default/kernel_parameter_spec.rb
436
- - test/integration/default/package_spec.rb
437
- - test/integration/default/service_spec.rb
438
- - test/integration/default/user_spec.rb
435
+ - test/integration/cookbooks/os_prepare/recipes/registry_key.rb
436
+ - test/integration/cookbooks/os_prepare/recipes/service.rb
437
+ - test/integration/test/integration/default/_debug_spec.rb
438
+ - test/integration/test/integration/default/apt_spec.rb
439
+ - test/integration/test/integration/default/file_spec.rb
440
+ - test/integration/test/integration/default/group_spec.rb
441
+ - test/integration/test/integration/default/kernel_module_spec.rb
442
+ - test/integration/test/integration/default/kernel_parameter_spec.rb
443
+ - test/integration/test/integration/default/package_spec.rb
444
+ - test/integration/test/integration/default/port_spec.rb
445
+ - test/integration/test/integration/default/registry_key_spec.rb
446
+ - test/integration/test/integration/default/service_spec.rb
447
+ - test/integration/test/integration/default/user_spec.rb
439
448
  - test/resource/command_test.rb
440
449
  - test/resource/dsl_test.rb
441
450
  - test/resource/file_test.rb
@@ -443,10 +452,10 @@ test_files:
443
452
  - test/resource/sshd_config.rb
444
453
  - test/test-extra.yaml
445
454
  - test/test.yaml
455
+ - test/unit/mock/cmd/$env-PATH
446
456
  - test/unit/mock/cmd/Get-NetAdapter
447
457
  - test/unit/mock/cmd/GetUserAccount
448
458
  - test/unit/mock/cmd/GetWin32Group
449
- - test/unit/mock/cmd/PATH
450
459
  - test/unit/mock/cmd/Resolve-DnsName
451
460
  - test/unit/mock/cmd/Test-NetConnection
452
461
  - test/unit/mock/cmd/auditctl
@@ -455,6 +464,7 @@ test_files:
455
464
  - test/unit/mock/cmd/chage-l-root
456
465
  - test/unit/mock/cmd/dpkg-s-curl
457
466
  - test/unit/mock/cmd/dscl
467
+ - test/unit/mock/cmd/env
458
468
  - test/unit/mock/cmd/etc-apt
459
469
  - test/unit/mock/cmd/find-etc-rc-d-name-S
460
470
  - test/unit/mock/cmd/find-net-interface