Skip to content

Commit

Permalink
Allow passing a CA key password when signing a cert
Browse files Browse the repository at this point in the history
  • Loading branch information
ehelms authored and bastelfreak committed Jul 18, 2024
1 parent 581139a commit a54070a
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 10 deletions.
14 changes: 14 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

##### <a name="-openssl--certificate--x509--ensure"></a>`ensure`

Expand Down Expand Up @@ -648,6 +649,14 @@ provided.

Default value: `undef`

##### <a name="-openssl--certificate--x509--cakey_password"></a>`cakey_password`

Data type: `Optional[Variant[Sensitive[String[1]], String[1]]]`

Optional password that has encrypted the CA key.

Default value: `undef`

### <a name="openssl--config"></a>`openssl::config`

Generates an openssl.conf file using defaults
Expand Down Expand Up @@ -1312,6 +1321,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)
Expand All @@ -1338,6 +1348,10 @@ The optional ca certificate filepath

The optional ca private key filepath

##### <a name="-x509_cert--cakey_password"></a>`cakey_password`

The optional CA key password

##### <a name="-x509_cert--csr"></a>`csr`

The optional certificate signing request path
Expand Down
5 changes: 4 additions & 1 deletion lib/puppet/provider/x509_cert/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/puppet/type/x509_cert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,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
Expand Down
22 changes: 13 additions & 9 deletions manifests/certificate/x509.pp
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
Expand Down Expand Up @@ -147,6 +149,7 @@
Boolean $encrypted = true,
Optional[Stdlib::Absolutepath] $ca = undef,
Optional[Stdlib::Absolutepath] $cakey = undef,
Optional[Variant[Sensitive[String[1]], String[1]]] $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.')
Expand Down Expand Up @@ -179,15 +182,16 @@
encrypted => $encrypted,
}
~> x509_cert { $crt:
ensure => $ensure,
template => $cnf,
csr => $csr,
days => $days,
password => $password,
req_ext => !empty($altnames) or !empty($extkeyusage),
force => $force,
ca => $ca,
cakey => $cakey,
ensure => $ensure,
template => $cnf,
csr => $csr,
days => $days,
password => $password,
req_ext => !empty($altnames) or !empty($extkeyusage),
force => $force,
ca => $ca,
cakey => $cakey,
cakey_password => $cakey_password,
}

# Set owner of all files
Expand Down
107 changes: 107 additions & 0 deletions spec/defines/openssl_certificate_x509_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -604,4 +604,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: '[email protected]',
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
23 changes: 23 additions & 0 deletions spec/unit/puppet/provider/x509_cert/openssl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a54070a

Please sign in to comment.