chef 14.6.47-universal-mingw32 → 14.7.17-universal-mingw32

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/chef-universal-mingw32.gemspec +1 -0
  3. data/lib/chef/application/apply.rb +6 -4
  4. data/lib/chef/knife/config_list_profiles.rb +1 -1
  5. data/lib/chef/knife/list.rb +1 -1
  6. data/lib/chef/knife/raw.rb +1 -1
  7. data/lib/chef/knife/role_env_run_list_clear.rb +1 -1
  8. data/lib/chef/knife/role_env_run_list_remove.rb +1 -1
  9. data/lib/chef/knife/role_env_run_list_replace.rb +1 -1
  10. data/lib/chef/knife/role_env_run_list_set.rb +1 -1
  11. data/lib/chef/knife/role_run_list_clear.rb +1 -1
  12. data/lib/chef/knife/role_run_list_remove.rb +1 -1
  13. data/lib/chef/knife/role_run_list_replace.rb +1 -1
  14. data/lib/chef/knife/role_run_list_set.rb +1 -1
  15. data/lib/chef/knife/show.rb +1 -1
  16. data/lib/chef/knife/upload.rb +1 -1
  17. data/lib/chef/knife/xargs.rb +1 -1
  18. data/lib/chef/node/attribute.rb +189 -185
  19. data/lib/chef/platform/rebooter.rb +1 -0
  20. data/lib/chef/property.rb +25 -1
  21. data/lib/chef/provider/windows_task.rb +19 -6
  22. data/lib/chef/resource.rb +17 -2
  23. data/lib/chef/resource/apt_preference.rb +2 -1
  24. data/lib/chef/resource/apt_repository.rb +1 -1
  25. data/lib/chef/resource/apt_update.rb +1 -0
  26. data/lib/chef/resource/build_essential.rb +1 -1
  27. data/lib/chef/resource/cab_package.rb +1 -1
  28. data/lib/chef/resource/chef_gem.rb +1 -1
  29. data/lib/chef/resource/cookbook_file.rb +2 -1
  30. data/lib/chef/resource/cron_d.rb +1 -1
  31. data/lib/chef/resource/dmg_package.rb +52 -40
  32. data/lib/chef/resource/execute.rb +2 -2
  33. data/lib/chef/resource/file.rb +1 -1
  34. data/lib/chef/resource/group.rb +2 -2
  35. data/lib/chef/resource/homebrew_cask.rb +3 -2
  36. data/lib/chef/resource/homebrew_tap.rb +2 -2
  37. data/lib/chef/resource/hostname.rb +2 -2
  38. data/lib/chef/resource/kernel_module.rb +19 -13
  39. data/lib/chef/resource/locale.rb +1 -0
  40. data/lib/chef/resource/macos_userdefaults.rb +7 -6
  41. data/lib/chef/resource/mdadm.rb +3 -2
  42. data/lib/chef/resource/mount.rb +3 -3
  43. data/lib/chef/resource/openssl_dhparam.rb +1 -1
  44. data/lib/chef/resource/openssl_ec_private_key.rb +1 -1
  45. data/lib/chef/resource/openssl_ec_public_key.rb +3 -3
  46. data/lib/chef/resource/openssl_rsa_private_key.rb +2 -2
  47. data/lib/chef/resource/openssl_rsa_public_key.rb +3 -3
  48. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  49. data/lib/chef/resource/openssl_x509_crl.rb +1 -1
  50. data/lib/chef/resource/openssl_x509_request.rb +1 -1
  51. data/lib/chef/resource/package.rb +1 -1
  52. data/lib/chef/resource/powershell_package.rb +1 -1
  53. data/lib/chef/resource/remote_directory.rb +2 -2
  54. data/lib/chef/resource/rhsm_errata.rb +1 -1
  55. data/lib/chef/resource/rhsm_errata_level.rb +1 -1
  56. data/lib/chef/resource/rhsm_register.rb +7 -7
  57. data/lib/chef/resource/rhsm_repo.rb +1 -1
  58. data/lib/chef/resource/rhsm_subscription.rb +1 -1
  59. data/lib/chef/resource/sudo.rb +8 -8
  60. data/lib/chef/resource/swap_file.rb +1 -1
  61. data/lib/chef/resource/sysctl.rb +2 -2
  62. data/lib/chef/resource/systemd_unit.rb +19 -11
  63. data/lib/chef/resource/timezone.rb +60 -32
  64. data/lib/chef/resource/windows_ad_join.rb +1 -1
  65. data/lib/chef/resource/windows_auto_run.rb +1 -1
  66. data/lib/chef/resource/windows_certificate.rb +269 -0
  67. data/lib/chef/resource/windows_env.rb +12 -3
  68. data/lib/chef/resource/windows_feature.rb +6 -11
  69. data/lib/chef/resource/windows_feature_dism.rb +2 -2
  70. data/lib/chef/resource/windows_feature_powershell.rb +5 -9
  71. data/lib/chef/resource/windows_firewall_rule.rb +205 -0
  72. data/lib/chef/resource/windows_path.rb +3 -1
  73. data/lib/chef/resource/windows_printer.rb +2 -2
  74. data/lib/chef/resource/windows_printer_port.rb +3 -3
  75. data/lib/chef/resource/windows_service.rb +1 -0
  76. data/lib/chef/resource/windows_share.rb +315 -0
  77. data/lib/chef/resource/windows_task.rb +4 -0
  78. data/lib/chef/resource/windows_workgroup.rb +6 -4
  79. data/lib/chef/resource/yum_repository.rb +13 -7
  80. data/lib/chef/resource/zypper_package.rb +2 -2
  81. data/lib/chef/resource/zypper_repository.rb +2 -1
  82. data/lib/chef/resource_inspector.rb +4 -4
  83. data/lib/chef/resources.rb +3 -0
  84. data/lib/chef/version.rb +1 -1
  85. data/spec/functional/resource/windows_task_spec.rb +39 -0
  86. data/spec/support/platform_helpers.rb +2 -1
  87. data/spec/unit/resource/windows_certificate.rb +46 -0
  88. data/spec/unit/resource/windows_firewall_rule_spec.rb +401 -0
  89. data/spec/unit/resource/windows_share.rb +39 -0
  90. metadata +24 -4
@@ -37,17 +37,17 @@ class Chef
37
37
  # acording to the sudo man pages sudo will ignore files in an include dir that have a `.` or `~`
38
38
  # We convert either to `__`
39
39
  property :filename, String,
40
- description: "The name of the sudoers.d file.",
40
+ description: "The name of the sudoers.d file, if it differs from the name of the resource block",
41
41
  name_property: true,
42
42
  coerce: proc { |x| x.gsub(/[\.~]/, "__") }
43
43
 
44
44
  property :users, [String, Array],
45
- description: "User(s) to provide sudo privileges to. This accepts either an array or a comma separated.",
45
+ description: "User(s) to provide sudo privileges to. This property accepts either an array or a comma separated list.",
46
46
  default: lazy { [] },
47
47
  coerce: proc { |x| x.is_a?(Array) ? x : x.split(/\s*,\s*/) }
48
48
 
49
49
  property :groups, [String, Array],
50
- description: "Group(s) to provide sudo privileges to. This accepts either an array or a comma separated list. Leading % on group names is optional.",
50
+ description: "Group(s) to provide sudo privileges to. This property accepts either an array or a comma separated list. Leading % on group names is optional.",
51
51
  default: lazy { [] },
52
52
  coerce: proc { |x| coerce_groups(x) }
53
53
 
@@ -72,10 +72,10 @@ class Chef
72
72
  default: false
73
73
 
74
74
  property :template, String,
75
- description: "The name of the erb template in your cookbook if you wish to supply your own template."
75
+ description: "The name of the erb template in your cookbook, if you wish to supply your own template."
76
76
 
77
77
  property :variables, [Hash, nil],
78
- description: "The variables to pass to the custom template. Ignored if not using a custom template.",
78
+ description: "The variables to pass to the custom template. This property is ignored if not using a custom template.",
79
79
  default: nil
80
80
 
81
81
  property :defaults, Array,
@@ -99,15 +99,15 @@ class Chef
99
99
  default: lazy { [] }
100
100
 
101
101
  property :visudo_path, String,
102
- description: "Deprecated property. Do not use."
102
+ deprecated: true
103
103
 
104
104
  property :visudo_binary, String,
105
105
  description: "The path to visudo for configuration verification.",
106
106
  default: "/usr/sbin/visudo"
107
107
 
108
108
  property :config_prefix, String,
109
- description: "The directory that contains the sudoers configuration file",
110
- default: lazy { platform_config_prefix }
109
+ description: "The directory that contains the sudoers configuration file.",
110
+ default: lazy { platform_config_prefix }, default_description: "Prefix values based on the node's platform"
111
111
 
112
112
  # handle legacy cookbook property
113
113
  def after_created
@@ -27,7 +27,7 @@ class Chef
27
27
  introduced "14.0"
28
28
 
29
29
  property :path, String,
30
- description: "The path to put the swap file on the system.",
30
+ description: "The path where the swap file will be created on the system, if it differs from the resource block name.",
31
31
  name_property: true
32
32
 
33
33
  property :size, Integer,
@@ -24,7 +24,7 @@ class Chef
24
24
  provides(:sysctl) { true }
25
25
  provides(:sysctl_param) { true }
26
26
 
27
- description "Use the sysctl resource to set kernel parameters using the sysctl"\
27
+ description "Use the sysctl resource to set or remove kernel parameters using the sysctl"\
28
28
  " command line tool and configuration files in the system's sysctl.d directory. "\
29
29
  "Configuration files managed by this resource are named 99-chef-KEYNAME.conf. If"\
30
30
  " an existing value was already set for the value it will be backed up to the node"\
@@ -33,7 +33,7 @@ class Chef
33
33
  introduced "14.0"
34
34
 
35
35
  property :key, String,
36
- description: "The kernel parameter key in dotted format.",
36
+ description: "The kernel parameter key in dotted format, if it differs from the resource block name.",
37
37
  name_property: true
38
38
 
39
39
  property :ignore_error, [TrueClass, FalseClass],
@@ -38,22 +38,30 @@ class Chef
38
38
  :reload_or_try_restart
39
39
 
40
40
  # Internal provider-managed properties
41
- property :enabled, [TrueClass, FalseClass]
42
- property :active, [TrueClass, FalseClass]
43
- property :masked, [TrueClass, FalseClass]
44
- property :static, [TrueClass, FalseClass]
41
+ property :enabled, [TrueClass, FalseClass], skip_docs: true
42
+ property :active, [TrueClass, FalseClass], skip_docs: true
43
+ property :masked, [TrueClass, FalseClass], skip_docs: true
44
+ property :static, [TrueClass, FalseClass], skip_docs: true
45
45
 
46
46
  # User-provided properties
47
- property :user, String, desired_state: false
48
- property :content, [String, Hash]
47
+ property :user, String, desired_state: false,
48
+ description: "The user account that the systemd unit process is run under. The path to the unit for that user would be something like '/etc/systemd/user/sshd.service'. If no user account is specified, the systemd unit will run under a 'system' account, with the path to the unit being something like '/etc/systemd/system/sshd.service'."
49
+
50
+ property :content, [String, Hash],
51
+ description: "A string or hash that contains a systemd `unit file <https://www.freedesktop.org/software/systemd/man/systemd.unit.html>`_ definition that describes the properties of systemd-managed entities, such as services, sockets, devices, and so on. In Chef 14.4 or later, repeatable options can be implemented with an array."
52
+
49
53
  property :triggers_reload, [TrueClass, FalseClass],
50
- default: true, desired_state: false
54
+ description: "Specifies whether to trigger a daemon reload when creating or deleting a unit.",
55
+ default: true, desired_state: false
56
+
51
57
  property :verify, [TrueClass, FalseClass],
52
- default: true, desired_state: false
58
+ default: true, desired_state: false,
59
+ description: "Specifies if the unit will be verified before installation. Systemd can be overly strict when verifying units, so in certain cases it is preferable not to verify the unit."
60
+
53
61
  property :unit_name, String, desired_state: false,
54
- identity: true,
55
- name_property: true,
56
- introduced: "13.7"
62
+ identity: true, name_property: true,
63
+ description: "The name of the unit file if it differs from the resource block name.",
64
+ introduced: "13.7"
57
65
 
58
66
  def to_ini
59
67
  case content
@@ -25,7 +25,7 @@ class Chef
25
25
  preview_resource true
26
26
  resource_name :timezone
27
27
 
28
- description "Use the timezone resource to change the system timezone."
28
+ description "Use the timezone resource to change the system timezone on Linux and macOS hosts. Timezones are specified in tz database format, with a complete list of available TZ values here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones."
29
29
  introduced "14.6"
30
30
 
31
31
  property :timezone, String,
@@ -35,12 +35,15 @@ class Chef
35
35
  action :set do
36
36
  description "Set the timezone."
37
37
 
38
- package "tzdata" do
39
- package_name platform_family?("suse") ? "timezone" : "tzdata"
38
+ # some linux systems may be missing the timezone data
39
+ if node["os"] == "linux"
40
+ package "tzdata" do
41
+ package_name platform_family?("suse") ? "timezone" : "tzdata"
42
+ end
40
43
  end
41
44
 
45
+ # Modern Amazon, Fedora, RHEL, Ubuntu & Debian
42
46
  if node["init_package"] == "systemd"
43
- # Modern Amazon, Fedora, CentOS, RHEL, Ubuntu & Debian
44
47
  cmd_set_tz = "/usr/bin/timedatectl --no-ask-password set-timezone #{new_resource.timezone}"
45
48
 
46
49
  cmd_check_if_set = "/usr/bin/timedatectl status"
@@ -51,38 +54,63 @@ class Chef
51
54
  action :run
52
55
  not_if cmd_check_if_set
53
56
  end
54
- elsif platform_family?("rhel", "amazon")
55
- # Old version of RHEL & CentOS
56
- file "/etc/sysconfig/clock" do
57
- owner "root"
58
- group "root"
59
- mode "0644"
60
- action :create
61
- content %{ZONE="#{new_resource.timezone}"\nUTC="true"\n}
62
- end
57
+ else
58
+ case node["platform_family"]
59
+ # Old version of RHEL < 7 and Amazon 201X
60
+ when "rhel", "amazon"
61
+ file "/etc/sysconfig/clock" do
62
+ owner "root"
63
+ group "root"
64
+ mode "0644"
65
+ action :create
66
+ content %{ZONE="#{new_resource.timezone}"\nUTC="true"\n}
67
+ end
63
68
 
64
- execute "tzdata-update" do
65
- command "/usr/sbin/tzdata-update"
66
- action :nothing
67
- only_if { ::File.executable?("/usr/sbin/tzdata-update") }
68
- subscribes :run, "file[/etc/sysconfig/clock]", :immediately
69
- end
69
+ execute "tzdata-update" do
70
+ command "/usr/sbin/tzdata-update"
71
+ action :nothing
72
+ only_if { ::File.executable?("/usr/sbin/tzdata-update") }
73
+ subscribes :run, "file[/etc/sysconfig/clock]", :immediately
74
+ end
70
75
 
71
- link "/etc/localtime" do
72
- to "/usr/share/zoneinfo/#{new_resource.timezone}"
73
- not_if { ::File.executable?("/usr/sbin/tzdata-update") }
74
- end
75
- elsif platform_family?("debian")
76
- file "/etc/timezone" do
77
- action :create
78
- content "#{new_resource.timezone}\n"
76
+ link "/etc/localtime" do
77
+ to "/usr/share/zoneinfo/#{new_resource.timezone}"
78
+ not_if { ::File.executable?("/usr/sbin/tzdata-update") }
79
+ end
80
+ # debian < 8 and Ubuntu < 16.04
81
+ when "debian"
82
+ file "/etc/timezone" do
83
+ action :create
84
+ content "#{new_resource.timezone}\n"
85
+ end
86
+
87
+ bash "dpkg-reconfigure tzdata" do
88
+ user "root"
89
+ code "/usr/sbin/dpkg-reconfigure -f noninteractive tzdata"
90
+ action :nothing
91
+ subscribes :run, "file[/etc/timezone]", :immediately
92
+ end
93
+ when "mac_os_x"
94
+ unless current_darwin_tz == new_resource.timezone
95
+ converge_by("set timezone to #{new_resource.timezone}") do
96
+ shell_out!("sudo systemsetup -settimezone #{new_resource.timezone}")
97
+ end
98
+ end
79
99
  end
100
+ end
101
+ end
80
102
 
81
- bash "dpkg-reconfigure tzdata" do
82
- user "root"
83
- code "/usr/sbin/dpkg-reconfigure -f noninteractive tzdata"
84
- action :nothing
85
- subscribes :run, "file[/etc/timezone]", :immediately
103
+ action_class do
104
+ # detect the current TZ on darwin hosts
105
+ #
106
+ # @since 14.7
107
+ # @return [String] TZ database value
108
+ def current_darwin_tz
109
+ tz_shellout = shell_out!("systemsetup -gettimezone")
110
+ if /You need administrator access/.match?(tz_shellout.stdout)
111
+ raise "The timezone resource requires adminstrative priveleges to run on macOS hosts!"
112
+ else
113
+ /Time Zone: (.*)/.match(tz_shellout.stdout)[1]
86
114
  end
87
115
  end
88
116
  end
@@ -58,7 +58,7 @@ class Chef
58
58
 
59
59
  # define this again so we can default it to true. Otherwise failures print the password
60
60
  property :sensitive, [TrueClass, FalseClass],
61
- default: true
61
+ default: true, desired_state: false
62
62
 
63
63
  action :join do
64
64
  description "Join the Active Directory domain."
@@ -28,7 +28,7 @@ class Chef
28
28
  introduced "14.0"
29
29
 
30
30
  property :program_name, String,
31
- description: "The name of the program to run at login if different from the resource name.",
31
+ description: "The name of the program to run at login, if it differs from the resource block name.",
32
32
  name_property: true
33
33
 
34
34
  property :path, String,
@@ -0,0 +1,269 @@
1
+ #
2
+ # Author:: Richard Lavey (richard.lavey@calastone.com)
3
+ #
4
+ # Copyright:: 2015-2017, Calastone Ltd.
5
+ # Copyright:: 2018, Chef Software, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require "chef/resource"
21
+ require "win32-certstore" if Chef::Platform.windows?
22
+ require "openssl"
23
+
24
+ class Chef
25
+ class Resource
26
+ class WindowsCertificate < Chef::Resource
27
+ preview_resource true
28
+ resource_name :windows_certificate
29
+
30
+ description "Use the windows_certificate resource to install a certificate into the Windows certificate store from a file. The resource grants read-only access to the private key for designated accounts. Due to current limitations in WinRM, installing certificates remotely may not work if the operation requires a user profile. Operations on the local machine store should still work."
31
+ introduced "14.7"
32
+
33
+ property :source, String,
34
+ description: "The source file (for create and acl_add), thumbprint (for delete and acl_add) or subject (for delete).",
35
+ name_property: true
36
+
37
+ property :pfx_password, String,
38
+ description: "The password to access the source if it is a pfx file."
39
+
40
+ property :private_key_acl, Array,
41
+ description: "An array of 'domain\account' entries to be granted read-only access to the certificate's private key. Not idempotent."
42
+
43
+ property :store_name, String,
44
+ description: "The certificate store to manipulate.",
45
+ default: "MY", equal_to: ["TRUSTEDPUBLISHER", "TrustedPublisher", "CLIENTAUTHISSUER", "REMOTE DESKTOP", "ROOT", "TRUSTEDDEVICES", "WEBHOSTING", "CA", "AUTHROOT", "TRUSTEDPEOPLE", "MY", "SMARTCARDROOT", "TRUST", "DISALLOWED"]
46
+
47
+ property :user_store, [TrueClass, FalseClass],
48
+ description: "Use the user store of the local machine store if set to false.",
49
+ default: false
50
+
51
+ property :cert_path, String,
52
+ description: ""
53
+
54
+ # lazy used to set default value of sensitive to true if password is set
55
+ property :sensitive, [ TrueClass, FalseClass ],
56
+ description: "Ensure that sensitive resource data is not logged by the chef-client.",
57
+ default: lazy { |r| r.pfx_password ? true : false }, skip_docs: true
58
+
59
+ action :create do
60
+ description "Creates or updates a certificate."
61
+
62
+ add_cert(OpenSSL::X509::Certificate.new(raw_source))
63
+ end
64
+
65
+ # acl_add is a modify-if-exists operation : not idempotent
66
+ action :acl_add do
67
+ description "Adds read-only entries to a certificate's private key ACL."
68
+
69
+ if ::File.exist?(new_resource.source)
70
+ hash = "$cert.GetCertHashString()"
71
+ code_script = cert_script(false)
72
+ guard_script = cert_script(false)
73
+ else
74
+ # make sure we have no spaces in the hash string
75
+ hash = "\"#{new_resource.source.gsub(/\s/, '')}\""
76
+ code_script = ""
77
+ guard_script = ""
78
+ end
79
+ code_script << acl_script(hash)
80
+ guard_script << cert_exists_script(hash)
81
+
82
+ powershell_script "setting the acls on #{new_resource.source} in #{cert_location}\\#{new_resource.store_name}" do
83
+ guard_interpreter :powershell_script
84
+ convert_boolean_return true
85
+ code code_script
86
+ only_if guard_script
87
+ sensitive if new_resource.sensitive
88
+ end
89
+ end
90
+
91
+ action :delete do
92
+ description "Deletes a certificate."
93
+
94
+ delete_cert
95
+ end
96
+
97
+ action :fetch do
98
+ description "Fetches a certificate."
99
+
100
+ cert_obj = fetch_cert
101
+ if cert_obj
102
+ show_or_store_cert(cert_obj)
103
+ else
104
+ Chef::Log.info("Certificate not found")
105
+ end
106
+ end
107
+
108
+ action :verify do
109
+ description ""
110
+
111
+ out = verify_cert
112
+ if !!out == out
113
+ out = out ? "Certificate is valid" : "Certificate not valid"
114
+ end
115
+ Chef::Log.info(out.to_s)
116
+ end
117
+
118
+ action_class do
119
+ def add_cert(cert_obj)
120
+ store = ::Win32::Certstore.open(new_resource.store_name)
121
+ store.add(cert_obj)
122
+ end
123
+
124
+ def delete_cert
125
+ store = ::Win32::Certstore.open(new_resource.store_name)
126
+ store.delete(new_resource.source)
127
+ end
128
+
129
+ def fetch_cert
130
+ store = ::Win32::Certstore.open(new_resource.store_name)
131
+ store.get(new_resource.source)
132
+ end
133
+
134
+ def verify_cert
135
+ store = ::Win32::Certstore.open(new_resource.store_name)
136
+ store.valid?(new_resource.source)
137
+ end
138
+
139
+ def show_or_store_cert(cert_obj)
140
+ if new_resource.cert_path
141
+ export_cert(cert_obj, new_resource.cert_path)
142
+ if ::File.size(new_resource.cert_path) > 0
143
+ Chef::Log.info("Certificate export in #{new_resource.cert_path}")
144
+ else
145
+ ::File.delete(new_resource.cert_path)
146
+ end
147
+ else
148
+ Chef::Log.info(cert_obj.display)
149
+ end
150
+ end
151
+
152
+ def export_cert(cert_obj, cert_path)
153
+ out_file = ::File.new(cert_path, "w+")
154
+ case ::File.extname(cert_path)
155
+ when ".pem"
156
+ out_file.puts(cert_obj.to_pem)
157
+ when ".der"
158
+ out_file.puts(cert_obj.to_der)
159
+ when ".cer"
160
+ cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CER").stdout
161
+ out_file.puts(cert_out)
162
+ when ".crt"
163
+ cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CRT").stdout
164
+ out_file.puts(cert_out)
165
+ when ".pfx"
166
+ cert_out = powershell_out("openssl pkcs12 -export -nokeys -in #{cert_obj.to_pem} -outform PFX").stdout
167
+ out_file.puts(cert_out)
168
+ when ".p7b"
169
+ cert_out = powershell_out("openssl pkcs7 -export -nokeys -in #{cert_obj.to_pem} -outform P7B").stdout
170
+ out_file.puts(cert_out)
171
+ else
172
+ Chef::Log.info("Supported certificate format .pem, .der, .cer, .crt, .pfx and .p7b")
173
+ end
174
+ out_file.close
175
+ end
176
+
177
+ def cert_location
178
+ @location ||= new_resource.user_store ? "CurrentUser" : "LocalMachine"
179
+ end
180
+
181
+ def cert_script(persist)
182
+ cert_script = "$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2"
183
+ file = win_friendly_path(new_resource.source)
184
+ cert_script << " \"#{file}\""
185
+ if ::File.extname(file.downcase) == ".pfx"
186
+ cert_script << ", \"#{new_resource.pfx_password}\""
187
+ if persist && new_resource.user_store
188
+ cert_script << ", ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)"
189
+ elsif persist
190
+ cert_script << ", ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeyset)"
191
+ end
192
+ end
193
+ cert_script << "\n"
194
+ end
195
+
196
+ def cert_exists_script(hash)
197
+ <<-EOH
198
+ $hash = #{hash}
199
+ Test-Path "Cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
200
+ EOH
201
+ end
202
+
203
+ def within_store_script
204
+ inner_script = yield "$store"
205
+ <<-EOH
206
+ $store = New-Object System.Security.Cryptography.X509Certificates.X509Store "#{new_resource.store_name}", ([System.Security.Cryptography.X509Certificates.StoreLocation]::#{cert_location})
207
+ $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
208
+ #{inner_script}
209
+ $store.Close()
210
+ EOH
211
+ end
212
+
213
+ def acl_script(hash)
214
+ return "" if new_resource.private_key_acl.nil? || new_resource.private_key_acl.empty?
215
+ # this PS came from http://blogs.technet.com/b/operationsguy/archive/2010/11/29/provide-access-to-private-keys-commandline-vs-powershell.aspx
216
+ # and from https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx
217
+ set_acl_script = <<-EOH
218
+ $hash = #{hash}
219
+ $storeCert = Get-ChildItem "cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
220
+ if ($storeCert -eq $null) { throw 'no key exists.' }
221
+ $keyname = $storeCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
222
+ if ($keyname -eq $null) { throw 'no private key exists.' }
223
+ if ($storeCert.PrivateKey.CspKeyContainerInfo.MachineKeyStore)
224
+ {
225
+ $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\$keyname"
226
+ }
227
+ else
228
+ {
229
+ $currentUser = New-Object System.Security.Principal.NTAccount($Env:UserDomain, $Env:UserName)
230
+ $userSID = $currentUser.Translate([System.Security.Principal.SecurityIdentifier]).Value
231
+ $fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\$userSID\\$keyname"
232
+ }
233
+ EOH
234
+ new_resource.private_key_acl.each do |name|
235
+ set_acl_script << "$uname='#{name}'; icacls $fullpath /grant $uname`:RX\n"
236
+ end
237
+ set_acl_script
238
+ end
239
+
240
+ def raw_source
241
+ ext = ::File.extname(new_resource.source)
242
+ convert_pem(ext, new_resource.source)
243
+ end
244
+
245
+ def convert_pem(ext, source)
246
+ out = case ext
247
+ when ".crt", ".der"
248
+ powershell_out("openssl x509 -text -inform DER -in #{source} -outform PEM").stdout
249
+ when ".cer"
250
+ powershell_out("openssl x509 -text -inform DER -in #{source} -outform PEM").stdout
251
+ when ".pfx"
252
+ powershell_out("openssl pkcs12 -in #{source} -nodes -passin pass:#{new_resource.pfx_password}").stdout
253
+ when ".p7b"
254
+ powershell_out("openssl pkcs7 -print_certs -in #{source} -outform PEM").stdout
255
+ end
256
+ out = ::File.read(source) if out.nil? || out.empty?
257
+ format_raw_out(out)
258
+ end
259
+
260
+ def format_raw_out(out)
261
+ begin_cert = "-----BEGIN CERTIFICATE-----"
262
+ end_cert = "-----END CERTIFICATE-----"
263
+ begin_cert + out[/#{begin_cert}(.*?)#{end_cert}/m, 1] + end_cert
264
+ end
265
+ end
266
+
267
+ end
268
+ end
269
+ end