Skip to content

Commit

Permalink
✨ mongoRealmAuthenticator can manage accounts in multiple dbs
Browse files Browse the repository at this point in the history
  • Loading branch information
ujibang committed Nov 12, 2024
1 parent 1fd12b1 commit 3ff32bd
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 189 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.bson.BsonDocument;
import org.restheart.utils.BsonUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Expand All @@ -36,30 +38,37 @@ public class MongoRealmAccount extends PwdCredentialAccount implements WithPrope
private static final long serialVersionUID = -5840534832968478775L;

private final BsonDocument properties;
private final String db;

/**
*
* @param name
* @param db
* @param password
* @param roles
* @param accountDocument
* @param properties
*/
public MongoRealmAccount(final String name, final char[] password, final Set<String> roles, BsonDocument properties) {
public MongoRealmAccount(final String db, final String name, final char[] password, final Set<String> roles, BsonDocument properties) {
super(name, password, roles);

if (password == null) {
throw new IllegalArgumentException("argument password cannot be null");
}

this.properties = properties;
this.db = db;
}

@Override
public BsonDocument properties() {
return properties;
}

private static Gson GSON = new GsonBuilder().serializeNulls().create();
public String db() {
return this.db;
}

private static final Gson GSON = new GsonBuilder().serializeNulls().create();

@Override
@SuppressWarnings("unchecked")
Expand Down
10 changes: 6 additions & 4 deletions core/src/main/resources/restheart-default-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fileRealmAuthenticator:
mongoRealmAuthenticator:
enabled: true
users-db: restheart
override-users-db-header: null # eg. X-Auth-Db; when present override users-db from request header
users-collection: users
prop-id: _id
prop-password: password
Expand Down Expand Up @@ -240,7 +241,11 @@ mongo:
#
# Special variables {host[n]} can be used in path templates for mounting
# MongoDB resources based on the request's host name.
# Example: If the request is GET test.restheart.org/coll, then {host[0]}="test" and {host[1]}="restheart".
# Example:
# - what: /{host[0]}/{*}
# where: /{*}
#
# If the request is GET test.restheart.org/coll, then {host[0]}="test" and {host[1]}="restheart".
# WARNING: The Host header can be manually altered, potentially allowing unauthorized access to
# arbitrary MongoDB resources. To secure access, ensure strict validation of authenticated users.
# It is recommended to implement a veto permission mechanism to restrict resource access.
Expand Down Expand Up @@ -270,9 +275,6 @@ mongo:
- what: /restheart
where: /

- what: /{host[2]}
where: /

# Default representation format https://restheart.org/docs/mongodb-rest/representation-format/#other-representation-formats
default-representation-format: STANDARD

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
import org.restheart.plugins.InterceptPoint;
import org.restheart.plugins.MongoInterceptor;
import org.restheart.plugins.OnInit;
import org.restheart.plugins.PluginRecord;
import org.restheart.plugins.PluginsRegistry;
import org.restheart.plugins.RegisterPlugin;
import org.restheart.plugins.security.Authenticator;
import org.restheart.utils.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -50,8 +48,8 @@
public class DenyFilterOnUserPwd implements MongoInterceptor {
static final Logger LOGGER = LoggerFactory.getLogger(DenyFilterOnUserPwd.class);

private MongoRealmAuthenticator mra = null;
private boolean enabled = false;
private String usersDb;
private String usersCollection;
private String propNamePassword;

Expand All @@ -60,27 +58,22 @@ public class DenyFilterOnUserPwd implements MongoInterceptor {

@OnInit
public void init() {
PluginRecord<Authenticator> _mra;

final var pr = registry.getAuthenticator("mongoRealmAuthenticator");
try {
_mra = registry.getAuthenticator("mongoRealmAuthenticator");
} catch (ConfigurationException ce) {
enabled = false;
return;
}

if (_mra == null || !_mra.isEnabled()) {
if (pr == null || !pr.isEnabled()) {
enabled = false;
} else {
var rhAuth = (MongoRealmAuthenticator) _mra.getInstance();
this.mra = (MongoRealmAuthenticator) pr.getInstance();

this.usersDb = rhAuth.getUsersDb();
this.usersCollection = rhAuth.getUsersCollection();
this.propNamePassword = rhAuth.getPropPassword();
this.usersCollection = this.mra.getUsersCollection();
this.propNamePassword = this.mra.getPropPassword();

if (usersDb == null
|| usersCollection == null
|| propNamePassword == null) {
if (usersCollection == null || propNamePassword == null) {
LOGGER.error("Wrong configuration of mongoRealmAuthenticator! "
+ "Requests with filters on the password property "
+ "are not blocked!");
Expand All @@ -94,10 +87,10 @@ public void init() {
@Override
public boolean resolve(MongoRequest request, MongoResponse response) {
return enabled
&& request.isGet()
&& this.usersDb.equalsIgnoreCase(request.getDBName())
&& this.usersCollection.equalsIgnoreCase(request.getCollectionName())
&& hasFilterOnPassword(request.getFiltersDocument());
&& request.isGet()
&& (this.mra.overrideUsersDbHeader() != null || this.mra.getUsersDb(request).equalsIgnoreCase(request.getDBName())) // if usersdb is overridden then any users collection in any db must be processed
&& this.usersCollection.equalsIgnoreCase(request.getCollectionName())
&& hasFilterOnPassword(request.getFiltersDocument());
}

@Override
Expand Down
Loading

0 comments on commit 3ff32bd

Please sign in to comment.