linuxserver / docker-unifi-network-application

GNU General Public License v3.0
703 stars 52 forks source link

[BUG] Access control is not enabled for the database. #102

Closed nickurak closed 2 months ago

nickurak commented 3 months ago

Is there an existing issue for this?

Current Behavior

After starting the mongo container as documented, with mongo 7.0, and then connecting to the database with mongosh, the following error is displayed:

   The server generated these startup warnings when booting
   2024-08-02T01:00:53.190+00:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
   2024-08-02T01:00:53.191+00:00: vm.max_map_count is too low

I have the following init-mongo.js:

db.getSiblingDB("unifi").createUser({user: "unifi-user", pwd: "unifi-password", roles: [{role: "dbOwner", db: "unifi"}]});
db.getSiblingDB("unifi_stat").createUser({user: "unifi-user", pwd: "unifi-password", roles: [{role: "dbOwner", db: "unifi_stat"}]});

Note: In case it's relevant, I'm using podman instead of docker.

Expected Behavior

No such warning should occur.

Steps To Reproduce

  1. Create directories for volume mounts: mkdir -p ~/unifi/db
  2. Fill in ~/unifi/init-mongo.js as above.
  3. Run mongo container:
    podman run -d  \
    -v ~/unifi/db/:/data/db:Z \
    -v ~/unifi/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro,Z \
    -e MONGO_USER=unifi-user \
    -e MONGO_PASS=unifi-password \
    --name unifidb \
    --network unifi \
    docker.io/mongo:7.0
  4. Check if mongo access control is enabled: podman exec -it unifidb mongosh, looking for Access control is not enabled for the database. Read and write access to data and configuration is unrestricted message

Environment

- OS: Fedora 40
- How docker service was installed: `dnf install podman`

CPU architecture

x86-64

Docker creation

podman run -d  \
   -v ~/unifi/db/:/data/db:Z \
   -v ~/unifi/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro,Z \
   -e MONGO_USER=unifi-user \
   -e MONGO_PASS=unifi-password \
   --name unifidb \
   --network unifi \
   docker.io/mongo:7.0

### Container logs

```bash
Output of `podman logs unifidb`: 

https://pastebin.com/vjRzh5Ca (github rejected this log as too large)
github-actions[bot] commented 3 months ago

Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.

nickurak commented 3 months ago

I should also point out, I discovered this while trying (and failing) to get unifi-network-application to connect to this mongo container. I suspect this issue is at the root of what I'm running into, but I'm not sure. The application container gets these logs, in case that's relevant for seeing what's going on here:

───────────────────────────────────────

User UID:    1000
User GID:    1000
───────────────────────────────────────

*** Waiting for MONGO_HOST unifidb to be reachable. ***
Generating 4,096 bit RSA key pair and self-signed certificate (SHA384withRSA) with a validity of 3,650 days
    for: CN=unifi
[custom-init] No custom files found, skipping...
Exception in thread "launcher" java.lang.IllegalStateException: Tomcat failed to start up
    at com.ubnt.net.O0OO.ÓÔ0000(Unknown Source)
    at com.ubnt.service.C.Òo0000(Unknown Source)
    at com.ubnt.ace.Launcher.Object(Unknown Source)
    at com.ubnt.ace.Launcher.main(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoRuntimeService' defined in com.ubnt.service.db.CoreDatabaseSpringContext: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='unifi-user', source='unifi', password=<hidden>, mechanismProperties=<hidden>}
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
    at com.ubnt.service.E.Ô00000(Unknown Source)
    at com.ubnt.service.C.intsuper(Unknown Source)
    at com.ubnt.net.O0OO.ÕÔ0000(Unknown Source)
    at com.ubnt.net.O0OO.oÔ0000(Unknown Source)
    ... 4 more
Caused by: com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-256, userName='unifi-user', source='unifi', password=<hidden>, mechanismProperties=<hidden>}
    at com.mongodb.internal.connection.SaslAuthenticator.wrapException(SaslAuthenticator.java:270)
    at com.mongodb.internal.connection.SaslAuthenticator.lambda$authenticate$0(SaslAuthenticator.java:86)
    at com.mongodb.internal.connection.SaslAuthenticator.doAsSubject(SaslAuthenticator.java:277)
    at com.mongodb.internal.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:59)
    at com.mongodb.internal.connection.DefaultAuthenticator.authenticate(DefaultAuthenticator.java:57)
    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.authenticate(InternalStreamConnectionInitializer.java:206)
    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.finishHandshake(InternalStreamConnectionInitializer.java:86)
    at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:216)
    at com.mongodb.internal.connection.UsageTrackingInternalConnection.open(UsageTrackingInternalConnection.java:55)
    at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.open(DefaultConnectionPool.java:647)
    at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openWithConcurrencyLimit(DefaultConnectionPool.java:993)
    at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openOrGetAvailable(DefaultConnectionPool.java:934)
    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:203)
    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:192)
    at com.mongodb.internal.connection.DefaultServer.getConnection(DefaultServer.java:96)
    at com.mongodb.internal.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:186)
    at com.mongodb.client.internal.ClientSessionBinding$SessionBindingConnectionSource.getConnection(ClientSessionBinding.java:196)
    at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:144)
    at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$1(SyncOperationHelper.java:126)
    at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:152)
    at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:125)
    at com.mongodb.internal.operation.SyncOperationHelper.lambda$executeRetryableRead$4(SyncOperationHelper.java:189)
    at com.mongodb.internal.operation.SyncOperationHelper.lambda$decorateReadWithRetries$12(SyncOperationHelper.java:292)
    at com.mongodb.internal.async.function.RetryingSyncSupplier.get(RetryingSyncSupplier.java:67)
    at com.mongodb.internal.operation.SyncOperationHelper.executeRetryableRead(SyncOperationHelper.java:194)
    at com.mongodb.internal.operation.SyncOperationHelper.executeRetryableRead(SyncOperationHelper.java:176)
    at com.mongodb.internal.operation.CommandReadOperation.execute(CommandReadOperation.java:48)
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:153)
    at com.mongodb.client.internal.MongoDatabaseImpl.executeCommand(MongoDatabaseImpl.java:196)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:165)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:160)
    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:150)
    at com.ubnt.service.db.J.Óo0000(Unknown Source)
    at com.ubnt.service.db.J.afterPropertiesSet(Unknown Source)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782)
    ... 17 more
Caused by: java.lang.IllegalArgumentException: Empty key
    at java.base/javax.crypto.spec.SecretKeySpec.<init>(SecretKeySpec.java:113)
    at com.mongodb.internal.connection.ScramShaAuthenticator$ScramShaSaslClient.hi(ScramShaAuthenticator.java:274)
    at com.mongodb.internal.connection.ScramShaAuthenticator$ScramShaSaslClient.getClientProof(ScramShaAuthenticator.java:250)
    at com.mongodb.internal.connection.ScramShaAuthenticator$ScramShaSaslClient.computeClientFinalMessage(ScramShaAuthenticator.java:227)
    at com.mongodb.internal.connection.ScramShaAuthenticator$ScramShaSaslClient.evaluateChallenge(ScramShaAuthenticator.java:166)
    at com.mongodb.internal.connection.SaslAuthenticator.lambda$authenticate$0(SaslAuthenticator.java:67)
    ... 51 more
dampfhamm3r commented 3 months ago

I ran into the same issue. I discovered the behaviour while running a backup of the containers with Duplicati. Duplicati runs a pre- and post script (stopping containers with docker compose stop and after backup running docker compose up -d). Almost after every backup, the unifi-network-application container has the Tomcat startup error.

While in the loop of the Tomcat starting exception, I can run another docker compose up -d and the containers start successfully.

No idea what's causing this issue.

Environment:

Docker Compose file:

services:
  unifi-network-application:
    env_file:
      - path: .env
        required: true
    image: lscr.io/linuxserver/unifi-network-application:latest
    hostname: unifi
    domainname: domain.com
    container_name: unifi-network-application
    depends_on:
      unifi-db:
        condition: service_healthy
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Zurich
      - MONGO_USER=unifi
      - MONGO_PASS=${MONGO_PASS}
      - MONGO_HOST=unifi-db
      - MONGO_PORT=27017
      - MONGO_DBNAME=UNIFI-DB
      - MEM_LIMIT=1024
      - MEM_STARTUP=1024
    healthcheck:
      test: curl -k -f https://localhost:8443
      interval: 1m30s
      timeout: 30s
      retries: 5
      start_period: 30s
    volumes:
      - ./data/unifi-network-application:/config
    networks:
      mgmt-100:
        ipv4_address: 192.168.100.50
      internal:
  unifi-db:
    image: docker.io/mongo:7
    container_name: unifi-db
    networks:
      - internal
    volumes:
      - ./data/unifi-db-data:/data/db
      - ./data/unifi-db-config:/data/configdb
      - ./data/unifi-db-init-mongo/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
    healthcheck:
      test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
      interval: 1m30s
      timeout: 30s
      retries: 5
      start_period: 30s
    restart: always

networks:
  mgmt-100:
    external: true
  internal:

Log:

unifi-network-application  | Exception in thread "launcher" java.lang.IllegalStateException: Tomcat failed to start up
unifi-network-application  |    at com.ubnt.net.O0OO.ÓÔ0000(Unknown Source)
unifi-network-application  |    at com.ubnt.service.C.Òo0000(Unknown Source)
unifi-network-application  |    at com.ubnt.ace.Launcher.Object(Unknown Source)
unifi-network-application  |    at com.ubnt.ace.Launcher.main(Unknown Source)
unifi-network-application  | Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoRuntimeService' defined in com.ubnt.service.db.CoreDatabaseSpringContext: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='unifi', source='UNIFI-DB', password=<hidden>, mechanismProperties=<hidden>}
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
unifi-network-application  |    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
unifi-network-application  |    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
unifi-network-application  |    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962)
unifi-network-application  |    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
unifi-network-application  |    at com.ubnt.service.E.Ô00000(Unknown Source)
unifi-network-application  |    at com.ubnt.service.C.intsuper(Unknown Source)
unifi-network-application  |    at com.ubnt.net.O0OO.ÕÔ0000(Unknown Source)
unifi-network-application  |    at com.ubnt.net.O0OO.oÔ0000(Unknown Source)
unifi-network-application  |    ... 4 more
unifi-network-application  | Caused by: com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='unifi', source='UNIFI-DB', password=<hidden>, mechanismProperties=<hidden>}
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.wrapException(SaslAuthenticator.java:270)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.getNextSaslResponse(SaslAuthenticator.java:133)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.lambda$authenticate$0(SaslAuthenticator.java:63)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.doAsSubject(SaslAuthenticator.java:277)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:59)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultAuthenticator.authenticate(DefaultAuthenticator.java:57)
unifi-network-application  |    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.authenticate(InternalStreamConnectionInitializer.java:206)
unifi-network-application  |    at com.mongodb.internal.connection.InternalStreamConnectionInitializer.finishHandshake(InternalStreamConnectionInitializer.java:86)
unifi-network-application  |    at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:216)
unifi-network-application  |    at com.mongodb.internal.connection.UsageTrackingInternalConnection.open(UsageTrackingInternalConnection.java:55)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.open(DefaultConnectionPool.java:647)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openWithConcurrencyLimit(DefaultConnectionPool.java:993)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openOrGetAvailable(DefaultConnectionPool.java:934)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:203)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:192)
unifi-network-application  |    at com.mongodb.internal.connection.DefaultServer.getConnection(DefaultServer.java:96)
unifi-network-application  |    at com.mongodb.internal.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:186)
unifi-network-application  |    at com.mongodb.client.internal.ClientSessionBinding$SessionBindingConnectionSource.getConnection(ClientSessionBinding.java:196)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:144)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.lambda$withSourceAndConnection$1(SyncOperationHelper.java:126)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.withSuppliedResource(SyncOperationHelper.java:152)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.withSourceAndConnection(SyncOperationHelper.java:125)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.lambda$executeRetryableRead$4(SyncOperationHelper.java:189)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.lambda$decorateReadWithRetries$12(SyncOperationHelper.java:292)
unifi-network-application  |    at com.mongodb.internal.async.function.RetryingSyncSupplier.get(RetryingSyncSupplier.java:67)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.executeRetryableRead(SyncOperationHelper.java:194)
unifi-network-application  |    at com.mongodb.internal.operation.SyncOperationHelper.executeRetryableRead(SyncOperationHelper.java:176)
unifi-network-application  |    at com.mongodb.internal.operation.CommandReadOperation.execute(CommandReadOperation.java:48)
unifi-network-application  |    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:153)
unifi-network-application  |    at com.mongodb.client.internal.MongoDatabaseImpl.executeCommand(MongoDatabaseImpl.java:196)
unifi-network-application  |    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:165)
unifi-network-application  |    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:160)
unifi-network-application  |    at com.mongodb.client.internal.MongoDatabaseImpl.runCommand(MongoDatabaseImpl.java:150)
unifi-network-application  |    at com.ubnt.service.db.J.Óo0000(Unknown Source)
unifi-network-application  |    at com.ubnt.service.db.J.afterPropertiesSet(Unknown Source)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833)
unifi-network-application  |    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782)
unifi-network-application  |    ... 17 more
unifi-network-application  | Caused by: com.mongodb.MongoCommandException: Command failed with error 18 (AuthenticationFailed): 'Authentication failed.' on server unifi-db:27017. The full response is {"ok": 0.0, "errmsg": "Authentication failed.", "code": 18, "codeName": "AuthenticationFailed"}
unifi-network-application  |    at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:205)
unifi-network-application  |    at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:454)
unifi-network-application  |    at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:372)
unifi-network-application  |    at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:92)
unifi-network-application  |    at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:48)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.sendSaslStart(SaslAuthenticator.java:224)
unifi-network-application  |    at com.mongodb.internal.connection.SaslAuthenticator.getNextSaslResponse(SaslAuthenticator.java:131)
unifi-network-application  |    ... 52 more
eseub commented 3 months ago

Authentication on Mongo docker image is only enabled if MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD environment variables are provided

Mongo Docker image:

By default Mongo's configuration requires no authentication for access, even for the administrative user.

What I do is set the environment variables mentioned and instead of using the init-mongo.js to initialize the database I use a mongo-init.sh file:

set -e

mongosh << EOF

db.getSiblingDB("${MONGO_DBNAME}").createUser(
  {
    user: "${MONGO_USER}",
    pwd: "${MONGO_PASS}",
    roles: [
      { role: "dbOwner", db: "${MONGO_DBNAME}" },
      { role: "dbOwner", db: "${MONGO_DBNAME}_stat" }
    ]
  }
);

db.getSiblingDB("${MONGO_DBNAME}_stat").createUser(
  {
    user: "${MONGO_USER}",
    pwd: "${MONGO_PASS}",
    roles: [{role: "dbOwner", db: "${MONGO_DBNAME}_stat"}]
  }
);

EOF
nickurak commented 3 months ago

I'm attempting to use the JS method, and the instructions for that explicitly say not to use those variables:

If you are using the init JS method do not also set MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD, or any other "INITDB" values as they will cause conflicts. Setting these variables for the .sh file is necessary

eseub commented 3 months ago

Guess the docs are incomplete

You don't have to believe me, all you have to do is look at /usr/local/bin/docker-entrypoint.sh in the Mongo Docker image:

if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
                # if we have a username/password, let's set "--auth"
                _mongod_hack_ensure_arg '--auth' "$@"
                set -- "${mongodHackedArgs[@]}"
...
aptalca commented 3 months ago

Just tell us how you interpret it. I don't follow what you're trying to say.

I'm looking at it and I am not having an aha moment.

eseub commented 3 months ago

In order to have authentication you need the --auth arg to be passed to mongod and that arg is only passed if it has MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD set

https://www.mongodb.com/docs/manual/reference/program/mongod/#std-option-mongod.--auth

--auth Enables authorization to control user's access to database resources and operations. When authorization is enabled, MongoDB requires all clients to authenticate themselves first in order to determine the access for the client.

aptalca commented 3 months ago

My dude, the readme explicitly tells you NOT to set the auth vars if you're relying on the js file we provide. If you set them, our js file does not work.

Nobody is arguing with you about how to enable auth in mongodb. That's completely out of scope.

If you want to enable auth, go ahead and do so. But you'll have to come up with your own js file or you'll have to create the necessary dbs yourself manually via cli. Nobody's stopping you.

Please stop claiming our docs are incorrect just because you're refusing to follow them.

eseub commented 3 months ago

I did follow the docs, that's why I'm saying that they are incomplete not that they are incorrect. It's no the same thing.

I know that those vars + init-mongo.js mess up with yours, that's why I said to use .sh instead.

All I'm trying to do is help @nickurak with the same problem I had a few months ago, it's literally on the title.

In order to have "Access control" you need --auth on mongo, and to have that you need MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD set + a mongo-init.sh.

If you don't have that, authentication on the database is disabled, you can try it yourself with mongodb compass.

That's my final answer.

iamwyza commented 3 months ago

I followed the docs exactly as described, and I get the same error:

docker-compose.yml:

services:
  unifi-network-application:
    image: lscr.io/linuxserver/unifi-network-application:latest
    container_name: unifi-network-application
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=CDT/UTC
      - MONGO_USER=unifi
      - MONGO_PASS=password
      - MONGO_HOST=unifi-db
      - MONGO_PORT=27017
      - MONGO_DBNAME=unifi
      - MEM_LIMIT=1024 #optional
      - MEM_STARTUP=1024 #optional
    volumes:
      - /storage/docker/unifi/data:/config
    ports:
      - 8443:8443
      - 3478:3478/udp
      - 10001:10001/udp
      - 8080:8080
      - 1900:1900/udp #optional
      - 8843:8843 #optional
      - 8880:8880 #optional
      - 6789:6789 #optional
      - 5514:5514/udp #optional
    restart: unless-stopped
  unifi-db:
    hostname: unifi-db
    image: docker.io/mongo:7
    container_name: unifi-db
    volumes:
      - /storage/docker/unifi/mongo/data:/data/db
      - /storage/docker/unifi/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
    ports:
      - 27017:27017
    restart: unless-stopped

init-mongo.js:

db.getSiblingDB("unifi").createUser({user: "unifi", pwd: "password", roles: [{role: "dbOwner", db: "unifi"}]);
db.getSiblingDB("unifi_stat").createUser({user: "unifi", pwd: "password", roles: [{role: "dbOwner", db: "unifi_stat"}]});

and the logs show that the init is getting executed:

unifi-db                   | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init-mongo.js

but it still fails auth

unifi-db                   | {"t":{"$date":"2024-08-04T01:55:05.819+00:00"},"s":"I",  "c":"ACCESS",   "id":5286307, "ctx":"conn7","msg":"Failed to authenticate","attr":{"client":"172.22.0.3:58574","isSpeculative":false,"isClusterMember":false,"mechanism":"SCRAM-SHA-1","user":"unifi","db":"unifi","error":"UserNotFound: Could not find user \"unifi\" for db \"unifi\"","result":11,"metrics":{"conversation_duration":{"micros":82,"summary":{"0":{"step":1,"step_total":2,"duration_micros":72}}}},"extraInfo":{}}}
unifi-db                   | {"t":{"$date":"2024-08-04T01:55:05.819+00:00"},"s":"I",  "c":"ACCESS",   "id":5286307, "ctx":"conn8","msg":"Failed to authenticate","attr":{"client":"172.22.0.3:58584","isSpeculative":false,"isClusterMember":false,"mechanism":"SCRAM-SHA-1","user":"unifi","db":"unifi","error":"UserNotFound: Could not find user \"unifi\" for db \"unifi\"","result":11,"metrics":{"conversation_duration":{"micros":132,"summary":{"0":{"step":1,"step_total":2,"duration_micros":117}}}},"extraInfo":{}}}
aptalca commented 3 months ago

Can't reproduce: https://github.com/linuxserver/docker-unifi-network-application/issues/103

eseub commented 3 months ago

Can't reproduce: #103

I appreciate you taking the time to try it out.

Now check your unifi-db container logs as well or run mongosh inside the unifi-db container, you will see the following message:

Access control is not enabled for the database. Read and write access to data and configuration is unrestricted

That message means that your init-mongo.js credentials are useless.

aptalca commented 3 months ago

you will see the following message

Yes. Role Based Access Control (RBAC) is not enabled, which is the default configuration for mongodb.

That message means that your init-mongo.js credentials are useless.

Do me a favor and change the password in unifi's system.properties to an incorrect one and restart the container. See if it's able to still connect to the database. If so, you can open a new issue and report it as a bug or a security issue. If not, then please refrain from making wild and sensational claims that are simply not true.

Without a root user and password for mongodb, and without RBAC, local users (connecting from inside the mongodb container, from 127.0.0.1) can administer the mongodb instance, which is how the js file we provide is able to create the unifi dbs and the user. That behavior has nothing to do with remote connections such as unifi connecting from a different container, and the credentials used.

RBAC is beyond the scope of our documentation.

I'm not a fan of repeating myself but I will do so one last time: If you want to enable auth, go ahead and do so. But you'll have to come up with your own js file or you'll have to create the necessary dbs yourself manually via cli. Nobody's stopping you.

eseub commented 3 months ago

RBAC is what OP is asking for, it's literally in the title of this issue. Although I do agree that this is out of scope of this project.

I said it's useless because you are able to connect to the database without credentials, e.g. with MongoDB Compass. If you are able to login without credentials, what's the point of using them?

I'm perfectly happy with my RBAC setup, all I had to do was set those vars and use the .sh file I posted above, no manual setup was required for the database.

At the end of the day, unifi-db container usually isn't exposed to the local network, so who cares. I see no point in arguing any further.

Have a nice day 😃

aptalca commented 3 months ago

You're right, the initial question was on rbac, but it quickly turned into I followed the instructions and it's not working with others piling on with same issue.

I may have been overly sensitive and I apologize. It's just that ever since this image was released, we have been getting swamped with the readme is wrong, it doesn't work type of issues in every support channel. Most of our team members use this image and we all followed the instructions and confirmed they are accurate.

The current behavior (lack of root user/pass, and direct access from inside the container) matches the previous image's behavior where mongodb ran inside unifi and was installed from the Ubuntu repo. Access into the container requires root access.

I'm not familiar with compass at all, can it connect to the mongodb instance remotely (from outside of the container) without credentials? If so, that's a security issue. But if it needs to run inside the container or perhaps need direct access to the db files, we wouldn't consider that a security issue. Unifi keeps the db credentials in plain text in its system.properties file anyway.

eseub commented 3 months ago

No worries mate, I've been using this image almost since day 1 and is rock solid. I appreciate all the effort that has been put into this image. 🙂

The readme example is perfectly fine, maybe I didn't express myself well and I apologize for that, my concerns were regards this issue and that specific use case was not clear on the docs. I think the problem is that a lot of people are used to SQL authentication which is veeery different from what Mongo does.

I'm not familiar with compass at all, can it connect to the mongodb instance remotely (from outside of the container) without credentials?

Yes, you can try it yourself. Expose the port 27017 on your unifi-db and just connect with compass: image image

As I said before, unifi-db container usually isn't exposed to the local network, so it's not that big of a deal. Maybe just leave a note to not expose those ports.

https://www.mongodb.com/try/download/compass

aptalca commented 3 months ago

Ugh!!!! Just tried compass and it is able to connect remotely as admin without any credentials over the port. WTF mongodb?!? According to the docs, that should only be allowed when connecting from 127.0.0.1. This is ridiculous.

Unfortunately our users do often map the ports and may even publish it publicly (accidentally when running it on a VPS).

So yeah, we'll have to modify our instructions. Thanks for the heads up.

eseub commented 3 months ago

Yeah, MongoDB does its own thing. 🙃

Thank you and everyone in the team for doing the hard work, I'm glad to help.

This may not be the best example but here's is my current setup, If it helps:

docker-compose (empty values are set from portainer environment variables):

services:
  unifi-network-application:
    image: linuxserver/unifi-network-application:8.3.32
    container_name: unifi-network-application
    environment:
      PUID: 1000
      PGID: 1000
      TZ: Etc/UTC
      MEM_LIMIT: 1024
      MEM_STARTUP: 1024
      MONGO_USER:
      MONGO_PASS:
      MONGO_HOST:
      MONGO_PORT:
      MONGO_DBNAME:
    volumes:
      - conf:/config
    restart: unless-stopped
    depends_on:
      - unifi-db
    networks:
      default:
      shared-lan:
        ipv4_address: 192.168.88.193
  unifi-db:
    image: mongo:7.0.12
    container_name: unifi-db
    environment:
      MONGO_INITDB_ROOT_USERNAME:
      MONGO_INITDB_ROOT_PASSWORD:
    #env_file:
    #  - stack.env
    volumes:
      - db:/data/db
      - db_conf:/data/configdb
    #  - /srv/docker/unifi/mongo-init.sh:/docker-entrypoint-initdb.d/init-mongo.sh:ro
    restart: unless-stopped

volumes:
  conf:
  db:
  db_conf:

networks:
  shared-lan:
    external: true

mongo-init.sh:

set -e

mongosh << EOF

db.getSiblingDB("${MONGO_DBNAME}").createUser(
  {
    user: "${MONGO_USER}",
    pwd: "${MONGO_PASS}",
    roles: [
      { role: "dbOwner", db: "${MONGO_DBNAME}" },
      { role: "dbOwner", db: "${MONGO_DBNAME}_stat" }
    ]
  }
);

db.getSiblingDB("${MONGO_DBNAME}_stat").createUser(
  {
    user: "${MONGO_USER}",
    pwd: "${MONGO_PASS}",
    roles: [{role: "dbOwner", db: "${MONGO_DBNAME}_stat"}]
  }
);

EOF
nickurak commented 3 months ago

So yeah, we'll have to modify our instructions. Thanks for the heads up.

First, thanks to everybody involved for pushing through the confusion and ambiguity and unknowns here, and thanks for all the work that's already gone into this packaging.

Second, in light of ^, should this issue be re-opened, or would it be better tracked in a different issue?

aptalca commented 3 months ago

104