From 8d15be576e7b6d6e738508a37fd6ae9b45c85248 Mon Sep 17 00:00:00 2001 From: Ricardo Gaspar Date: Thu, 23 Mar 2017 18:12:07 +0100 Subject: [PATCH 1/2] Adding a new argument to specify the location of the scripts. README updated with this info. Spec tests added. Tests use a different certificate thumbprint.The test certificate is spec/testCert.pfx fixing style errors,rubocop errors Committer: ricardogaspar2 --- README.md | 45 ++++++++++++--- manifests/init.pp | 81 ++++++++++++++++++++------ spec/defines/sslcertificate_spec.rb | 88 ++++++++++++++++++++++++++++- templates/import.ps1.erb | 10 ++-- templates/inspect.ps1.erb | 10 ++-- 5 files changed, 197 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index de8f66f..7c675e3 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ machines. It will manage pfx, cer, der, p7b, sst certificates. } ``` - To install a certifcate in an alterntative direcotory: + To install a certificate in an alternative directory: ```puppet sslcertificate { "Install-Intermediate-Certificate" : @@ -58,6 +58,29 @@ machines. It will manage pfx, cer, der, p7b, sst certificates. } ``` +To install a certificate in the My directory of the LocalMachine root store using a different directory to store the scripts: + +```puppet + sslcertificate { "Install-PFX-Certificate" : + name => 'mycert.pfx', + password => 'password123', + location => 'C:', + thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', + scripts_dir => 'C:\scripts_dir' + } +``` + +To install a certificate in the My directory of the LocalMachine root store and set the key as not exportable: +```puppet + sslcertificate { "Install-PFX-Certificate" : + name => 'mycert.pfx', + password => 'password123', + location => 'C:', + thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', + is_exportable => false + } +``` + For more details on the different options available with certificate management directories, see [Windows Dev Center](http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136(v=vs.85).aspx). @@ -74,27 +97,35 @@ certificates into your keystore(s). ##### `password` -The password for the given certifcate +The password for the given certificate ##### `location` -The location to store intermediate certificates +The location where the file certificate is. +Do not end the string with any forward or backslash. ##### `thumbprint` -The thumbprint used to verify the certifcate +The thumbprint used to verify the certificate ##### `store_dir` -The certifcate store where the certifcate will be installed to +The certifcate store where the certificate will be installed to ##### `root_store` -The store location for the given certifcation store. Either LocalMachine or CurrentUser +The store location for the given certification store. Either LocalMachine or CurrentUser + +##### `scripts_dir` + +The directory where the scripts to verify and install the certificates will be stored. By default is C:\temp + +##### `is_exportable` +Flag to set the key as exportable. `true` == exportable; `false` == not exportable. By default is set to `true`. ## Reference -### Defintion +### Definition #### Public Definition diff --git a/manifests/init.pp b/manifests/init.pp index 65ab664..4008e6e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,7 +1,6 @@ # Author:: Paul Stack (mailto:pstack@opentable.com) # Copyright:: Copyright (c) 2013 OpenTable Inc # License:: MIT - # == Define: sslcertificate # # This defined type will install SSL Certs on windows @@ -17,7 +16,8 @@ # The password for the given certifcate # # [*location*] -# The location to store intermediate certificates +# The location to store intermediate certificates. +# Do not end the string with any forward or backslash. # # [*thumbprint*] # The thumbprint used to verify the certifcate @@ -28,6 +28,13 @@ # [*root_store*] # The store location for the given certifcation store. Either LocalMachine or CurrentUser # +# [*scripts_dir*] +# The directory where the scripts to verify and install the certificates will be stored. +# By default is C:\temp +# +# [*is_exportable*] +# Flag to set the key as exportable. true == exportable; false == not exportable. +# By default is set to true. # === Examples # # To install a certificate in the My directory of the LocalMachine root store: @@ -35,46 +42,84 @@ # sslcertificate { "Install-PFX-Certificate" : # name => 'mycert.pfx', # password => 'password123', -# location => 'C:\', +# location => 'C:', # thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B' # } # -# To install a certifcate in an alterntative direcotory: +# To install a certifcate in an alternative directory: # # sslcertificate { "Install-Intermediate-Certificate" : # name => 'go_daddy_intermediate.p7b', -# location => 'C:\', +# location => 'C:', # store_dir => 'CA', # root_store => 'LocalMachine', # thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B' # } # -define sslcertificate($password, $location, $thumbprint, $root_store = 'LocalMachine', $store_dir = 'My') { - validate_re($name, '^(.)+$',"Must pass name to ${module_name}[${title}]") - validate_re($location, '^(.)+$',"Must pass location to ${module_name}[${title}]") +# To install a certificate in the My directory of the LocalMachine root store +# using a different directory to store the scripts: +# +# sslcertificate { "Install-PFX-Certificate" : +# name => 'mycert.pfx', +# password => 'password123', +# location => 'C:', +# thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', +# scripts_dir => 'C:\scripts_dir' +# } +# +# To install a certificate in the My directory of the LocalMachine root store +# and set the key as not exportable: +# +# sslcertificate { "Install-PFX-Certificate" : +# name => 'mycert.pfx', +# password => 'password123', +# location => 'C:', +# thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', +# is_exportable => false +# } +# +define sslcertificate ( + $password, + $location, + $thumbprint, + $root_store = 'LocalMachine', + $store_dir = 'My', + $scripts_dir = 'C:\temp', + $is_exportable = true) { + validate_re($name, '^(.)+$', "Must pass name to ${module_name}[${title}]") + validate_re($location, '^(.)+$', "Must pass location to ${module_name}[${title}]") validate_re($thumbprint, '^(.)+$', "Must pass a certificate thumbprint to ${module_name}[${title}]") - ensure_resource('file', 'C:\temp', { ensure => directory }) + ensure_resource('file', $scripts_dir, { + ensure => directory + } + ) + + if($is_exportable){ + $key_storage_flags = 'Exportable,PersistKeySet' + }else{ + $key_storage_flags = 'PersistKeySet' + } - file { "inspect-${name}-certificate.ps1" : + file { "inspect-${name}-certificate.ps1": ensure => present, - path => "C:\\temp\\inspect-${name}.ps1", + path => "${scripts_dir}\\inspect-${name}.ps1", content => template('sslcertificate/inspect.ps1.erb'), - require => File['C:\temp'], + require => File[$scripts_dir], } - file { "import-${name}-certificate.ps1" : + file { "import-${name}-certificate.ps1": ensure => present, - path => "C:\\temp\\import-${name}.ps1", + path => "${scripts_dir}\\import-${name}.ps1", content => template('sslcertificate/import.ps1.erb'), - require => File['C:\temp'], + require => File[$scripts_dir], } exec { "Install-${name}-SSLCert": provider => powershell, - command => "c:\\temp\\import-${name}.ps1", - onlyif => "c:\\temp\\inspect-${name}.ps1", + command => "${scripts_dir}\\import-${name}.ps1", + onlyif => "${scripts_dir}\\inspect-${name}.ps1", logoutput => true, - require => [ File["inspect-${name}-certificate.ps1"], File["import-${name}-certificate.ps1"] ], + require => [File["inspect-${name}-certificate.ps1"], File["import-${name}-certificate.ps1"]], } } diff --git a/spec/defines/sslcertificate_spec.rb b/spec/defines/sslcertificate_spec.rb index 9ef3545..7d02922 100644 --- a/spec/defines/sslcertificate_spec.rb +++ b/spec/defines/sslcertificate_spec.rb @@ -16,8 +16,8 @@ it do is_expected.to contain_exec('Install-testCert-SSLCert').with( - 'command' => 'c:\temp\import-testCert.ps1', - 'onlyif' => 'c:\temp\inspect-testCert.ps1', + 'command' => 'C:\temp\import-testCert.ps1', + 'onlyif' => 'C:\temp\inspect-testCert.ps1', 'provider' => 'powershell' ) end @@ -42,6 +42,90 @@ it { is_expected.to contain_file('inspect-testCert-certificate.ps1').with_content(%r{\$installedCert in \$installedCerts}) } end + describe 'when managing a ssl certificate specifying a directory for scripts' do + let(:title) { 'certificate-testCert' } + let(:params) do + { + name: 'testCert', + password: 'testPass', + location: 'C:\SslCertificates', + thumbprint: '07E5C1AF7F5223CB975CC29B5455642F5570798B', + root_store: 'LocalMachine', + store_dir: 'My', + scripts_dir: 'C:\scripts' + } + end + + it do + is_expected.to contain_exec('Install-testCert-SSLCert').with( + 'command' => 'C:\scripts\import-testCert.ps1', + 'onlyif' => 'C:\scripts\inspect-testCert.ps1', + 'provider' => 'powershell' + ) + end + + it do + is_expected.to contain_file('import-testCert-certificate.ps1').with( + 'ensure' => 'present', + 'path' => 'C:\\scripts\\import-testCert.ps1', + 'require' => 'File[C:\scripts]' + ) + end + + it { is_expected.to contain_file('import-testCert-certificate.ps1').with_content(%r{store.Add}) } + + it do + is_expected.to contain_file('inspect-testCert-certificate.ps1').with( + 'ensure' => 'present', + 'path' => 'C:\\scripts\\inspect-testCert.ps1', + 'require' => 'File[C:\scripts]' + ) + end + it { is_expected.to contain_file('inspect-testCert-certificate.ps1').with_content(%r{\$installedCert in \$installedCerts}) } + end + + describe 'when managing a ssl certificate and set the key as not exportable' do + let(:title) { 'certificate-testCert' } + let(:params) do + { + name: 'testCert', + password: 'testPass', + location: 'C:\SslCertificates', + thumbprint: '07E5C1AF7F5223CB975CC29B5455642F5570798B', + root_store: 'LocalMachine', + store_dir: 'My', + is_exportable: false + } + end + + it do + is_expected.to contain_exec('Install-testCert-SSLCert').with( + 'command' => 'C:\temp\import-testCert.ps1', + 'onlyif' => 'C:\temp\inspect-testCert.ps1', + 'provider' => 'powershell' + ) + end + + it do + is_expected.to contain_file('import-testCert-certificate.ps1').with( + 'ensure' => 'present', + 'path' => 'C:\\temp\\import-testCert.ps1', + 'require' => 'File[C:\temp]' + ) + end + + it { is_expected.to contain_file('import-testCert-certificate.ps1').without_content(%r{Exportable,PersistKeySet}) } + + it do + is_expected.to contain_file('inspect-testCert-certificate.ps1').with( + 'ensure' => 'present', + 'path' => 'C:\\temp\\inspect-testCert.ps1', + 'require' => 'File[C:\temp]' + ) + end + it { is_expected.to contain_file('inspect-testCert-certificate.ps1').without_content(%r{Exportable,PersistKeySet}) } + end + describe 'when empty certificate name is provided' do let(:title) { 'certificate-testCert' } let(:params) do diff --git a/templates/import.ps1.erb b/templates/import.ps1.erb index 91a73c8..17432c9 100644 --- a/templates/import.ps1.erb +++ b/templates/import.ps1.erb @@ -1,21 +1,21 @@ $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 -$cert = gi <%= @location %>/<%= @name %> +$cert = gi "<%= @location %>\<%= @name %>" switch -regex ($cert.Extension.ToUpper()) { ".CER|.DER|.P12" { - $pfx.import("<%= @location %>\\<%= @name %>","<%= @password %>","Exportable,PersistKeySet") + $pfx.import("<%= @location %>\<%= @name %>","<%= @password %>","<%= @key_storage_flags %>") } ".CRT" { - $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\\<%= @name %>")) + $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\<%= @name %>")) } ".P7B|.SST" { $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection - $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\\<%= @name %>")) + $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\<%= @name %>")) } ".PFX" { $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection - $pfx.import("<%= @location %>\\<%= @name %>","<%= @password %>","Exportable,PersistKeySet") + $pfx.import("<%= @location %>\<%= @name %>","<%= @password %>","<%= @key_storage_flags %>") } } diff --git a/templates/inspect.ps1.erb b/templates/inspect.ps1.erb index 8045f3c..5e4c2f2 100644 --- a/templates/inspect.ps1.erb +++ b/templates/inspect.ps1.erb @@ -1,20 +1,20 @@ $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 -$certificate = gi <%= @location %>\<%= @name %> +$certificate = gi "<%= @location %>\<%= @name %>" switch -regex ($certificate.Extension.ToUpper()) { ".CER|.DER|.P12" { - $pfx.import("<%= @location %>\\<%= @name %>","<%= @password %>","Exportable,PersistKeySet") + $pfx.import("<%= @location %>\<%= @name %>","<%= @password %>","<%= @key_storage_flags %>") } ".CRT" { - $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\\<%= @name %>")) + $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\<%= @name %>")) } ".P7B|.SST" { $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection - $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\\<%= @name %>")) + $pfx.Import([System.IO.File]::ReadAllBytes("<%= @location %>\<%= @name %>")) } ".PFX" { $pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection - $pfx.import("<%= @location %>\\<%= @name %>","<%= @password %>","Exportable,PersistKeySet") + $pfx.import("<%= @location %>\<%= @name %>","<%= @password %>","<%= @key_storage_flags %>") } } From b1f4bdd9ec2fffc449d4d9b4ec55cb2a066dc775 Mon Sep 17 00:00:00 2001 From: Ricardo Gaspar Date: Thu, 27 Apr 2017 17:34:48 +0200 Subject: [PATCH 2/2] Code refactored, following changes sugested by oranenj --- README.md | 4 ++-- manifests/init.pp | 11 +++++------ spec/defines/sslcertificate_spec.rb | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7c675e3..a58dfc1 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ To install a certificate in the My directory of the LocalMachine root store and password => 'password123', location => 'C:', thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', - is_exportable => false + exportable => false } ``` @@ -120,7 +120,7 @@ The store location for the given certification store. Either LocalMachine or Cur The directory where the scripts to verify and install the certificates will be stored. By default is C:\temp -##### `is_exportable` +##### `exportable` Flag to set the key as exportable. `true` == exportable; `false` == not exportable. By default is set to `true`. ## Reference diff --git a/manifests/init.pp b/manifests/init.pp index 4008e6e..0838edc 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -75,7 +75,7 @@ # password => 'password123', # location => 'C:', # thumbprint => '07E5C1AF7F5223CB975CC29B5455642F5570798B', -# is_exportable => false +# exportable => false # } # define sslcertificate ( @@ -85,19 +85,18 @@ $root_store = 'LocalMachine', $store_dir = 'My', $scripts_dir = 'C:\temp', - $is_exportable = true) { + $exportable = true) { validate_re($name, '^(.)+$', "Must pass name to ${module_name}[${title}]") validate_re($location, '^(.)+$', "Must pass location to ${module_name}[${title}]") validate_re($thumbprint, '^(.)+$', "Must pass a certificate thumbprint to ${module_name}[${title}]") ensure_resource('file', $scripts_dir, { ensure => directory - } - ) + }) - if($is_exportable){ + if $exportable { $key_storage_flags = 'Exportable,PersistKeySet' - }else{ + } else { $key_storage_flags = 'PersistKeySet' } diff --git a/spec/defines/sslcertificate_spec.rb b/spec/defines/sslcertificate_spec.rb index 7d02922..6f44129 100644 --- a/spec/defines/sslcertificate_spec.rb +++ b/spec/defines/sslcertificate_spec.rb @@ -94,7 +94,7 @@ thumbprint: '07E5C1AF7F5223CB975CC29B5455642F5570798B', root_store: 'LocalMachine', store_dir: 'My', - is_exportable: false + exportable: false } end