From 07cab1caafc5e0f380fe08ba9c67a95ea24aba2c Mon Sep 17 00:00:00 2001 From: Alexey Palazhchenko Date: Wed, 22 Feb 2023 15:54:51 +0400 Subject: [PATCH] Add Tigris authentication support (#2040) Closes #1789. --- Taskfile.yml | 70 +++++++++------ cmd/ferretdb/main.go | 4 +- ferretdb/ferretdb.go | 13 +-- integration/shareddata_test.go | 2 +- internal/handlers/common/msg_saslstart.go | 67 --------------- internal/handlers/dummy/msg_saslstart.go | 13 ++- internal/handlers/pg/pg.go | 22 ++++- internal/handlers/registry/registry.go | 3 +- internal/handlers/registry/tigris.go | 9 +- internal/handlers/tigris/msg_saslstart.go | 65 +++++++++++++- internal/handlers/tigris/tigris.go | 100 +++++++++++++++------- website/docs/flags.md | 5 +- 12 files changed, 222 insertions(+), 151 deletions(-) delete mode 100644 internal/handlers/common/msg_saslstart.go diff --git a/Taskfile.yml b/Taskfile.yml index fdba815a5166..fd7fc407e48c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -48,7 +48,8 @@ tasks: run: once deps: [gen-version] cmds: - - go test -c -o=bin/ferretdb-testcover{{exeExt}} -trimpath {{.RACEFLAG}} -tags=ferretdb_testcover,{{.BUILDTAGS}} -coverpkg=./... ./cmd/ferretdb + # do not trim paths to make debugging with delve easier + - go test -c -o=bin/ferretdb-testcover{{exeExt}} -trimpath=false {{.RACEFLAG}} -tags=ferretdb_testcover,{{.BUILDTAGS}} -coverpkg=./... ./cmd/ferretdb init-tools: dir: tools @@ -177,9 +178,9 @@ tasks: go test -count=1 {{.RACEFLAG}} -tags={{.BUILDTAGS}} -shuffle=on -coverpkg=../... -coverprofile=integration-pg.txt . -target-backend=ferretdb-pg - {{.UNIXSOCKETFLAG}} - -postgresql-url=postgres://username@127.0.0.1:5432/ferretdb?pool_min_conns=1 - -compat-url=mongodb://127.0.0.1:47017/ + -target-tls + -postgresql-url=postgres://username@127.0.0.1:5432/ferretdb + -compat-url='mongodb://username:password@127.0.0.1:47018/?tls=true&tlsCertificateKeyFile=../build/certs/client.pem&tlsCaFile=../build/certs/rootCA-cert.pem' -records-dir=../records test-integration-tigris: @@ -190,9 +191,9 @@ tasks: go test -count=1 {{.RACEFLAG}} -tags={{.BUILDTAGS}} -shuffle=on -coverpkg=../... -coverprofile=integration-tigris.txt . -target-backend=ferretdb-tigris - -target-tls + {{.UNIXSOCKETFLAG}} -tigris-urls=127.0.0.1:8081,127.0.0.1:8091,127.0.0.1:8092,127.0.0.1:8093,127.0.0.1:8094 - -compat-url='mongodb://username:password@127.0.0.1:47018/?tls=true&tlsCertificateKeyFile=../build/certs/client.pem&tlsCaFile=../build/certs/rootCA-cert.pem' + -compat-url=mongodb://127.0.0.1:47017/ -records-dir=../records test-integration-mongodb: @@ -249,44 +250,64 @@ tasks: - go run {{.RACEFLAG}} ./cmd/fuzztool corpus {{.FUZZCORPUS}} generated run: - desc: "Run FerretDB" + desc: "Run FerretDB with `pg` handler" deps: [build-testcover] cmds: - > bin/ferretdb-testcover{{exeExt}} -test.coverprofile=cover.txt -- --listen-addr=:27017 + --proxy-addr=127.0.0.1:47017 --mode=diff-normal - --postgresql-url="postgres://username@127.0.0.1:5432/ferretdb" + --handler=pg + --postgresql-url=postgres://username@127.0.0.1:5432/ferretdb + --test-records-dir=records + + run-tigris: + desc: "Run FerretDB with `tigris` handler" + deps: [build-testcover] + cmds: + - > + bin/ferretdb-testcover{{exeExt}} -test.coverprofile=cover.txt -- + --listen-addr=:27017 --proxy-addr=127.0.0.1:47017 + --mode=diff-normal + --handler=tigris + --tigris-url=127.0.0.1:8081 --test-records-dir=records run-secured: - desc: "Run secured FerretDB with TLS and authentication" + desc: "Run FerretDB with `pg` handler (TLS, auth required)" deps: [build-testcover] cmds: - > bin/ferretdb-testcover{{exeExt}} -test.coverprofile=cover.txt -- --listen-addr='' + --listen-tls=:27018 --listen-tls-cert-file=./build/certs/server-cert.pem --listen-tls-key-file=./build/certs/server-key.pem --listen-tls-ca-file=./build/certs/rootCA-cert.pem - --listen-tls=:27018 - --mode=normal - --postgresql-url="postgres://127.0.0.1:5433/ferretdb" + --proxy-addr=127.0.0.1:47017 + --mode=diff-normal + --handler=pg + --postgresql-url=postgres://127.0.0.1:5433/ferretdb --test-records-dir=records - run-tigris: + # set FERRETDB_TIGRIS_CLIENT_ID and FERRETDB_TIGRIS_CLIENT_SECRET environment variables to use it + run-tigris-secured: + desc: "Run FerretDB with `tigris` handler (TLS, auth required; SaaS)" deps: [build-testcover] cmds: - > bin/ferretdb-testcover{{exeExt}} -test.coverprofile=cover.txt -- - --handler=tigris - --listen-addr=:27017 + --listen-addr='' + --listen-tls=:27018 --listen-tls-cert-file=./build/certs/server-cert.pem --listen-tls-key-file=./build/certs/server-key.pem - --listen-tls=:27018 - --mode=diff-normal + --listen-tls-ca-file=./build/certs/rootCA-cert.pem --proxy-addr=127.0.0.1:47017 + --mode=diff-normal + --handler=tigris + --tigris-url=api.preview.tigrisdata.cloud --test-records-dir=records run-proxy: @@ -296,12 +317,10 @@ tasks: - > bin/ferretdb-testcover{{exeExt}} -test.coverprofile=cover.txt -- --listen-addr=:27017 - --listen-tls-cert-file=./build/certs/server-cert.pem - --listen-tls-key-file=./build/certs/server-key.pem - --listen-tls=:27018 - --mode=diff-proxy - --postgresql-url="postgres://username@127.0.0.1:5432/ferretdb" --proxy-addr=127.0.0.1:47017 + --mode=diff-proxy + --handler=pg + --postgresql-url=postgres://username@127.0.0.1:5432/ferretdb --test-records-dir=records lint: @@ -355,17 +374,16 @@ tasks: cmds: - > docker compose exec mongodb mongosh - 'mongodb://host.docker.internal:27017/?heartbeatFrequencyMS=300000' --verbose --eval 'disableTelemetry()' --shell + 'mongodb://host.docker.internal:27017/?heartbeatFrequencyMS=300000' mongosh-secured: - desc: "Run MongoDB shell (`mongosh`) for secured FerretDB" + desc: "Run MongoDB shell (`mongosh`) with TLS and auth" cmds: - > docker compose exec mongodb mongosh - --tlsCertificateKeyFile=/etc/certs/client.pem --tlsCAFile=/etc/certs/rootCA-cert.pem - 'mongodb://username:password@host.docker.internal:27018/?authMechanism=PLAIN&tls=true&heartbeatFrequencyMS=300000' --verbose --eval 'disableTelemetry()' --shell + 'mongodb://username:password@host.docker.internal:27018/?authMechanism=PLAIN&tls=true&tlsCertificateKeyFile=/etc/certs/client.pem&tlsCaFile=/etc/certs/rootCA-cert.pem' mongo-test: desc: "Run legacy MongoDB shell (`mongo`) with test script" diff --git a/cmd/ferretdb/main.go b/cmd/ferretdb/main.go index b8778347546b..c8ba620234a7 100644 --- a/cmd/ferretdb/main.go +++ b/cmd/ferretdb/main.go @@ -97,7 +97,6 @@ var tigrisFlags struct { TigrisURL string `default:"127.0.0.1:8081" help:"Tigris URL for 'tigris' handler."` TigrisClientID string `default:"" help:"Tigris Client ID."` TigrisClientSecret string `default:"" help:"Tigris Client secret."` - TigrisToken string `default:"" help:"Tigris token."` } // The hanaFlags struct represents flags that are used specifically by "hana" handler. @@ -311,10 +310,9 @@ func run() { PostgreSQLURL: cli.PostgreSQLURL, + TigrisURL: tigrisFlags.TigrisURL, TigrisClientID: tigrisFlags.TigrisClientID, TigrisClientSecret: tigrisFlags.TigrisClientSecret, - TigrisToken: tigrisFlags.TigrisToken, - TigrisURL: tigrisFlags.TigrisURL, }) if err != nil { logger.Fatal(err.Error()) diff --git a/ferretdb/ferretdb.go b/ferretdb/ferretdb.go index bbbabca7dc42..e85fd08201e8 100644 --- a/ferretdb/ferretdb.go +++ b/ferretdb/ferretdb.go @@ -43,15 +43,17 @@ type Config struct { Handler string // PostgreSQL connection string for `pg` handler. + // See: + // * https://pkg.go.dev/github.com/jackc/pgx/v4/pgxpool#ParseConfig + // * https://pkg.go.dev/github.com/jackc/pgx/v4#ParseConfig + // * https://pkg.go.dev/github.com/jackc/pgconn#ParseConfig PostgreSQLURL string // For example: `postgres://hostname:5432/ferretdb`. // Tigris parameters for `tigris` handler. - // See https://docs.tigrisdata.com/overview/authentication - // and https://docs.tigrisdata.com/golang/getting-started. + // See https://www.tigrisdata.com/docs/sdkstools/golang/getting-started/ + TigrisURL string TigrisClientID string TigrisClientSecret string - TigrisToken string - TigrisURL string } // ListenerConfig represents listener configuration. @@ -107,10 +109,9 @@ func New(config *Config) (*FerretDB, error) { PostgreSQLURL: config.PostgreSQLURL, + TigrisURL: config.TigrisURL, TigrisClientID: config.TigrisClientID, TigrisClientSecret: config.TigrisClientSecret, - TigrisToken: config.TigrisToken, - TigrisURL: config.TigrisURL, }) if err != nil { return nil, fmt.Errorf("failed to construct handler: %s", err) diff --git a/integration/shareddata_test.go b/integration/shareddata_test.go index 9c065b05f0d4..3d0d69555892 100644 --- a/integration/shareddata_test.go +++ b/integration/shareddata_test.go @@ -18,7 +18,7 @@ // because all needed functionality is already available in setup helpers. // This file is skipped by default; we pass the build tag only in the `task env-data` command. -// go:build ferretdb_testenvdata +//go:build ferretdb_testenvdata package integration diff --git a/internal/handlers/common/msg_saslstart.go b/internal/handlers/common/msg_saslstart.go deleted file mode 100644 index 0ac9af71e0dc..000000000000 --- a/internal/handlers/common/msg_saslstart.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2021 FerretDB Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package common - -import ( - "context" - - "github.com/FerretDB/FerretDB/internal/types" - "github.com/FerretDB/FerretDB/internal/util/lazyerrors" - "github.com/FerretDB/FerretDB/internal/util/must" - "github.com/FerretDB/FerretDB/internal/wire" -) - -// MsgSASLStart is a common implementation of the SASLStart command. -func MsgSASLStart(_ context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { - doc, err := msg.Document() - if err != nil { - return nil, lazyerrors.Error(err) - } - - _, err = GetRequiredParam[string](doc, "$db") - if err != nil { - return nil, lazyerrors.Error(err) - } - - _, err = GetRequiredParam[int32](doc, "saslStart") - if err != nil { - return nil, lazyerrors.Error(err) - } - - _, err = GetRequiredParam[string](doc, "mechanism") - if err != nil { - return nil, lazyerrors.Error(err) - } - - _, err = GetRequiredParam[types.Binary](doc, "payload") - if err != nil { - return nil, lazyerrors.Error(err) - } - - _, err = GetOptionalParam(doc, "autoAuthorize", int32(0)) - if err != nil { - return nil, lazyerrors.Error(err) - } - - var reply wire.OpMsg - must.NoError(reply.SetSections(wire.OpMsgSection{ - Documents: []*types.Document{must.NotFail(types.NewDocument( - "done", true, - "ok", float64(1), - ))}, - })) - - return &reply, nil -} diff --git a/internal/handlers/dummy/msg_saslstart.go b/internal/handlers/dummy/msg_saslstart.go index 879df8a5b68b..887ee55d46f6 100644 --- a/internal/handlers/dummy/msg_saslstart.go +++ b/internal/handlers/dummy/msg_saslstart.go @@ -17,11 +17,20 @@ package dummy import ( "context" - "github.com/FerretDB/FerretDB/internal/handlers/common" + "github.com/FerretDB/FerretDB/internal/types" + "github.com/FerretDB/FerretDB/internal/util/must" "github.com/FerretDB/FerretDB/internal/wire" ) // MsgSASLStart implements HandlerInterface. func (h *Handler) MsgSASLStart(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { - return common.MsgSASLStart(ctx, msg) + var reply wire.OpMsg + must.NoError(reply.SetSections(wire.OpMsgSection{ + Documents: []*types.Document{must.NotFail(types.NewDocument( + "done", true, + "ok", float64(1), + ))}, + })) + + return &reply, nil } diff --git a/internal/handlers/pg/pg.go b/internal/handlers/pg/pg.go index 23562d56b923..f3d7f8420897 100644 --- a/internal/handlers/pg/pg.go +++ b/internal/handlers/pg/pg.go @@ -19,6 +19,7 @@ import ( "context" "net/url" "sync" + "time" "go.uber.org/zap" @@ -75,8 +76,8 @@ func (h *Handler) Close() { h.rw.Lock() defer h.rw.Unlock() - for k, pgPool := range h.pools { - pgPool.Close() + for k, p := range h.pools { + p.Close() delete(h.pools, k) } } @@ -98,18 +99,31 @@ func (h *Handler) DBPool(ctx context.Context) (*pgdb.Pool, error) { url := u.String() + // fast path + h.rw.RLock() - p, ok := h.pools[url] + p := h.pools[url] h.rw.RUnlock() - if ok { + if p != nil { h.L.Debug("DBPool: found existing pool", zap.String("username", username)) return p, nil } + // slow path + h.rw.Lock() defer h.rw.Unlock() + // a concurrent connection might have created a pool already; check again + if p = h.pools[url]; p != nil { + h.L.Debug("DBPool: found existing pool (after acquiring lock)", zap.String("username", username)) + return p, nil + } + + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + p, err := pgdb.NewPool(ctx, url, h.L, h.StateProvider) if err != nil { h.L.Warn("DBPool: authentication failed", zap.String("username", username), zap.Error(err)) diff --git a/internal/handlers/registry/registry.go b/internal/handlers/registry/registry.go index 27c7db15591b..112ebcbf2bcd 100644 --- a/internal/handlers/registry/registry.go +++ b/internal/handlers/registry/registry.go @@ -50,10 +50,9 @@ type NewHandlerOpts struct { PostgreSQLURL string // for `tigris` handler + TigrisURL string TigrisClientID string TigrisClientSecret string - TigrisToken string - TigrisURL string } // NewHandler constructs a new handler. diff --git a/internal/handlers/registry/tigris.go b/internal/handlers/registry/tigris.go index 0d1f7d1edf27..bde9ee2147a7 100644 --- a/internal/handlers/registry/tigris.go +++ b/internal/handlers/registry/tigris.go @@ -25,10 +25,11 @@ import ( func init() { registry["tigris"] = func(opts *NewHandlerOpts) (handlers.Interface, error) { handlerOpts := &tigris.NewOpts{ - ClientID: opts.TigrisClientID, - ClientSecret: opts.TigrisClientSecret, - Token: opts.TigrisToken, - URL: opts.TigrisURL, + AuthParams: tigris.AuthParams{ + URL: opts.TigrisURL, + ClientID: opts.TigrisClientID, + ClientSecret: opts.TigrisClientSecret, + }, L: opts.Logger, Metrics: opts.Metrics, diff --git a/internal/handlers/tigris/msg_saslstart.go b/internal/handlers/tigris/msg_saslstart.go index ec0b3056ef57..125327a3ce06 100644 --- a/internal/handlers/tigris/msg_saslstart.go +++ b/internal/handlers/tigris/msg_saslstart.go @@ -15,13 +15,76 @@ package tigris import ( + "bytes" "context" + "fmt" + "github.com/FerretDB/FerretDB/internal/clientconn/conninfo" "github.com/FerretDB/FerretDB/internal/handlers/common" + "github.com/FerretDB/FerretDB/internal/types" + "github.com/FerretDB/FerretDB/internal/util/lazyerrors" + "github.com/FerretDB/FerretDB/internal/util/must" "github.com/FerretDB/FerretDB/internal/wire" ) // MsgSASLStart implements the SASLStart command. func (h *Handler) MsgSASLStart(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) { - return common.MsgSASLStart(ctx, msg) + doc, err := msg.Document() + if err != nil { + return nil, lazyerrors.Error(err) + } + + mechanism, err := common.GetRequiredParam[string](doc, "mechanism") + if err != nil { + return nil, lazyerrors.Error(err) + } + + if mechanism != "PLAIN" { + return nil, common.NewCommandErrorMsgWithArgument( + common.ErrTypeMismatch, + "Unsupported mechanism '"+mechanism+"'", + "mechanism", + ) + } + + payload, err := common.GetRequiredParam[types.Binary](doc, "payload") + if err != nil { + return nil, lazyerrors.Error(err) + } + + parts := bytes.Split(payload.B, []byte{0}) + if l := len(parts); l != 3 { + return nil, common.NewCommandErrorMsgWithArgument( + common.ErrTypeMismatch, + fmt.Sprintf("Invalid payload (expected 3 parts, got %d)", l), + "payload", + ) + } + + authzid, authcid, passwd := parts[0], parts[1], parts[2] + + // Some drivers (Go) send empty authorization identity (authzid), + // while others (Java) set it to the same value as authentication identity (authcid) + // (see https://www.rfc-editor.org/rfc/rfc4616.html). + // Ignore authzid for now. + _ = authzid + + conninfo.Get(ctx).SetAuth(string(authcid), string(passwd)) + + if _, err = h.DBPool(ctx); err != nil { + return nil, lazyerrors.Error(err) + } + + var emptyPayload types.Binary + var reply wire.OpMsg + must.NoError(reply.SetSections(wire.OpMsgSection{ + Documents: []*types.Document{must.NotFail(types.NewDocument( + "conversationId", int32(1), + "done", true, + "payload", emptyPayload, + "ok", float64(1), + ))}, + })) + + return &reply, nil } diff --git a/internal/handlers/tigris/tigris.go b/internal/handlers/tigris/tigris.go index 98426d42ab26..42a07095d494 100644 --- a/internal/handlers/tigris/tigris.go +++ b/internal/handlers/tigris/tigris.go @@ -18,11 +18,12 @@ package tigris import ( "context" "sync" + "time" "github.com/tigrisdata/tigris-client-go/config" - "github.com/tigrisdata/tigris-client-go/driver" "go.uber.org/zap" + "github.com/FerretDB/FerretDB/internal/clientconn/conninfo" "github.com/FerretDB/FerretDB/internal/clientconn/connmetrics" "github.com/FerretDB/FerretDB/internal/handlers" "github.com/FerretDB/FerretDB/internal/handlers/tigris/tigrisdb" @@ -30,12 +31,20 @@ import ( "github.com/FerretDB/FerretDB/internal/util/state" ) +// Handler implements handlers.Interface on top of Tigris. +// +//nolint:vet // for readability +type Handler struct { + *NewOpts + + // accessed by DBPool(ctx) + rw sync.RWMutex + pools map[AuthParams]*tigrisdb.TigrisDB +} + // NewOpts represents handler configuration. type NewOpts struct { - ClientID string - ClientSecret string - Token string - URL string + AuthParams L *zap.Logger Metrics *connmetrics.ConnMetrics @@ -43,15 +52,11 @@ type NewOpts struct { DisablePushdown bool } -// Handler implements handlers.Interface on top of Tigris. -type Handler struct { - *NewOpts - - // accessed by DB(ctx) - // TODO replace with map - // https://github.com/FerretDB/FerretDB/issues/1789 - rw sync.RWMutex - db *tigrisdb.TigrisDB +// AuthParams represents authentication parameters. +type AuthParams struct { + URL string + ClientID string + ClientSecret string } // New returns a new handler. @@ -62,46 +67,77 @@ func New(opts *NewOpts) (handlers.Interface, error) { return &Handler{ NewOpts: opts, + pools: make(map[AuthParams]*tigrisdb.TigrisDB, 1), }, nil } +// Close implements HandlerInterface. +func (h *Handler) Close() { + h.rw.Lock() + defer h.rw.Unlock() + + for k, p := range h.pools { + p.Driver.Close() + delete(h.pools, k) + } +} + // DBPool returns database connection pool for the given client connection. // // Pool is not closed when ctx is canceled. -// -// TODO https://github.com/FerretDB/FerretDB/issues/1789 func (h *Handler) DBPool(ctx context.Context) (*tigrisdb.TigrisDB, error) { + connInfo := conninfo.Get(ctx) + username, password := connInfo.Auth() + + // do not log client secret + + // replace authentication info only if it is present in the connection + ap := h.AuthParams + if username != "" && password != "" { + ap.ClientID = username + ap.ClientSecret = password + } + + // fast path + h.rw.RLock() - db := h.db + p := h.pools[ap] h.rw.RUnlock() - if db != nil { - return db, nil + if p != nil { + h.L.Debug("DBPool: found existing pool", zap.String("username", username)) + return p, nil } + // slow path + h.rw.Lock() defer h.rw.Unlock() + // a concurrent connection might have created a pool already; check again + if p = h.pools[ap]; p != nil { + h.L.Debug("DBPool: found existing pool (after acquiring lock)", zap.String("username", username)) + return p, nil + } + + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + cfg := &config.Driver{ - ClientID: h.ClientID, - ClientSecret: h.ClientSecret, - Token: h.Token, - URL: h.URL, - Protocol: driver.GRPC, + URL: ap.URL, + ClientID: ap.ClientID, + ClientSecret: ap.ClientSecret, } - db, err := tigrisdb.New(ctx, cfg, h.L) + p, err := tigrisdb.New(ctx, cfg, h.L) if err != nil { + h.L.Warn("DBPool: authentication failed", zap.String("username", username), zap.Error(err)) return nil, lazyerrors.Error(err) } - h.db = db - - return h.db, nil -} + h.L.Info("DBPool: authentication succeed", zap.String("username", username)) + h.pools[ap] = p -// Close implements handlers.Interface. -func (h *Handler) Close() { - h.db.Driver.Close() + return p, nil } // check interfaces diff --git a/website/docs/flags.md b/website/docs/flags.md index d30345a690d2..2877085f31c1 100644 --- a/website/docs/flags.md +++ b/website/docs/flags.md @@ -29,8 +29,7 @@ Some default values are overridden in [our Docker image](quickstart_guide/docker | `postgresql-url` | PostgreSQL URL for `pg` handler | `FERRETDB_POSTGRESQL_URL` | `postgres://127.0.0.1:5432/ferretdb` | | `tigris-url` | Tigris URL for 'tigris' handler | `FERRETDB_TIGRIS_URL` | `127.0.0.1:8081` | | `tigris-client-id` | [Tigris Client ID][tigris-docs-auth] | `FERRETDB_TIGRIS_CLIENT_ID` | | -| `tigris-client-secret` | [Tigris Client secret][tigris-docs-auth] | `ferretdb_tigris_client_secret` | | -| `tigris-token` | [Tigris token][tigris-docs-auth] | `FERRETDB_TIGRIS_TOKEN` | | +| `tigris-client-secret` | [Tigris Client secret][tigris-docs-auth] | `FERRETDB_TIGRIS_CLIENT_SECRET` | | | **TLS** | | | | | `listen-tls` | See [Securing connections with TLS][securing-with-tls] | `FERRETDB_LISTEN_TLS` | | | `listen-tls-cert-file` | See [Securing connections with TLS][securing-with-tls] | `FERRETDB_LISTEN_TLS_CERT_FILE` | | @@ -42,5 +41,5 @@ Some default values are overridden in [our Docker image](quickstart_guide/docker | **Telemetry** | | | | | `telemetry` | See [Configure telemetry](telemetry.md#configure-telemetry) | `FERRETDB_TELEMETRY` | `undecided` | -[tigris-docs-auth]: https://docs.tigrisdata.com/apidocs/#tag/Authentication/operation/Auth_GetAccessToken +[tigris-docs-auth]: https://www.tigrisdata.com/docs/sdkstools/golang/getting-started/ [securing-with-tls]: /security#securing-connections-with-tls