summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2019-03-04 11:02:24 -0800
committerGitHub <noreply@github.com>2019-03-04 11:02:24 -0800
commit8c4542e8afd82d407a1eb7a853d22f3f64bbe44f (patch)
treeb5dfb41b233b62d72a3bc16faa4cd361d489e4ed
parent626d10f471cb50aec9a7a23c2f92bc5b48a46b46 (diff)
parent8989b00b3209a092fc07d3daae4683cf9fe682f2 (diff)
downloadchef-8c4542e8afd82d407a1eb7a853d22f3f64bbe44f.tar.gz
Merge pull request #8267 from chef/cert_14_more
windows_certificate: Add support to import Base 64 encoded CER certificates
-rw-r--r--lib/chef/resource/windows_certificate.rb61
-rw-r--r--spec/data/windows_certificates/base64_test.cer22
-rw-r--r--spec/functional/resource/windows_certificate_spec.rb18
3 files changed, 73 insertions, 28 deletions
diff --git a/lib/chef/resource/windows_certificate.rb b/lib/chef/resource/windows_certificate.rb
index ba942328d3..380cca2fdd 100644
--- a/lib/chef/resource/windows_certificate.rb
+++ b/lib/chef/resource/windows_certificate.rb
@@ -53,7 +53,7 @@ class Chef
description: ""
# lazy used to set default value of sensitive to true if password is set
- property :sensitive, [ TrueClass, FalseClass ],
+ property :sensitive, [TrueClass, FalseClass],
description: "Ensure that sensitive resource data is not logged by the chef-client.",
default: lazy { |r| r.pfx_password ? true : false }, skip_docs: true
@@ -62,9 +62,7 @@ class Chef
# Extension of the certificate
ext = ::File.extname(new_resource.source)
- raw_source = convert_pem(ext)
-
- cert_obj = OpenSSL::X509::Certificate.new(raw_source) # A certificate object in memory
+ cert_obj = fetch_cert_object(ext) # Fetch OpenSSL::X509::Certificate object
thumbprint = OpenSSL::Digest::SHA1.new(cert_obj.to_der).to_s # Fetch its thumbprint
# Need to check if return value is Boolean:true
@@ -248,6 +246,7 @@ class Chef
def acl_script(hash)
return "" if new_resource.private_key_acl.nil? || new_resource.private_key_acl.empty?
+
# this PS came from http://blogs.technet.com/b/operationsguy/archive/2010/11/29/provide-access-to-private-keys-commandline-vs-powershell.aspx
# and from https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx
set_acl_script = <<-EOH
@@ -273,35 +272,43 @@ class Chef
set_acl_script
end
- # Uses powershell command to convert crt/der/cer/pfx & p7b certificates
- # In PEM format and returns its certificate content
- def convert_pem(ext)
- out = case ext
- when ".crt", ".cer", ".der"
- powershell_out("openssl x509 -text -inform DER -in #{new_resource.source} -outform PEM")
- when ".pfx"
- powershell_out("openssl pkcs12 -in #{new_resource.source} -nodes -passin pass:'#{new_resource.pfx_password}'")
- when ".p7b"
- powershell_out("openssl pkcs7 -print_certs -in #{new_resource.source} -outform PEM")
- else
- powershell_out("openssl x509 -text -inform #{ext.delete(".")} -in #{new_resource.source} -outform PEM")
- end
-
- if out.exitstatus == 0
- format_raw_out(out.stdout)
+ # Method returns an OpenSSL::X509::Certificate object
+ #
+ # Based on its extension, the certificate contents are used to initialize
+ # PKCS12 (PFX), PKCS7 (P7B) objects which contains OpenSSL::X509::Certificate.
+ #
+ # @note Other then PEM, all the certificates are usually in binary format, and hence
+ # their contents are loaded by using File.binread
+ #
+ # @param ext [String] Extension of the certificate
+ #
+ # @return [OpenSSL::X509::Certificate] Object containing certificate's attributes
+ #
+ # @raise [OpenSSL::PKCS12::PKCS12Error] When incorrect password is provided for PFX certificate
+ #
+ def fetch_cert_object(ext)
+ contents = if binary_cert?
+ ::File.binread(new_resource.source)
+ else
+ ::File.read(new_resource.source)
+ end
+
+ case ext
+ when ".pfx"
+ OpenSSL::PKCS12.new(contents, new_resource.pfx_password).certificate
+ when ".p7b"
+ OpenSSL::PKCS7.new(contents).certificates.first
else
- raise out.stderr
+ OpenSSL::X509::Certificate.new(contents)
end
end
- # Returns the certificate content
- def format_raw_out(out)
- begin_cert = "-----BEGIN CERTIFICATE-----"
- end_cert = "-----END CERTIFICATE-----"
- begin_cert + out[/#{begin_cert}(.*?)#{end_cert}/m, 1] + end_cert
+ # @return [Boolean] Whether the certificate file is binary encoded or not
+ #
+ def binary_cert?
+ powershell_out!("file -b --mime-encoding #{new_resource.source}").stdout.strip == "binary"
end
end
-
end
end
end
diff --git a/spec/data/windows_certificates/base64_test.cer b/spec/data/windows_certificates/base64_test.cer
new file mode 100644
index 0000000000..0d90bf81e3
--- /dev/null
+++ b/spec/data/windows_certificates/base64_test.cer
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQNH6iXZnEKbFOEQ7D9f9iCTANBgkqhkiG9w0BAQsFADBK
+MSMwIQYDVQQDDBpBIEJhc2U2NCBEdW1teSBDZXJ0aWZpY2F0ZTEjMCEGCSqGSIb3
+DQEJARYUdGVzdGJ5cnNwZWNAY2hlZi5jb20wHhcNMTkwMjEyMDk1ODM2WhcNMjAw
+MjEyMTAxODM2WjBKMSMwIQYDVQQDDBpBIEJhc2U2NCBEdW1teSBDZXJ0aWZpY2F0
+ZTEjMCEGCSqGSIb3DQEJARYUdGVzdGJ5cnNwZWNAY2hlZi5jb20wggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSy2Qlf2k1X3y/YgEjnvD0K8NeKgXKKi62
+RHRMTJ2+6KSg+I1MqHZC+BVrfzehuJVby5kM7tGLF8FvM3q7X/5oSPg8pvLZzIV0
+pBrpVPCTYw8fnlmFKBt/+m2XOqsWyL59yP+p66SHAKmoLYTGu8dkGvgJn3dwKNen
+VFmwadteVfKs2wFW/ZwUxH4aLloCa8KSyqstIXrYQmdqqFOSuEgkynalD19dozSv
+QtkQ9FZPuFGDwNpdO7OrcjE1lTUlzuth7CqV/pj4GYJhK/PPtO8Ing/BtwZm5XB8
+2yvvLVnL7Y/hikg2ENKA9fOYk52zR/kkd7d8qoJva7WlYEXTZvpdAgMBAAGjcDBu
+MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
+HgYDVR0RBBcwFYITd3d3LnRlc3RieXJzcGVjLmNvbTAdBgNVHQ4EFgQUuL1l247K
+h+cVH9LehmQgXuV8F6MwDQYJKoZIhvcNAQELBQADggEBAMTJW5tSZ/g2AP45EUwj
+PLDnDLY4YnsJDQ7Jo58EAY6givUc+ZnKRWxYAYNBOKcqDM5E4pXi3Fa1lKYR1vMu
+5AThPaDXhv18ljGAs21MYt9hl7PqdzbfX4ejF+jCD4UrE8bGtxuDc1WQ2HbeJtdj
+0j7BPPNXfcvPAIyX3BEOQFUPgvVAqzWMQLpdUKg+sNUJZijqKQv11xVALGHtxqGB
+1MFrdl6D/idODfhcdo2n1tBMyOGhHwEOBLqB1PTH72g5J4BVx4iwH/gh8PRmMy0P
+eJkNspgOBGPOhNpe7bhmK45MBuJpmjyl/CYCqtQvaEdpbuRQIgc2e+YRMfR71qYp
+Em8=
+-----END CERTIFICATE-----
diff --git a/spec/functional/resource/windows_certificate_spec.rb b/spec/functional/resource/windows_certificate_spec.rb
index f60b63ade9..eac7ee31b2 100644
--- a/spec/functional/resource/windows_certificate_spec.rb
+++ b/spec/functional/resource/windows_certificate_spec.rb
@@ -60,6 +60,7 @@ describe Chef::Resource::WindowsCertificate, :windows_only, :appveyor_only do
let(:store) { "Chef-Functional-Test" }
let(:certificate_path) { File.expand_path(File.join(CHEF_SPEC_DATA, "windows_certificates")) }
let(:cer_path) { File.join(certificate_path, "test.cer") }
+ let(:base64_path) { File.join(certificate_path, "base64_test.cer") }
let(:pem_path) { File.join(certificate_path, "test.pem") }
let(:pfx_path) { File.join(certificate_path, "test.pfx") }
let(:out_path) { File.join(certificate_path, "testout.pem") }
@@ -174,6 +175,21 @@ describe Chef::Resource::WindowsCertificate, :windows_only, :appveyor_only do
end
end
+ context "Adds Base64 Encoded CER" do
+ before do
+ win_certificate.source = base64_path
+ win_certificate.run_action(:create)
+ end
+ it "Imports certificate into store" do
+ expect(no_of_certificates).to eq(1)
+ end
+ it "Idempotent: Does not converge while adding again" do
+ win_certificate.run_action(:create)
+ expect(no_of_certificates).to eq(1)
+ expect(win_certificate).not_to be_updated_by_last_action
+ end
+ end
+
context "Adds PEM" do
before do
win_certificate.source = pem_path
@@ -212,7 +228,7 @@ describe Chef::Resource::WindowsCertificate, :windows_only, :appveyor_only do
win_certificate.pfx_password = "Invalid password"
end
it "Raises an error" do
- expect { win_certificate.run_action(:create) }.to raise_error(RuntimeError)
+ expect { win_certificate.run_action(:create) }.to raise_error(OpenSSL::PKCS12::PKCS12Error)
end
end
end