diff --git a/docs/pages/database-access/faq.mdx b/docs/pages/database-access/faq.mdx index 728d95dd5ac..43542fe2a40 100644 --- a/docs/pages/database-access/faq.mdx +++ b/docs/pages/database-access/faq.mdx @@ -43,7 +43,7 @@ Teleport relies on client certificates for authentication so any database client that supports this method of authentication and uses modern TLS (1.2+) should work. -Standard command-line clients such as `psql`, `mysql`, or `mongo` are supported, +Standard command-line clients such as `psql`, `mysql`, `mongo` or `mongosh` are supported, there are also instructions for configuring select [graphical clients](./guides/gui-clients.mdx). ## When will you support X database? diff --git a/docs/pages/database-access/guides/mongodb-atlas.mdx b/docs/pages/database-access/guides/mongodb-atlas.mdx index 6741f4548ba..abc31a40228 100644 --- a/docs/pages/database-access/guides/mongodb-atlas.mdx +++ b/docs/pages/database-access/guides/mongodb-atlas.mdx @@ -185,8 +185,12 @@ $ tsh db connect mongodb-atlas ``` - The `mongo` command-line client should be available in PATH in order to be - able to connect. + Either the `mongosh` or `mongo` command-line clients should be available in PATH in order to be + able to connect. The Database Service attempts to run `mongosh` first and, if `mongosh` is not in PATH, runs `mongo`. + + + + Teleport 9.0 added support for `mongosh` and made it the default Mongo DB client. To log out of the database and remove credentials: diff --git a/docs/pages/database-access/guides/mongodb-self-hosted.mdx b/docs/pages/database-access/guides/mongodb-self-hosted.mdx index cf7f5e00f33..8e0aa413cf6 100644 --- a/docs/pages/database-access/guides/mongodb-self-hosted.mdx +++ b/docs/pages/database-access/guides/mongodb-self-hosted.mdx @@ -89,7 +89,7 @@ MongoDB treats the entire `Subject` line of the client certificate as a username When connecting to a MongoDB server, say as a user `alice`, Teleport will sign an ephemeral certificate with `CN=alice` subject. -To create this user in the database, connect to it using `mongo` shell and run +To create this user in the database, connect to it using the `mongosh` or `mongo` shell and run the following command: ```js @@ -225,8 +225,12 @@ $ tsh db connect example-mongo ``` - The `mongo` command-line client should be available in PATH in order to be - able to connect. + Either the `mongosh` or `mongo` command-line clients should be available in PATH in order to be + able to connect. The Database Service attempts to run `mongosh` first and, if `mongosh` is not in PATH, runs `mongo`. + + + + Teleport 9.0 added support for `mongosh` and made it the default Mongo DB client. To log out of the database and remove credentials: diff --git a/docs/pages/database-access/reference/cli.mdx b/docs/pages/database-access/reference/cli.mdx index 54d2768930f..dc77a23ce37 100644 --- a/docs/pages/database-access/reference/cli.mdx +++ b/docs/pages/database-access/reference/cli.mdx @@ -138,7 +138,7 @@ $ tsh db connect --db-user=alice --db-name=db example ``` - Respective database CLI clients (`psql`, `mysql` or `mongo`) should be + Respective database CLI clients (`psql`, `mysql`, `mongo` or `mongosh`) should be available in PATH. diff --git a/tool/tsh/db_test.go b/tool/tsh/db_test.go index 70ae4c6c013..b88ebf65d49 100644 --- a/tool/tsh/db_test.go +++ b/tool/tsh/db_test.go @@ -474,8 +474,11 @@ func TestCliCommandBuilderGetConnectCommand(t *testing.T) { wantErr: true, }, { - name: "mongodb", + name: "mongodb (legacy)", dbProtocol: defaults.ProtocolMongoDB, + execer: &fakeExec{ + execOutput: map[string][]byte{}, + }, cmd: []string{"mongo", "--host", "localhost", "--port", "12345", @@ -484,6 +487,22 @@ func TestCliCommandBuilderGetConnectCommand(t *testing.T) { "mydb"}, wantErr: false, }, + { + name: "mongosh", + dbProtocol: defaults.ProtocolMongoDB, + execer: &fakeExec{ + execOutput: map[string][]byte{ + "mongosh": []byte("1.1.6"), + }, + }, + cmd: []string{"mongosh", + "--host", "localhost", + "--port", "12345", + "--tls", + "--tlsCertificateKeyFile", "/tmp/keys/example.com/bob-db/db.example.com/mysql-x509.pem", + "mydb"}, + wantErr: false, + }, } for _, tt := range tests { diff --git a/tool/tsh/dbcmd.go b/tool/tsh/dbcmd.go index 440cd0ae3ed..ab6ec7d966d 100644 --- a/tool/tsh/dbcmd.go +++ b/tool/tsh/dbcmd.go @@ -42,6 +42,8 @@ const ( mysqlBin = "mysql" // mariadbBin is the MariaDB client binary name. mariadbBin = "mariadb" + // mongoshBin is the Mongo Shell client binary name. + mongoshBin = "mongosh" // mongoBin is the Mongo client binary name. mongoBin = "mongo" ) @@ -240,6 +242,12 @@ func (c *cliCommandBuilder) isMySQLBinAvailable() bool { return err == nil } +// isMongoshBinAvailable returns true if "mongosh" binary is found in the system PATH. +func (c *cliCommandBuilder) isMongoshBinAvailable() bool { + _, err := c.exe.LookPath(mongoshBin) + return err == nil +} + // isMySQLBinMariaDBFlavor checks if mysql binary comes from Oracle or MariaDB. // true is returned when binary comes from MariaDB, false when from Oracle. func (c *cliCommandBuilder) isMySQLBinMariaDBFlavor() (bool, error) { @@ -260,20 +268,47 @@ func (c *cliCommandBuilder) isMySQLBinMariaDBFlavor() (bool, error) { } func (c *cliCommandBuilder) getMongoCommand() *exec.Cmd { + // look for `mongosh` + hasMongosh := c.isMongoshBinAvailable() + + // Starting with Mongo 4.2 there is an updated set of flags. + // We are using them with `mongosh` as otherwise warnings will get displayed. + type tlsFlags struct { + tls string + tlsCertKeyFile string + tlsCAFile string + } + + var flags tlsFlags + + if hasMongosh { + flags = tlsFlags{tls: "--tls", tlsCertKeyFile: "--tlsCertificateKeyFile", tlsCAFile: "--tlsCAFile"} + } else { + flags = tlsFlags{tls: "--ssl", tlsCertKeyFile: "--sslPEMKeyFile", tlsCAFile: "--sslCAFile"} + } + args := []string{ "--host", c.host, "--port", strconv.Itoa(c.port), - "--ssl", - "--sslPEMKeyFile", c.profile.DatabaseCertPathForCluster(c.tc.SiteName, c.db.ServiceName), + flags.tls, + flags.tlsCertKeyFile, c.profile.DatabaseCertPathForCluster(c.tc.SiteName, c.db.ServiceName), } if c.options.caPath != "" { // caPath is set only if mongo connects to the Teleport Proxy via ALPN SNI Local Proxy // and connection is terminated by proxy identity certificate. - args = append(args, []string{"--sslCAFile", c.options.caPath}...) + args = append(args, []string{flags.tlsCAFile, c.options.caPath}...) } + if c.db.Database != "" { args = append(args, c.db.Database) } + + // use `mongosh` if available + if hasMongosh { + return exec.Command(mongoshBin, args...) + } + + // fall back to `mongo` if `mongosh` isn't found return exec.Command(mongoBin, args...) }