train 2.1.7 → 2.1.13
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.
- checksums.yaml +4 -4
- data/lib/train.rb +20 -20
- data/lib/train/errors.rb +1 -1
- data/lib/train/extras.rb +2 -2
- data/lib/train/extras/command_wrapper.rb +24 -24
- data/lib/train/extras/stat.rb +27 -27
- data/lib/train/file.rb +30 -30
- data/lib/train/file/local.rb +8 -8
- data/lib/train/file/local/unix.rb +5 -5
- data/lib/train/file/local/windows.rb +1 -1
- data/lib/train/file/remote.rb +8 -8
- data/lib/train/file/remote/aix.rb +1 -1
- data/lib/train/file/remote/linux.rb +2 -2
- data/lib/train/file/remote/qnx.rb +8 -8
- data/lib/train/file/remote/unix.rb +10 -14
- data/lib/train/file/remote/windows.rb +5 -5
- data/lib/train/globals.rb +1 -1
- data/lib/train/options.rb +8 -8
- data/lib/train/platforms.rb +8 -8
- data/lib/train/platforms/common.rb +1 -1
- data/lib/train/platforms/detect/helpers/os_common.rb +36 -32
- data/lib/train/platforms/detect/helpers/os_linux.rb +12 -12
- data/lib/train/platforms/detect/helpers/os_windows.rb +27 -29
- data/lib/train/platforms/detect/scanner.rb +4 -4
- data/lib/train/platforms/detect/specifications/api.rb +8 -8
- data/lib/train/platforms/detect/specifications/os.rb +252 -252
- data/lib/train/platforms/detect/uuid.rb +5 -7
- data/lib/train/platforms/platform.rb +9 -5
- data/lib/train/plugin_test_helper.rb +12 -12
- data/lib/train/plugins.rb +5 -5
- data/lib/train/plugins/base_connection.rb +13 -13
- data/lib/train/plugins/transport.rb +7 -7
- data/lib/train/transports/azure.rb +23 -23
- data/lib/train/transports/cisco_ios_connection.rb +20 -20
- data/lib/train/transports/clients/azure/graph_rbac.rb +2 -2
- data/lib/train/transports/clients/azure/vault.rb +4 -4
- data/lib/train/transports/docker.rb +4 -10
- data/lib/train/transports/gcp.rb +23 -23
- data/lib/train/transports/helpers/azure/file_credentials.rb +8 -8
- data/lib/train/transports/helpers/azure/file_parser.rb +1 -1
- data/lib/train/transports/helpers/azure/subscription_number_file_parser.rb +1 -1
- data/lib/train/transports/local.rb +22 -22
- data/lib/train/transports/mock.rb +33 -35
- data/lib/train/transports/ssh.rb +47 -47
- data/lib/train/transports/ssh_connection.rb +28 -28
- data/lib/train/transports/vmware.rb +32 -34
- data/lib/train/transports/winrm.rb +37 -37
- data/lib/train/transports/winrm_connection.rb +12 -12
- data/lib/train/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3f1acf1dad7c8f838071070a8d440d91d7ca2247ed58b30c9d2276efb9af120
|
4
|
+
data.tar.gz: ad583ee440c0e4b3ca19e719e333ab82f88ad8b0659b05b1a7ac19ab106496c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81153fd511325cef5fc5d9ed031718c058b9a6330aecc49d22f9adced40493b5c7cad90b478a37e36751595fd4cc30aefc4d493bae076136d453d52343cfe1d9
|
7
|
+
data.tar.gz: 11f3b1494d0fc4e5971fa2f0112ac1320babe51a298952fd57d3bd9c00d2d73249f5b4eb4389e50cff269cefe1135f29f71957d6640337ee1e8756cfbd49c283
|
data/lib/train.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
#
|
3
3
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
5
|
+
require "train/version"
|
6
|
+
require "train/options"
|
7
|
+
require "train/plugins"
|
8
|
+
require "train/errors"
|
9
|
+
require "train/platforms"
|
10
|
+
require "uri"
|
11
11
|
|
12
12
|
module Train
|
13
13
|
# Create a new transport instance, with the plugin indicated by the
|
@@ -42,12 +42,12 @@ module Train
|
|
42
42
|
return transport_class unless transport_class.nil?
|
43
43
|
|
44
44
|
# Try to load the transport name from the core transports...
|
45
|
-
require
|
46
|
-
|
45
|
+
require "train/transports/" + transport_name
|
46
|
+
Train::Plugins.registry[transport_name]
|
47
47
|
rescue LoadError => _
|
48
48
|
begin
|
49
49
|
# If it's not in the core transports, try loading from a train plugin gem.
|
50
|
-
gem_name =
|
50
|
+
gem_name = "train-" + transport_name
|
51
51
|
require gem_name
|
52
52
|
return Train::Plugins.registry[transport_name]
|
53
53
|
# rubocop: disable Lint/HandleExceptions
|
@@ -92,7 +92,7 @@ module Train
|
|
92
92
|
|
93
93
|
# split up the target's host/scheme configuration
|
94
94
|
uri = parse_uri(uri_string)
|
95
|
-
unless uri.host.nil?
|
95
|
+
unless uri.host.nil? && uri.scheme.nil?
|
96
96
|
creds[:backend] ||= uri.scheme
|
97
97
|
creds[:host] ||= uri.hostname
|
98
98
|
creds[:port] ||= uri.port
|
@@ -128,9 +128,9 @@ module Train
|
|
128
128
|
# e.g. mock://. To do this, we match it manually and fake the hostname
|
129
129
|
case string
|
130
130
|
when %r{^([a-z]+)://$}
|
131
|
-
string +=
|
131
|
+
string += "dummy"
|
132
132
|
when /^([a-z]+):$/
|
133
|
-
string +=
|
133
|
+
string += "//dummy"
|
134
134
|
else
|
135
135
|
raise Train::UserError, e
|
136
136
|
end
|
@@ -144,15 +144,15 @@ module Train
|
|
144
144
|
# Examine the given credential information, and if all is well,
|
145
145
|
# return the transport name.
|
146
146
|
# TODO: this actually does no validation of the credential options whatsoever
|
147
|
-
def self.validate_backend(credentials, default_transport_name =
|
147
|
+
def self.validate_backend(credentials, default_transport_name = "local")
|
148
148
|
return default_transport_name if credentials.nil?
|
149
149
|
transport_name = credentials[:backend]
|
150
150
|
|
151
151
|
# TODO: Determine if it is ever possible (or supported) for transport_name to be 'localhost'
|
152
152
|
# TODO: After inspec/inspec/pull/3750 is merged, should be able to remove nil from the list
|
153
|
-
if credentials[:sudo] && [nil,
|
154
|
-
|
155
|
-
|
153
|
+
if credentials[:sudo] && [nil, "local", "localhost"].include?(transport_name)
|
154
|
+
raise Train::UserError, "Sudo is only valid when running against a remote host. "\
|
155
|
+
"To run this locally with elevated privileges, run the command with `sudo ...`."
|
156
156
|
end
|
157
157
|
|
158
158
|
return transport_name if !transport_name.nil?
|
@@ -160,13 +160,13 @@ module Train
|
|
160
160
|
if !credentials[:target].nil?
|
161
161
|
# We should not get here, because if target_uri unpacking was successful,
|
162
162
|
# it would have set credentials[:backend]
|
163
|
-
|
163
|
+
raise Train::UserError, "Cannot determine backend from target "\
|
164
164
|
"configuration #{credentials[:target]}. Valid example: ssh://192.168.0.1"
|
165
165
|
end
|
166
166
|
|
167
167
|
if !credentials[:host].nil?
|
168
|
-
|
169
|
-
|
168
|
+
raise Train::UserError, "Host configured, but no backend was provided. Please "\
|
169
|
+
"specify how you want to connect. Valid example: ssh://192.168.0.1"
|
170
170
|
end
|
171
171
|
|
172
172
|
credentials[:backend] = default_transport_name
|
@@ -181,7 +181,7 @@ module Train
|
|
181
181
|
conf[:key_files] = []
|
182
182
|
conf[:keys] = []
|
183
183
|
keys_mixed.each do |key|
|
184
|
-
if !key.nil?
|
184
|
+
if !key.nil? && File.file?(key)
|
185
185
|
conf[:key_files].push(key)
|
186
186
|
else
|
187
187
|
conf[:keys].push(key)
|
data/lib/train/errors.rb
CHANGED
data/lib/train/extras.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
4
|
|
5
5
|
module Train::Extras
|
6
|
-
require
|
7
|
-
require
|
6
|
+
require "train/extras/command_wrapper"
|
7
|
+
require "train/extras/stat"
|
8
8
|
|
9
9
|
CommandResult = Struct.new(:stdout, :stderr, :exit_status)
|
10
10
|
LoginCommand = Struct.new(:command, :arguments)
|
@@ -2,8 +2,8 @@
|
|
2
2
|
# author: Dominik Richter
|
3
3
|
# author: Christoph Hartmann
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "base64"
|
6
|
+
require "train/errors"
|
7
7
|
|
8
8
|
module Train::Extras
|
9
9
|
# Define the interface of all command wrappers.
|
@@ -12,7 +12,7 @@ module Train::Extras
|
|
12
12
|
#
|
13
13
|
# @return [Any] verification result, nil if all went well, otherwise a message
|
14
14
|
def verify
|
15
|
-
|
15
|
+
raise Train::ClientError, "#{self.class} does not implement #verify()"
|
16
16
|
end
|
17
17
|
|
18
18
|
# Wrap a command and return the augmented command which can be executed.
|
@@ -20,7 +20,7 @@ module Train::Extras
|
|
20
20
|
# @param [Strin] command that will be wrapper
|
21
21
|
# @return [String] result of wrapping the command
|
22
22
|
def run(_command)
|
23
|
-
|
23
|
+
raise Train::ClientError, "#{self.class} does not implement #run(command)"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -53,20 +53,20 @@ module Train::Extras
|
|
53
53
|
|
54
54
|
# (see CommandWrapperBase::verify)
|
55
55
|
def verify
|
56
|
-
res = @backend.run_command(run(
|
56
|
+
res = @backend.run_command(run("echo"))
|
57
57
|
return nil if res.exit_status == 0
|
58
|
-
rawerr = res.stdout +
|
58
|
+
rawerr = res.stdout + " " + res.stderr
|
59
59
|
|
60
60
|
{
|
61
|
-
|
62
|
-
|
63
|
-
[
|
64
|
-
|
61
|
+
"Sorry, try again" => ["Wrong sudo password.", :bad_sudo_password],
|
62
|
+
"sudo: no tty present and no askpass program specified" =>
|
63
|
+
["Sudo requires a password, please configure it.", :sudo_password_required],
|
64
|
+
"sudo: command not found" =>
|
65
65
|
["Can't find sudo command. Please either install and "\
|
66
|
-
|
67
|
-
|
68
|
-
[
|
69
|
-
|
66
|
+
"configure it on the target or deactivate sudo.", :sudo_command_not_found],
|
67
|
+
"sudo: sorry, you must have a tty to run sudo" =>
|
68
|
+
["Sudo requires a TTY. Please see the README on how to configure "\
|
69
|
+
"sudo to allow for non-interactive usage.", :sudo_no_tty],
|
70
70
|
}.each do |sudo, human|
|
71
71
|
rawerr = human if rawerr.include? sudo
|
72
72
|
end
|
@@ -91,13 +91,13 @@ module Train::Extras
|
|
91
91
|
# wrap the cmd in a sudo command
|
92
92
|
def sudo_wrap(cmd)
|
93
93
|
return cmd unless @sudo
|
94
|
-
return cmd if @user ==
|
94
|
+
return cmd if @user == "root"
|
95
95
|
|
96
|
-
res = (@sudo_command ||
|
96
|
+
res = (@sudo_command || "sudo") + " "
|
97
97
|
|
98
98
|
res = "#{safe_string(@sudo_password + "\n")} | #{res}-S " unless @sudo_password.nil?
|
99
99
|
|
100
|
-
res << @sudo_options.to_s +
|
100
|
+
res << @sudo_options.to_s + " " unless @sudo_options.nil?
|
101
101
|
|
102
102
|
res + cmd
|
103
103
|
end
|
@@ -107,8 +107,8 @@ module Train::Extras
|
|
107
107
|
def shell_wrap(cmd)
|
108
108
|
return cmd unless @shell
|
109
109
|
|
110
|
-
shell = @shell_command ||
|
111
|
-
options =
|
110
|
+
shell = @shell_command || "$SHELL"
|
111
|
+
options = " " + @shell_options.to_s unless @shell_options.nil?
|
112
112
|
|
113
113
|
"#{safe_string(cmd)} | #{shell}#{options}"
|
114
114
|
end
|
@@ -143,13 +143,13 @@ module Train::Extras
|
|
143
143
|
|
144
144
|
# Wrap the cmd in an encoded command to allow pipes and quotes
|
145
145
|
def powershell_wrap(cmd)
|
146
|
-
shell = @shell_command ||
|
146
|
+
shell = @shell_command || "powershell"
|
147
147
|
|
148
148
|
# Prevent progress stream from leaking into stderr
|
149
149
|
script = "$ProgressPreference='SilentlyContinue';" + cmd
|
150
150
|
|
151
151
|
# Encode script so PowerShell can use it
|
152
|
-
script = script.encode(
|
152
|
+
script = script.encode("UTF-16LE", "UTF-8")
|
153
153
|
base64_script = Base64.strict_encode64(script)
|
154
154
|
|
155
155
|
cmd = "#{shell} -NoProfile -EncodedCommand #{base64_script}"
|
@@ -162,16 +162,16 @@ module Train::Extras
|
|
162
162
|
include_options WindowsCommand
|
163
163
|
|
164
164
|
def self.load(transport, options)
|
165
|
-
if transport.
|
165
|
+
if transport.platform.unix?
|
166
166
|
return nil unless LinuxCommand.active?(options)
|
167
167
|
res = LinuxCommand.new(transport, options)
|
168
168
|
verification_res = res.verify
|
169
169
|
if verification_res
|
170
170
|
msg, reason = verification_res
|
171
|
-
raise Train::UserError
|
171
|
+
raise Train::UserError, "Sudo failed: #{msg}", reason
|
172
172
|
end
|
173
173
|
res
|
174
|
-
elsif transport.
|
174
|
+
elsif transport.platform.windows?
|
175
175
|
res = WindowsCommand.new(transport, options)
|
176
176
|
res
|
177
177
|
end
|
data/lib/train/extras/stat.rb
CHANGED
@@ -4,13 +4,13 @@
|
|
4
4
|
module Train::Extras
|
5
5
|
class Stat
|
6
6
|
TYPES = {
|
7
|
-
socket:
|
8
|
-
symlink:
|
9
|
-
file:
|
10
|
-
block_device:
|
11
|
-
directory:
|
7
|
+
socket: 00140000,
|
8
|
+
symlink: 00120000,
|
9
|
+
file: 00100000,
|
10
|
+
block_device: 00060000,
|
11
|
+
directory: 00040000,
|
12
12
|
character_device: 00020000,
|
13
|
-
pipe:
|
13
|
+
pipe: 00010000,
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
def self.find_type(mode)
|
@@ -33,8 +33,8 @@ module Train::Extras
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.linux_stat(shell_escaped_path, backend, follow_symlink)
|
36
|
-
lstat = follow_symlink ?
|
37
|
-
format = (backend.os.esx? || backend.os[:name] ==
|
36
|
+
lstat = follow_symlink ? " -L" : ""
|
37
|
+
format = (backend.os.esx? || backend.os[:name] == "alpine") ? "-c" : "--printf"
|
38
38
|
res = backend.run_command("stat#{lstat} #{shell_escaped_path} 2>/dev/null #{format} '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'")
|
39
39
|
# ignore the exit_code: it is != 0 if selinux labels are not supported
|
40
40
|
# on the system.
|
@@ -45,16 +45,16 @@ module Train::Extras
|
|
45
45
|
tmask = fields[1].to_i(16)
|
46
46
|
selinux = fields[8]
|
47
47
|
## selinux security context string not available on esxi
|
48
|
-
selinux = nil if selinux ==
|
48
|
+
selinux = nil if (selinux == "?") || (selinux == "(null)") || (selinux == "C")
|
49
49
|
{
|
50
|
-
type:
|
51
|
-
mode:
|
50
|
+
type: find_type(tmask),
|
51
|
+
mode: tmask & 07777,
|
52
52
|
owner: fields[2],
|
53
|
-
uid:
|
53
|
+
uid: fields[3].to_i,
|
54
54
|
group: fields[4],
|
55
|
-
gid:
|
55
|
+
gid: fields[5].to_i,
|
56
56
|
mtime: fields[7].to_i,
|
57
|
-
size:
|
57
|
+
size: fields[0].to_i,
|
58
58
|
selinux_label: selinux,
|
59
59
|
}
|
60
60
|
end
|
@@ -74,7 +74,7 @@ module Train::Extras
|
|
74
74
|
# in combination with:
|
75
75
|
# ...
|
76
76
|
# gu Display group or user name.
|
77
|
-
lstat = follow_symlink ?
|
77
|
+
lstat = follow_symlink ? " -L" : ""
|
78
78
|
res = backend.run_command(
|
79
79
|
"stat#{lstat} -f '%z\n%p\n%Su\n%u\n%Sg\n%g\n%a\n%m' "\
|
80
80
|
"#{shell_escaped_path}")
|
@@ -87,21 +87,21 @@ module Train::Extras
|
|
87
87
|
tmask = fields[1].to_i(8)
|
88
88
|
|
89
89
|
{
|
90
|
-
type:
|
91
|
-
mode:
|
90
|
+
type: find_type(tmask),
|
91
|
+
mode: tmask & 07777,
|
92
92
|
owner: fields[2],
|
93
|
-
uid:
|
93
|
+
uid: fields[3].to_i,
|
94
94
|
group: fields[4],
|
95
|
-
gid:
|
95
|
+
gid: fields[5].to_i,
|
96
96
|
mtime: fields[7].to_i,
|
97
|
-
size:
|
97
|
+
size: fields[0].to_i,
|
98
98
|
selinux_label: fields[8],
|
99
99
|
}
|
100
100
|
end
|
101
101
|
|
102
102
|
def self.aix_stat(shell_escaped_path, backend, follow_symlink)
|
103
103
|
# Perl here b/c it is default on AIX
|
104
|
-
lstat = follow_symlink ?
|
104
|
+
lstat = follow_symlink ? "lstat" : "stat"
|
105
105
|
stat_cmd = <<-EOP
|
106
106
|
perl -e '
|
107
107
|
@a = #{lstat}(shift) or exit 2;
|
@@ -115,16 +115,16 @@ module Train::Extras
|
|
115
115
|
return {} if res.exit_status != 0
|
116
116
|
fields = res.stdout.split("\n")
|
117
117
|
return {} if fields.length != 7
|
118
|
-
tmask
|
118
|
+
tmask = fields[0].to_i(8)
|
119
119
|
{
|
120
|
-
type:
|
121
|
-
mode:
|
120
|
+
type: find_type(tmask),
|
121
|
+
mode: tmask & 07777,
|
122
122
|
owner: fields[1],
|
123
|
-
uid:
|
123
|
+
uid: fields[2].to_i,
|
124
124
|
group: fields[3],
|
125
|
-
gid:
|
125
|
+
gid: fields[4].to_i,
|
126
126
|
mtime: fields[5].to_i,
|
127
|
-
size:
|
127
|
+
size: fields[6].to_i,
|
128
128
|
selinux_label: nil,
|
129
129
|
}
|
130
130
|
end
|
data/lib/train/file.rb
CHANGED
@@ -3,15 +3,15 @@
|
|
3
3
|
# author: Christoph Hartmann
|
4
4
|
# author: Dominik Richter
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require "train/file/local"
|
7
|
+
require "train/file/remote"
|
8
|
+
require "train/extras/stat"
|
9
9
|
|
10
10
|
module Train
|
11
11
|
class File # rubocop:disable Metrics/ClassLength
|
12
12
|
def initialize(backend, path, follow_symlink = true)
|
13
13
|
@backend = backend
|
14
|
-
@path = path ||
|
14
|
+
@path = path || ""
|
15
15
|
@follow_symlink = follow_symlink
|
16
16
|
|
17
17
|
sanitize_filename(path)
|
@@ -30,15 +30,15 @@ module Train
|
|
30
30
|
|
31
31
|
DATA_FIELDS.each do |m|
|
32
32
|
define_method m.to_sym do
|
33
|
-
|
33
|
+
raise NotImplementedError, "File must implement the #{m}() method."
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
def to_json
|
38
38
|
res = Hash[DATA_FIELDS.map { |x| [x, method(x).call] }]
|
39
39
|
# additional fields provided as input
|
40
|
-
res[
|
41
|
-
res[
|
40
|
+
res["type"] = type
|
41
|
+
res["follow_symlink"] = @follow_symlink
|
42
42
|
res
|
43
43
|
end
|
44
44
|
|
@@ -73,36 +73,36 @@ module Train
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def version?(version)
|
76
|
-
product_version == version
|
77
|
-
file_version == version
|
76
|
+
(product_version == version) ||
|
77
|
+
(file_version == version)
|
78
78
|
end
|
79
79
|
|
80
80
|
def block_device?
|
81
|
-
type.to_s ==
|
81
|
+
type.to_s == "block_device"
|
82
82
|
end
|
83
83
|
|
84
84
|
def character_device?
|
85
|
-
type.to_s ==
|
85
|
+
type.to_s == "character_device"
|
86
86
|
end
|
87
87
|
|
88
88
|
def pipe?
|
89
|
-
type.to_s ==
|
89
|
+
type.to_s == "pipe"
|
90
90
|
end
|
91
91
|
|
92
92
|
def file?
|
93
|
-
type.to_s ==
|
93
|
+
type.to_s == "file"
|
94
94
|
end
|
95
95
|
|
96
96
|
def socket?
|
97
|
-
type.to_s ==
|
97
|
+
type.to_s == "socket"
|
98
98
|
end
|
99
99
|
|
100
100
|
def directory?
|
101
|
-
type.to_s ==
|
101
|
+
type.to_s == "directory"
|
102
102
|
end
|
103
103
|
|
104
104
|
def symlink?
|
105
|
-
source.type.to_s ==
|
105
|
+
source.type.to_s == "symlink"
|
106
106
|
end
|
107
107
|
|
108
108
|
def owned_by?(sth)
|
@@ -134,16 +134,16 @@ module Train
|
|
134
134
|
# Skip processing rest of method if fallback method is selected
|
135
135
|
return perform_checksum_ruby(:md5) if defined?(@ruby_checksum_fallback)
|
136
136
|
|
137
|
-
checksum = if @backend.os.family ==
|
137
|
+
checksum = if @backend.os.family == "windows"
|
138
138
|
perform_checksum_windows(:md5)
|
139
139
|
else
|
140
140
|
@md5_command ||= case @backend.os.family
|
141
|
-
when
|
142
|
-
|
143
|
-
when
|
144
|
-
|
141
|
+
when "darwin"
|
142
|
+
"md5 -r"
|
143
|
+
when "solaris"
|
144
|
+
"digest -a md5"
|
145
145
|
else
|
146
|
-
|
146
|
+
"md5sum"
|
147
147
|
end
|
148
148
|
|
149
149
|
perform_checksum_unix(@md5_command)
|
@@ -156,16 +156,16 @@ module Train
|
|
156
156
|
# Skip processing rest of method if fallback method is selected
|
157
157
|
return perform_checksum_ruby(:sha256) if defined?(@ruby_checksum_fallback)
|
158
158
|
|
159
|
-
checksum = if @backend.os.family ==
|
159
|
+
checksum = if @backend.os.family == "windows"
|
160
160
|
perform_checksum_windows(:sha256)
|
161
161
|
else
|
162
162
|
@sha256_command ||= case @backend.os.family
|
163
|
-
when
|
164
|
-
|
165
|
-
when
|
166
|
-
|
163
|
+
when "darwin", "hpux", "qnx"
|
164
|
+
"shasum -a 256"
|
165
|
+
when "solaris"
|
166
|
+
"digest -a sha256"
|
167
167
|
else
|
168
|
-
|
168
|
+
"sha256sum"
|
169
169
|
end
|
170
170
|
|
171
171
|
perform_checksum_unix(@sha256_command)
|
@@ -178,13 +178,13 @@ module Train
|
|
178
178
|
|
179
179
|
def perform_checksum_unix(cmd)
|
180
180
|
res = @backend.run_command("#{cmd} #{@path}")
|
181
|
-
res.stdout.split(
|
181
|
+
res.stdout.split(" ").first if res.exit_status == 0
|
182
182
|
end
|
183
183
|
|
184
184
|
def perform_checksum_windows(method)
|
185
185
|
cmd = "CertUtil -hashfile #{@path} #{method.to_s.upcase}"
|
186
186
|
res = @backend.run_command(cmd)
|
187
|
-
res.stdout.split("\r\n")[1].tr(
|
187
|
+
res.stdout.split("\r\n")[1].tr(" ", "") if res.exit_status == 0
|
188
188
|
end
|
189
189
|
|
190
190
|
# This pulls the content of the file to the machine running Train and uses
|