Closed fischerscode closed 4 years ago
All modules support the following ssl options...
ssl (False, bool, False)
Whether to use an SSL connection when connecting to the database.
ssl_cert_reqs (False, str, CERT_REQUIRED)
Specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided.
ssl_ca_certs (False, str, None)
The ssl_ca_certs option takes a path to a CA file.
ssl_crlfile (False, str, None)
The ssl_crlfile option takes a path to a CRL file.
ssl_certfile (False, str, None)
Present a client certificate using the ssl_certfile option.
ssl_keyfile (False, str, None)
Private key for the client certificate.
ssl_pem_passphrase (False, str, None)
Passphrase to decrypt encrypted private keys.
The documentation states these provide the same functionality as the tls options...
Starting in version 4.2, MongoDB provides net.tls settings (and corresponding command-line options) that corresponds to the net.ssl settings (and their corresponding command-line options). The net.tls settings provide identical functionality as the net.ssl options since MongoDB has always supported TLS 1.0 and later.
https://docs.mongodb.com/manual/tutorial/configure-ssl/#procedures-using-net-ssl-settings
Is there anything missing meaning your above approach won't work?
As far as I know, there is a difference between Membership Authentication and Client Authentication. I think, the provided ssl options only work for client authentication.
I am able to create a a user using this task through x509 Membership Authentication.
- name: create admin user
command: |
/usr/bin/mongo mongodb-host.test \
--tls \
--tlsCAFile /tmp/ca.crt \
--tlsCertificateKeyFile=/tmp/tls.key \
--authenticationMechanism MONGODB-X509 \
--authenticationDatabase '$external' \
--eval \
'{{ lookup('template', 'templates/create-admin-user.js') }}'
register: mongoout
changed_when: "'{ \0ok\0 : 1 }' in mongoout.stdout"
and this fails for me with: fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unable to add or update user: 'ServerSelectionTimeoutError' object has no attribute 'code'"}
- name: create admin user
community.mongodb.mongodb_user:
login_host: "mongodb-host.test"
login_port: 27001
login_database: "$external"
database: "admin"
name: "admin"
password: "{{admin_password}}"
roles:
- dbAdminAnyDatabase
ssl: true
ssl_ca_certs: "/tmp/ca.crt"
ssl_certfile: "/tmp/tls.key"
state: present
But maybe I am just missing something.
Well... you've found a bug here I need to fix.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unable to add or update user: 'ServerSelectionTimeoutError' object has no attribute 'code'"}
ssl/tls are definitely the same thing as far as I can see in the documentation. We don't specify authenticationMechanism anywhere in the mongodb module so your example would be attempting with the default (SCRAM). It should be fairly simple to add this to the modules as follows...
- name: create admin user
community.mongodb.mongodb_user:
login_host: "mongodb-host.test"
login_port: 27001
login_database: "$external"
database: "admin"
name: "admin"
password: "{{admin_password}}"
roles:
- dbAdminAnyDatabase
ssl: true
ssl_ca_certs: "/tmp/ca.crt"
ssl_certfile: "/tmp/tls.key"
auth_mechanism: "MONGODB-X509"
state: present
I probably need to add the mechanisms from here...
https://api.mongodb.com/python/current/examples/authentication.html
and probably remove the auth database from the arguments when x.509 is used. Should be able to get this done in the next day or two.
Cheers,
Rhys
Nice, thank you! 👍
I've added the auth_mechanism feature in the following pr...
https://github.com/ansible-collections/community.mongodb/pull/179
Assuming I'm correct in my assumptions this should work. I don't currently have the ability to easily test this. If you are able to do so that would be helpful.
Thank you 👍 I'll be happy to test it.
Unfortunately I have not been able to make it work. I have tried different combinations like this:
community.mongodb.mongodb_user:
login_host: "mongodb-host.test"
login_port: 27001
login_database: "$external"
database: "admin"
name: "admin"
password: "test"
roles:
- dbAdminAnyDatabase
ssl: true
ssl_ca_certs: "/tmp/ca.crt"
ssl_certfile: "/tmp/tls.key" #cert and key in one file
state: present
auth_mechanism: "MONGODB-X509"
I am still getting this this error:
fatal: [localhost]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "changed": false, "msg": "Unable to add or update user: 'ServerSelectionTimeoutError' object has no attribute 'code'"}
OK. It's probably best I create some form of test setup in Docker to debug this.
I have uploaded such a test environment based on Kubernetes and the operator-sdk.
@fischerscode Great stuff. Very useful. I'll start looking at this over the next week.
@rhysmeister Great! 👍 Have a nice weekend.
Had some free time this afternoon so I decided to look at this.
Tested with the following command...
ansible localhost -m mongodb_user -a "login_host=localhost login_port=27017 login_database='$external' database='admin' password='secret' ssl=true ssl_ca_certs=/Users/rhyscampbell/Documents/git/mongodb-kub/tests/ansible-operator/ca.crt ssl_certfile=/Users/rhyscampbell/Documents/git/mongodb-kub/tests/ansible-operator/tls.key auth_mechanism=MONGODB-X509 name="test" state=present connection_options='tlsAllowInvalidHostnames=true'"
This is essentially the same as your example with the addition of the tlsAllowInvalidHostnames flag. Here's the log from the test MongoDB instance showing the member auth works...
2020-09-20T11:19:25.274+0000 W NETWORK [conn116] Client connecting with server's own TLS certificate 2020-09-20T11:19:25.286+0000 I NETWORK [conn116] received client metadata from 127.0.0.1:42388 conn116: { driver: { name: "PyMongo", version: "3.11.0" }, os: { type: "Darwin", name: "Darwin", architecture: "x86_64", version: "10.15.6" }, platform: "CPython 3.7.5.final.0" } 2020-09-20T11:19:25.299+0000 I NETWORK [listener] connection accepted from 127.0.0.1:42390 #117 (2 connections now open) 2020-09-20T11:19:25.308+0000 W NETWORK [conn117] Client connecting with server's own TLS certificate 2020-09-20T11:19:25.308+0000 I NETWORK [conn117] received client metadata from 127.0.0.1:42390 conn117: { driver: { name: "PyMongo", version: "3.11.0" }, os: { type: "Darwin", name: "Darwin", architecture: "x86_64", version: "10.15.6" }, platform: "CPython 3.7.5.final.0" } 2020-09-20T11:19:25.311+0000 I ACCESS [conn117] authenticate db: $external { authenticate: 1, mechanism: "MONGODB-X509", $db: "$external", $readPreference: { mode: "primary" } } 2020-09-20T11:19:25.312+0000 W ACCESS [conn117] Client isn't a mongod or mongos, but is connecting with a certificate with cluster membership 2020-09-20T11:19:25.312+0000 I ACCESS [conn117] Successfully authenticated as principal CN=mongodb-sample.default.svc.cluster.local,OU=organizationUnit,O=organizationName on $external from client 127.0.0.1:42390 2020-09-20T11:19:25.373+0000 I STORAGE [conn117] createCollection: admin.system.users with generated UUID: fb39dbc5-71c1-47e6-b2bf-8c354d13786a and options: {} 2020-09-20T11:19:25.387+0000 I INDEX [conn117] index build: done building index id on ns admin.system.users 2020-09-20T11:19:25.395+0000 I INDEX [conn117] index build: done building index user_1_db_1 on ns admin.system.users
This should work with all modules using pymongo, basically all apart from mongodb_shell, but I've only tested the mongodb_user module for now. If this is to be an officially supported authentication method then we should probably have a set of tests for this. Would you mind if I included your test env?
TODO
Thanks, it works! I do absolutely not mind if you add this test env. Should I create a PR?
@fischerscode Yes, please do.
Merged in https://github.com/ansible-collections/community.mongodb/pull/179
Will be available in latest tar archive.
@rhysmeister Thank you, it works perfectly in my current project.
SUMMARY
For setting up a mongodb, being able to authenticate using the x509 Membership Authentication would be quite useful, as it would allow secure authentication before any user is configured.
ISSUE TYPE
COMPONENT NAME
mongodb_common
ADDITIONAL INFORMATION
This feature could be used to configure a cluster from the first second with little preparation, in addition to that, the cluster could be set up without restarting any node, as authentication could be enabled at the first boot.
When implemented, the plugins could be used for doing something like this:
Mongopy seems to support this. The mongodb doc for x509 membership authentication.