Skip to content

Commit

Permalink
Add a TLS option to use TLS in args for mongo command and mongod conf…
Browse files Browse the repository at this point in the history
  • Loading branch information
poloz-lab committed Oct 7, 2022
1 parent 61c6690 commit c898a2c
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 1 deletion.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,30 @@ Default: False
Ssl authorization mode. Valid options are: requireSSL, preferSSL, allowSSL.
Default: requireSSL

##### `tls`
Set to true to enable tls. Default: <>
*Important*: You need to have tls_key set as well, and the file needs to
pre-exist on node. If you wish to use certificate validation, tls_ca must also
be set.

##### `tls_key`
Default: <>

##### `tls_ca`
Default: <>

##### `tls_conn_without_cert`
Set to true to disable mandatory TLS client authentication
Default: False

##### `tls_invalid_hostnames`
Set to true to disable fqdn TLS cert check
Default: False

##### `tls_mode`
Tls authorization mode. Valid options are: requireTLS, preferTLS, allowTLS.
Default: requireTLS

##### `service_manage`
Whether or not the MongoDB service resource should be part of the catalog.
Default: true
Expand Down
16 changes: 16 additions & 0 deletions lib/facter/is_master.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ def get_options_from_hash_config(config)
result << "--ssl --host #{Facter.value(:fqdn)}" if config['net.ssl.mode'] == 'requireSSL' || !config['net.ssl.PEMKeyFile'].nil? || !config['net.ssl.CAFile'].nil?
result << "--sslPEMKeyFile #{config['net.ssl.PEMKeyFile']}" unless config['net.ssl.PEMKeyFile'].nil?
result << "--sslCAFile #{config['net.ssl.CAFile']}" unless config['net.ssl.CAFile'].nil?
# use --tls and --host if:
# - tlsMode is "requireTLS"
# - Parameter --tlsCertificateKeyFile is set
# - Parameter --tlsCAFile is set
result << "--tls --host #{Facter.value(:fqdn)}" if config['net.tls.mode'] == 'requireTLS' || !config['net.tls.certificateKeyFile'].nil? || !config['net.tls.CAFile'].nil?
result << "--tlsCertificateKeyFile #{config['net.tls.certificateKeyFile']}" unless config['net.tls.certificateKeyFile'].nil?
result << "--tlsCAFile #{config['net.tls.CAFile']}" unless config['net.tls.CAFile'].nil?

result << '--ipv6' unless config['net.ipv6'].nil?

result.join(' ')
Expand All @@ -39,6 +47,14 @@ def get_options_from_keyvalue_config(file)
result << "--ssl --host #{Facter.value(:fqdn)}" if config['ssl'] == 'requireSSL' || !config['sslcert'].nil? || !config['sslca'].nil?
result << "--sslPEMKeyFile #{config['sslcert']}" unless config['sslcert'].nil?
result << "--sslCAFile #{config['sslca']}" unless config['sslca'].nil?
# use --tls and --host if:
# - tlsMode is "requireTLS"
# - Parameter --tlsCertificateKeyFile is set
# - Parameter --tlsCAFile is set
result << "--tls --host #{Facter.value(:fqdn)}" if config['tls'] == 'requireTLS' || !config['tlscert'].nil? || !config['tlsca'].nil?
result << "--tlsCertificateKeyFile #{config['tlscert']}" unless config['tlscert'].nil?
result << "--tlsCAFile #{config['tlsca']}" unless config['tlsca'].nil?

result << '--ipv6' unless config['ipv6'].nil?

result.join(' ')
Expand Down
25 changes: 25 additions & 0 deletions lib/puppet/provider/mongodb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def self.mongo_conf
'ssl' => config['net.ssl.mode'],
'sslcert' => config['net.ssl.PEMKeyFile'],
'sslca' => config['net.ssl.CAFile'],
'tlsallowInvalidHostnames' => config['net.tls.allowInvalidHostnames'],
'tls' => config['net.tls.mode'],
'tlscert' => config['net.tls.certificateKeyFile'],
'tlsca' => config['net.tls.CAFile'],
'auth' => config['security.authorization'],
'shardsvr' => config['sharding.clusterRole'],
'confsvr' => config['sharding.clusterRole']
Expand All @@ -52,11 +56,22 @@ def self.ssl_is_enabled(config = nil)
!ssl_mode.nil? && ssl_mode != 'disabled'
end

def self.tls_is_enabled(config = nil)
config ||= mongo_conf
tls_mode = config.fetch('tls')
!tls_mode.nil? && tls_mode != 'disabled'
end

def self.ssl_invalid_hostnames(config = nil)
config ||= mongo_conf
config['allowInvalidHostnames']
end

def self.tls_invalid_hostnames(config = nil)
config ||= mongo_conf
config['tlsallowInvalidHostnames']
end

def self.mongo_cmd(db, host, cmd)
config = mongo_conf

Expand All @@ -72,6 +87,16 @@ def self.mongo_cmd(db, host, cmd)
args += ['--sslCAFile', ssl_ca] unless ssl_ca.nil?
end

if tls_is_enabled(config)
args.push('--tls')
args += ['--tlsCertificateKeyFile', config['tlscert']]

tls_ca = config['tlsca']
args += ['--tlsCAFile', tls_ca] unless tls_ca.nil?

args.push('--tlsAllowInvalidHostnames') if tls_invalid_hostnames(config)
end

args += ['--eval', cmd]
mongo(args)
end
Expand Down
22 changes: 21 additions & 1 deletion manifests/server.pp
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# This installs a MongoDB server. See README.md for more details.
# @summary This installs a MongoDB server. See README.md for more details.
#
# @param tls
# Ensure tls is enabled.
# @param tls_key
# Defines the path of the file that contains the TLS/SSL certificate and key.
# @param tls_ca
# Defines the path of the file that contains the certificate chain for verifying client certificates.
# @param tls_conn_without_cert
# Set to true to bypass client certificate validation for clients that do not present a certificate.
# @param tls_invalid_hostnames
# Set to true to disable the validation of the hostnames in TLS certificates.
# @param tls_mode
# Defines if TLS is used for all network connections. Allowed values are 'requireTLS', 'preferTLS' or 'allowTLS'.
#
class mongodb::server (
Variant[Boolean, String] $ensure = $mongodb::params::ensure,
String $user = $mongodb::params::user,
Expand Down Expand Up @@ -71,6 +85,12 @@
Boolean $ssl_weak_cert = false,
Boolean $ssl_invalid_hostnames = false,
Enum['requireSSL', 'preferSSL', 'allowSSL'] $ssl_mode = 'requireSSL',
Optional[Boolean] $tls = undef,
Optional[Stdlib::Absolutepath] $tls_key = undef,
Optional[Stdlib::Absolutepath] $tls_ca = undef,
Boolean $tls_conn_without_cert = false,
Boolean $tls_invalid_hostnames = false,
Enum['requireTLS', 'preferTLS', 'allowTLS'] $tls_mode = 'requireTLS',
Boolean $restart = $mongodb::params::restart,
Optional[String] $storage_engine = undef,
Boolean $create_admin = $mongodb::params::create_admin,
Expand Down
8 changes: 8 additions & 0 deletions manifests/server/config.pp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@
$ssl_weak_cert = $mongodb::server::ssl_weak_cert
$ssl_invalid_hostnames = $mongodb::server::ssl_invalid_hostnames
$ssl_mode = $mongodb::server::ssl_mode
$tls = $mongodb::server::tls
$tls_key = $mongodb::server::tls_key
$tls_ca = $mongodb::server::tls_ca
$tls_conn_without_cert = $mongodb::server::tls_conn_without_cert
$tls_invalid_hostnames = $mongodb::server::tls_invalid_hostnames
$tls_mode = $mongodb::server::tls_mode
$storage_engine = $mongodb::server::storage_engine

File {
Expand All @@ -75,6 +81,8 @@

if ($logpath and $syslog) { fail('You cannot use syslog with logpath') }

if ($ssl and $tls) { fail('You cannot use ssl and tls options together') }

if ($ensure == 'present' or $ensure == true) {
# Exists for future compatibility and clarity.
if $auth {
Expand Down
182 changes: 182 additions & 0 deletions spec/classes/server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,188 @@
end
end

describe 'with tls' do
context 'enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem'
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$})
}
end

context 'disabled' do
let :params do
{
tls: false
}
end

it {
is_expected.not_to contain_file(config_file).
with_content(%r{net\.tls\.mode}).
with_content(%r{net\.tls\.certificateKeyFile})
}
end
end

describe 'with tls and client certificate validation' do
context 'enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem',
tls_ca: '/etc/ssl/caToValidateClientCertificates.pem'
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$}).
with_content(%r{^net\.tls\.CAFile: /etc/ssl/caToValidateClientCertificates.pem$})
}
end

context 'client certificate validation disabled but tls enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem'
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$})
is_expected.not_to contain_file(config_file).
with_content(%r{net\.tls\.CAFile})
}
end

context 'disabled' do
let :params do
{
tls: false
}
end

it { is_expected.not_to contain_file(config_file).with_content(%r{net\.tls\.CAFile}) }
end
end

describe 'with tls, client certificate validation and allow connection without certificates' do
context 'enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem',
tls_ca: '/etc/ssl/caToValidateClientCertificates.pem',
tls_conn_without_cert: true
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$}).
with_content(%r{^net\.tls\.CAFile: /etc/ssl/caToValidateClientCertificates.pem$}).
with_content(%r{^net\.tls\.allowConnectionsWithoutCertificates: true$})
}
end

context 'connection without certificates disabled but tls and client certificate validation enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem',
tls_ca: '/etc/ssl/caToValidateClientCertificates.pem',
tls_conn_without_cert: false
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$}).
with_content(%r{net\.tls\.CAFile})
is_expected.not_to contain_file(config_file).
with_content(%r{net\.tls\.allowConnectionsWithoutCertificates:\s*true})
}
end

context 'disabled' do
let :params do
{
tls: false
}
end

it { is_expected.not_to contain_file(config_file).with_content(%r{net\.tls\.allowConnectionsWithoutCertificates:\s*true}) }
end
end

describe 'with tls and allow invalid hostnames' do
context 'enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem',
tls_invalid_hostnames: true
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$}).
with_content(%r{^net\.tls\.allowInvalidHostnames: true$})
}
end

context 'disallow invalid hostnames but tls enabled' do
let :params do
{
tls: true,
tls_mode: 'requireTLS',
tls_key: '/etc/ssl/mongodb.pem',
tls_invalid_hostnames: false
}
end

it {
is_expected.to contain_file(config_file).
with_content(%r{^net\.tls\.mode: requireTLS$}).
with_content(%r{^net\.tls\.certificateKeyFile: /etc/ssl/mongodb.pem$})
is_expected.not_to contain_file(config_file).
with_content(%r{net\.tls\.allowInvalidHostnames:\s*true})
}
end

context 'disabled' do
let :params do
{
tls: false
}
end

it { is_expected.not_to contain_file(config_file).with_content(%r{net\.tls\.allowInvalidHostnames:\s*true}) }
end
end

context 'setting nohttpinterface' do
it "isn't set when undef" do
is_expected.not_to contain_file(config_file).with_content(%r{net\.http\.enabled})
Expand Down
13 changes: 13 additions & 0 deletions templates/mongodb.conf.2.6.erb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ net.ssl.weakCertificateValidation: <%= @ssl_weak_cert %>
net.ssl.allowInvalidHostnames: <%= @ssl_invalid_hostnames %>
<% end -%>
<% end -%>
<% if @tls -%>
net.tls.mode: <%= @tls_mode %>
net.tls.certificateKeyFile: <%= @tls_key %>
<% if @tls_ca -%>
net.tls.CAFile: <%= @tls_ca %>
<% end -%>
<% if @tls_conn_without_cert -%>
net.tls.allowConnectionsWithoutCertificates: <%= @tls_conn_without_cert %>
<% end -%>
<% if @tls_invalid_hostnames -%>
net.tls.allowInvalidHostnames: <%= @tls_invalid_hostnames %>
<% end -%>
<% end -%>

#Replication
<% if @replset -%>
Expand Down

0 comments on commit c898a2c

Please sign in to comment.