win32-certstore 0.6.1 → 0.6.11
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/win32/certstore/mixin/assertions.rb +3 -3
- data/lib/win32/certstore/mixin/helper.rb +14 -43
- data/lib/win32/certstore/mixin/string.rb +12 -16
- data/lib/win32/certstore/store_base.rb +44 -27
- data/lib/win32/certstore/version.rb +1 -1
- data/lib/win32/certstore.rb +26 -17
- metadata +6 -7
- data/lib/win32/certstore/mixin/shell_exec.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 809701f00c09da8b2bbcf78e30eb51d03e939d33ea7a19b17d45ce51c078fdd4
|
4
|
+
data.tar.gz: dbb26074a01b06639bbc1bae73b45f1937c54035ad57d56bbecc64a3fb377bb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ba534e93f989c33a735ea57f525b5357f25cbd0f7c9d2ad0bfe770a0d59f49973dde9669cfb878de35853a81d4af7257d39348d3406879273cdf338b108acd7
|
7
|
+
data.tar.gz: c16cd054c55671396b73d0d41450d89e54dd7157a7b21ea7df0dedadea67c5f376ef45b9e6a70bfaf4eb9ceadfaa520399caa0ee49fb722afec3fcef6e39d405
|
@@ -37,13 +37,13 @@ module Win32
|
|
37
37
|
# Validate certificate Object
|
38
38
|
def validate_certificate_obj(cert_obj)
|
39
39
|
unless cert_obj.class == OpenSSL::X509::Certificate
|
40
|
-
raise ArgumentError, "Invalid Certificate object."
|
40
|
+
raise ArgumentError, "Invalid Certificate object. This is not a properly formatted x509 object"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
# Validate thumbprint
|
45
45
|
def validate_thumbprint(cert_thumbprint)
|
46
|
-
if cert_thumbprint.nil? || cert_thumbprint.strip.empty?
|
46
|
+
if cert_thumbprint.nil? || cert_thumbprint.empty? || cert_thumbprint.strip.empty?
|
47
47
|
raise ArgumentError, "Invalid certificate thumbprint."
|
48
48
|
end
|
49
49
|
end
|
@@ -82,7 +82,7 @@ module Win32
|
|
82
82
|
# ROOT -> Root certificates.
|
83
83
|
# SPC -> Software Publisher Certificate.
|
84
84
|
def valid_store_name
|
85
|
-
|
85
|
+
["MY", "CA", "ROOT", "AUTHROOT", "DISALLOWED", "SPC", "TRUST", "TRUSTEDPEOPLE", "TRUSTEDPUBLISHER", "CLIENTAUTHISSUER", "TRUSTEDDEVICES", "SMARTCARDROOT", "WEBHOSTING", "REMOTE DESKTOP"]
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
@@ -21,52 +21,23 @@ module Win32
|
|
21
21
|
class Certstore
|
22
22
|
module Mixin
|
23
23
|
module Helper
|
24
|
-
|
25
|
-
|
24
|
+
def cert_ps_cmd(thumbprint, store_location: "LocalMachine", store_name: "My")
|
25
|
+
# the PowerShell block below uses a "Here-String" - it is explicitly formatted against the left margin.
|
26
26
|
<<-EOH
|
27
|
-
$cert = Get-ChildItem Cert
|
27
|
+
$cert = Get-ChildItem Cert:\\#{store_location}\\#{store_name} -Recurse | Where-Object { $_.Thumbprint -eq "#{thumbprint}" }
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
}
|
40
|
-
|
41
|
-
$result = test_cert_values
|
42
|
-
|
43
|
-
$output_path = "#{output_path}"
|
44
|
-
if([string]::IsNullOrEmpty($output_path)){
|
45
|
-
$temproot = [System.IO.Path]::GetTempPath()
|
46
|
-
}
|
47
|
-
else{
|
48
|
-
$temproot = $output_path
|
49
|
-
}
|
50
|
-
|
51
|
-
if((($cert).HasPrivateKey) -and ($result -eq $true)){
|
52
|
-
$file_name = '#{thumbprint}'
|
53
|
-
$file_path = $(Join-Path -Path $temproot -ChildPath "$file_name.pfx")
|
54
|
-
$mypwd = ConvertTo-SecureString -String '#{export_password}' -Force -AsPlainText
|
55
|
-
$cert | Export-PfxCertificate -FilePath $file_path -Password $mypwd | Out-Null
|
56
|
-
$file_path
|
57
|
-
}
|
58
|
-
else {
|
59
|
-
$content = $null
|
60
|
-
if($cert -ne $null)
|
61
|
-
{
|
62
|
-
$content = @(
|
63
|
-
'-----BEGIN CERTIFICATE-----'
|
64
|
-
[System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks')
|
65
|
-
'-----END CERTIFICATE-----'
|
66
|
-
)
|
67
|
-
}
|
68
|
-
$content
|
29
|
+
$certdata = [System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks')
|
30
|
+
$content = $null
|
31
|
+
if($null -ne $cert)
|
32
|
+
{
|
33
|
+
$content =
|
34
|
+
@"
|
35
|
+
-----BEGIN CERTIFICATE-----
|
36
|
+
$($certdata)
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
"@
|
69
39
|
}
|
40
|
+
$content
|
70
41
|
EOH
|
71
42
|
end
|
72
43
|
|
@@ -36,14 +36,12 @@ module Win32
|
|
36
36
|
ustring += "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000"
|
37
37
|
|
38
38
|
# encode it all as UTF-16LE AKA Windows Wide Character AKA Windows Unicode
|
39
|
-
ustring =
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|
39
|
+
ustring = if ustring.respond_to?(:encode)
|
40
|
+
ustring.encode("UTF-16LE")
|
41
|
+
else
|
42
|
+
require "iconv"
|
43
|
+
Iconv.conv("UTF-16LE", "UTF-8", ustring)
|
44
|
+
end
|
47
45
|
ustring
|
48
46
|
end
|
49
47
|
|
@@ -53,14 +51,12 @@ module Win32
|
|
53
51
|
wstring = wstring.force_encoding("UTF-16LE") if wstring.respond_to?(:force_encoding)
|
54
52
|
|
55
53
|
# encode it all as UTF-8
|
56
|
-
wstring =
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
54
|
+
wstring = if wstring.respond_to?(:encode)
|
55
|
+
wstring.encode("UTF-8")
|
56
|
+
else
|
57
|
+
require "iconv"
|
58
|
+
Iconv.conv("UTF-8", "UTF-16LE", wstring)
|
59
|
+
end
|
64
60
|
# remove trailing CRLF and NULL characters
|
65
61
|
wstring.strip!
|
66
62
|
wstring
|
@@ -17,20 +17,25 @@
|
|
17
17
|
|
18
18
|
require_relative "mixin/crypto"
|
19
19
|
require_relative "mixin/string"
|
20
|
-
require_relative "mixin/shell_exec"
|
21
20
|
require_relative "mixin/unicode"
|
22
21
|
require "openssl" unless defined?(OpenSSL)
|
23
22
|
require "json" unless defined?(JSON)
|
24
23
|
|
24
|
+
begin
|
25
|
+
require "chef-powershell"
|
26
|
+
rescue LoadError
|
27
|
+
puts "Not loading powershell_exec during testing"
|
28
|
+
end
|
29
|
+
|
25
30
|
module Win32
|
26
31
|
class Certstore
|
27
32
|
module StoreBase
|
28
33
|
include Win32::Certstore::Mixin::Crypto
|
29
34
|
include Win32::Certstore::Mixin::Assertions
|
30
35
|
include Win32::Certstore::Mixin::String
|
31
|
-
include Win32::Certstore::Mixin::ShellExec
|
32
36
|
include Win32::Certstore::Mixin::Unicode
|
33
37
|
include Win32::Certstore::Mixin::Helper
|
38
|
+
include ChefPowerShell::ChefPowerShellModule::PowerShellExec
|
34
39
|
|
35
40
|
# Adding new certification in open certificate and return boolean
|
36
41
|
# store_handler => Open certificate store handler
|
@@ -92,9 +97,8 @@ module Win32
|
|
92
97
|
thumbprint = update_thumbprint(certificate_thumbprint)
|
93
98
|
cert_pem = get_cert_pem(thumbprint)
|
94
99
|
cert_pem = format_pem(cert_pem)
|
95
|
-
|
96
|
-
|
97
|
-
end
|
100
|
+
verify_certificate(cert_pem)
|
101
|
+
build_openssl_obj(cert_pem)
|
98
102
|
end
|
99
103
|
|
100
104
|
# Listing certificate of open certstore and return list in json
|
@@ -121,6 +125,7 @@ module Win32
|
|
121
125
|
def cert_delete(store_handler, certificate_thumbprint)
|
122
126
|
validate_thumbprint(certificate_thumbprint)
|
123
127
|
thumbprint = update_thumbprint(certificate_thumbprint)
|
128
|
+
|
124
129
|
cert_delete_flag = false
|
125
130
|
begin
|
126
131
|
cert_args = cert_find_args(store_handler, thumbprint)
|
@@ -141,6 +146,7 @@ module Win32
|
|
141
146
|
def cert_validate(certificate_thumbprint)
|
142
147
|
validate_thumbprint(certificate_thumbprint)
|
143
148
|
thumbprint = update_thumbprint(certificate_thumbprint)
|
149
|
+
|
144
150
|
cert_pem = get_cert_pem(thumbprint)
|
145
151
|
cert_pem = format_pem(cert_pem)
|
146
152
|
verify_certificate(cert_pem)
|
@@ -167,6 +173,26 @@ module Win32
|
|
167
173
|
certificate_list
|
168
174
|
end
|
169
175
|
|
176
|
+
# how can I find a cert if I don't have the thumbprint? This should be replaced by a call to CertFindCertificateInStore
|
177
|
+
def cert_lookup_by_token(search_token, store_name: @store_name, store_location: @store_location, timeout: -1)
|
178
|
+
raise ArgumentError, "Invalid search token" if !search_token || search_token.strip.empty?
|
179
|
+
|
180
|
+
converted_store = if store_location == CERT_SYSTEM_STORE_LOCAL_MACHINE || store_location == 131072
|
181
|
+
"LocalMachine"
|
182
|
+
else
|
183
|
+
"CurrentUser"
|
184
|
+
end
|
185
|
+
powershell_cmd = <<~EOH
|
186
|
+
$result = Get-ChildItem -Path Cert:\\#{converted_store}\\#{store_name} | Where-Object { $_.Subject -match "#{search_token.strip}" } | Select-Object Thumbprint
|
187
|
+
return $result[0].Thumbprint
|
188
|
+
EOH
|
189
|
+
|
190
|
+
powershell_exec!(powershell_cmd, :powershell, timeout: timeout).result
|
191
|
+
|
192
|
+
rescue ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed
|
193
|
+
return "Certificate not found"
|
194
|
+
end
|
195
|
+
|
170
196
|
# To close and destroy pointer of open certificate store handler
|
171
197
|
def close_cert_store(certstore_handler = @certstore_handler)
|
172
198
|
closed = CertCloseStore(certstore_handler, CERT_CLOSE_STORE_FORCE_FLAG)
|
@@ -190,6 +216,11 @@ module Win32
|
|
190
216
|
[certstore_handler, cert_context, CERT_STORE_ADD_REPLACE_EXISTING, nil]
|
191
217
|
end
|
192
218
|
|
219
|
+
# Remove extra space and : from thumbprint
|
220
|
+
def update_thumbprint(certificate_thumbprint)
|
221
|
+
certificate_thumbprint.gsub(/[^A-Za-z0-9]/, "")
|
222
|
+
end
|
223
|
+
|
193
224
|
# Match certificate CN exist in cert_rdn
|
194
225
|
def is_cn_match?(cert_rdn, certificate_name)
|
195
226
|
cert_rdn.read_wstring.match(/(^|\W)#{certificate_name}($|\W)/i)
|
@@ -212,14 +243,9 @@ module Win32
|
|
212
243
|
[pcert_context, search_type, CERT_NAME_ISSUER_FLAG, nil, cert_name, 1024]
|
213
244
|
end
|
214
245
|
|
215
|
-
# Remove extra space and : from thumbprint
|
216
|
-
def update_thumbprint(certificate_thumbprint)
|
217
|
-
certificate_thumbprint.gsub(/[^A-Za-z0-9]/, "")
|
218
|
-
end
|
219
|
-
|
220
246
|
# Verify OpenSSL::X509::Certificate object
|
221
247
|
def verify_certificate(cert_pem)
|
222
|
-
|
248
|
+
raise ArgumentError, "Certificate not found" if cert_pem.empty?
|
223
249
|
|
224
250
|
valid_duration?(build_openssl_obj(cert_pem))
|
225
251
|
end
|
@@ -229,26 +255,17 @@ module Win32
|
|
229
255
|
FFI::MemoryPointer.from_string(cert_obj.to_der)
|
230
256
|
end
|
231
257
|
|
232
|
-
# Get certificate pem
|
233
|
-
def get_cert_pem(thumbprint)
|
234
|
-
converted_store = if
|
235
|
-
"LocalMachine"
|
236
|
-
else
|
237
|
-
"CurrentUser"
|
238
|
-
end
|
239
|
-
get_data = powershell_exec!(cert_ps_cmd(thumbprint, store_location: converted_store))
|
240
|
-
get_data.stdout
|
241
|
-
end
|
242
|
-
|
243
|
-
# Get PFX object
|
244
|
-
def get_cert_pfx(thumbprint, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE, export_password:, output_path: )
|
245
|
-
converted_store = if store_location == CERT_SYSTEM_STORE_LOCAL_MACHINE
|
258
|
+
# Get certificate pem.
|
259
|
+
def get_cert_pem(thumbprint, store_name: @store_name, store_location: @store_location, timeout: -1)
|
260
|
+
converted_store = if store_location == CERT_SYSTEM_STORE_LOCAL_MACHINE || store_location == 131072
|
246
261
|
"LocalMachine"
|
247
262
|
else
|
248
263
|
"CurrentUser"
|
249
264
|
end
|
250
|
-
get_data = powershell_exec!(cert_ps_cmd(thumbprint,
|
251
|
-
get_data.
|
265
|
+
get_data = powershell_exec!(cert_ps_cmd(thumbprint, store_location: converted_store, store_name: store_name), :powershell, timeout: timeout)
|
266
|
+
get_data.result
|
267
|
+
rescue ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed
|
268
|
+
raise ArgumentError, "PowerShell threw an error retreiving the certificate. You asked for a cert with this thumbprint : #{thumbprint}, located in this store : #{store_name}, at this location : #{store_location}"
|
252
269
|
end
|
253
270
|
|
254
271
|
# Format pem
|
data/lib/win32/certstore.rb
CHANGED
@@ -29,23 +29,23 @@ module Win32
|
|
29
29
|
include Win32::Certstore::Mixin::String
|
30
30
|
include Win32::Certstore::StoreBase
|
31
31
|
|
32
|
-
attr_accessor :store_name
|
32
|
+
attr_accessor :store_name, :store_location
|
33
33
|
|
34
34
|
# Initializes a new instance of a certificate store.
|
35
35
|
# takes 2 parameters - the store name (My, Root, etc) and the location (CurrentUser or LocalMachine), it defaults to LocalMachine for backwards compatibility
|
36
|
-
def initialize(store_name, store_location
|
36
|
+
def initialize(store_name, store_location)
|
37
37
|
@store_name = store_name
|
38
38
|
@store_location = store_location
|
39
|
-
@certstore_handler = open(store_name, store_location
|
39
|
+
@certstore_handler = open(store_name, store_location)
|
40
40
|
end
|
41
41
|
|
42
42
|
# To open given certificate store
|
43
43
|
def self.open(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
|
44
44
|
validate_store(store_name)
|
45
45
|
if block_given?
|
46
|
-
yield new(store_name, store_location
|
46
|
+
yield new(store_name, store_location)
|
47
47
|
else
|
48
|
-
new(store_name, store_location
|
48
|
+
new(store_name, store_location)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -78,16 +78,15 @@ module Win32
|
|
78
78
|
cert_get(certificate_thumbprint)
|
79
79
|
end
|
80
80
|
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# @
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
get_cert_pfx(certificate_thumbprint, store_location: store_location, export_password: export_password, output_path: output_path)
|
81
|
+
# Return `OpenSSL::X509` certificate object if present otherwise raise a "Certificate not found!" error
|
82
|
+
# @param request [thumbprint<string>] of certificate
|
83
|
+
# @return [Object] of certificates in OpenSSL::X509 format
|
84
|
+
def get!(certificate_thumbprint)
|
85
|
+
cert_pem = cert_get(certificate_thumbprint)
|
86
|
+
|
87
|
+
raise ArgumentError, "Unable to retrieve the certificate" if cert_pem.empty?
|
88
|
+
|
89
|
+
cert_pem
|
91
90
|
end
|
92
91
|
|
93
92
|
# Returns all the certificates in a store
|
@@ -111,11 +110,21 @@ module Win32
|
|
111
110
|
cert_search(certstore_handler, search_token)
|
112
111
|
end
|
113
112
|
|
113
|
+
def get_thumbprint(search_token)
|
114
|
+
cert_lookup_by_token(search_token)
|
115
|
+
end
|
116
|
+
|
114
117
|
# Validates a certificate in a certificate store on the basis of time validity
|
115
118
|
# @param request[thumbprint<string>] of certificate
|
116
119
|
# @return [true, false] only true or false
|
117
120
|
def valid?(certificate_thumbprint)
|
118
|
-
cert_validate(certificate_thumbprint)
|
121
|
+
cert_validate(certificate_thumbprint).yield_self do |x|
|
122
|
+
if x.is_a?(TrueClass) || x.is_a?(FalseClass)
|
123
|
+
x
|
124
|
+
else
|
125
|
+
false
|
126
|
+
end
|
127
|
+
end
|
119
128
|
end
|
120
129
|
|
121
130
|
# To close and destroy pointer of open certificate store handler
|
@@ -134,7 +143,7 @@ module Win32
|
|
134
143
|
|
135
144
|
# To open certstore and return open certificate store pointer
|
136
145
|
|
137
|
-
def open(store_name, store_location
|
146
|
+
def open(store_name, store_location)
|
138
147
|
certstore_handler = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, nil, store_location, wstring(store_name))
|
139
148
|
unless certstore_handler
|
140
149
|
last_error = FFI::LastError.error
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-certstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: ffi
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,19 +53,19 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: chef-powershell
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.0.12
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.0.12
|
69
69
|
description:
|
70
70
|
email:
|
71
71
|
- oss@chef.io
|
@@ -79,7 +79,6 @@ files:
|
|
79
79
|
- lib/win32/certstore/mixin/assertions.rb
|
80
80
|
- lib/win32/certstore/mixin/crypto.rb
|
81
81
|
- lib/win32/certstore/mixin/helper.rb
|
82
|
-
- lib/win32/certstore/mixin/shell_exec.rb
|
83
82
|
- lib/win32/certstore/mixin/string.rb
|
84
83
|
- lib/win32/certstore/mixin/unicode.rb
|
85
84
|
- lib/win32/certstore/store_base.rb
|
@@ -1,105 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Daniel DeLeo (<dan@chef.io>)
|
3
|
-
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
|
18
|
-
require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
|
19
|
-
|
20
|
-
module Win32
|
21
|
-
class Certstore
|
22
|
-
module Mixin
|
23
|
-
module ShellExec
|
24
|
-
def shell_out_command(*command_args)
|
25
|
-
cmd = Mixlib::ShellOut.new(*command_args)
|
26
|
-
cmd.live_stream
|
27
|
-
cmd.run_command
|
28
|
-
if cmd.error!
|
29
|
-
raise Mixlib::ShellOut::ShellCommandFailed, cmd.error!
|
30
|
-
end
|
31
|
-
|
32
|
-
cmd
|
33
|
-
end
|
34
|
-
|
35
|
-
# Run a command under powershell with the same API as shell_out. The
|
36
|
-
# options hash is extended to take an "architecture" flag which
|
37
|
-
# can be set to :i386 or :x86_64 to force the windows architecture.
|
38
|
-
#
|
39
|
-
# @param script [String] script to run
|
40
|
-
# @param options [Hash] options hash
|
41
|
-
# @return [Mixlib::Shellout] mixlib-shellout object
|
42
|
-
def powershell_exec(*command_args)
|
43
|
-
script = command_args.first
|
44
|
-
options = command_args.last.is_a?(Hash) ? command_args.last : nil
|
45
|
-
|
46
|
-
run_command_with_os_architecture(script, options)
|
47
|
-
end
|
48
|
-
|
49
|
-
# Run a command under powershell with the same API as shell_out!
|
50
|
-
# (raises exceptions on errors)
|
51
|
-
#
|
52
|
-
# @param script [String] script to run
|
53
|
-
# @param options [Hash] options hash
|
54
|
-
# @return [Mixlib::Shellout] mixlib-shellout object
|
55
|
-
def powershell_exec!(*command_args)
|
56
|
-
cmd = powershell_exec(*command_args)
|
57
|
-
cmd.error!
|
58
|
-
cmd
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
# Helper function to run shell_out and wrap it with the correct
|
64
|
-
# flags to possibly disable WOW64 redirection (which we often need
|
65
|
-
# because chef-client runs as a 32-bit app on 64-bit windows).
|
66
|
-
#
|
67
|
-
# @param script [String] script to run
|
68
|
-
# @param options [Hash] options hash
|
69
|
-
# @return [Mixlib::Shellout] mixlib-shellout object
|
70
|
-
def run_command_with_os_architecture(script, options)
|
71
|
-
options ||= {}
|
72
|
-
options = options.dup
|
73
|
-
|
74
|
-
shell_out_command(
|
75
|
-
build_powershell_command(script),
|
76
|
-
options
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Helper to build a powershell command around the script to run.
|
81
|
-
#
|
82
|
-
# @param script [String] script to run
|
83
|
-
# @return [String] powershell command to execute
|
84
|
-
def build_powershell_command(script)
|
85
|
-
flags = [
|
86
|
-
# Hides the copyright banner at startup.
|
87
|
-
"-NoLogo",
|
88
|
-
# Does not present an interactive prompt to the user.
|
89
|
-
"-NonInteractive",
|
90
|
-
# Does not load the Windows PowerShell profile.
|
91
|
-
"-NoProfile",
|
92
|
-
# always set the ExecutionPolicy flag
|
93
|
-
# see http://technet.microsoft.com/en-us/library/ee176961.aspx
|
94
|
-
"-ExecutionPolicy Unrestricted",
|
95
|
-
# Powershell will hang if STDIN is redirected
|
96
|
-
# http://connect.microsoft.com/PowerShell/feedback/details/572313/powershell-exe-can-hang-if-stdin-is-redirected
|
97
|
-
"-InputFormat None",
|
98
|
-
]
|
99
|
-
|
100
|
-
"powershell.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|