knife-windows 1.2.1 → 1.3.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.
- checksums.yaml +4 -4
- data/.gitignore +5 -5
- data/.travis.yml +26 -23
- data/CHANGELOG.md +108 -104
- data/DOC_CHANGES.md +14 -14
- data/Gemfile +12 -12
- data/LICENSE +201 -201
- data/README.md +385 -376
- data/RELEASE_NOTES.md +34 -34
- data/Rakefile +21 -21
- data/appveyor.yml +42 -42
- data/ci.gemfile +15 -15
- data/features/knife_help.feature +20 -20
- data/features/support/env.rb +5 -5
- data/knife-windows.gemspec +25 -25
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +247 -247
- data/lib/chef/knife/bootstrap_windows_base.rb +415 -415
- data/lib/chef/knife/bootstrap_windows_ssh.rb +115 -115
- data/lib/chef/knife/bootstrap_windows_winrm.rb +95 -95
- data/lib/chef/knife/core/windows_bootstrap_context.rb +366 -366
- data/lib/chef/knife/knife_windows_base.rb +33 -33
- data/lib/chef/knife/windows_cert_generate.rb +155 -155
- data/lib/chef/knife/windows_cert_install.rb +68 -68
- data/lib/chef/knife/windows_helper.rb +36 -36
- data/lib/chef/knife/windows_listener_create.rb +107 -107
- data/lib/chef/knife/winrm.rb +122 -122
- data/lib/chef/knife/winrm_base.rb +117 -113
- data/lib/chef/knife/winrm_knife_base.rb +303 -298
- data/lib/chef/knife/winrm_session.rb +86 -86
- data/lib/chef/knife/winrm_shared_options.rb +47 -47
- data/lib/chef/knife/wsman_endpoint.rb +44 -44
- data/lib/chef/knife/wsman_test.rb +117 -117
- data/lib/knife-windows/path_helper.rb +234 -234
- data/lib/knife-windows/version.rb +6 -6
- data/spec/assets/win_template_rendered_with_bootstrap_install_command.txt +217 -217
- data/spec/assets/win_template_rendered_with_bootstrap_install_command_on_12_5_client.txt +217 -217
- data/spec/assets/win_template_rendered_without_bootstrap_install_command.txt +329 -329
- data/spec/assets/win_template_rendered_without_bootstrap_install_command_on_12_5_client.txt +329 -329
- data/spec/assets/win_template_unrendered.txt +246 -246
- data/spec/functional/bootstrap_download_spec.rb +234 -234
- data/spec/spec_helper.rb +93 -93
- data/spec/unit/knife/bootstrap_options_spec.rb +155 -154
- data/spec/unit/knife/bootstrap_template_spec.rb +92 -92
- data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +295 -295
- data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +177 -177
- data/spec/unit/knife/windows_cert_generate_spec.rb +90 -90
- data/spec/unit/knife/windows_cert_install_spec.rb +51 -51
- data/spec/unit/knife/windows_listener_create_spec.rb +76 -76
- data/spec/unit/knife/winrm_session_spec.rb +64 -64
- data/spec/unit/knife/winrm_spec.rb +516 -516
- data/spec/unit/knife/wsman_test_spec.rb +201 -201
- metadata +4 -4
@@ -1,33 +1,33 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Aliasgar Batterywala (<aliasgar.batterywala@clogeny.com>)
|
3
|
-
# Copyright:: Copyright (c) 2015 Opscode, 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
|
-
|
19
|
-
class Chef
|
20
|
-
class Knife
|
21
|
-
module KnifeWindowsBase
|
22
|
-
|
23
|
-
def locate_config_value(key)
|
24
|
-
key = key.to_sym
|
25
|
-
value = config[key] || Chef::Config[:knife][key] || default_config[key]
|
26
|
-
Chef::Log.debug("Looking for key #{key} and found value #{value}")
|
27
|
-
value
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
1
|
+
#
|
2
|
+
# Author:: Aliasgar Batterywala (<aliasgar.batterywala@clogeny.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 Opscode, 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
|
+
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
module KnifeWindowsBase
|
22
|
+
|
23
|
+
def locate_config_value(key)
|
24
|
+
key = key.to_sym
|
25
|
+
value = config[key] || Chef::Config[:knife][key] || default_config[key]
|
26
|
+
Chef::Log.debug("Looking for key #{key} and found value #{value}")
|
27
|
+
value
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -1,155 +1,155 @@
|
|
1
|
-
# Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
|
2
|
-
# Copyright:: Copyright (c) 2014 Opscode, Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require 'chef/knife'
|
19
|
-
require 'chef/knife/winrm_base'
|
20
|
-
require 'openssl'
|
21
|
-
require 'socket'
|
22
|
-
|
23
|
-
class Chef
|
24
|
-
class Knife
|
25
|
-
class WindowsCertGenerate < Knife
|
26
|
-
|
27
|
-
attr_accessor :thumbprint, :hostname
|
28
|
-
|
29
|
-
banner "knife windows cert generate FILE_PATH (options)"
|
30
|
-
|
31
|
-
option :hostname,
|
32
|
-
:short => "-H HOSTNAME",
|
33
|
-
:long => "--hostname HOSTNAME",
|
34
|
-
:description => "Use to specify the hostname for the listener.
|
35
|
-
For example, --hostname something.mydomain.com or *.mydomain.com.",
|
36
|
-
:required => true
|
37
|
-
|
38
|
-
option :output_file,
|
39
|
-
:short => "-o PATH",
|
40
|
-
:long => "--output-file PATH",
|
41
|
-
:description => "Specifies the file path at which to generate the 3 certificate files of type .pfx, .b64, and .pem. The default is './winrmcert'.",
|
42
|
-
:default => "winrmcert"
|
43
|
-
|
44
|
-
option :key_length,
|
45
|
-
:short => "-k LENGTH",
|
46
|
-
:long => "--key-length LENGTH",
|
47
|
-
:description => "Default is 2048",
|
48
|
-
:default => "2048"
|
49
|
-
|
50
|
-
option :cert_validity,
|
51
|
-
:short => "-cv MONTHS",
|
52
|
-
:long => "--cert-validity MONTHS",
|
53
|
-
:description => "Default is 24 months",
|
54
|
-
:default => "24"
|
55
|
-
|
56
|
-
option :cert_passphrase,
|
57
|
-
:short => "-cp PASSWORD",
|
58
|
-
:long => "--cert-passphrase PASSWORD",
|
59
|
-
:description => "Password for certificate."
|
60
|
-
|
61
|
-
def generate_keypair
|
62
|
-
OpenSSL::PKey::RSA.new(config[:key_length].to_i)
|
63
|
-
end
|
64
|
-
|
65
|
-
def prompt_for_passphrase
|
66
|
-
passphrase = ""
|
67
|
-
begin
|
68
|
-
print "Passphrases do not match. Try again.\n" unless passphrase.empty?
|
69
|
-
print "Enter certificate passphrase (empty for no passphrase):"
|
70
|
-
passphrase = STDIN.gets
|
71
|
-
return passphrase.strip if passphrase == "\n"
|
72
|
-
print "Enter same passphrase again:"
|
73
|
-
confirm_passphrase = STDIN.gets
|
74
|
-
end until passphrase == confirm_passphrase
|
75
|
-
passphrase.strip
|
76
|
-
end
|
77
|
-
|
78
|
-
def generate_certificate rsa_key
|
79
|
-
@hostname = config[:hostname] if config[:hostname]
|
80
|
-
|
81
|
-
#Create a self-signed X509 certificate from the rsa_key (unencrypted)
|
82
|
-
cert = OpenSSL::X509::Certificate.new
|
83
|
-
cert.version = 2
|
84
|
-
cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
|
85
|
-
|
86
|
-
cert.subject = OpenSSL::X509::Name.parse "/CN=#{@hostname}"
|
87
|
-
cert.issuer = cert.subject
|
88
|
-
cert.public_key = rsa_key.public_key
|
89
|
-
cert.not_before = Time.now
|
90
|
-
cert.not_after = cert.not_before + 2 * 365 * config[:cert_validity].to_i * 60 * 60 # 2 years validity
|
91
|
-
ef = OpenSSL::X509::ExtensionFactory.new
|
92
|
-
ef.subject_certificate = cert
|
93
|
-
ef.issuer_certificate = cert
|
94
|
-
cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
|
95
|
-
cert.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
|
96
|
-
cert.add_extension(ef.create_extension("extendedKeyUsage", "1.3.6.1.5.5.7.3.1", false))
|
97
|
-
cert.sign(rsa_key, OpenSSL::Digest::SHA1.new)
|
98
|
-
@thumbprint = OpenSSL::Digest::SHA1.new(cert.to_der)
|
99
|
-
cert
|
100
|
-
end
|
101
|
-
|
102
|
-
def write_certificate_to_file(cert, file_path, rsa_key)
|
103
|
-
File.open(file_path + ".pem", "wb") { |f| f.print cert.to_pem }
|
104
|
-
config[:cert_passphrase] = prompt_for_passphrase unless config[:cert_passphrase]
|
105
|
-
pfx = OpenSSL::PKCS12.create("#{config[:cert_passphrase]}", "winrmcert", rsa_key, cert)
|
106
|
-
File.open(file_path + ".pfx", "wb") { |f| f.print pfx.to_der }
|
107
|
-
File.open(file_path + ".b64", "wb") { |f| f.print Base64.strict_encode64(pfx.to_der) }
|
108
|
-
end
|
109
|
-
|
110
|
-
def certificates_already_exist?(file_path)
|
111
|
-
certs_exists = false
|
112
|
-
%w{pem pfx b64}.each do |extn|
|
113
|
-
if !Dir.glob("#{file_path}.*#{extn}").empty?
|
114
|
-
certs_exists = true
|
115
|
-
break
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
if certs_exists
|
120
|
-
begin
|
121
|
-
confirm("Do you really want to overwrite existing certificates")
|
122
|
-
rescue SystemExit # Need to handle this as confirming with N/n raises SystemExit exception
|
123
|
-
exit!
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def run
|
129
|
-
STDOUT.sync = STDERR.sync = true
|
130
|
-
|
131
|
-
# takes user specified first cli value as a destination file path for generated cert.
|
132
|
-
file_path = @name_args.empty? ? config[:output_file].sub(/\.(\w+)$/,'') : @name_args.first
|
133
|
-
|
134
|
-
# check if certs already exists at given file path
|
135
|
-
certificates_already_exist? file_path
|
136
|
-
|
137
|
-
begin
|
138
|
-
filename = File.basename(file_path)
|
139
|
-
rsa_key = generate_keypair
|
140
|
-
cert = generate_certificate rsa_key
|
141
|
-
write_certificate_to_file cert, file_path, rsa_key
|
142
|
-
ui.info "Generated Certificates:"
|
143
|
-
ui.info "- #{filename}.pfx - PKCS12 format key pair. Contains public and private keys, can be used with an SSL server."
|
144
|
-
ui.info "- #{filename}.b64 - Base64 encoded PKCS12 key pair. Contains public and private keys, used by some cloud provider API's to configure SSL servers."
|
145
|
-
ui.info "- #{filename}.pem - Base64 encoded public certificate only. Required by the client to connect to the server."
|
146
|
-
ui.info "Certificate Thumbprint: #{@thumbprint.to_s.upcase}"
|
147
|
-
rescue => e
|
148
|
-
puts "ERROR: + #{e}"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
1
|
+
# Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
|
2
|
+
# Copyright:: Copyright (c) 2014 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/knife'
|
19
|
+
require 'chef/knife/winrm_base'
|
20
|
+
require 'openssl'
|
21
|
+
require 'socket'
|
22
|
+
|
23
|
+
class Chef
|
24
|
+
class Knife
|
25
|
+
class WindowsCertGenerate < Knife
|
26
|
+
|
27
|
+
attr_accessor :thumbprint, :hostname
|
28
|
+
|
29
|
+
banner "knife windows cert generate FILE_PATH (options)"
|
30
|
+
|
31
|
+
option :hostname,
|
32
|
+
:short => "-H HOSTNAME",
|
33
|
+
:long => "--hostname HOSTNAME",
|
34
|
+
:description => "Use to specify the hostname for the listener.
|
35
|
+
For example, --hostname something.mydomain.com or *.mydomain.com.",
|
36
|
+
:required => true
|
37
|
+
|
38
|
+
option :output_file,
|
39
|
+
:short => "-o PATH",
|
40
|
+
:long => "--output-file PATH",
|
41
|
+
:description => "Specifies the file path at which to generate the 3 certificate files of type .pfx, .b64, and .pem. The default is './winrmcert'.",
|
42
|
+
:default => "winrmcert"
|
43
|
+
|
44
|
+
option :key_length,
|
45
|
+
:short => "-k LENGTH",
|
46
|
+
:long => "--key-length LENGTH",
|
47
|
+
:description => "Default is 2048",
|
48
|
+
:default => "2048"
|
49
|
+
|
50
|
+
option :cert_validity,
|
51
|
+
:short => "-cv MONTHS",
|
52
|
+
:long => "--cert-validity MONTHS",
|
53
|
+
:description => "Default is 24 months",
|
54
|
+
:default => "24"
|
55
|
+
|
56
|
+
option :cert_passphrase,
|
57
|
+
:short => "-cp PASSWORD",
|
58
|
+
:long => "--cert-passphrase PASSWORD",
|
59
|
+
:description => "Password for certificate."
|
60
|
+
|
61
|
+
def generate_keypair
|
62
|
+
OpenSSL::PKey::RSA.new(config[:key_length].to_i)
|
63
|
+
end
|
64
|
+
|
65
|
+
def prompt_for_passphrase
|
66
|
+
passphrase = ""
|
67
|
+
begin
|
68
|
+
print "Passphrases do not match. Try again.\n" unless passphrase.empty?
|
69
|
+
print "Enter certificate passphrase (empty for no passphrase):"
|
70
|
+
passphrase = STDIN.gets
|
71
|
+
return passphrase.strip if passphrase == "\n"
|
72
|
+
print "Enter same passphrase again:"
|
73
|
+
confirm_passphrase = STDIN.gets
|
74
|
+
end until passphrase == confirm_passphrase
|
75
|
+
passphrase.strip
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_certificate rsa_key
|
79
|
+
@hostname = config[:hostname] if config[:hostname]
|
80
|
+
|
81
|
+
#Create a self-signed X509 certificate from the rsa_key (unencrypted)
|
82
|
+
cert = OpenSSL::X509::Certificate.new
|
83
|
+
cert.version = 2
|
84
|
+
cert.serial = Random.rand(65534) + 1 # 2 digit byte range random number for better security aspect
|
85
|
+
|
86
|
+
cert.subject = OpenSSL::X509::Name.parse "/CN=#{@hostname}"
|
87
|
+
cert.issuer = cert.subject
|
88
|
+
cert.public_key = rsa_key.public_key
|
89
|
+
cert.not_before = Time.now
|
90
|
+
cert.not_after = cert.not_before + 2 * 365 * config[:cert_validity].to_i * 60 * 60 # 2 years validity
|
91
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
92
|
+
ef.subject_certificate = cert
|
93
|
+
ef.issuer_certificate = cert
|
94
|
+
cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
|
95
|
+
cert.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
|
96
|
+
cert.add_extension(ef.create_extension("extendedKeyUsage", "1.3.6.1.5.5.7.3.1", false))
|
97
|
+
cert.sign(rsa_key, OpenSSL::Digest::SHA1.new)
|
98
|
+
@thumbprint = OpenSSL::Digest::SHA1.new(cert.to_der)
|
99
|
+
cert
|
100
|
+
end
|
101
|
+
|
102
|
+
def write_certificate_to_file(cert, file_path, rsa_key)
|
103
|
+
File.open(file_path + ".pem", "wb") { |f| f.print cert.to_pem }
|
104
|
+
config[:cert_passphrase] = prompt_for_passphrase unless config[:cert_passphrase]
|
105
|
+
pfx = OpenSSL::PKCS12.create("#{config[:cert_passphrase]}", "winrmcert", rsa_key, cert)
|
106
|
+
File.open(file_path + ".pfx", "wb") { |f| f.print pfx.to_der }
|
107
|
+
File.open(file_path + ".b64", "wb") { |f| f.print Base64.strict_encode64(pfx.to_der) }
|
108
|
+
end
|
109
|
+
|
110
|
+
def certificates_already_exist?(file_path)
|
111
|
+
certs_exists = false
|
112
|
+
%w{pem pfx b64}.each do |extn|
|
113
|
+
if !Dir.glob("#{file_path}.*#{extn}").empty?
|
114
|
+
certs_exists = true
|
115
|
+
break
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if certs_exists
|
120
|
+
begin
|
121
|
+
confirm("Do you really want to overwrite existing certificates")
|
122
|
+
rescue SystemExit # Need to handle this as confirming with N/n raises SystemExit exception
|
123
|
+
exit!
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def run
|
129
|
+
STDOUT.sync = STDERR.sync = true
|
130
|
+
|
131
|
+
# takes user specified first cli value as a destination file path for generated cert.
|
132
|
+
file_path = @name_args.empty? ? config[:output_file].sub(/\.(\w+)$/,'') : @name_args.first
|
133
|
+
|
134
|
+
# check if certs already exists at given file path
|
135
|
+
certificates_already_exist? file_path
|
136
|
+
|
137
|
+
begin
|
138
|
+
filename = File.basename(file_path)
|
139
|
+
rsa_key = generate_keypair
|
140
|
+
cert = generate_certificate rsa_key
|
141
|
+
write_certificate_to_file cert, file_path, rsa_key
|
142
|
+
ui.info "Generated Certificates:"
|
143
|
+
ui.info "- #{filename}.pfx - PKCS12 format key pair. Contains public and private keys, can be used with an SSL server."
|
144
|
+
ui.info "- #{filename}.b64 - Base64 encoded PKCS12 key pair. Contains public and private keys, used by some cloud provider API's to configure SSL servers."
|
145
|
+
ui.info "- #{filename}.pem - Base64 encoded public certificate only. Required by the client to connect to the server."
|
146
|
+
ui.info "Certificate Thumbprint: #{@thumbprint.to_s.upcase}"
|
147
|
+
rescue => e
|
148
|
+
puts "ERROR: + #{e}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
@@ -1,68 +1,68 @@
|
|
1
|
-
# Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
|
2
|
-
# Copyright:: Copyright (c) 2014 Opscode, Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require 'chef/knife'
|
19
|
-
require 'chef/knife/winrm_base'
|
20
|
-
|
21
|
-
class Chef
|
22
|
-
class Knife
|
23
|
-
class WindowsCertInstall < Knife
|
24
|
-
|
25
|
-
banner "knife windows cert install CERT [CERT] (options)"
|
26
|
-
|
27
|
-
option :cert_passphrase,
|
28
|
-
:short => "-cp PASSWORD",
|
29
|
-
:long => "--cert-passphrase PASSWORD",
|
30
|
-
:description => "Password for certificate."
|
31
|
-
|
32
|
-
def get_cert_passphrase
|
33
|
-
print "Enter given certificate's passphrase (empty for no passphrase):"
|
34
|
-
passphrase = STDIN.gets
|
35
|
-
passphrase.strip
|
36
|
-
end
|
37
|
-
|
38
|
-
def run
|
39
|
-
STDOUT.sync = STDERR.sync = true
|
40
|
-
|
41
|
-
if Chef::Platform.windows?
|
42
|
-
if @name_args.empty?
|
43
|
-
ui.error "Please specify the certificate path. e.g- 'knife windows cert install <path>"
|
44
|
-
exit 1
|
45
|
-
end
|
46
|
-
file_path = @name_args.first
|
47
|
-
config[:cert_passphrase] = get_cert_passphrase unless config[:cert_passphrase]
|
48
|
-
|
49
|
-
begin
|
50
|
-
ui.info "Adding certificate to the Windows Certificate Store..."
|
51
|
-
result = %x{powershell.exe -Command " '#{config[:cert_passphrase]}' | certutil -importPFX '#{file_path}' AT_KEYEXCHANGE"}
|
52
|
-
if $?.exitstatus == 0
|
53
|
-
ui.info "Certificate added to Certificate Store"
|
54
|
-
else
|
55
|
-
ui.info "Error adding the certificate. Use -VV option for details"
|
56
|
-
end
|
57
|
-
Chef::Log.debug "#{result}"
|
58
|
-
rescue => e
|
59
|
-
puts "ERROR: + #{e}"
|
60
|
-
end
|
61
|
-
else
|
62
|
-
ui.error "Certificate can be installed on Windows system only"
|
63
|
-
exit 1
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
1
|
+
# Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
|
2
|
+
# Copyright:: Copyright (c) 2014 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/knife'
|
19
|
+
require 'chef/knife/winrm_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class WindowsCertInstall < Knife
|
24
|
+
|
25
|
+
banner "knife windows cert install CERT [CERT] (options)"
|
26
|
+
|
27
|
+
option :cert_passphrase,
|
28
|
+
:short => "-cp PASSWORD",
|
29
|
+
:long => "--cert-passphrase PASSWORD",
|
30
|
+
:description => "Password for certificate."
|
31
|
+
|
32
|
+
def get_cert_passphrase
|
33
|
+
print "Enter given certificate's passphrase (empty for no passphrase):"
|
34
|
+
passphrase = STDIN.gets
|
35
|
+
passphrase.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
STDOUT.sync = STDERR.sync = true
|
40
|
+
|
41
|
+
if Chef::Platform.windows?
|
42
|
+
if @name_args.empty?
|
43
|
+
ui.error "Please specify the certificate path. e.g- 'knife windows cert install <path>"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
file_path = @name_args.first
|
47
|
+
config[:cert_passphrase] = get_cert_passphrase unless config[:cert_passphrase]
|
48
|
+
|
49
|
+
begin
|
50
|
+
ui.info "Adding certificate to the Windows Certificate Store..."
|
51
|
+
result = %x{powershell.exe -Command " '#{config[:cert_passphrase]}' | certutil -importPFX '#{file_path}' AT_KEYEXCHANGE"}
|
52
|
+
if $?.exitstatus == 0
|
53
|
+
ui.info "Certificate added to Certificate Store"
|
54
|
+
else
|
55
|
+
ui.info "Error adding the certificate. Use -VV option for details"
|
56
|
+
end
|
57
|
+
Chef::Log.debug "#{result}"
|
58
|
+
rescue => e
|
59
|
+
puts "ERROR: + #{e}"
|
60
|
+
end
|
61
|
+
else
|
62
|
+
ui.error "Certificate can be installed on Windows system only"
|
63
|
+
exit 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|