Skip to content
This repository has been archived by the owner on Jan 8, 2021. It is now read-only.

Start Mongo with enabled access control #77

Closed
difince opened this issue Jan 9, 2020 · 13 comments · Fixed by #81
Closed

Start Mongo with enabled access control #77

difince opened this issue Jan 9, 2020 · 13 comments · Fixed by #81
Projects

Comments

@difince
Copy link
Member

difince commented Jan 9, 2020

Currently, mongo database is started by mongod --bind_ip_all & (see edgex-mongo-launch.sh).
Because the authentication is not explicitly enabled (by setting it in mongod.conf file , or using --auth parameter), mongo comes without access control.

Once mongo is started, edgex-mongo app creates User for each service. Each User has privileges to manipulate the data in specific database (exp, user "meta" could access only "metadata" database and etc)

Nevertheless,the existence of all these users, restriction free control could be taken over the entire database if the client do not provide any credentials at all.

@difince
Copy link
Member Author

difince commented Jan 9, 2020

My proposal for fixing the issue is edgex-mongo-launch.sh to be modified like this:

set -e

mongod &

cd cmd/
./edgex-mongo --profile=docker --confdir=res

mongod --shutdown
mongod --bind_ip_all --auth &

wait

First mongo is started without access control, bound to localhost. Then edgex-mongo go app creates all the Users and once it is done -> mongo is stopped and then started with --bind_ip_all --auth.
This is the same as what some of the developers scripts are doing, but are tent to be removed.

From developers point of view, working with --auth enabled will make the developers work harder because username and password will be always required in order to get in mongo mongo --username xxx --password yyy. In addition, all the users that are currently creating have privileges to work only with one database. This means that the developer won't be able just to log in once and take a look of the entire database - metadata, coredata, notifications and etc.
Instead of creating one super-user that will be able to manage all the data inside all databases in mongo my suggestion is NOT to start mongo with --auth if working in development mode. (plus this super user will also have a username and password ..that should be taken from somewhere that get harder if the credentials comes from vault)

@bnevis-i bnevis-i added this to New Issues in Security WG Jan 15, 2020
@tingyuz
Copy link
Contributor

tingyuz commented Jan 15, 2020

If Mongo starts without any protection then it is a serious issue and would be a good candidate of ticket for SIR team. We may need to develop a fix, record the issue into SIR and notify the community. This would be a common practice.

@hutchic
Copy link
Member

hutchic commented Jan 15, 2020

It was discussed at a meeting this wasn't SIR worthy as mongo is optional and going away next release.

The official mongo docker image handles auth quite well I'd suggest lifting what they do wrt MONGO_INITDB_ROOT_PASSWORD which I mentioned at said meeting

https://github.com/docker-library/mongo/blob/2628a9b53013985d9aec377567f664b68b79e3d9/3.4/docker-entrypoint.sh

@difince
Copy link
Member Author

difince commented Jan 20, 2020

Fix of the current issue will remove some of the warning messages, reported by issue #9

[initandlisten] ** WARNING: Access control is not enabled for the database.
Jan 27 10:38:49 tex1 edgexfoundry-core.mongod[19510]: 2018-01-27T10:38:49.976-0500 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.

@difince
Copy link
Member Author

difince commented Jan 21, 2020

@hutchic
As I see, this script provides:

  • database initialization mechanism by deploying custom js or sh files in if /docker-entrypoint-initdb.d/* that are run against test database by default or against MONGO_INITDB_DATABASE if defined in the environment

  • if env vars MONGO_INITDB_ROOT_USERNAME andMONGO_INITDB_ROOT_PASSWORD are set the script automatically creates user with root privileges

Both are executed if there is no data populated in dbPath

In addition the script handle automatically set/remove --auth param if MONGO_INITDB_ROOT_USERNAME andMONGO_INITDB_ROOT_PASSWORD are set and if very first initialization is needed.

@hutchic
Copy link
Member

hutchic commented Jan 21, 2020

Right now I think docker-edgex-mongo overrides the entrypoint but the better solution IMO would be to place custom startup scripts into /docker-entrypoint-init.d/* and then reference the official mongo docker image docs

@difince
Copy link
Member Author

difince commented Jan 22, 2020

@hutchic
Currently, if vault is in use - all the db credentials are inside vault, otherwise they are in configuration file.
MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD are not set at all.

In addition, we have used java script file responsible for initializing the data inside mongo, but the logic was re-written , so now we have go application inside docker-edgex-mongo.
Part of the logic inside docker-edgex-mongo ( creating the users with their credentials) need to be executed on every restart, not just on initial startup, because the credentials inside vault changes constantly.
Only the collections initialization could be executed on the initial startup of mongo.

Sо, I do not think we could use the original mongo entry point. At all, I see that this script also restarts mongo in order to do data initialization.

Nevertheless, I suggest current admin user to be given with root privileges.
This admin user will be used later when /purge endpoint is implemented inside docker-edgex-mongo (see edgexfoundry/edgex-docs#74 )

So, my suggestion is as th original one + give root privileges to the admin user

set -e

mongod --bind_ip 127.0.0.1 &

cd cmd/
./edgex-mongo --profile=docker --confdir=res

mongod --shutdown
mongod --bind_ip_all --auth &

wait

Note: Another thing I have noticed in this script is that mongo is started with numactl --interleave=all. I will eventually address this in separate issue if needed

@difince
Copy link
Member Author

difince commented Jan 22, 2020

@hutchic
Could you please write down what was your suggestion ?

@difince
Copy link
Member Author

difince commented Jan 30, 2020

@hutchic
Could we clarify what is your suggestion about solving the problem ?
If I am not wrong, your suggestion was - to re-write what we currently have as go application by using javascript/bash, and to define MONGO_ROOT_PASSWORD and USERNAME with some default values (if not set explicitly) in order to take advantage of the official endpoint.
Is this your proposal ?

If, yes, I would say that I am not in favor of rewriting again everything just to take advantage of the official endpoint. Plus, there are additional thoughts around database schema initialization - like each micro-service should own the schema and should be responsible for data initialization thus keeping micro services encapsulated. So, I guess that in the future releases this will be rewritten anyway.

I agree with adding root user. I only have concerns with the way credentials are provided.
In production nobody will want to use "ChangeMe" credentials. What this means for me

  • we will need to update some user related documentation about that
  • EdgexFoundry user will need to do some manual action ... that at all looks error prone.

But from developers perspective this looks like the easiest solution - having root user with human readable credentials.

What about .. if env variables are set (developers case) - use their values for root user creation, otherwise use the credentials coming from vault ? This way, we will need to update developers related documentation, and this manual work will be done by the developers, if needed at all.

@hutchic
Copy link
Member

hutchic commented Feb 10, 2020

For the scope of this issue I'd agree it's not worth the rewrite 👍

I think the use cases you've captured would be achievable via something like this

mongo-container:
  image: mongo:3.4.2
  environment:
      # provide root credentials let environment variables override
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USER:-root}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD:-mongorootpw}
  ports:
    - "27017:27017"
  volumes:
      # per DB use initialization scripts go here
    - "$PWD/mongo-entrypoint/:/docker-entrypoint-initdb.d/"

reference: https://www.frodehus.dev/running-mongodb-in-docker-with-authentication/

Part of the logic inside docker-edgex-mongo ( creating the users with their credentials) need to be executed on every restart, not just on initial startup, because the credentials inside vault changes constantly.

In the future EdgeX should probably consider using vault secret engines https://www.vaultproject.io/docs/secrets/databases/mongodb/

@difince
Copy link
Member Author

difince commented Feb 12, 2020

  environment:
      # provide root credentials let environment variables override
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USER:-root}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD:-mongorootpw}

@tingyuz @hutchic By adding the environment statement in the production docker-compose file, we will force the client to provide these root mongodb credentials. This is a manual work that should be done by the end user , and is error prone

Any idea how could we gracefully handle development vs production mode without forcing the client to do extra actions and all this still to be convenient for the developers ?

@hutchic
Copy link
Member

hutchic commented Feb 12, 2020

Not having setup a production environment I might not have the knowledge to weigh in here.

  1. How do other services that require a secret handle this?
  2. The vault secret engine would be invaluable https://www.vaultproject.io/docs/secrets/mongodb/

The mongodb secrets engine for Vault generates MongoDB database credentials dynamically based on configured roles. This means that services that need to access a MongoDB database no longer need to hard-code credentials: they can request them from Vault and use Vault's leasing mechanism to more easily roll them.

For the purposes of "start mongo with enabled access control" I still think do what gets it secured easily / now and punt on dynamic secrets / secret leasing for a future time

@difince
Copy link
Member Author

difince commented Feb 18, 2020

So, lets approach this issue by the easiest way - just enable the authentication mode.
By doing this each service will be able to write only into their database.
It is supposed that developers run mongo locally, if not it will be their responsibility to remove the --auth param from edgex-mongo-launch.sh and rebuild the image.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Security WG
  
Done
Development

Successfully merging a pull request may close this issue.

3 participants