From 4e8bae5294096ee7f1b8ae3bc0b6ca742c90b425 Mon Sep 17 00:00:00 2001 From: Johan De Wit Date: Tue, 11 Apr 2023 12:55:03 +0200 Subject: [PATCH] add x509 auth for admin user using mongosh --- lib/facter/is_master.rb | 35 +++- lib/puppet/provider/mongodb.rb | 33 +++- lib/puppet/provider/mongodb_replset/mongo.rb | 8 +- lib/puppet/provider/mongodb_user/mongodb.rb | 23 ++- lib/puppet/type/mongodb_replset.rb | 2 + lib/puppet/type/mongodb_user.rb | 18 ++- manifests/db.pp | 38 +++-- manifests/params.pp | 4 +- manifests/server.pp | 11 +- manifests/server/config.pp | 158 ++++++++++--------- manifests/server/install.pp | 6 + templates/mongodb.conf.2.6.erb | 7 + templates/mongorc.js.erb | 1 + templates/mongoshrc.js.erb | 65 ++++++++ 14 files changed, 290 insertions(+), 119 deletions(-) create mode 100644 templates/mongoshrc.js.erb diff --git a/lib/facter/is_master.rb b/lib/facter/is_master.rb index 9414f44ee..43457b1bd 100644 --- a/lib/facter/is_master.rb +++ b/lib/facter/is_master.rb @@ -6,7 +6,23 @@ def mongod_conf_file locations.find { |location| File.exist? location } end +def mongosh_conf_file + '/root/.mongosh.yaml' if File.exist?('/root/mongosh.yaml') +end + def get_options_from_hash_config(config) + # read also the mongoshrc.yaml yaml file, to retrieve the admins certkey file + if mongosh_conf_file + mongosh_config = YAML.load_file(mongosh_conf_file) + # check which tlscert we need to use + _tlscert = if config['setParameter'] && config['setParameter']['authenticationMechanisms'] == 'MONGODB-X509' && + mongosh_config['admin'] && mongosh_config['admin']['tlsCertificateKeyFile'] + mongosh_config['admin']['tlsCertificateKeyFile'] + end + else + _tlscert = config['net.tls.certificateKeyFile'] + end + result = [] result << "--port #{config['net.port']}" unless config['net.port'].nil? @@ -21,15 +37,21 @@ def get_options_from_hash_config(config) # - 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 << "--tls --host #{Facter.value(:fqdn)}" if config['net.tls.mode'] == 'requireTLS' || !_tlscert.nil? || !config['net.tls.CAFile'].nil? + result << "--tlsCertificateKeyFile #{_tlscert}" unless _tlscert.nil? result << "--tlsCAFile #{config['net.tls.CAFile']}" unless config['net.tls.CAFile'].nil? + # use --authenticationMechanism, ---authenticationDatabase + # when + # - authenticationMechanism MONGODB-X509 + result << "--authenticationDatabase '$external' --authenticationMechanism MONGODB-X509" unless config['setParameter'].nil? || config['setParameter']['authenticationMechanisms'] != 'MONGODB-X509' + result << '--ipv6' unless config['net.ipv6'].nil? result.join(' ') end +# I think we can get rid of this ? def get_options_from_keyvalue_config(file) config = {} File.readlines(file).map do |line| @@ -72,16 +94,19 @@ def get_options_from_config(file) Facter.add('mongodb_is_master') do setcode do if %w[mongo mongod].all? { |m| Facter::Util::Resolution.which m } + # if we have a mongod_conf_file we use mongosh, else stick to mongo + # this will only work for < 6.x versions file = mongod_conf_file if file options = get_options_from_config(file) - e = File.exist?('/root/.mongorc.js') ? 'load(\'/root/.mongorc.js\'); ' : '' + e = File.exist?('/root/.mongoshrc.js') ? 'load(\'/root/.mongoshrc.js\'); ' : '' # Check if the mongodb server is responding: - Facter::Core::Execution.exec("mongo --quiet #{options} --eval \"#{e}printjson(db.adminCommand({ ping: 1 }))\"") + Facter::Core::Execution.exec("mongosh --quiet #{options} --eval \"#{e}printjson(db.adminCommand({ ping: 1 }))\"") if $CHILD_STATUS.success? - Facter::Core::Execution.exec("mongo --quiet #{options} --eval \"#{e}db.isMaster().ismaster\"") + # TODO: need to catch errors like 'Error: Authentication failed.' ? + Facter::Core::Execution.exec("mongosh --quiet #{options} --eval \"#{e}db.isMaster().ismaster\"") else 'not_responding' end diff --git a/lib/puppet/provider/mongodb.rb b/lib/puppet/provider/mongodb.rb index 91b16f36a..bd27e9961 100644 --- a/lib/puppet/provider/mongodb.rb +++ b/lib/puppet/provider/mongodb.rb @@ -6,11 +6,12 @@ class Puppet::Provider::Mongodb < Puppet::Provider # Without initvars commands won't work. initvars - commands mongo: 'mongo' + # TODO: do we still need to support mongo ? Since it is removed from 6.x, not in this PR + commands mongo: 'mongosh' # Optional defaults file def self.mongorc_file - "load('#{Facter.value(:root_home)}/.mongorc.js'); " if File.file?("#{Facter.value(:root_home)}/.mongorc.js") + "load('#{Facter.value(:root_home)}/.mongoshrc.js'); " if File.file?("#{Facter.value(:root_home)}/.mongoshrc.js") end def mongorc_file @@ -26,7 +27,16 @@ def self.mongod_conf_file end def self.mongo_conf + mongosh_config = YAML.load_file('/root/.mongosh.yaml') || {} config = YAML.load_file(mongod_conf_file) || {} + # determine if we need the tls for connecion or client + _tlscert = if config['setParameter'] && config['setParameter']['authenticationMechanisms'] == 'MONGODB-X509' + if mongosh_config['admin'] && mongosh_config['admin']['tlsCertificateKeyFile'] + mongosh_config['admin']['tlsCertificateKeyFile'] + else + config['net.tls.certificateKeyFile'] + end + end { 'bindip' => config['net.bindIp'], 'port' => config['net.port'], @@ -37,11 +47,11 @@ def self.mongo_conf 'sslca' => config['net.ssl.CAFile'], 'tlsallowInvalidHostnames' => config['net.tls.allowInvalidHostnames'], 'tls' => config['net.tls.mode'], - 'tlscert' => config['net.tls.certificateKeyFile'], + 'tlscert' => _tlscert, 'tlsca' => config['net.tls.CAFile'], 'auth' => config['security.authorization'], 'shardsvr' => config['sharding.clusterRole'], - 'confsvr' => config['sharding.clusterRole'] + 'confsvr' => config['sharding.clusterRole'], } end @@ -90,15 +100,16 @@ def self.mongo_cmd(db, host, cmd) 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 += ['--tlsCertificateKeyFile', config['tlscert']] + args.push('--tlsAllowInvalidHostnames') if tls_invalid_hostnames(config) end - args += ['--eval', cmd] + args += ['--eval', "\"#{cmd}\""] mongo(args) end @@ -192,6 +203,7 @@ def mongo_version self.class.mongo_version end + # TODO: moingosh only from 4.2 bersion ?, so do we remove this? def self.mongo_26? v = mongo_version !v[%r{^2\.6\.}].nil? @@ -218,4 +230,13 @@ def self.mongo_5? def mongo_5? self.class.mongo_5? end + + def self.mongo_6? + v = mongo_version + !v[%r{^6\.}].nil? + end + + def mongo_6? + self.class.mongo_6? + end end diff --git a/lib/puppet/provider/mongodb_replset/mongo.rb b/lib/puppet/provider/mongodb_replset/mongo.rb index 5f995c73b..1197f4326 100644 --- a/lib/puppet/provider/mongodb_replset/mongo.rb +++ b/lib/puppet/provider/mongodb_replset/mongo.rb @@ -30,6 +30,7 @@ def members=(hosts) def self.instances instance = replset_properties + Puppet.debug("In replset.instances with #{instance}") if instance # There can only be one replset per node [new(instance)] @@ -39,6 +40,7 @@ def self.instances end def self.prefetch(resources) + Puppet.debug("In replset.prefetch") instances.each do |prov| resource = resources[prov.name] resource.provider = prov if resource @@ -147,6 +149,7 @@ def self.replset_properties end def get_hosts_status(members) + Puppet.debug("In get_hosts_status") alive = [] members.select do |member| begin @@ -189,6 +192,7 @@ def get_hosts_status(members) end def get_members_changes(current_members_conf, new_members_conf) + Puppet.debug("In get_members_changes") # no changes in members config return [[], [], []] if new_members_conf.nil? @@ -284,7 +288,7 @@ def set_members Puppet.debug 'Replica set initialization has successfully ended' return true else - Puppet.debug "Wainting for replica initialization. Retry: #{n}" + Puppet.debug "Waiting for replica initialization. Retry: #{n}" sleep retry_sleep next end @@ -388,7 +392,7 @@ def mongo_command(command, host, retries = 4) def self.mongo_command(command, host = nil, retries = 4) begin - output = mongo_eval("printjson(#{command})", 'admin', retries, host) + output = mongo_eval("EJSON.stringify(#{command})", 'admin', retries, host) rescue Puppet::ExecutionFailure => e Puppet.debug "Got an exception: #{e}" raise diff --git a/lib/puppet/provider/mongodb_user/mongodb.rb b/lib/puppet/provider/mongodb_user/mongodb.rb index 07762fd57..c9c2d8e7f 100644 --- a/lib/puppet/provider/mongodb_user/mongodb.rb +++ b/lib/puppet/provider/mongodb_user/mongodb.rb @@ -5,6 +5,7 @@ defaultfor kernel: 'Linux' def self.instances + # TODO: add supprt for x509 client certs require 'json' if db_ismaster @@ -59,27 +60,31 @@ def create roles: role_hashes(@resource[:roles], @resource[:database]), } - if mongo_4? || mongo_5? - if @resource[:auth_mechanism] == :scram_sha_256 + if mongo_4? || mongo_5? || mongo_6? + case @resource[:auth_mechanism] + when :scram_sha_256 command[:mechanisms] = ['SCRAM-SHA-256'] command[:pwd] = @resource[:password] command[:digestPassword] = true - else + when :scram_sha_1 command[:mechanisms] = ['SCRAM-SHA-1'] command[:pwd] = password_hash command[:digestPassword] = false + when :x509 + command[:mechanisms] = ['MONGODB-X509'] + else + command[:pwd] = password_hash + command[:digestPassword] = false end - else - command[:pwd] = password_hash - command[:digestPassword] = false end - + Puppet.debug("create a user: db.runCommand(#{command.to_json}), #{@resource[:database]}") mongo_eval("db.runCommand(#{command.to_json})", @resource[:database]) else Puppet.warning 'User creation is available only from master host' @property_hash[:ensure] = :present @property_hash[:username] = @resource[:username] + # TODO: enforce '$external$' database here when x509, or in the manifest ? @property_hash[:database] = @resource[:database] @property_hash[:password_hash] = '' @property_hash[:roles] = @resource[:roles] @@ -111,6 +116,7 @@ def password_hash=(_value) end def password=(value) + # TODO: remove since mongosh not available in this version ? if mongo_26? mongo_eval("db.changeUserPassword(#{@resource[:username].to_json}, #{value.to_json})", @resource[:database]) else @@ -120,7 +126,8 @@ def password=(value) digestPassword: true } - if mongo_4? || mongo_5? + if mongo_4? || mongo_5? || mongo_6? + # TODO: x509 doesnt use password, how to handle ? command[:mechanisms] = @resource[:auth_mechanism] == :scram_sha_256 ? ['SCRAM-SHA-256'] : ['SCRAM-SHA-1'] end diff --git a/lib/puppet/type/mongodb_replset.rb b/lib/puppet/type/mongodb_replset.rb index 728577b07..d191c3348 100644 --- a/lib/puppet/type/mongodb_replset.rb +++ b/lib/puppet/type/mongodb_replset.rb @@ -30,6 +30,7 @@ desc 'The replicaSet settings config' def insync?(is) + Puppet.debug("in type replset attribute settings with #{is}") should.each do |k, v| if v != is[k] Puppet.debug 'The replicaset settings config is not insync' @@ -50,6 +51,7 @@ def insync?(is) # check if is different def insync?(is) + Puppet.debug("in type replset attribute members #{is}") sync = true current = is.clone should.each do |sm| diff --git a/lib/puppet/type/mongodb_user.rb b/lib/puppet/type/mongodb_user.rb index 03af4cea4..d92c57a14 100644 --- a/lib/puppet/type/mongodb_user.rb +++ b/lib/puppet/type/mongodb_user.rb @@ -55,7 +55,7 @@ def to_s?(value) newproperty(:password_hash) do desc 'The password hash of the user. Use mongodb_password() for creating hash. Only available on MongoDB 3.0 and later. SCRAM-SHA-256 authentication mechanism is not supported.' defaultto do - if @resource[:password].nil? + if @resource[:auth_mechanism] != :x509 && @resource[:password].nil? raise Puppet::Error, "Property 'password_hash' must be set. Use mongodb_password() for creating hash." if provider.database == :absent end end @@ -99,7 +99,7 @@ def insync?(_is) newparam(:auth_mechanism) do desc 'Authentication mechanism. Password verification is not supported with SCRAM-SHA-256.' defaultto :scram_sha_1 - newvalues(:scram_sha_256, :scram_sha_1) + newvalues(:scram_sha_256, :scram_sha_1, :x509) end newparam(:update_password, boolean: true) do @@ -124,12 +124,14 @@ def insync?(_is) end validate do - if self[:password_hash].nil? && self[:password].nil? && provider.password.nil? && provider.password_hash.nil? - err("Either 'password_hash' or 'password' should be provided") - elsif !self[:password_hash].nil? && !self[:password].nil? - err("Only one of 'password_hash' or 'password' should be provided") - elsif !self[:password_hash].nil? && self[:auth_mechanism] == :scram_sha_256 - err("'password_hash' is not supported with SCRAM-SHA-256 authentication mechanism") + if self[:auth_mechanism] != :x509 + if self[:password_hash].nil? && self[:password].nil? && provider.password.nil? && provider.password_hash.nil? + err("Either 'password_hash' or 'password' should be provided") + elsif !self[:password_hash].nil? && !self[:password].nil? + err("Only one of 'password_hash' or 'password' should be provided") + elsif !self[:password_hash].nil? && self[:auth_mechanism] == :scram_sha_256 + err("'password_hash' is not supported with SCRAM-SHA-256 authentication mechanism") + end end if should(:scram_credentials) raise("The parameter 'scram_credentials' is read-only and cannot be changed") diff --git a/manifests/db.pp b/manifests/db.pp index e89e5980d..949e93a4a 100644 --- a/manifests/db.pp +++ b/manifests/db.pp @@ -15,7 +15,7 @@ # define mongodb::db ( String $user, - Enum['scram_sha_1', 'scram_sha_256'] $auth_mechanism = 'scram_sha_1', + Enum['scram_sha_1', 'scram_sha_256', 'x509'] $auth_mechanism = 'scram_sha_1', String $db_name = $name, Optional[Variant[String[1], Sensitive[String[1]]]] $password_hash = undef, Optional[Variant[String[1], Sensitive[String[1]]]] $password = undef, @@ -29,25 +29,29 @@ tries => $tries, } - if $password_hash =~ Sensitive[String] { - $hash = $password_hash.unwrap - } elsif $password_hash { - $hash = $password_hash - } elsif $password { - $hash = mongodb_password($user, $password) - } else { - fail("Parameter 'password_hash' or 'password' should be provided to mongodb::db.") - } + if $auth_mechanism != 'x509' { + if $password_hash =~ Sensitive[String] { + $hash = $password_hash.unwrap + } elsif $password_hash { + $hash = $password_hash + } elsif $password { + $hash = mongodb_password($user, $password) + } else { + fail("Parameter 'password_hash' or 'password' should be provided to mongodb::db.") + } - if $auth_mechanism == 'scram_sha_256' { - $password_config = { - password => $password, - update_password => $update_password, + if $auth_mechanism == 'scram_sha_256' { + $password_config = { + password => $password, + update_password => $update_password, + } + } else { + $password_config = { + password_hash => $hash, + } } } else { - $password_config = { - password_hash => $hash, - } + $password_config = {} } mongodb_user { "User ${user} on db ${db_name}": diff --git a/manifests/params.pp b/manifests/params.pp index f71e512d5..83f3b092d 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -19,7 +19,7 @@ ] $handle_creds = true $store_creds = false - $rcfile = "${facts['root_home']}/.mongorc.js" + $rcfile = "${facts['root_home']}/.mongoshrc.js" $dbpath_fix = false $manage_package = pick($mongodb::globals::manage_package, $mongodb::globals::manage_package_repo, false) @@ -38,6 +38,8 @@ $package_ensure_mongos = true } + $mongosh_package_name = 'mongodb-mongosh' + # Amazon Linux's OS Family is 'Linux', operating system 'Amazon'. case $facts['os']['family'] { 'RedHat', 'Linux', 'Suse': { diff --git a/manifests/server.pp b/manifests/server.pp index 3dd036878..a62bb4393 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -32,6 +32,7 @@ Optional[Enum['stopped', 'running']] $service_status = $mongodb::params::service_status, Variant[Boolean, String] $package_ensure = $mongodb::params::package_ensure, String $package_name = $mongodb::params::server_package_name, + String $mongosh_package_name = $mongodb::params::mongosh_package_name, Variant[Boolean, Stdlib::Absolutepath] $logpath = $mongodb::params::logpath, Array[Stdlib::Compat::Ip_address] $bind_ip = $mongodb::params::bind_ip, Optional[Boolean] $ipv6 = undef, @@ -96,7 +97,8 @@ Boolean $create_admin = $mongodb::params::create_admin, String $admin_username = $mongodb::params::admin_username, Optional[Variant[String, Sensitive[String]]] $admin_password = undef, - Enum['scram_sha_1', 'scram_sha_256'] $admin_auth_mechanism = $mongodb::params::admin_auth_mechanism, + Enum['scram_sha_1', 'scram_sha_256', 'x509'] $admin_auth_mechanism = $mongodb::params::admin_auth_mechanism, + Optional[Stdlib::Absolutepath] $admin_tls_key = undef, Boolean $admin_update_password = false, Boolean $handle_creds = $mongodb::params::handle_creds, Boolean $store_creds = $mongodb::params::store_creds, @@ -125,6 +127,13 @@ } else { $admin_password } + + # using x509, we need the admin clent certificate in the parameter --tlsCertificateKeyFile + # there is no way where we can set this in neither the /etc/momgosh.yaml or the /etc/mongod.conf + # The mongodb provider reads in /etc/mongod.conf setParameters.authenticationMechanisms: MONGODB-X509 settings + # to determine that a client cert authentication is used. There is no setting to set the client cert to be used. + # so we store it in a file in roots home directory. (this is done in mongodb::server::config + if $create_admin and ($service_ensure == 'running' or $service_ensure == true) { mongodb::db { 'admin': user => $admin_username, diff --git a/manifests/server/config.pp b/manifests/server/config.pp index 4514fbc4c..254f2b30d 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -1,78 +1,80 @@ # PRIVATE CLASS: do not call directly class mongodb::server::config { - $ensure = $mongodb::server::ensure - $user = $mongodb::server::user - $group = $mongodb::server::group - $config = $mongodb::server::config - $config_content = $mongodb::server::config_content - $config_template = $mongodb::server::config_template - $config_data = $mongodb::server::config_data - $dbpath = $mongodb::server::dbpath - $dbpath_fix = $mongodb::server::dbpath_fix - $pidfilepath = $mongodb::server::pidfilepath - $pidfilemode = $mongodb::server::pidfilemode - $manage_pidfile = $mongodb::server::manage_pidfile - $logpath = $mongodb::server::logpath - $logappend = $mongodb::server::logappend - $system_logrotate = $mongodb::server::system_logrotate - $fork = $mongodb::server::fork - $port = $mongodb::server::port - $journal = $mongodb::server::journal - $nojournal = $mongodb::server::nojournal - $smallfiles = $mongodb::server::smallfiles - $cpu = $mongodb::server::cpu - $auth = $mongodb::server::auth - $noath = $mongodb::server::noauth - $create_admin = $mongodb::server::create_admin - $admin_username = $mongodb::server::admin_username - $admin_password = $mongodb::server::admin_password - $handle_creds = $mongodb::server::handle_creds - $store_creds = $mongodb::server::store_creds - $rcfile = $mongodb::server::rcfile - $verbose = $mongodb::server::verbose - $verbositylevel = $mongodb::server::verbositylevel - $objcheck = $mongodb::server::objcheck - $quota = $mongodb::server::quota - $quotafiles = $mongodb::server::quotafiles - $diaglog = $mongodb::server::diaglog - $oplog_size = $mongodb::server::oplog_size - $nohints = $mongodb::server::nohints - $nohttpinterface = $mongodb::server::nohttpinterface - $noscripting = $mongodb::server::noscripting - $notablescan = $mongodb::server::notablescan - $noprealloc = $mongodb::server::noprealloc - $nssize = $mongodb::server::nssize - $mms_token = $mongodb::server::mms_token - $mms_name = $mongodb::server::mms_name - $mms_interval = $mongodb::server::mms_interval - $configsvr = $mongodb::server::configsvr - $shardsvr = $mongodb::server::shardsvr - $replset = $mongodb::server::replset - $rest = $mongodb::server::rest - $quiet = $mongodb::server::quiet - $slowms = $mongodb::server::slowms - $keyfile = $mongodb::server::keyfile - $key = $mongodb::server::key - $ipv6 = $mongodb::server::ipv6 - $bind_ip = $mongodb::server::bind_ip - $directoryperdb = $mongodb::server::directoryperdb - $profile = $mongodb::server::profile - $maxconns = $mongodb::server::maxconns - $set_parameter = $mongodb::server::set_parameter - $syslog = $mongodb::server::syslog - $ssl = $mongodb::server::ssl - $ssl_key = $mongodb::server::ssl_key - $ssl_ca = $mongodb::server::ssl_ca - $ssl_weak_cert = $mongodb::server::ssl_weak_cert + $ensure = $mongodb::server::ensure + $user = $mongodb::server::user + $group = $mongodb::server::group + $config = $mongodb::server::config + $config_content = $mongodb::server::config_content + $config_template = $mongodb::server::config_template + $config_data = $mongodb::server::config_data + $dbpath = $mongodb::server::dbpath + $dbpath_fix = $mongodb::server::dbpath_fix + $pidfilepath = $mongodb::server::pidfilepath + $pidfilemode = $mongodb::server::pidfilemode + $manage_pidfile = $mongodb::server::manage_pidfile + $logpath = $mongodb::server::logpath + $logappend = $mongodb::server::logappend + $system_logrotate = $mongodb::server::system_logrotate + $fork = $mongodb::server::fork + $port = $mongodb::server::port + $journal = $mongodb::server::journal + $nojournal = $mongodb::server::nojournal + $smallfiles = $mongodb::server::smallfiles + $cpu = $mongodb::server::cpu + $auth = $mongodb::server::auth + $noath = $mongodb::server::noauth + $create_admin = $mongodb::server::create_admin + $admin_username = $mongodb::server::admin_username + $admin_password = $mongodb::server::admin_password + $admin_auth_mechanism = $mongodb::server::admin_auth_mechanism + $admin_tls_key = $mongodb::server::admin_tls_key + $handle_creds = $mongodb::server::handle_creds + $store_creds = $mongodb::server::store_creds + $rcfile = $mongodb::server::rcfile + $verbose = $mongodb::server::verbose + $verbositylevel = $mongodb::server::verbositylevel + $objcheck = $mongodb::server::objcheck + $quota = $mongodb::server::quota + $quotafiles = $mongodb::server::quotafiles + $diaglog = $mongodb::server::diaglog + $oplog_size = $mongodb::server::oplog_size + $nohints = $mongodb::server::nohints + $nohttpinterface = $mongodb::server::nohttpinterface + $noscripting = $mongodb::server::noscripting + $notablescan = $mongodb::server::notablescan + $noprealloc = $mongodb::server::noprealloc + $nssize = $mongodb::server::nssize + $mms_token = $mongodb::server::mms_token + $mms_name = $mongodb::server::mms_name + $mms_interval = $mongodb::server::mms_interval + $configsvr = $mongodb::server::configsvr + $shardsvr = $mongodb::server::shardsvr + $replset = $mongodb::server::replset + $rest = $mongodb::server::rest + $quiet = $mongodb::server::quiet + $slowms = $mongodb::server::slowms + $keyfile = $mongodb::server::keyfile + $key = $mongodb::server::key + $ipv6 = $mongodb::server::ipv6 + $bind_ip = $mongodb::server::bind_ip + $directoryperdb = $mongodb::server::directoryperdb + $profile = $mongodb::server::profile + $maxconns = $mongodb::server::maxconns + $set_parameter = $mongodb::server::set_parameter + $syslog = $mongodb::server::syslog + $ssl = $mongodb::server::ssl + $ssl_key = $mongodb::server::ssl_key + $ssl_ca = $mongodb::server::ssl_ca + $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 + $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 + $tls_mode = $mongodb::server::tls_mode + $storage_engine = $mongodb::server::storage_engine File { owner => $user, @@ -126,6 +128,20 @@ mode => '0644', } + # TODO: we kind of use this file to force x509 autehntication in the providers when it exsists + # Open for suugestions how to deal with this + if $admin_auth_mechanism == 'x509' { + $_ensure = 'present' + } else { + $_ensure = 'absent' + } + + file { '/root/.mongosh.yaml': + ensure => $_ensure, + mode => '0400', + content => "---\n${admin_username}:\n tlsCertificateKeyFile: ${admin_tls_key}", + } + file { $dbpath: ensure => directory, mode => '0750', @@ -176,7 +192,7 @@ if $handle_creds { file { $rcfile: ensure => file, - content => template('mongodb/mongorc.js.erb'), + content => template('mongodb/mongoshrc.js.erb'), owner => 'root', group => 'root', mode => '0600', diff --git a/manifests/server/install.pp b/manifests/server/install.pp index b40502ada..1c30d91c8 100644 --- a/manifests/server/install.pp +++ b/manifests/server/install.pp @@ -33,4 +33,10 @@ tag => 'mongodb_package', } } + + if $mongodb::server::admin_auth_mechanism == 'x509' { + package { $mongodb::server::mongosh_package_name: + ensure => present, + } + } } diff --git a/templates/mongodb.conf.2.6.erb b/templates/mongodb.conf.2.6.erb index 5c846a254..5a3b021c5 100644 --- a/templates/mongodb.conf.2.6.erb +++ b/templates/mongodb.conf.2.6.erb @@ -169,6 +169,13 @@ setParameter: <%= v %> <% end -%> <% end -%> +<% if @admin_auth_mechanism == 'x509' -%> +<%# setParameters.auth... gives an error on startup status=2/INVALIDARGUMENT -%> +<% if !@set_parameter -%> +setParameter: +<% end -%> + authenticationMechanisms: MONGODB-X509 +<% end -%> <% if @config_data -%> <% @config_data.each do |k,v| -%> diff --git a/templates/mongorc.js.erb b/templates/mongorc.js.erb index 9e060306f..073fa7312 100644 --- a/templates/mongorc.js.erb +++ b/templates/mongorc.js.erb @@ -1,3 +1,4 @@ +<%# TODO: clean this up in the manifest ? (kind of supporting upgrad to momgosh only ? -%> function rsReconfigMember(member){ var cfg = rs.config() cfg.members.forEach(function(part,index,memberArray){ diff --git a/templates/mongoshrc.js.erb b/templates/mongoshrc.js.erb new file mode 100644 index 000000000..13fe67a34 --- /dev/null +++ b/templates/mongoshrc.js.erb @@ -0,0 +1,65 @@ +function rsReconfigMember(member){ + var cfg = rs.config() + cfg.members.forEach(function(part,index,memberArray){ + if (member.host == part.host) { + for(k in member){ + memberArray[index][k] = member[k] + } + } + }) + return rs.reconfig(cfg) +} + +function rsReconfigSettings(settings){ + var cfg = rs.config() + cfg.settings = settings + return rs.reconfig(cfg) +} + +<% if @auth and @store_creds -%> +function authRequired() { + try { + db.serverCmdLineOpts(); + return false; + } catch (err) { + return true; + } +} + +if (authRequired()) { + <%- if @replset -%> + <%- if @admin_auth_mechanism == 'x509' -%> + db.getMongo().setReadPref() + try { + db.getSiblingDB('$external').auth( + { + mechanism: 'MONGODB-X509' + } + ) + } + catch (err) { + // This isn't catching authentication errors as I'd expect... + abort('Unknown error') + } + <%- else -%> + // rs.slaveOk has been deprecated, use secondaryOk if available + try { + rs.secondaryOk() + } + catch (err) { + rs.slaveOk() + } + try { + var prev_db = db + db = db.getSiblingDB('admin') + db.auth('<%= @admin_username %>', '<%= @admin_password_unsensitive %>') + db = db.getSiblingDB(prev_db) + } + catch (err) { + // This isn't catching authentication errors as I'd expect... + abort('Unknown error') + } + <% end -%> + <% end -%> +} +<% end -%>