[ZBXNEXT-9490] Zabbix-Agent2 MongoDB Plugin error when using SCRAM-SHA-256 authentication while requiring TLS Created: 2023 Nov 14  Updated: 2025 Feb 20

Status: Confirmed
Project: ZABBIX FEATURE REQUESTS
Component/s: Agent2 plugin (G)
Affects Version/s: 6.0.34rc1, 7.0.4rc1, 7.2.0alpha1
Fix Version/s: None

Type: New Feature Request Priority: Major
Reporter: Patrick Voland Assignee: Stanislavs Jurgensons
Resolution: Unresolved Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Kubernetes Cluster


Attachments: File mongodburi.go     File patch_mongodb_plugin.diff    
Issue Links:
Duplicate
duplicates ZBXNEXT-9791 MongoDB Plugin and replicaSet with TL... Spec. sign-off

 Description   

Steps to reproduce:

Dear Zabbix support, we are facing the following situation :

  • we have a MongoDB replica-set configured with TLS but the authentication mechanism is SCRAM-SHA-256
  • we want to monitor the MongoDB nodes using the zabbix-agent2 MongoDB plugin
  • the plugin is not taking the URI parameters in account when setting up the SSL context
  • when configuring the plugin with the following configuration file :
    ================================================== 
    Plugins.MongoDB.System.Path=/usr/sbin/zabbix-agent2-plugin/zabbix-agent2-plugin-mongodb
    Plugins.MongoDB.Sessions.mongodbI.Uri=tcp://REDACTED:27017/admin?authMechanism=SCRAM-SHA-256&authSource=admin&appName=zabbix-agent2
    Plugins.MongoDB.Sessions.mongodbI.TLSConnect=verif y_full
    Plugins.MongoDB.Sessions.mongodbI.TLSCAFile=/var/lib/tls/ca.pem
    ================================================== 
    

    we get the following error :

    -----------------------------------------------------------------------------------------
    failed to execute direct exporter task for key 'mongodb.ping["REDACTED","zabbix_mon","REDACTED"]'
    error: 'Invalid configuration: missing TLS certificate file uri tcp://REDACTED:27017/admin?authMechanism=SCRAM-SHA-256&authSource=admin&appName=zabbix-agent2, with session REDACTED
    -----------------------------------------------------------------------------------------
    

     

After digging deeper into the MongoDB plugin's code, it appears that it is using the standard Zabbix URI library instead of parsing the connection-string to handle the MongoDB options passed in the connection-string (c.f. https://www.mongodb.com/docs/manual/...ection-options)

Attached is an example enhanced copy of your original /git.zabbix.com/ap/plugin-support/uri/uri.go that would handle all URI parameters required for MongoDB monitoring. Then the plugin logic should be adapted to give precedence to those options, then look at the macro params and finally use the values from the config.

Regarding the scheme, this change would be needed in mongodb/plugin/metrics.go for handling the standard schemes mongodb:// and mongodb+srv:// supported by go.mongodb.org/mongo-driver :

================================================== 
diff --git a/plugin/metrics.go b/plugin/metrics.go
index 9da777b..6d31191 100644
--- a/plugin/metrics.go
+++ b/plugin/metrics.go
@@ -71,7 +71,7 @@ const (
var (
paramURI = metric.NewConnParam("URI", "URI to connect or session name.").
WithDefault(handlers.UriDefaults.Scheme + "://localhost:" + handlers.UriDefaults.Port).WithSession().
- WithValidator(uri.URIValidator\{Defaults: handlers.UriDefaults, AllowedSchemes: []string{"tcp"}})
+ WithValidator(uri.URIValidator\{Defaults: handlers.UriDefaults, AllowedSchemes: []string{"tcp", "mongodb", "mongodb+srv"}})
paramUser = metric.NewConnParam("User", "MongoDB user.")
paramPassword = metric.NewConnParam("Password", "User's password.")
paramDatabase = metric.NewParam("Database", "Database name.").WithDefault("admin")​
================================================== 


 Comments   
Comment by Patrick Voland [ 2023 Nov 22 ]

Hi, Thanks for picking this and Do you have any timeline when there will be fix for this bug or anything planned?

Comment by Patrick Voland [ 2023 Dec 24 ]

Dear Zabbix support,

we could fix the situation by compiling our own version of the MongoDB plugin for Zabbix-Agent2. Attached is our patch (patch_mongodb_plugin.diff) that was tested with the 6.0 and the 6.4 release-branches.

In order to not break the current behavior, the implementation only differs when the scheme is "mongodb://" or "mongodb+srv://". For "tcp://" the logic remains unchanged.

The only thing that we could not figure out is why the validation of the connection-string fails with

(username|password) required for SCRAM-SHA-256

even when credentials are defined in the macros. The workaround is simply to provide a fake "user:pass" in the connection-string, those are overridden by the "${MONGODB.USER}" macro when it is defined and non-empty.

We definitely hope to see this being integrated in a future release, don't hesitate to contact us if you need more information.

Best regards

Comment by Suraj [ 2024 Sep 12 ]

Hi [email protected] 

 

I made the changes to all files mentioned in your git.diff and now plugin accepts the mongodb:// connection string but still I am getting authentication error when connection is happening it is still using SHA-1 

can you please help me around this if possible... what am I doing wrong...

 

 

 

 
 error reason for "mongodb-prod-1:mongodb.connections.available" changed: Failed to create new connection: connection() error occured during connection handshake:
auth error: sasl conversation error: unable to authenticate using mechanism "SCRAM-SHA-1": (AuthenticationFailed) Authentication failed.
 
 
 [MongoDB] Failed to create new connection: connection() error occured during connection handshake: auth error: sasl conversation error: unable to authenticate using mechanism "SCRAM-SHA-1": (AuthenticationFailed) Authentication failed.
 
 
 
*****conn.go****
// create_mongodb creates a new connection 'mongodb://' or 'mongodb+srv://' using the given URI and credentials.
func (c *ConnManager) create_mongodb(ck connKey, params map[string]string) (*MongoConn, error)

{     Impl.Infof("Creating new MongoDB connection: %s", ck.rawUri)     ctx, cancel := context.WithTimeout(context.Background(), c.timeout)     defer cancel()     // Create the Options object     opts := options.Client()     // Use the same defaults as the normal behavior     /*        opts.SetHosts([]string\{ck.uri.Addr()}

)
    */
    opts.SetConnectTimeout(c.timeout)
    opts.SetDirect(true)
    opts.SetMaxPoolSize(1)
    opts.SetServerSelectionTimeout(c.timeout)

    if ck.uri.User() != "" {
        Impl.Infof("Setting credentials for user [%s]", ck.uri.User())
        creds := options.Credential

{             Username:    ck.uri.User(),             Password:    ck.uri.Password(),             PasswordSet: true,         }

        // Let the driver set all options from the connection-string and set the credentials
        opts.ApplyURI(ck.rawUri).SetAuth(creds)
    } else

{         // Let the driver set all options from the connection-string         opts.ApplyURI(ck.rawUri)     }

    // The rest remains unmodified
    client, err := mongo.Connect(ctx, opts)
    if err != nil

{         return nil, err     }

    session, err := client.StartSession()
    if err != nil {         return nil, err     }

    err = session.Client().Ping(ctx, readpref.Nearest())
    if err != nil

{         return nil, err     }

    c.connMutex.Lock()
    defer c.connMutex.Unlock()

    c.connections[ck] = &MongoConn{         addr:           ck.uri.Addr(),         timeout:        c.timeout,         lastTimeAccess: time.Now(),         session:        session,     }

    Impl.Debugf("Created new connection: %s", ck.uri.Addr())

    return c.connections[ck], nil
}

// create creates a new 'tcp://' connection with given credentials.
func (c *ConnManager) create_tcp(ck connKey, params map[string]string) (*MongoConn, error) {
    Impl.Infof("Creating new TCP connection: %s", ck.rawUri)
    opt, err := c.createOptions(ck.uri, params)
    ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
    defer cancel()
    if err != nil {         return nil, err     }

    client, err := mongo.NewClient(opt)
    if err != nil

{         return nil, err     }

    err = client.Connect(context.Background())
    if err != nil {         return nil, err     }

    session, err := client.StartSession()
    if err != nil

{         return nil, err     }
    err = session.Client().Ping(ctx, readpref.Nearest())
    if err != nil {         return nil, err     }

    c.connMutex.Lock()
    defer c.connMutex.Unlock()

    c.connections[ck] = &MongoConn

{         addr:           ck.uri.Addr(),         timeout:        c.timeout,         lastTimeAccess: time.Now(),         session:        session,     }

    Impl.Debugf("Created new connection: %s", ck.uri.Addr())

    return c.connections[ck], nil
}
 
 
 

Comment by Patrick Voland [ 2024 Sep 17 ]

Hi suraj, my guess is that the "SCRAM-SHA-1" auth-mechanism is deprecated in modern MongoDB server installations. You should be able to get it working by switching to "SCRAM-SHA-256". Here is our relevant MongoDB configuration section :

security:
  authorization: enabled
  keyFile: /path/to/keyfile
setParameter:
  authenticationMechanisms: SCRAM-SHA-256

Hope this helps, if that doesn't work I can look further into it.

Best regards !

Comment by Suraj [ 2024 Sep 18 ]

Hi [email protected] ,

actually I am using SHA-256 only but the logs of agent even after altering source code were showing SHA-1 but for that I have hardcoded it in conn.go as below

 
if ck.uri.User() != "" {
        Impl.Infof("Setting credentials for user [%s]", ck.uri.User())
        Impl.Infof("Setting credentials for password [%s]", ck.uri.Password())
        creds := options.Credential{
            Username:    ck.uri.User(),
            Password:    ck.uri.Password(),
            PasswordSet: true,
            // AuthMechanism: ck.uri.AuthMechanism(),
            AuthMechanism: "SCRAM-SHA-256",
            // Database: ck.uri.Database(),
        }
 
but still I am not able to get through getting below error
 
 [MongoDB] Failed to create new connection: connection() error occured during connection handshake: auth error: sasl conversation error: unable to authenticate using mechanism "SCRAM-SHA-256": (AuthenticationFailed) Authentication failed.
 
 
my connection string is FYR...
mongodb://user:pass@ x.x.x.x:27010/dbname?replicaSet=rs1&authSource=dbname

but the plugin is still attempting to connect to admin database 
 

Comment by Patrick Voland [ 2024 Sep 18 ]

I see, here is our Zabbix Macro `{$MONGODB.CONNSTRING}` :

mongodb://foo:bar@<MONGODB_SVC_FQDN>:27017/?directConnection=true&tls=true&tlsCAFile=%2Fpath%2Fto%2Fmongodb_ca.pem&authMechanism=SCRAM-SHA-256&authSource=admin&appName=zabbix-agent2

Note that :

  • `foo:bar` can be anything, without it the native driver fails to authenticate
  • the actual credentials are stored in Zabbix under the `{$MONGODB.USER}` and `{$MONGODB.PASSWORD}` host macros
  • `%2Fpath%2Fto%2Fmongodb_ca.pem` is the URL-encoded version of the path to the TLS CA file (`/path/to/mongodb_ca.pem`) used for this MongoDB cluster PKI
  • we don't specify a specific DB since we monitor the whole cluster-node metrics, but we do specify `authSource=admin` in the URI
  • we have Zabbix-Server v6.0.33 and zabbix-agent2 v6.4.10

I hope this helps diagnosing your issue.

Best regards and keep us posted !

Comment by Suraj [ 2024 Sep 19 ]

Hi [email protected] ,

 

my use case is to monitor nodes of a self managed mongodb instance running as replicaset.
we do not have TLS in place using plain connection and database is enabled with key authorization.

I want to monitor all the database and now the plugin is able to connect to the database but it is closing the connection by itself any idea around this???

 

 

my new connstring is : mongodb://user:foo@ x.x.x.x:27010/?replicaSet=rs1&directConnection=true&authMechanism=SCRAM-SHA-256&authSource=admin

my user is in admin database and have read only permission all over the replicaset.

Do I need to create a admin user or is there any other issue you notice......

 

below are the agent2 logs for reference

 

 User: ReadOnlyUser
2024/09/19 07:50:00.914740 [MongoDB] Setting credentials for password [6Qf26tC08XYGRGUzM83LzMCJvw]
2024/09/19 07:50:00.914743 [MongoDB] Password: 
2024/09/19 07:50:00.914747 [MongoDB] Setting credentials for user [ReadOnlyUser]
2024/09/19 07:50:00.914769 [MongoDB] Creating new MongoDB connection with URI: mongodb://user:foo@ x.x.x.x:27010/?replicaSet=rs1&directConnection=true&authMechanism=SCRAM-SHA-256&authSource=admin
2024/09/19 07:50:00.919415 [MongoDB] Created new connection: x.x.x.x:27010
2024/09/19 07:50:00.919649 [MongoDB] plugin MongoDB export request completed
2024/09/19 07:50:00.919673 [MongoDB] ping failed, client is disconnected
2024/09/19 07:50:00.919679 [MongoDB] failed to ping database  x.x.x.x:27010, client is disconnected
2024/09/19 07:50:00.919685 [MongoDB] executing ping for address:  x.x.x.x:27010
2024/09/19 07:50:00.919690 [MongoDB] Closed unused connection:  x.x.x.x:27010

 

 

mongo logs below

 

{"t":

{"$date":"2024-09-18T10:03:00.917+00:00"}

,"s":"I",  "c":"NETWORK",  "id":51800,   "ctx":"conn2971436","msg":"client metadata","attr":{"remote":" x.x.x.x:52478","client":"conn2971436","negotiatedCompressors":[],"doc":{"driver":

{"name":"mongo-go-driver","version":"v1.7.6"}

,"os":{"type":"linux","architecture":"amd64"},"platform":"go1.19"}}}

{"t":

{"$date":"2024-09-18T10:03:00.917+00:00"}

,"s":"I",  "c":"ACCESS",   "id":6788604, "ctx":"conn2971436","msg":"Auth metrics report","attr":{"metric":"acquireUser","micros":0}}

{"t":

{"$date":"2024-09-18T10:03:00.923+00:00"}

,"s":"I",  "c":"ACCESS",   "id":5286306, "ctx":"conn2971436","msg":"Successfully authenticated","attr":{"client":" x.x.x.x:52478","isSpeculative":true,"isClusterMember":false,"mechanism":"SCRAM-SHA-256","user":"ReadOnlyUser","db":"admin","result":0,"metrics":{"conversation_duration":{"micros":5973,"summary":{"0":

{"step":1,"step_total":2,"duration_micros":38}

,"1":{"step":2,"step_total":2,"duration_micros":18}}}},"extraInfo":{}}}

{"t":

{"$date":"2024-09-18T10:03:00.923+00:00"}

,"s":"I",  "c":"NETWORK",  "id":6788700, "ctx":"conn2971436","msg":"Received first command on ingress connection since session start or auth handshake","attr":{"elapsedMillis":0}}

{"t":

{"$date":"2024-09-18T10:03:00.924+00:00"}

,"s":"I",  "c":"-",        "id":20883,   "ctx":"conn2971435","msg":"Interrupted operation as its client disconnected","attr":{"opId":1066353083}}

{"t":

{"$date":"2024-09-18T10:03:00.924+00:00"}

,"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn2971436","msg":"Connection ended","attr":{"remote":" x.x.x.x:52478","uuid":{"uuid":{"$uuid":"a11dbec7-97b9-417f-9a7b-1ebb7194d803"}},"connectionId":2971436,"connectionCount":1872}}

{"t":

{"$date":"2024-09-18T10:03:00.924+00:00"}

,"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn2971434","msg":"Connection ended","attr":{"remote":" x.x.x.x:52462","uuid":{"uuid":{"$uuid":"22ed6c93-f363-4cf5-a87e-93b6474e6c3b"}},"connectionId":2971434,"connectionCount":1871}}

{"t":

{"$date":"2024-09-18T10:03:00.924+00:00"}

,"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn2971435","msg":"Connection ended","attr":{"remote":" x.x.x.x:52474","uuid":{"uuid":{"$uuid":"839173ea-f420-497c-b0f0-39240cf98421"}},"connectionId":2971435,"connectionCount":1870}}

Generated at Wed Apr 30 06:25:54 EEST 2025 using Jira 9.12.4#9120004-sha1:625303b708afdb767e17cb2838290c41888e9ff0.