diff --git a/REFERENCE.md b/REFERENCE.md
index 15bcf45..6d50878 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -369,6 +369,7 @@ The following parameters are available in the `openssl::certificate::x509` defin
* [`encrypted`](#-openssl--certificate--x509--encrypted)
* [`ca`](#-openssl--certificate--x509--ca)
* [`cakey`](#-openssl--certificate--x509--cakey)
+* [`cakey_password`](#-openssl--certificate--x509--cakey_password)
##### `ensure`
@@ -648,6 +649,14 @@ provided.
Default value: `undef`
+##### `cakey_password`
+
+Data type: `Optional[Variant[Sensitive, String]]`
+
+Optional password that has encrypted the CA key.
+
+Default value: `undef`
+
### `openssl::config`
Generates an openssl.conf file using defaults
@@ -1258,6 +1267,7 @@ The following parameters are available in the `x509_cert` type.
* [`authentication`](#-x509_cert--authentication)
* [`ca`](#-x509_cert--ca)
* [`cakey`](#-x509_cert--cakey)
+* [`cakey_password`](#-x509_cert--cakey_password)
* [`csr`](#-x509_cert--csr)
* [`days`](#-x509_cert--days)
* [`force`](#-x509_cert--force)
@@ -1284,6 +1294,10 @@ The optional ca certificate filepath
The optional ca private key filepath
+##### `cakey_password`
+
+The optional CA key password
+
##### `csr`
The optional certificate signing request path
diff --git a/lib/puppet/provider/x509_cert/openssl.rb b/lib/puppet/provider/x509_cert/openssl.rb
index e5262a7..997d7da 100644
--- a/lib/puppet/provider/x509_cert/openssl.rb
+++ b/lib/puppet/provider/x509_cert/openssl.rb
@@ -99,7 +99,10 @@ def create
'-out', resource[:path]
]
end
- options << ['-passin', "pass:#{resource[:password]}"] if resource[:password]
+
+ password = resource[:cakey_password] || resource[:password]
+
+ options << ['-passin', "pass:#{password}"] if password
options << ['-extensions', 'v3_req'] if resource[:req_ext] != :false
openssl options
end
diff --git a/lib/puppet/type/x509_cert.rb b/lib/puppet/type/x509_cert.rb
index fce7223..b304827 100644
--- a/lib/puppet/type/x509_cert.rb
+++ b/lib/puppet/type/x509_cert.rb
@@ -77,6 +77,10 @@
desc 'The optional ca private key filepath'
end
+ newparam(:cakey_password) do
+ desc 'The optional CA key password'
+ end
+
autorequire(:file) do
self[:template]
end
diff --git a/manifests/certificate/x509.pp b/manifests/certificate/x509.pp
index 7543d7e..7e19b70 100644
--- a/manifests/certificate/x509.pp
+++ b/manifests/certificate/x509.pp
@@ -93,6 +93,8 @@
# @param cakey
# Path to CA private key for signing. Undef mean no CAkey will be
# provided.
+# @param cakey_password
+# Optional password that has encrypted the CA key.
#
# @example basic usage
#
@@ -116,37 +118,38 @@
# and set $key_mode to '0640'.
#
define openssl::certificate::x509 (
- Enum['present', 'absent'] $ensure = present,
- Optional[String] $country = undef,
- Optional[String] $organization = undef,
- Optional[String] $unit = undef,
- Optional[String] $state = undef,
- Optional[String] $commonname = undef,
- Optional[String] $locality = undef,
- Array $altnames = [],
- Array $extkeyusage = [],
- Optional[String] $email = undef,
- Integer $days = 365,
- Stdlib::Absolutepath $base_dir = '/etc/ssl/certs',
- Stdlib::Absolutepath $cnf_dir = $base_dir,
- Stdlib::Absolutepath $crt_dir = $base_dir,
- Stdlib::Absolutepath $csr_dir = $base_dir,
- Stdlib::Absolutepath $key_dir = $base_dir,
- Stdlib::Absolutepath $cnf = "${cnf_dir}/${name}.cnf",
- Stdlib::Absolutepath $crt = "${crt_dir}/${name}.crt",
- Stdlib::Absolutepath $csr = "${csr_dir}/${name}.csr",
- Stdlib::Absolutepath $key = "${key_dir}/${name}.key",
- Integer $key_size = 3072,
- Variant[String, Integer] $owner = 'root',
- Variant[String, Integer] $group = 'root',
- Variant[String, Integer] $key_owner = $owner,
- Variant[String, Integer] $key_group = $group,
- Stdlib::Filemode $key_mode = '0600',
- Optional[String] $password = undef,
- Boolean $force = true,
- Boolean $encrypted = true,
- Optional[Stdlib::Absolutepath] $ca = undef,
- Optional[Stdlib::Absolutepath] $cakey = undef,
+ Enum['present', 'absent'] $ensure = present,
+ Optional[String] $country = undef,
+ Optional[String] $organization = undef,
+ Optional[String] $unit = undef,
+ Optional[String] $state = undef,
+ Optional[String] $commonname = undef,
+ Optional[String] $locality = undef,
+ Array $altnames = [],
+ Array $extkeyusage = [],
+ Optional[String] $email = undef,
+ Integer $days = 365,
+ Stdlib::Absolutepath $base_dir = '/etc/ssl/certs',
+ Stdlib::Absolutepath $cnf_dir = $base_dir,
+ Stdlib::Absolutepath $crt_dir = $base_dir,
+ Stdlib::Absolutepath $csr_dir = $base_dir,
+ Stdlib::Absolutepath $key_dir = $base_dir,
+ Stdlib::Absolutepath $cnf = "${cnf_dir}/${name}.cnf",
+ Stdlib::Absolutepath $crt = "${crt_dir}/${name}.crt",
+ Stdlib::Absolutepath $csr = "${csr_dir}/${name}.csr",
+ Stdlib::Absolutepath $key = "${key_dir}/${name}.key",
+ Integer $key_size = 3072,
+ Variant[String, Integer] $owner = 'root',
+ Variant[String, Integer] $group = 'root',
+ Variant[String, Integer] $key_owner = $owner,
+ Variant[String, Integer] $key_group = $group,
+ Stdlib::Filemode $key_mode = '0600',
+ Optional[String] $password = undef,
+ Boolean $force = true,
+ Boolean $encrypted = true,
+ Optional[Stdlib::Absolutepath] $ca = undef,
+ Optional[Stdlib::Absolutepath] $cakey = undef,
+ Optional[Variant[Sensitive, String]] $cakey_password = undef,
) {
unless $country or $organization or $unit or $state or $commonname {
fail('At least one of $country, $organization, $unit, $state or $commonname is required.')
@@ -179,15 +182,16 @@
encrypted => $encrypted,
}
~> x509_cert { $crt:
- ensure => $ensure,
- template => $cnf,
- csr => $csr,
- days => $days,
- password => $password,
- req_ext => !empty($altnames) and !empty($extkeyusage),
- force => $force,
- ca => $ca,
- cakey => $cakey,
+ ensure => $ensure,
+ template => $cnf,
+ csr => $csr,
+ days => $days,
+ password => $password,
+ req_ext => !empty($altnames) and !empty($extkeyusage),
+ force => $force,
+ ca => $ca,
+ cakey => $cakey,
+ cakey_password => $cakey_password,
}
# Set owner of all files
diff --git a/spec/defines/openssl_certificate_x509_spec.rb b/spec/defines/openssl_certificate_x509_spec.rb
index e2df33d..1782dff 100644
--- a/spec/defines/openssl_certificate_x509_spec.rb
+++ b/spec/defines/openssl_certificate_x509_spec.rb
@@ -524,4 +524,111 @@
)
}
end
+
+ context 'when passing CA properties' do
+ let(:params) do
+ {
+ country: 'com',
+ organization: 'bar',
+ commonname: 'baz',
+ state: 'FR',
+ locality: 'here',
+ unit: 'braz',
+ altnames: ['a.com', 'b.com', 'c.com'],
+ extkeyusage: %w[serverAuth clientAuth],
+ email: 'contact@foo.com',
+ days: 4567,
+ key_size: 4096,
+ owner: 'www-data',
+ ca: '/etc/pki/ca.crt',
+ cakey: '/etc/pki/ca.key',
+ cakey_password: '5r$}^',
+ force: false,
+ base_dir: '/tmp/foobar',
+ }
+ end
+
+ it {
+ is_expected.to contain_file('/tmp/foobar/foo.cnf').with(
+ ensure: 'present',
+ owner: 'www-data'
+ ).with_content(
+ %r{countryName\s+=\s+com}
+ ).with_content(
+ %r{stateOrProvinceName\s+=\s+FR}
+ ).with_content(
+ %r{localityName\s+=\s+here}
+ ).with_content(
+ %r{organizationName\s+=\s+bar}
+ ).with_content(
+ %r{organizationalUnitName\s+=\s+braz}
+ ).with_content(
+ %r{commonName\s+=\s+baz}
+ ).with_content(
+ %r{emailAddress\s+=\s+contact@foo\.com}
+ ).with_content(
+ %r{extendedKeyUsage\s+=\s+serverAuth,\s+clientAuth}
+ ).with_content(
+ %r{subjectAltName\s+=\s+@alt_names}
+ ).with_content(
+ %r{DNS\.0\s+=\s+a\.com}
+ ).with_content(
+ %r{DNS\.1\s+=\s+b\.com}
+ ).with_content(
+ %r{DNS\.2\s+=\s+c\.com}
+ )
+ }
+
+ it {
+ is_expected.to contain_ssl_pkey('/tmp/foobar/foo.key').with(
+ ensure: 'present',
+ password: nil,
+ size: 4096
+ )
+ }
+
+ it {
+ is_expected.to contain_x509_cert('/tmp/foobar/foo.crt').with(
+ ensure: 'present',
+ template: '/tmp/foobar/foo.cnf',
+ csr: '/tmp/foobar/foo.csr',
+ days: 4567,
+ ca: '/etc/pki/ca.crt',
+ cakey: '/etc/pki/ca.key',
+ cakey_password: '5r$}^',
+ force: false
+ )
+ }
+
+ it {
+ is_expected.to contain_x509_request('/tmp/foobar/foo.csr').with(
+ ensure: 'present',
+ template: '/tmp/foobar/foo.cnf',
+ private_key: '/tmp/foobar/foo.key',
+ password: nil,
+ force: false
+ )
+ }
+
+ it {
+ is_expected.to contain_file('/tmp/foobar/foo.key').with(
+ ensure: 'present',
+ owner: 'www-data'
+ )
+ }
+
+ it {
+ is_expected.to contain_file('/tmp/foobar/foo.crt').with(
+ ensure: 'present',
+ owner: 'www-data'
+ )
+ }
+
+ it {
+ is_expected.to contain_file('/tmp/foobar/foo.csr').with(
+ ensure: 'present',
+ owner: 'www-data'
+ )
+ }
+ end
end
diff --git a/spec/unit/puppet/provider/x509_cert/openssl_spec.rb b/spec/unit/puppet/provider/x509_cert/openssl_spec.rb
index 88b42de..8a11059 100644
--- a/spec/unit/puppet/provider/x509_cert/openssl_spec.rb
+++ b/spec/unit/puppet/provider/x509_cert/openssl_spec.rb
@@ -79,6 +79,29 @@
end
end
+ context 'when using a CA for signing with a password' do
+ it 'creates a certificate with the proper options' do
+ resource[:csr] = '/tmp/foo.csr'
+ resource[:ca] = '/tmp/foo-ca.crt'
+ resource[:cakey] = '/tmp/foo-ca.key'
+ resource[:cakey_password] = '5i;6%'
+ expect(provider_class).to receive(:openssl).with([
+ 'x509',
+ '-req',
+ '-days', 3650,
+ '-in', '/tmp/foo.csr',
+ '-out', '/tmp/foo.crt',
+ ['-extfile', '/tmp/foo.cnf'],
+ ['-CAcreateserial'],
+ ['-CA', '/tmp/foo-ca.crt'],
+ ['-CAkey', '/tmp/foo-ca.key'],
+ ['-passin', 'pass:5i;6%'],
+ ['-extensions', 'v3_req']
+ ])
+ resource.provider.create
+ end
+ end
+
context 'when forcing key' do
it 'exists? should return true if certificate exists and is synced' do
resource[:force] = true