[Breaking] Default to mongosh when connecting to MongoDB. (#8472) (#9754)

* Use `mongosh` client when available.

* Document `mongosh` as default client from 9.0 and `mongo` being the fallback.

Co-authored-by: Paul Gottschling <paul.gottschling@goteleport.com>
This commit is contained in:
Krzysztof Skrzętnicki
2022-01-21 15:04:23 +01:00
committed by GitHub
co-authored by Paul Gottschling
parent 28f101ae8f
commit f3364f77fd
6 changed files with 73 additions and 11 deletions
+1 -1
View File
@@ -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?
@@ -185,8 +185,12 @@ $ tsh db connect mongodb-atlas
```
<Admonition type="note" title="Note">
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`.
</Admonition>
<Admonition type="note" title="Note">
Teleport 9.0 added support for `mongosh` and made it the default Mongo DB client.
</Admonition>
To log out of the database and remove credentials:
@@ -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
```
<Admonition type="note" title="Note">
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`.
</Admonition>
<Admonition type="note" title="Note">
Teleport 9.0 added support for `mongosh` and made it the default Mongo DB client.
</Admonition>
To log out of the database and remove credentials:
+1 -1
View File
@@ -138,7 +138,7 @@ $ tsh db connect --db-user=alice --db-name=db example
```
<Admonition type="note" title="Note">
Respective database CLI clients (`psql`, `mysql` or `mongo`) should be
Respective database CLI clients (`psql`, `mysql`, `mongo` or `mongosh`) should be
available in PATH.
</Admonition>
+20 -1
View File
@@ -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 {
+38 -3
View File
@@ -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...)
}