Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix persistence error mongo authentication #1851

Conversation

srrspace
Copy link
Contributor

@srrspace srrspace commented Apr 1, 2020

Please check this PR that solve the issue #1849 ([cygnus][bug] Persistence Error Mongo Authentication and side effect #1849)

I made exhaustive tests and it work fine with various configuration and various users created by different way and with several data source (iotagents) send to the Orion Context Broker.

Now the databases (based on "Fiware-Service") and corresponding collections (based on "Fiware-ServicePath") are created automatically on the fly without manual action on mongodb when cygnus receive the data by notification (i.e. by subscription).

With this modification using auth_source option for mongo authentication, there is no side effect when more than one data source is received with different "Fiware-Service" and different "Fiware-ServicePath" at the same time or concurrently.

The "agent_1.conf" must add the following entry as example:

# a valid user in the MongoDB server (or empty if authentication is not enabled in MongoDB)
cygnus-ngsi.sinks.mongo-sink.mongo_username = TheUser
# password for the user above (or empty if authentication is not enabled in MongoDB)
cygnus-ngsi.sinks.mongo-sink.mongo_password = ThePassword
# Mongo option to specify which common user database source to use for authentication
cygnus-ngsi.sinks.mongo-sink.mongo_auth_source = TheAuthSource

The new entry in the agent configuration file for mongo sink is:

# Mongo option to specify which common user database source to use for authentication
cygnus-ngsi.sinks.mongo-sink.mongo_auth_source = TheAuthSource

If this new entry is not specified in the agent configuration file and authentication with the credentials is enabled, then the cygnus will work the same as before with the side effect as described in the issue (because it will use the corresponding dbName as before). I mean if we want to access mongodb with authentication mechanism auth_source must be specified and all will work fine.

Usually mongo_auth_source could be "admin" but could be another database where the user created must have the correct rights and correct privileges to access read/write the other DB based on the "Fiware-Service" value (i.e. DB name starting with "sth_").

The pertinent user should be created in the auth source DB:

For example:
use admin

db.createUser(
  {
    user: "TheUser",
    pwd: "ThePassword",
    roles : ["readWriteAnyDatabase"],
    mechanisms : [
      "SCRAM-SHA-1",
      "SCRAM-SHA-256"
    ]
  }
)

Or to adding more restrictions on the DB, if you know in advance the name of the database based on the "Fiware-Service" value:

db.createUser(
  {
    user: "TheUser",
    pwd: "ThePassword",
    roles : [
      {
        role : "readWrite",
        db : "sth_service1"
      },
      {
        role : "readWrite",
        db : "sth_service2"
      }
    ],
    mechanisms : [
      "SCRAM-SHA-1",
      "SCRAM-SHA-256"
    ]
  }
)

Notice that just after creating the user in the DB auth source, it is recommended to restart the mongo database, just in case, to apply the changes correctly (by using "sudo service mongod restart").

The only file modifies are:

  • cygnus-common - MongoBackendImpl.java
  • cygnus-ngsi - NGSIMongoBaseSink.java

@fgalan
Copy link
Member

fgalan commented Apr 2, 2020

Thank you for your contribution! Some comments:

  • Please modify documentation according to the changes in the PR. For instance, if you have added a new configuration parameter for the mongo sink (not sure...), then it should be properly described in the sink section in the documentation.
  • I understand this PR covers the mongo sink authentication. However, the sth sink works in a very similar way (it is also persisting information in MongoDB, but with a different data structure). Is your PR solving also the auth in sth sink?
  • An entry in CHANGES_NEXT_RELEASE describing the change (and citing the issue number) is needed. Have a look to current CHANGEX_NEXT_RELEASE in master to see which style we use.

* @param mongoAuthSource
* @param dataModel
*/
public MongoBackendImpl(String mongoHosts, String mongoUsername, String mongoPassword,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to overload the costructor in this case, since mongoAuthSource has a not null validation on getDatabase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my point of view it is better to have this new constructor to avoid side effect and maintain the backward compatibility. There is no problem to have 2 constructors in OOP and it is common to do it allowing to initialize and/or construct objects with different parameters depending of the use cases and future needs and maintaining the interface.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but the constructor is actually only used in NGSIMongoBaseSink and in tests, so there is no need to have both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @IvanHdzC . The constructor is only used in one point of the code, so lest's adapt constructor and calling code better than adding a second constructor. In addition, the lesser constructor we have, the easier it would be to have good code coverage in tests.

mongoHosts = context.getString("mongo_hosts", "localhost:27017");
LOGGER.debug("[" + this.getName() + "] Reading configuration (mongo_hosts=" + mongoHosts + ")");
mongoUsername = context.getString("mongo_username", "");
LOGGER.debug("[" + this.getName() + "] Reading configuration (mongo_username=" + mongoUsername + ")");
// FIXME: mongoPassword should be read as a SHA1 and decoded here
mongoPassword = context.getString("mongo_password", "");
LOGGER.debug("[" + this.getName() + "] Reading configuration (mongo_password=" + mongoPassword + ")");

mongoAuthSource = context.getString("mongo_auth_source", "");
Copy link
Contributor

@IvanHdzC IvanHdzC Apr 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thing it's more usuall that the default authSource is "admin". It would be better if the default value of mongo_auth_source is "admin".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO authSource is necessary to be configured and not fixed as default constant value to admin for security reason. Admin is a sensible and critical database with rights and high privileges. Giving the possibility to configure the authentication database will allow to provide other specific databases with some restrictions and with just the necesary privileges with a set of user depending of the uses and applications needed and it is more secure tha using only the admin database.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I misunderstood the "defaultauthdb" value, it actually is the db where the connection is created.

NTC

if ((mongoAuthSource != null) && !mongoAuthSource.isEmpty()) {
authSource = mongoAuthSource;
} else {
authSource = dbName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if the dbName is the right authSource in case it is not specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this modification dbName was the value used in the previous version. If authSource is not configured then the behavior of the code is the same as before maintaining the backward compatibility. From my point of view it is better to keep the code as it is and not setting authSource as a constant to "admin".

Copy link
Contributor

@IvanHdzC IvanHdzC Apr 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I misunderstood the "defaultauthdb" value, it actually is the db where the connection is created.

NTC

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, dbName is one thing and authSource is another. The parameter dbName is the name of the database to create and based on "Fiware-Service" where the collections will be stored. And authSource is used to specify a user DB where the credentials are defined, as documented by Mongo and for the credentials objects. These are 2 different things.
dbName is used in client.getDatabase(dbName) (class MongoClient) and authSource is used by credential object (MongoCredential) if only there is a need of authentication.

@IvanHdzC
Copy link
Contributor

IvanHdzC commented Apr 2, 2020

Missing tests for this PR.

Comment on lines 634 to 653
/**
* Gets the mongo auth_source
* @return
*/
public String getAuthSource() {
return mongoAuthSource;
} // getAuthSource

/**
* Set the mongo auth_source
* @param authSource DB used for mongo authentication
*/
public void setAuthSource(String authSource) {
if (authSource != null) {
this.mongoAuthSource = authSource;
} else {
this.mongoAuthSource = "";
}
} // setAuthSource

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this ever used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, if somebody or other piece of code (allowing other new sink in the future to use mongo as a DB with authentication), and want to use the first constructor without authSource in parameter, it will have the opportunity to set the authSource after to build the backend object using the setAuthSource(...) operation when needed and in some place in the code. It is typical and best practices to do it in OOP (overload constructors and get/set operations), and give more possibilities.
Notice that in this case mongoAuthSource shoud not be annotated as "final" in the declaration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get/setAuthSource(...) could be used, if somebody build the object without authSource parameter and if after they want to initialize this parameter.
This is what I tested successfully and put in comment as documentation (see start() operation), and use of the new constructor.

BTW, What does it mean "NTC" and "LGTM"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTC = Nothing to change
LGTM = Looks good to me

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srrspace
Copy link
Contributor Author

srrspace commented Apr 2, 2020

@fgalan:

Yes I will update the documentation in this cygnus repository (but do not know to do it in readthedocs.org).

And yes there is new configuration parameters:

In MongoSink:

# Mongo option to specify which common user database source to use for authentication
cygnus-ngsi.sinks.mongo-sink.mongo_auth_source = 

And probably In STHSink:

# Mongo option to specify which common user database source to use for authentication
cygnus-ngsi.sinks.sth-sink.mongo_auth_source =

This PR covers the mongo sink authentication issues.
According to my analysis of the code of STH Sink, YES this PR solve also the authentication issues in STH Sink.

Yes, I will update CHANGES_NEXT_RELEASE

@srrspace
Copy link
Contributor Author

srrspace commented Apr 2, 2020

In order to be aligned to your thoughts concerning the backend constructor I will review the code removing the old backend constructor and removing get/setAuthSource.

But impact on the tests, i.e. need to modify "MongoBackendImplTest.java"

@srrspace
Copy link
Contributor Author

srrspace commented Apr 2, 2020

Please could you check the PR with the new commit related to the code, documentation, docker, agent conf,...

Copy link
Contributor

@IvanHdzC IvanHdzC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -332,6 +332,7 @@ A configuration example could be:
cygnus-ngsi.sinks.mongo-sink.mongo_hosts = 192.168.80.34:27017
cygnus-ngsi.sinks.mongo-sink.mongo_username = myuser
cygnus-ngsi.sinks.mongo-sink.mongo_password = mypassword
cygnus-ngsi.sinks.mongo-sink.mongo_auth_source = admin
cygnus-ngsi.sinks.mongo-sink.db_prefix = cygnus_
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter mongo_auth_source should be also added to the configuration table included in this file .md file.

@@ -330,6 +330,7 @@ A configuration example could be:
cygnus-ngsi.sinks.sth-sink.mongo_hosts = 192.168.80.34:27017
cygnus-ngsi.sinks.sth-sink.mongo_username = myuser
cygnus-ngsi.sinks.sth-sink.mongo_password = mypassword
cygnus-ngsi.sinks.sth-sink.mongo_auth_source = admin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter mongo_auth_source should be also added to the configuration table included in this file .md file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter mongo_auth_source have been added to the configuration table for both sinks.

CHANGES_NEXT_RELEASE Outdated Show resolved Hide resolved
@fgalan
Copy link
Member

fgalan commented Apr 3, 2020

Please could you check the PR with the new commit related to the code, documentation, docker, agent conf,...

The PR looks good after the modification :)

I provided some extra comments (in CHANGEX_NEXT_RELEASE and documentation files). Once they get addressed I think the PR could be merged.

With regards to readthedocs.org don't worry about it. RTD is generated automatically from .md files, once the PR is merged.

CHANGES_NEXT_RELEASE Outdated Show resolved Hide resolved
@srrspace
Copy link
Contributor Author

srrspace commented Apr 6, 2020

Please could you check if now this PR is OK to be merged.
Thanks

@srrspace srrspace requested review from IvanHdzC and fgalan April 8, 2020 09:12
Copy link
Contributor

@IvanHdzC IvanHdzC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fgalan
Copy link
Member

fgalan commented Apr 13, 2020

Please could you check if now this PR is OK to be merged.
Thanks

I think the PR is mostly fine. However, I'm still seeing two suggesiton in the CHANGES_NEXT_RELEASE that hasn't been addressed. Please confirm them (buttom "Commit suggestion") or explain why do you think are not valid, please.

Co-Authored-By: Fermín Galán Márquez <[email protected]>
@srrspace
Copy link
Contributor Author

I confirmed the commit suggestion. Please check the PR to proceed with the merge.

@fgalan
Copy link
Member

fgalan commented Apr 14, 2020

I confirmed the commit suggestion. Please check the PR to proceed with the merge.

I think there is still one pending:

imagen

Co-Authored-By: Fermín Galán Márquez <[email protected]>
Copy link
Member

@fgalan fgalan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@fgalan fgalan merged commit a4e1807 into telefonicaid:master Apr 14, 2020
@srrspace srrspace deleted the fix/1849_persistence_error_mongo_authentication branch April 22, 2020 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants