sous-chefs / sc-mongodb

Development repository for the sc-mongodb cookbook
https://supermarket.chef.io/cookbooks/sc-mongodb
Apache License 2.0
75 stars 93 forks source link

auth=true creates users but does not limit other logins in recent mongo versions #192

Open miedward opened 6 years ago

miedward commented 6 years ago

As discussed in the documentation for the latest release (https://docs.mongodb.com/manual/tutorial/enable-authentication/) if a configuration file is in use then --auth doesn't have any effect but the security.authorization setting is required in the configuration file. There is a catch22 implied by that tutorial also. If we simply add the security.authorization setting (default['mongodb']['config']['mongod']['security']['authorization'] = 'enabled') this blows up with huge errors because the users cannot be created (since there is no admin login by default)

My workaround, which seems okay but ugly is something like this:

Set passwords from databag for admin user

node.default['mongodb']['admin']['username'] = 'myadminuser' node.default['mongodb']['admin']['password'] = db_passwords["mongodb_password"] node.default['mongodb']['admin']["roles"] = [ "userAdminAnyDatabase" ] node.default['mongodb']['admin']["database"] = 'admin'

myuser = { "username" => "rouser", "password" => db_passwords["mongodb_ro_password"], "roles" => [ "read" ], "database" => "#{node.chef_environment}" }

node.default['mongodb']['users'] << myuser

include_recipe "sc-mongodb::default"

There is a restart here

include_recipe "sc-mongodb::user_management"

There is a restart here

bash 'add in user level security after mongo users are created' do code <<-EOH echo "security:\n authorization: enabled\nsetParameter:\n enableLocalhostAuthBypass: false" >> /etc/mongod.conf EOH not_if 'grep -c "enableLocalhostAuthBypass" /etc/mongod.conf' end

There is a restart after everything finishes

miedward commented 6 years ago

Oh, the default properties for my environment don't contain the properties added later, in case that was unclear.

miedward commented 6 years ago

roles and database being required should be updated in the documentation too, it is very unclear

miedward commented 6 years ago

This still doesn't work exactly how I would expect, you can still open mongo client without specifying a user, but at least you can't really do anything. So other options might be needed in addition...

[vagrant@bluesky-db-prod ~]$ mongo fish MongoDB shell version: 3.2.11 connecting to: fish

show collections; 2018-02-09T23:32:16.998+0000 E QUERY [thread1] Error: listCollections failed: { "ok" : 0, "errmsg" : "not authorized on fish to execute command { listCollections: 1.0, filter: {} }", "code" : 13 } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 DB.prototype._getCollectionInfosCommand@src/mongo/shell/db.js:773:1 DB.prototype.getCollectionInfos@src/mongo/shell/db.js:785:19 DB.prototype.getCollectionNames@src/mongo/shell/db.js:796:16 shellHelper.show@src/mongo/shell/utils.js:754:9 shellHelper@src/mongo/shell/utils.js:651:15 @(shellhelp2):1:1

swalberg commented 6 years ago

My mongo-fu is kinda weak, but doesn't the localhost exception allow a way out of that catch-22?

miedward commented 6 years ago

Using localhost exception would be fine to create initial admin user (or all of them I guess), but for defense in depth it should be disabled after that I would think.

In any event I am currently having to not include user_management after first run because it throws a bunch of warnings and occasionally caused the run to fail.

iCanLogIntoMongo = system('mongo --quiet -u adminuser -p adminpass --eval "db.system.users.find({user:\'someuser\'}).count()" admin') include_recipe "sc-mongodb::user_management" if ( !iCanLogIntoMongo )

swalberg commented 6 years ago

The local host exemption seems to be automatically disabled once you've used it by the server. Basically, "if authentication is enabled and there are no users in the admin db, allow someone to create that user". So once that user is made, the conditions of the exemption stop applying.

I've been playing a bit with this recipe trying to get an understanding of both the code and mongo authentication. So bear with me, part of this is rubber duck debugging.

Are you using v1 or v2 of the mongodb gem? There seem to be different code paths based on which version is installed.

Part of the problem seems to be that the act of creating the admin user calls some functionality that requires admin privileges, such as listing users and databases. Part of this is because, as you've noted, the cookbook doesn't actually enable authentication, so it's gone unnoticed.

The good news is I'm able to replicate the problem and also have an inspec test to ensure that authentication is turned on (basically looking through startup logs to make sure that "authentication is disabled you fool!" message doesn't appear)

I think the code solution here is to build a separate mechanism for creating that admin user rather than the current method of prepending it to the list of users and treating it the same. But would love to hear from people more learned than myself.

swalberg commented 6 years ago

Did you ever find out if you were using v1 or v2 of the mongo gem?

/opt/chef/embedded/bin/gem list mongo

For test-kitchen, I'm able to create users and enable auth with the following attributes when using the default v1 of the gem, but it gets the same problems as you for v2.

 mongodb:
      config:
        auth: true
        mongod:
          security:
            authorization: enabled
miedward commented 6 years ago

[root@bluesky-db-uat dbsave]# /opt/chef/embedded/bin/gem list --local

LOCAL GEMS

addressable (2.5.2, 2.4.0) appbundler (0.10.0) ast (2.3.0) bigdecimal (default: 1.3.0) binding_of_caller (0.7.2) blankslate (2.1.2.4) bson (1.12.5) bson_ext (1.12.5) builder (3.2.3) bundler (1.15.4) byebug (9.1.0) chef (13.5.3) chef-config (13.5.3, 13.4.24) chef-vault (3.3.0) chef-zero (13.1.0) cheffish (13.0.0) coderay (1.1.2) crack (0.4.3) debug_inspector (0.0.3) did_you_mean (1.1.0) diff-lcs (1.3) docile (1.1.5) docker-api (1.33.6) erubis (2.7.0) excon (0.59.0) faraday (0.13.1) ffi (1.9.18) ffi-yajl (2.3.1) fuzzyurl (0.9.0) gssapi (1.2.0) gyoku (1.3.1) hashdiff (0.3.6) hashie (3.5.6) highline (1.7.8) htmlentities (4.3.4) httpclient (2.8.3) iniparse (1.4.4) inspec (1.39.1) io-console (default: 0.4.6) ipaddress (0.8.3) iso8601 (0.9.1) json (2.1.0, default: 2.0.4) libyajl2 (1.2.0) little-plugger (1.1.4) logging (2.2.2) method_source (0.9.0) mime-types (2.6.2) mini_portile2 (2.2.0) minitest (5.10.1) mixlib-archive (0.4.1) mixlib-authentication (1.4.2) mixlib-cli (1.7.0) mixlib-config (2.2.4) mixlib-log (1.7.1) mixlib-shellout (2.3.2) mongo (1.12.5) multi_json (1.12.2) multipart-post (2.0.0) mysql2 (0.4.9) net-scp (1.2.1) net-sftp (2.1.2) net-ssh (4.2.0) net-ssh-gateway (2.0.0) net-ssh-multi (1.2.1) net-telnet (0.1.1) netrc (0.11.0) nokogiri (1.8.0) nori (2.6.0) ohai (13.5.0) openssl (default: 2.0.5) parallel (1.12.0) parser (2.4.0.0) parslet (1.5.0) plist (3.3.0) power_assert (0.4.1) powerpack (0.1.1) proxifier (1.0.3) pry (0.11.1) pry-byebug (3.5.0) pry-remote (0.1.8) pry-stack_explorer (0.4.9.2) psych (default: 2.2.2) public_suffix (3.0.0) rack (2.0.3) rainbow (2.2.2) rake (12.1.0, 12.0.0) rb-readline (0.5.5) rdoc (default: 5.0.0) rest-client (1.7.3) rspec (3.6.0) rspec-core (3.6.0) rspec-expectations (3.6.0) rspec-its (1.2.0) rspec-mocks (3.6.0) rspec-support (3.6.0) rspec_junit_formatter (0.2.3) rubocop (0.49.1) ruby-prof (0.16.2) ruby-progressbar (1.9.0) ruby-shadow (2.5.0) rubyntlm (0.6.2) rubyzip (1.2.1) safe_yaml (1.0.4) semverse (2.0.0) serverspec (2.41.0) sfl (2.3) simplecov (0.15.1) simplecov-html (0.10.2) slop (3.6.0) specinfra (2.72.0) sslshake (1.2.0) syslog-logger (1.6.8) systemu (2.6.5) test-unit (3.2.3) thor (0.20.0) toml (0.1.2) train (0.28.0) unicode-display_width (1.3.0) uuidtools (2.1.5) webmock (3.0.1) winrm (2.2.3) winrm-fs (1.0.2) wmi-lite (1.0.0) xmlrpc (0.2.1)

miedward commented 6 years ago

Still hitting this with v1 so bump. [root@docker-db-dev ~]# /opt/chef/embedded/bin/gem list mongo

LOCAL GEMS

mongo (1.12.5)

miedward commented 6 years ago

[root@docker-db-dev ~]# mongo -version MongoDB shell version: 3.2.11

hrak commented 5 years ago

There are multiple reasons why this is failing on MongoDB > 3.0.

First and foremost, as already indicated, authentication is not even enabled by the cookbook if node['mongodb']['config']['auth'] = true, because the cookbook doesn't set node['mongodb']['config']['mongod']['security']['authorization'] = 'enabled'

Second it seems that the localhost exception no longer allows more than just the initial admin user to be added

And third, when using mongo gem ~> 2.0, the method retrieve_db_v2 executes a client.database_names as a means to verify server connection, but this operation is not allowed within the localhost exception:

WARN: Unable to connect to MongoDB instance: not authorized on admin to execute command { listDatabases: 1, $readPreference: { mode: "secondaryPreferred" }, $db: "admin" } (13)

And fourth, it seems that user_exists_v2, which executes a connection['system.users'].find(user: username).count > 0 also doesn't work within the restrictions of the localhost exception:

> use admin
switched to db admin
> db.system.users.find()
Error: error: {
    "ok" : 0,
    "errmsg" : "not authorized on admin to execute command { find: \"system.users\", filter: {}, $db: \"admin\" }",
    "code" : 13,
    "codeName" : "Unauthorized"
}
>

So it looks like for adding the initial admin user, the current library functions will not work.

I'm currently trying to fix this issue (and address several others, like converting the definition into a custom resource, and systemd unit files) in a fork and will file PR's when done.

github-actions[bot] commented 3 years ago

Marking stale due to inactivity. Remove stale label or comment or this will be closed in 7 days. Alternatively drop by the #sous-chefs channel on the Chef Community Slack and we'll be happy to help! Thanks, Sous-Chefs.