diff --git a/go.mod b/go.mod index 9165128..56115cc 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/shirou/gopsutil/v3 v3.24.5 github.com/stretchr/testify v1.9.0 github.com/umputun/go-flags v1.5.1 - go.mongodb.org/mongo-driver v1.16.1 + go.mongodb.org/mongo-driver v1.17.1 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index bfd35d5..9b5e5cf 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8= -go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= +go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM= +go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go index bb52a0e..f0702d9 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go @@ -305,7 +305,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) { } // remove hyphens - uuidNoHyphens := strings.Replace(uuid, "-", "", -1) + uuidNoHyphens := strings.ReplaceAll(uuid, "-", "") if len(uuidNoHyphens) != 32 { return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens") } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go index bb93031..57781ff 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go @@ -628,13 +628,14 @@ func (ejvw *extJSONValueWriter) WriteArrayEnd() error { func formatDouble(f float64) string { var s string - if math.IsInf(f, 1) { + switch { + case math.IsInf(f, 1): s = "Infinity" - } else if math.IsInf(f, -1) { + case math.IsInf(f, -1): s = "-Infinity" - } else if math.IsNaN(f) { + case math.IsNaN(f): s = "NaN" - } else { + default: // Print exactly one decimalType place for integers; otherwise, print as many are necessary to // perfectly represent it. s = strconv.FormatFloat(f, 'G', -1, 64) @@ -739,9 +740,7 @@ func (ss sortableString) Less(i, j int) bool { } func (ss sortableString) Swap(i, j int) { - oldI := ss[i] - ss[i] = ss[j] - ss[j] = oldI + ss[i], ss[j] = ss[j], ss[i] } func sortStringAlphebeticAscending(s string) string { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go index 43f3e4f..9782891 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go @@ -82,12 +82,13 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) { return js.scanString() default: // check if it's a number - if c == '-' || isDigit(c) { + switch { + case c == '-' || isDigit(c): return js.scanNumber(c) - } else if c == 't' || c == 'f' || c == 'n' { + case c == 't' || c == 'f' || c == 'n': // maybe a literal return js.scanLiteral(c) - } else { + default: return nil, fmt.Errorf("invalid JSON input. Position: %d. Character: %c", js.pos-1, c) } } @@ -174,7 +175,7 @@ func getu4(s []byte) rune { for _, c := range s[:4] { switch { case '0' <= c && c <= '9': - c = c - '0' + c -= '0' case 'a' <= c && c <= 'f': c = c - 'a' + 10 case 'A' <= c && c <= 'F': @@ -325,13 +326,14 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) { c5, err := js.readNextByte() - if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { + switch { + case bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)): js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttBool, v: true, p: p}, nil - } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { + case bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)): js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttNull, v: nil, p: p}, nil - } else if bytes.Equal([]byte("fals"), lit) { + case bytes.Equal([]byte("fals"), lit): if c5 == 'e' { c5, err = js.readNextByte() @@ -430,12 +432,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || errors.Is(err, io.EOF) { + switch { + case isWhiteSpace(c) || errors.Is(err, io.EOF): s = nssDone - } else if isDigit(c) { + case isDigit(c): s = nssSawIntegerDigits b.WriteByte(c) - } else { + default: s = nssInvalid } } @@ -455,12 +458,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || errors.Is(err, io.EOF) { + switch { + case isWhiteSpace(c) || errors.Is(err, io.EOF): s = nssDone - } else if isDigit(c) { + case isDigit(c): s = nssSawFractionDigits b.WriteByte(c) - } else { + default: s = nssInvalid } } @@ -490,12 +494,13 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || errors.Is(err, io.EOF) { + switch { + case isWhiteSpace(c) || errors.Is(err, io.EOF): s = nssDone - } else if isDigit(c) { + case isDigit(c): s = nssSawExponentDigits b.WriteByte(c) - } else { + default: s = nssInvalid } } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go index 311518a..501c6d7 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go @@ -598,7 +598,7 @@ func (vw *valueWriter) writeLength() error { return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))} } frame := &vw.stack[vw.frame] - length = length - int(frame.start) + length -= int(frame.start) start := frame.start _ = vw.buf[start+3] // BCE diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go index af60984..fb075b4 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/doc.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go @@ -107,10 +107,13 @@ // The name may be empty in order to specify options without overriding the default field name. The following options can // be used to configure behavior: // -// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if -// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, -// slice, map, or string. -// NOTE: It is recommended that this tag be used for all slice and map fields. +// 1. omitempty: If the "omitempty" struct tag is specified on a field, the field will not be marshaled if it is set to +// an "empty" value. Numbers, booleans, and strings are considered empty if their value is equal to the zero value for +// the type (i.e. 0 for numbers, false for booleans, and "" for strings). Slices, maps, and arrays are considered +// empty if they are of length zero. Interfaces and pointers are considered empty if their value is nil. By default, +// structs are only considered empty if the struct type implements [bsoncodec.Zeroer] and the IsZero +// method returns true. Struct types that do not implement [bsoncodec.Zeroer] are never considered empty and will be +// marshaled as embedded documents. NOTE: It is recommended that this tag be used for all slice and map fields. // // 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of // the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go index 08c3951..db8be74 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go @@ -70,7 +70,6 @@ func (d Decimal128) String() string { // Bits: 1*sign 2*ignored 14*exponent 111*significand. // Implicit 0b100 prefix in significand. exp = int(d.h >> 47 & (1<<14 - 1)) - //high = 4<<47 | d.h&(1<<47-1) // Spec says all of these values are out of range. high, low = 0, 0 } else { @@ -152,13 +151,12 @@ func (d Decimal128) BigInt() (*big.Int, int, error) { // Bits: 1*sign 2*ignored 14*exponent 111*significand. // Implicit 0b100 prefix in significand. exp = int(high >> 47 & (1<<14 - 1)) - //high = 4<<47 | d.h&(1<<47-1) // Spec says all of these values are out of range. high, low = 0, 0 } else { // Bits: 1*sign 14*exponent 113*significand exp = int(high >> 49 & (1<<14 - 1)) - high = high & (1<<49 - 1) + high &= (1<<49 - 1) } exp += MinDecimal128Exp @@ -352,7 +350,7 @@ var ( // ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value. func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) { - //copy + // copy bi = new(big.Int).Set(bi) q := new(big.Int) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go b/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go index 3fdb67b..40f1181 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/bulk_write.go @@ -186,7 +186,7 @@ func (bw *bulkWrite) runInsert(ctx context.Context, batch bulkWriteBatch) (opera Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE). ServerAPI(bw.collection.client.serverAPI).Timeout(bw.collection.client.timeout). - Logger(bw.collection.client.logger) + Logger(bw.collection.client.logger).Authenticator(bw.collection.client.authenticator) if bw.comment != nil { comment, err := marshalValue(bw.comment, bw.collection.bsonOpts, bw.collection.registry) if err != nil { @@ -256,7 +256,7 @@ func (bw *bulkWrite) runDelete(ctx context.Context, batch bulkWriteBatch) (opera Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE).Hint(hasHint). ServerAPI(bw.collection.client.serverAPI).Timeout(bw.collection.client.timeout). - Logger(bw.collection.client.logger) + Logger(bw.collection.client.logger).Authenticator(bw.collection.client.authenticator) if bw.comment != nil { comment, err := marshalValue(bw.comment, bw.collection.bsonOpts, bw.collection.registry) if err != nil { @@ -387,7 +387,8 @@ func (bw *bulkWrite) runUpdate(ctx context.Context, batch bulkWriteBatch) (opera Database(bw.collection.db.name).Collection(bw.collection.name). Deployment(bw.collection.client.deployment).Crypt(bw.collection.client.cryptFLE).Hint(hasHint). ArrayFilters(hasArrayFilters).ServerAPI(bw.collection.client.serverAPI). - Timeout(bw.collection.client.timeout).Logger(bw.collection.client.logger) + Timeout(bw.collection.client.timeout).Logger(bw.collection.client.logger). + Authenticator(bw.collection.client.authenticator) if bw.comment != nil { comment, err := marshalValue(bw.comment, bw.collection.bsonOpts, bw.collection.registry) if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go b/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go index 8d0a203..3ea8baf 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/change_stream.go @@ -137,7 +137,8 @@ func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline in ReadPreference(config.readPreference).ReadConcern(config.readConcern). Deployment(cs.client.deployment).ClusterClock(cs.client.clock). CommandMonitor(cs.client.monitor).Session(cs.sess).ServerSelector(cs.selector).Retry(driver.RetryNone). - ServerAPI(cs.client.serverAPI).Crypt(config.crypt).Timeout(cs.client.timeout) + ServerAPI(cs.client.serverAPI).Crypt(config.crypt).Timeout(cs.client.timeout). + Authenticator(cs.client.authenticator) if cs.options.Collation != nil { cs.aggregate.Collation(bsoncore.Document(cs.options.Collation.ToDocument())) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/client.go b/vendor/go.mongodb.org/mongo-driver/mongo/client.go index 4266412..0ce6d2e 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/client.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/client.go @@ -26,6 +26,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/writeconcern" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" + "go.mongodb.org/mongo-driver/x/mongo/driver/auth" "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt" mcopts "go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options" "go.mongodb.org/mongo-driver/x/mongo/driver/operation" @@ -79,6 +80,7 @@ type Client struct { metadataClientFLE *Client internalClientFLE *Client encryptedFieldsMap map[string]interface{} + authenticator driver.Authenticator } // Connect creates a new Client and then initializes it using the Connect method. This is equivalent to calling @@ -209,10 +211,22 @@ func NewClient(opts ...*options.ClientOptions) (*Client, error) { clientOpt.SetMaxPoolSize(defaultMaxPoolSize) } - cfg, err := topology.NewConfig(clientOpt, client.clock) + if clientOpt.Auth != nil { + client.authenticator, err = auth.CreateAuthenticator( + clientOpt.Auth.AuthMechanism, + topology.ConvertCreds(clientOpt.Auth), + clientOpt.HTTPClient, + ) + if err != nil { + return nil, fmt.Errorf("error creating authenticator: %w", err) + } + } + + cfg, err := topology.NewConfigWithAuthenticator(clientOpt, client.clock, client.authenticator) if err != nil { return nil, err } + client.serverAPI = topology.ServerAPIFromServerOptions(cfg.ServerOpts) if client.deployment == nil { @@ -690,7 +704,7 @@ func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ... op := operation.NewListDatabases(filterDoc). Session(sess).ReadPreference(c.readPreference).CommandMonitor(c.monitor). ServerSelector(selector).ClusterClock(c.clock).Database("admin").Deployment(c.deployment).Crypt(c.cryptFLE). - ServerAPI(c.serverAPI).Timeout(c.timeout) + ServerAPI(c.serverAPI).Timeout(c.timeout).Authenticator(c.authenticator) if ldo.NameOnly != nil { op = op.NameOnly(*ldo.NameOnly) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go b/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go index b51f57b..352dac1 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/client_encryption.go @@ -204,7 +204,12 @@ func transformExplicitEncryptionOptions(opts ...*options.EncryptOptions) *mcopts if eo.RangeOptions.Precision != nil { transformedRange.Precision = eo.RangeOptions.Precision } - transformedRange.Sparsity = eo.RangeOptions.Sparsity + if eo.RangeOptions.Sparsity != nil { + transformedRange.Sparsity = eo.RangeOptions.Sparsity + } + if eo.RangeOptions.TrimFactor != nil { + transformedRange.TrimFactor = eo.RangeOptions.TrimFactor + } transformed.SetRangeOptions(transformedRange) } return transformed @@ -230,8 +235,7 @@ func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue, // 2. An Aggregate Expression of this form: // {$and: [{$gt: [, ]}, {$lt: [, ]}] // $gt may also be $gte. $lt may also be $lte. -// Only supported for queryType "rangePreview" -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. +// Only supported for queryType "range" func (ce *ClientEncryption) EncryptExpression(ctx context.Context, expr interface{}, result interface{}, opts ...*options.EncryptOptions) error { transformed := transformExplicitEncryptionOptions(opts...) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/collection.go b/vendor/go.mongodb.org/mongo-driver/mongo/collection.go index 4cf6fd1..dbe238a 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/collection.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/collection.go @@ -291,7 +291,8 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{}, ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true). - ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).Logger(coll.client.logger) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).Logger(coll.client.logger). + Authenticator(coll.client.authenticator) imo := options.MergeInsertManyOptions(opts...) if imo.BypassDocumentValidation != nil && *imo.BypassDocumentValidation { op = op.BypassDocumentValidation(*imo.BypassDocumentValidation) @@ -471,7 +472,8 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Ordered(true). - ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).Logger(coll.client.logger) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).Logger(coll.client.logger). + Authenticator(coll.client.authenticator) if do.Comment != nil { comment, err := marshalValue(do.Comment, coll.bsonOpts, coll.registry) if err != nil { @@ -588,7 +590,7 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).Hint(uo.Hint != nil). ArrayFilters(uo.ArrayFilters != nil).Ordered(true).ServerAPI(coll.client.serverAPI). - Timeout(coll.client.timeout).Logger(coll.client.logger) + Timeout(coll.client.timeout).Logger(coll.client.logger).Authenticator(coll.client.authenticator) if uo.Let != nil { let, err := marshal(uo.Let, coll.bsonOpts, coll.registry) if err != nil { @@ -861,7 +863,8 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { ServerAPI(a.client.serverAPI). HasOutputStage(hasOutputStage). Timeout(a.client.timeout). - MaxTime(ao.MaxTime) + MaxTime(ao.MaxTime). + Authenticator(a.client.authenticator) // Omit "maxTimeMS" from operations that return a user-managed cursor to // prevent confusing "cursor not found" errors. To maintain existing @@ -992,7 +995,7 @@ func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, op := operation.NewAggregate(pipelineArr).Session(sess).ReadConcern(rc).ReadPreference(coll.readPreference). CommandMonitor(coll.client.monitor).ServerSelector(selector).ClusterClock(coll.client.clock).Database(coll.db.name). Collection(coll.name).Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). - Timeout(coll.client.timeout).MaxTime(countOpts.MaxTime) + Timeout(coll.client.timeout).MaxTime(countOpts.MaxTime).Authenticator(coll.client.authenticator) if countOpts.Collation != nil { op.Collation(bsoncore.Document(countOpts.Collation.ToDocument())) } @@ -1077,7 +1080,7 @@ func (coll *Collection) EstimatedDocumentCount(ctx context.Context, Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference). ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). - Timeout(coll.client.timeout).MaxTime(co.MaxTime) + Timeout(coll.client.timeout).MaxTime(co.MaxTime).Authenticator(coll.client.authenticator) if co.Comment != nil { comment, err := marshalValue(co.Comment, coll.bsonOpts, coll.registry) @@ -1144,7 +1147,7 @@ func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter i Database(coll.db.name).Collection(coll.name).CommandMonitor(coll.client.monitor). Deployment(coll.client.deployment).ReadConcern(rc).ReadPreference(coll.readPreference). ServerSelector(selector).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). - Timeout(coll.client.timeout).MaxTime(option.MaxTime) + Timeout(coll.client.timeout).MaxTime(option.MaxTime).Authenticator(coll.client.authenticator) if option.Collation != nil { op.Collation(bsoncore.Document(option.Collation.ToDocument())) @@ -1257,7 +1260,7 @@ func (coll *Collection) find( ClusterClock(coll.client.clock).Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE).ServerAPI(coll.client.serverAPI). Timeout(coll.client.timeout).MaxTime(fo.MaxTime).Logger(coll.client.logger). - OmitCSOTMaxTimeMS(omitCSOTMaxTimeMS) + OmitCSOTMaxTimeMS(omitCSOTMaxTimeMS).Authenticator(coll.client.authenticator) cursorOpts := coll.client.createBaseCursorOptions() @@ -1521,7 +1524,7 @@ func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{} } fod := options.MergeFindOneAndDeleteOptions(opts...) op := operation.NewFindAndModify(f).Remove(true).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout). - MaxTime(fod.MaxTime) + MaxTime(fod.MaxTime).Authenticator(coll.client.authenticator) if fod.Collation != nil { op = op.Collation(bsoncore.Document(fod.Collation.ToDocument())) } @@ -1601,7 +1604,8 @@ func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{ fo := options.MergeFindOneAndReplaceOptions(opts...) op := operation.NewFindAndModify(f).Update(bsoncore.Value{Type: bsontype.EmbeddedDocument, Data: r}). - ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).MaxTime(fo.MaxTime) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout).MaxTime(fo.MaxTime).Authenticator(coll.client.authenticator) + if fo.BypassDocumentValidation != nil && *fo.BypassDocumentValidation { op = op.BypassDocumentValidation(*fo.BypassDocumentValidation) } @@ -1688,7 +1692,7 @@ func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{} fo := options.MergeFindOneAndUpdateOptions(opts...) op := operation.NewFindAndModify(f).ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout). - MaxTime(fo.MaxTime) + MaxTime(fo.MaxTime).Authenticator(coll.client.authenticator) u, err := marshalUpdateValue(update, coll.bsonOpts, coll.registry, true) if err != nil { @@ -1894,7 +1898,8 @@ func (coll *Collection) drop(ctx context.Context) error { ServerSelector(selector).ClusterClock(coll.client.clock). Database(coll.db.name).Collection(coll.name). Deployment(coll.client.deployment).Crypt(coll.client.cryptFLE). - ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout) + ServerAPI(coll.client.serverAPI).Timeout(coll.client.timeout). + Authenticator(coll.client.authenticator) err = op.Execute(ctx) // ignore namespace not found errors diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go b/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go index c77d110..1e01e39 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/cursor.go @@ -286,8 +286,9 @@ func (c *Cursor) Close(ctx context.Context) error { } // All iterates the cursor and decodes each document into results. The results parameter must be a pointer to a slice. -// The slice pointed to by results will be completely overwritten. This method will close the cursor after retrieving -// all documents. If the cursor has been iterated, any previously iterated documents will not be included in results. +// The slice pointed to by results will be completely overwritten. A nil slice pointer will not be modified if the cursor +// has been closed, exhausted, or is empty. This method will close the cursor after retrieving all documents. If the +// cursor has been iterated, any previously iterated documents will not be included in results. // // This method requires driver version >= 1.1.0. func (c *Cursor) All(ctx context.Context, results interface{}) error { diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/database.go b/vendor/go.mongodb.org/mongo-driver/mongo/database.go index 57c0186..5344c96 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/database.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/database.go @@ -189,7 +189,7 @@ func (db *Database) processRunCommand(ctx context.Context, cmd interface{}, ServerSelector(readSelect).ClusterClock(db.client.clock). Database(db.name).Deployment(db.client.deployment). Crypt(db.client.cryptFLE).ReadPreference(ro.ReadPreference).ServerAPI(db.client.serverAPI). - Timeout(db.client.timeout).Logger(db.client.logger), sess, nil + Timeout(db.client.timeout).Logger(db.client.logger).Authenticator(db.client.authenticator), sess, nil } // RunCommand executes the given command against the database. @@ -308,7 +308,7 @@ func (db *Database) Drop(ctx context.Context) error { Session(sess).WriteConcern(wc).CommandMonitor(db.client.monitor). ServerSelector(selector).ClusterClock(db.client.clock). Database(db.name).Deployment(db.client.deployment).Crypt(db.client.cryptFLE). - ServerAPI(db.client.serverAPI) + ServerAPI(db.client.serverAPI).Authenticator(db.client.authenticator) err = op.Execute(ctx) @@ -402,7 +402,7 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt Session(sess).ReadPreference(db.readPreference).CommandMonitor(db.client.monitor). ServerSelector(selector).ClusterClock(db.client.clock). Database(db.name).Deployment(db.client.deployment).Crypt(db.client.cryptFLE). - ServerAPI(db.client.serverAPI).Timeout(db.client.timeout) + ServerAPI(db.client.serverAPI).Timeout(db.client.timeout).Authenticator(db.client.authenticator) cursorOpts := db.client.createBaseCursorOptions() @@ -679,7 +679,7 @@ func (db *Database) createCollection(ctx context.Context, name string, opts ...* func (db *Database) createCollectionOperation(name string, opts ...*options.CreateCollectionOptions) (*operation.Create, error) { cco := options.MergeCreateCollectionOptions(opts...) - op := operation.NewCreate(name).ServerAPI(db.client.serverAPI) + op := operation.NewCreate(name).ServerAPI(db.client.serverAPI).Authenticator(db.client.authenticator) if cco.Capped != nil { op.Capped(*cco.Capped) @@ -805,7 +805,8 @@ func (db *Database) CreateView(ctx context.Context, viewName, viewOn string, pip op := operation.NewCreate(viewName). ViewOn(viewOn). Pipeline(pipelineArray). - ServerAPI(db.client.serverAPI) + ServerAPI(db.client.serverAPI). + Authenticator(db.client.authenticator) cvo := options.MergeCreateViewOptions(opts...) if cvo.Collation != nil { op.Collation(bsoncore.Document(cvo.Collation.ToDocument())) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/description/server.go b/vendor/go.mongodb.org/mongo-driver/mongo/description/server.go index cf39423..19f2760 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/description/server.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/description/server.go @@ -316,21 +316,23 @@ func NewServer(addr address.Address, response bson.Raw) Server { desc.Kind = Standalone - if isReplicaSet { + switch { + case isReplicaSet: desc.Kind = RSGhost - } else if desc.SetName != "" { - if isWritablePrimary { + case desc.SetName != "": + switch { + case isWritablePrimary: desc.Kind = RSPrimary - } else if hidden { + case hidden: desc.Kind = RSMember - } else if secondary { + case secondary: desc.Kind = RSSecondary - } else if arbiterOnly { + case arbiterOnly: desc.Kind = RSArbiter - } else { + default: desc.Kind = RSMember } - } else if msg == "isdbgrid" { + case msg == "isdbgrid": desc.Kind = Mongos } diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go b/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go index 8d3555d..db65f75 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/index_view.go @@ -94,7 +94,7 @@ func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOption ServerSelector(selector).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name). Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). - Timeout(iv.coll.client.timeout) + Timeout(iv.coll.client.timeout).Authenticator(iv.coll.client.authenticator) cursorOpts := iv.coll.client.createBaseCursorOptions() @@ -262,7 +262,7 @@ func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts .. Session(sess).WriteConcern(wc).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name).CommandMonitor(iv.coll.client.monitor). Deployment(iv.coll.client.deployment).ServerSelector(selector).ServerAPI(iv.coll.client.serverAPI). - Timeout(iv.coll.client.timeout).MaxTime(option.MaxTime) + Timeout(iv.coll.client.timeout).MaxTime(option.MaxTime).Authenticator(iv.coll.client.authenticator) if option.CommitQuorum != nil { commitQuorum, err := marshalValue(option.CommitQuorum, iv.coll.bsonOpts, iv.coll.registry) if err != nil { @@ -367,7 +367,7 @@ func (iv IndexView) createOptionsDoc(opts *options.IndexOptions) (bsoncore.Docum return optsDoc, nil } -func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error) { +func (iv IndexView) drop(ctx context.Context, index any, opts ...*options.DropIndexesOptions) (bson.Raw, error) { if ctx == nil { ctx = context.Background() } @@ -397,12 +397,12 @@ func (iv IndexView) drop(ctx context.Context, name string, opts ...*options.Drop // TODO(GODRIVER-3038): This operation should pass CSE to the DropIndexes // Crypt setter to be applied to the operation. - op := operation.NewDropIndexes(name). - Session(sess).WriteConcern(wc).CommandMonitor(iv.coll.client.monitor). + op := operation.NewDropIndexes(index).Session(sess).WriteConcern(wc).CommandMonitor(iv.coll.client.monitor). ServerSelector(selector).ClusterClock(iv.coll.client.clock). Database(iv.coll.db.name).Collection(iv.coll.name). Deployment(iv.coll.client.deployment).ServerAPI(iv.coll.client.serverAPI). - Timeout(iv.coll.client.timeout).MaxTime(dio.MaxTime) + Timeout(iv.coll.client.timeout).MaxTime(dio.MaxTime). + Authenticator(iv.coll.client.authenticator) err = op.Execute(ctx) if err != nil { @@ -435,6 +435,20 @@ func (iv IndexView) DropOne(ctx context.Context, name string, opts ...*options.D return iv.drop(ctx, name, opts...) } +// DropOneWithKey drops a collection index by key using the dropIndexes operation. If the operation succeeds, this returns +// a BSON document in the form {nIndexesWas: }. The "nIndexesWas" field in the response contains the number of +// indexes that existed prior to the drop. +// +// This function is useful to drop an index using its key specification instead of its name. +func (iv IndexView) DropOneWithKey(ctx context.Context, keySpecDocument interface{}, opts ...*options.DropIndexesOptions) (bson.Raw, error) { + doc, err := marshal(keySpecDocument, iv.coll.bsonOpts, iv.coll.registry) + if err != nil { + return nil, err + } + + return iv.drop(ctx, doc, opts...) +} + // DropAll executes a dropIndexes operation to drop all indexes on the collection. If the operation succeeds, this // returns a BSON document in the form {nIndexesWas: }. The "nIndexesWas" field in the response contains the // number of indexes that existed prior to the drop. diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go b/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go index 17b3731..c3a9d43 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/options/clientoptions.go @@ -30,6 +30,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/writeconcern" "go.mongodb.org/mongo-driver/tag" "go.mongodb.org/mongo-driver/x/mongo/driver" + "go.mongodb.org/mongo-driver/x/mongo/driver/auth" "go.mongodb.org/mongo-driver/x/mongo/driver/connstring" "go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage" ) @@ -89,9 +90,9 @@ type ContextDialer interface { // The SERVICE_HOST and CANONICALIZE_HOST_NAME properties must not be used at the same time on Linux and Darwin // systems. // -// AuthSource: the name of the database to use for authentication. This defaults to "$external" for MONGODB-X509, -// GSSAPI, and PLAIN and "admin" for all other mechanisms. This can also be set through the "authSource" URI option -// (e.g. "authSource=otherDb"). +// AuthSource: the name of the database to use for authentication. This defaults to "$external" for MONGODB-AWS, +// MONGODB-OIDC, MONGODB-X509, GSSAPI, and PLAIN. It defaults to "admin" for all other auth mechanisms. This can +// also be set through the "authSource" URI option (e.g. "authSource=otherDb"). // // Username: the username for authentication. This can also be set through the URI as a username:password pair before // the first @ character. For example, a URI for user "user", password "pwd", and host "localhost:27017" would be @@ -111,6 +112,34 @@ type Credential struct { Username string Password string PasswordSet bool + OIDCMachineCallback OIDCCallback + OIDCHumanCallback OIDCCallback +} + +// OIDCCallback is the type for both Human and Machine Callback flows. +// RefreshToken will always be nil in the OIDCArgs for the Machine flow. +type OIDCCallback func(context.Context, *OIDCArgs) (*OIDCCredential, error) + +// OIDCArgs contains the arguments for the OIDC callback. +type OIDCArgs struct { + Version int + IDPInfo *IDPInfo + RefreshToken *string +} + +// OIDCCredential contains the access token and refresh token. +type OIDCCredential struct { + AccessToken string + ExpiresAt *time.Time + RefreshToken *string +} + +// IDPInfo contains the information needed to perform OIDC authentication with +// an Identity Provider. +type IDPInfo struct { + Issuer string + ClientID string + RequestScopes []string } // BSONOptions are optional BSON marshaling and unmarshaling behaviors. @@ -332,6 +361,37 @@ func (c *ClientOptions) validate() error { return fmt.Errorf("invalid server monitoring mode: %q", *mode) } + // OIDC Validation + if c.Auth != nil && c.Auth.AuthMechanism == auth.MongoDBOIDC { + if c.Auth.Password != "" { + return fmt.Errorf("password must not be set for the %s auth mechanism", auth.MongoDBOIDC) + } + if c.Auth.OIDCMachineCallback != nil && c.Auth.OIDCHumanCallback != nil { + return fmt.Errorf("cannot set both OIDCMachineCallback and OIDCHumanCallback, only one may be specified") + } + if c.Auth.OIDCHumanCallback == nil && c.Auth.AuthMechanismProperties[auth.AllowedHostsProp] != "" { + return fmt.Errorf("Cannot specify ALLOWED_HOSTS without an OIDCHumanCallback") + } + if env, ok := c.Auth.AuthMechanismProperties[auth.EnvironmentProp]; ok { + switch env { + case auth.GCPEnvironmentValue, auth.AzureEnvironmentValue: + if c.Auth.OIDCMachineCallback != nil { + return fmt.Errorf("OIDCMachineCallback cannot be specified with the %s %q", env, auth.EnvironmentProp) + } + if c.Auth.OIDCHumanCallback != nil { + return fmt.Errorf("OIDCHumanCallback cannot be specified with the %s %q", env, auth.EnvironmentProp) + } + if c.Auth.AuthMechanismProperties[auth.ResourceProp] == "" { + return fmt.Errorf("%q must be set for the %s %q", auth.ResourceProp, env, auth.EnvironmentProp) + } + default: + if c.Auth.AuthMechanismProperties[auth.ResourceProp] != "" { + return fmt.Errorf("%q must not be set for the %s %q", auth.ResourceProp, env, auth.EnvironmentProp) + } + } + } + } + return nil } @@ -1258,7 +1318,10 @@ func addClientCertFromBytes(cfg *tls.Config, data []byte, keyPasswd string) (str } } var encoded bytes.Buffer - pem.Encode(&encoded, &pem.Block{Type: currentBlock.Type, Bytes: keyBytes}) + err = pem.Encode(&encoded, &pem.Block{Type: currentBlock.Type, Bytes: keyBytes}) + if err != nil { + return "", fmt.Errorf("error encoding private key as PEM: %w", err) + } keyBlock := encoded.Bytes() keyBlocks = append(keyBlocks, keyBlock) start = len(data) - len(remaining) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/options/encryptoptions.go b/vendor/go.mongodb.org/mongo-driver/mongo/options/encryptoptions.go index 88517d0..68278ba 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/options/encryptoptions.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/options/encryptoptions.go @@ -17,13 +17,13 @@ const ( QueryTypeEquality string = "equality" ) -// RangeOptions specifies index options for a Queryable Encryption field supporting "rangePreview" queries. -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. +// RangeOptions specifies index options for a Queryable Encryption field supporting "range" queries. type RangeOptions struct { - Min *bson.RawValue - Max *bson.RawValue - Sparsity int64 - Precision *int32 + Min *bson.RawValue + Max *bson.RawValue + Sparsity *int64 + TrimFactor *int32 + Precision *int32 } // EncryptOptions represents options to explicitly encrypt a value. @@ -58,6 +58,7 @@ func (e *EncryptOptions) SetKeyAltName(keyAltName string) *EncryptOptions { // - AEAD_AES_256_CBC_HMAC_SHA_512-Random // - Indexed // - Unindexed +// - Range // This is required. // Indexed and Unindexed are used for Queryable Encryption. func (e *EncryptOptions) SetAlgorithm(algorithm string) *EncryptOptions { @@ -81,36 +82,37 @@ func (e *EncryptOptions) SetContentionFactor(contentionFactor int64) *EncryptOpt return e } -// SetRangeOptions specifies the options to use for explicit encryption with range. It is only valid to set if algorithm is "rangePreview". -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. +// SetRangeOptions specifies the options to use for explicit encryption with range. It is only valid to set if algorithm is "Range". func (e *EncryptOptions) SetRangeOptions(ro RangeOptions) *EncryptOptions { e.RangeOptions = &ro return e } // SetMin sets the range index minimum value. -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. func (ro *RangeOptions) SetMin(min bson.RawValue) *RangeOptions { ro.Min = &min return ro } // SetMax sets the range index maximum value. -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. func (ro *RangeOptions) SetMax(max bson.RawValue) *RangeOptions { ro.Max = &max return ro } // SetSparsity sets the range index sparsity. -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. func (ro *RangeOptions) SetSparsity(sparsity int64) *RangeOptions { - ro.Sparsity = sparsity + ro.Sparsity = &sparsity + return ro +} + +// SetTrimFactor sets the range index trim factor. +func (ro *RangeOptions) SetTrimFactor(trimFactor int32) *RangeOptions { + ro.TrimFactor = &trimFactor return ro } // SetPrecision sets the range index precision. -// Beta: The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes. func (ro *RangeOptions) SetPrecision(precision int32) *RangeOptions { ro.Precision = &precision return ro diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/options/serverapioptions.go b/vendor/go.mongodb.org/mongo-driver/mongo/options/serverapioptions.go index 5beb795..4eef2e1 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/options/serverapioptions.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/options/serverapioptions.go @@ -52,8 +52,7 @@ const ( // Validate determines if the provided ServerAPIVersion is currently supported by the driver. func (sav ServerAPIVersion) Validate() error { - switch sav { - case ServerAPIVersion1: + if sav == ServerAPIVersion1 { return nil } return fmt.Errorf("api version %q not supported; this driver version only supports API version \"1\"", sav) diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/search_index_view.go b/vendor/go.mongodb.org/mongo-driver/mongo/search_index_view.go index 73fe853..3253a73 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/search_index_view.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/search_index_view.go @@ -143,7 +143,7 @@ func (siv SearchIndexView) CreateMany( ServerSelector(selector).ClusterClock(siv.coll.client.clock). Collection(siv.coll.name).Database(siv.coll.db.name). Deployment(siv.coll.client.deployment).ServerAPI(siv.coll.client.serverAPI). - Timeout(siv.coll.client.timeout) + Timeout(siv.coll.client.timeout).Authenticator(siv.coll.client.authenticator) err = op.Execute(ctx) if err != nil { @@ -198,7 +198,7 @@ func (siv SearchIndexView) DropOne( ServerSelector(selector).ClusterClock(siv.coll.client.clock). Collection(siv.coll.name).Database(siv.coll.db.name). Deployment(siv.coll.client.deployment).ServerAPI(siv.coll.client.serverAPI). - Timeout(siv.coll.client.timeout) + Timeout(siv.coll.client.timeout).Authenticator(siv.coll.client.authenticator) err = op.Execute(ctx) if de, ok := err.(driver.Error); ok && de.NamespaceNotFound() { @@ -252,7 +252,7 @@ func (siv SearchIndexView) UpdateOne( ServerSelector(selector).ClusterClock(siv.coll.client.clock). Collection(siv.coll.name).Database(siv.coll.db.name). Deployment(siv.coll.client.deployment).ServerAPI(siv.coll.client.serverAPI). - Timeout(siv.coll.client.timeout) + Timeout(siv.coll.client.timeout).Authenticator(siv.coll.client.authenticator) return op.Execute(ctx) } diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/session.go b/vendor/go.mongodb.org/mongo-driver/mongo/session.go index 8f1e029..77be4ab 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/session.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/session.go @@ -296,7 +296,8 @@ func (s *sessionImpl) AbortTransaction(ctx context.Context) error { _ = operation.NewAbortTransaction().Session(s.clientSession).ClusterClock(s.client.clock).Database("admin"). Deployment(s.deployment).WriteConcern(s.clientSession.CurrentWc).ServerSelector(selector). Retry(driver.RetryOncePerCommand).CommandMonitor(s.client.monitor). - RecoveryToken(bsoncore.Document(s.clientSession.RecoveryToken)).ServerAPI(s.client.serverAPI).Execute(ctx) + RecoveryToken(bsoncore.Document(s.clientSession.RecoveryToken)).ServerAPI(s.client.serverAPI). + Authenticator(s.client.authenticator).Execute(ctx) s.clientSession.Aborting = false _ = s.clientSession.AbortTransaction() @@ -328,7 +329,7 @@ func (s *sessionImpl) CommitTransaction(ctx context.Context) error { Session(s.clientSession).ClusterClock(s.client.clock).Database("admin").Deployment(s.deployment). WriteConcern(s.clientSession.CurrentWc).ServerSelector(selector).Retry(driver.RetryOncePerCommand). CommandMonitor(s.client.monitor).RecoveryToken(bsoncore.Document(s.clientSession.RecoveryToken)). - ServerAPI(s.client.serverAPI).MaxTime(s.clientSession.CurrentMct) + ServerAPI(s.client.serverAPI).MaxTime(s.clientSession.CurrentMct).Authenticator(s.client.authenticator) err = op.Execute(ctx) // Return error without updating transaction state if it is a timeout, as the transaction has not diff --git a/vendor/go.mongodb.org/mongo-driver/version/version.go b/vendor/go.mongodb.org/mongo-driver/version/version.go index d929c46..3dc006a 100644 --- a/vendor/go.mongodb.org/mongo-driver/version/version.go +++ b/vendor/go.mongodb.org/mongo-driver/version/version.go @@ -8,4 +8,4 @@ package version // import "go.mongodb.org/mongo-driver/version" // Driver is the current version of the driver. -var Driver = "1.16.1" +var Driver = "1.17.1" diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go index 1fe0897..9c1ab2a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/element.go @@ -51,7 +51,7 @@ func (e Element) KeyErr() (string, error) { // KeyBytesErr returns the key for this element as a []byte, returning an error if the element is // not valid. func (e Element) KeyBytesErr() ([]byte, error) { - if len(e) <= 0 { + if len(e) == 0 { return nil, ErrElementMissingType } idx := bytes.IndexByte(e[1:], 0x00) @@ -99,7 +99,7 @@ func (e Element) Value() Value { // ValueErr returns the value for this element, returning an error if the element is not valid. func (e Element) ValueErr() (Value, error) { - if len(e) <= 0 { + if len(e) == 0 { return Value{}, ErrElementMissingType } idx := bytes.IndexByte(e[1:], 0x00) @@ -116,7 +116,7 @@ func (e Element) ValueErr() (Value, error) { // String implements the fmt.String interface. The output will be in extended JSON format. func (e Element) String() string { - if len(e) <= 0 { + if len(e) == 0 { return "" } t := bsontype.Type(e[0]) @@ -135,7 +135,7 @@ func (e Element) String() string { // DebugString outputs a human readable version of RawElement. It will attempt to stringify the // valid components of the element even if the entire element is not valid. func (e Element) DebugString() string { - if len(e) <= 0 { + if len(e) == 0 { return "" } t := bsontype.Type(e[0]) diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go index 69c1f9e..fcb0428 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go +++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go @@ -924,13 +924,14 @@ func escapeString(s string) string { func formatDouble(f float64) string { var s string - if math.IsInf(f, 1) { + switch { + case math.IsInf(f, 1): s = "Infinity" - } else if math.IsInf(f, -1) { + case math.IsInf(f, -1): s = "-Infinity" - } else if math.IsNaN(f) { + case math.IsNaN(f): s = "NaN" - } else { + default: // Print exactly one decimalType place for integers; otherwise, print as many are necessary to // perfectly represent it. s = strconv.FormatFloat(f, 'G', -1, 64) @@ -953,9 +954,7 @@ func (ss sortableString) Less(i, j int) bool { } func (ss sortableString) Swap(i, j int) { - oldI := ss[i] - ss[i] = ss[j] - ss[j] = oldI + ss[i], ss[j] = ss[j], ss[i] } func sortStringAlphebeticAscending(s string) string { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go index 6eeaf0e..34a4a68 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/auth.go @@ -19,8 +19,13 @@ import ( "go.mongodb.org/mongo-driver/x/mongo/driver/session" ) +const sourceExternal = "$external" + +// Config contains the configuration for an Authenticator. +type Config = driver.AuthConfig + // AuthenticatorFactory constructs an authenticator. -type AuthenticatorFactory func(cred *Cred) (Authenticator, error) +type AuthenticatorFactory func(*Cred, *http.Client) (Authenticator, error) var authFactories = make(map[string]AuthenticatorFactory) @@ -33,12 +38,13 @@ func init() { RegisterAuthenticatorFactory(GSSAPI, newGSSAPIAuthenticator) RegisterAuthenticatorFactory(MongoDBX509, newMongoDBX509Authenticator) RegisterAuthenticatorFactory(MongoDBAWS, newMongoDBAWSAuthenticator) + RegisterAuthenticatorFactory(MongoDBOIDC, newOIDCAuthenticator) } // CreateAuthenticator creates an authenticator. -func CreateAuthenticator(name string, cred *Cred) (Authenticator, error) { +func CreateAuthenticator(name string, cred *Cred, httpClient *http.Client) (Authenticator, error) { if f, ok := authFactories[name]; ok { - return f(cred) + return f(cred, httpClient) } return nil, newAuthError(fmt.Sprintf("unknown authenticator: %s", name), nil) @@ -61,7 +67,6 @@ type HandshakeOptions struct { ClusterClock *session.ClusterClock ServerAPI *driver.ServerAPIOptions LoadBalanced bool - HTTPClient *http.Client } type authHandshaker struct { @@ -97,12 +102,17 @@ func (ah *authHandshaker) GetHandshakeInformation(ctx context.Context, addr addr return driver.HandshakeInformation{}, newAuthError("failed to create conversation", err) } - firstMsg, err := ah.conversation.FirstMessage() - if err != nil { - return driver.HandshakeInformation{}, newAuthError("failed to create speculative authentication message", err) - } + // It is possible for the speculative conversation to be nil even without error if the authenticator + // cannot perform speculative authentication. An example of this is MONGODB-OIDC when there is + // no AccessToken in the cache. + if ah.conversation != nil { + firstMsg, err := ah.conversation.FirstMessage() + if err != nil { + return driver.HandshakeInformation{}, newAuthError("failed to create speculative authentication message", err) + } - op = op.SpeculativeAuthenticate(firstMsg) + op = op.SpeculativeAuthenticate(firstMsg) + } } } @@ -132,7 +142,6 @@ func (ah *authHandshaker) FinishHandshake(ctx context.Context, conn driver.Conne ClusterClock: ah.options.ClusterClock, HandshakeInfo: ah.handshakeInfo, ServerAPI: ah.options.ServerAPI, - HTTPClient: ah.options.HTTPClient, } if err := ah.authenticate(ctx, cfg); err != nil { @@ -170,21 +179,8 @@ func Handshaker(h driver.Handshaker, options *HandshakeOptions) driver.Handshake } } -// Config holds the information necessary to perform an authentication attempt. -type Config struct { - Description description.Server - Connection driver.Connection - ClusterClock *session.ClusterClock - HandshakeInfo driver.HandshakeInformation - ServerAPI *driver.ServerAPIOptions - HTTPClient *http.Client -} - // Authenticator handles authenticating a connection. -type Authenticator interface { - // Auth authenticates the connection. - Auth(context.Context, *Config) error -} +type Authenticator = driver.Authenticator func newAuthError(msg string, inner error) error { return &Error{ diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go index 7b2b8f1..a9685f6 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/cred.go @@ -6,11 +6,9 @@ package auth -// Cred is a user's credential. -type Cred struct { - Source string - Username string - Password string - PasswordSet bool - Props map[string]string -} +import ( + "go.mongodb.org/mongo-driver/x/mongo/driver" +) + +// Cred is the type of user credential +type Cred = driver.Cred diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go index 6f2ca52..785a419 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/default.go @@ -9,10 +9,13 @@ package auth import ( "context" "fmt" + "net/http" + + "go.mongodb.org/mongo-driver/x/mongo/driver" ) -func newDefaultAuthenticator(cred *Cred) (Authenticator, error) { - scram, err := newScramSHA256Authenticator(cred) +func newDefaultAuthenticator(cred *Cred, httpClient *http.Client) (Authenticator, error) { + scram, err := newScramSHA256Authenticator(cred, httpClient) if err != nil { return nil, newAuthError("failed to create internal authenticator", err) } @@ -25,6 +28,7 @@ func newDefaultAuthenticator(cred *Cred) (Authenticator, error) { return &DefaultAuthenticator{ Cred: cred, speculativeAuthenticator: speculative, + httpClient: httpClient, }, nil } @@ -36,6 +40,8 @@ type DefaultAuthenticator struct { // The authenticator to use for speculative authentication. Because the correct auth mechanism is unknown when doing // the initial hello, SCRAM-SHA-256 is used for the speculative attempt. speculativeAuthenticator SpeculativeAuthenticator + + httpClient *http.Client } var _ SpeculativeAuthenticator = (*DefaultAuthenticator)(nil) @@ -52,11 +58,11 @@ func (a *DefaultAuthenticator) Auth(ctx context.Context, cfg *Config) error { switch chooseAuthMechanism(cfg) { case SCRAMSHA256: - actual, err = newScramSHA256Authenticator(a.Cred) + actual, err = newScramSHA256Authenticator(a.Cred, a.httpClient) case SCRAMSHA1: - actual, err = newScramSHA1Authenticator(a.Cred) + actual, err = newScramSHA1Authenticator(a.Cred, a.httpClient) default: - actual, err = newMongoDBCRAuthenticator(a.Cred) + actual, err = newMongoDBCRAuthenticator(a.Cred, a.httpClient) } if err != nil { @@ -66,6 +72,11 @@ func (a *DefaultAuthenticator) Auth(ctx context.Context, cfg *Config) error { return actual.Auth(ctx, cfg) } +// Reauth reauthenticates the connection. +func (a *DefaultAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("DefaultAuthenticator does not support reauthentication", nil) +} + // If a server provides a list of supported mechanisms, we choose // SCRAM-SHA-256 if it exists or else MUST use SCRAM-SHA-1. // Otherwise, we decide based on what is supported. diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go index 4b860ba..b342e9a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi.go @@ -14,15 +14,17 @@ import ( "context" "fmt" "net" + "net/http" + "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi" ) // GSSAPI is the mechanism name for GSSAPI. const GSSAPI = "GSSAPI" -func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) { - if cred.Source != "" && cred.Source != "$external" { +func newGSSAPIAuthenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + if cred.Source != "" && cred.Source != sourceExternal { return nil, newAuthError("GSSAPI source must be empty or $external", nil) } @@ -55,5 +57,10 @@ func (a *GSSAPIAuthenticator) Auth(ctx context.Context, cfg *Config) error { if err != nil { return newAuthError("error creating gssapi", err) } - return ConductSaslConversation(ctx, cfg, "$external", client) + return ConductSaslConversation(ctx, cfg, sourceExternal, client) +} + +// Reauth reauthenticates the connection. +func (a *GSSAPIAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("GSSAPI does not support reauthentication", nil) } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go index 7ba5fe8..e50553c 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_enabled.go @@ -9,9 +9,11 @@ package auth +import "net/http" + // GSSAPI is the mechanism name for GSSAPI. const GSSAPI = "GSSAPI" -func newGSSAPIAuthenticator(*Cred) (Authenticator, error) { +func newGSSAPIAuthenticator(*Cred, *http.Client) (Authenticator, error) { return nil, newAuthError("GSSAPI support not enabled during build (-tags gssapi)", nil) } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go index 10312c2..12046ff 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/gssapi_not_supported.go @@ -11,12 +11,13 @@ package auth import ( "fmt" + "net/http" "runtime" ) // GSSAPI is the mechanism name for GSSAPI. const GSSAPI = "GSSAPI" -func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) { +func newGSSAPIAuthenticator(*Cred, *http.Client) (Authenticator, error) { return nil, newAuthError(fmt.Sprintf("GSSAPI is not supported on %s", runtime.GOOS), nil) } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go index abfa4db..4960578 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/gss.go @@ -19,6 +19,7 @@ package gssapi */ import "C" import ( + "context" "fmt" "runtime" "strings" @@ -91,12 +92,12 @@ func (sc *SaslClient) Start() (string, []byte, error) { return mechName, nil, sc.getError("unable to initialize client") } - payload, err := sc.Next(nil) + payload, err := sc.Next(nil, nil) return mechName, payload, err } -func (sc *SaslClient) Next(challenge []byte) ([]byte, error) { +func (sc *SaslClient) Next(_ context.Context, challenge []byte) ([]byte, error) { var buf unsafe.Pointer var bufLen C.size_t diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go index 6e7d3ed..f1da5a8 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/internal/gssapi/sspi.go @@ -12,6 +12,7 @@ package gssapi // #include "sspi_wrapper.h" import "C" import ( + "context" "fmt" "net" "strconv" @@ -115,12 +116,12 @@ func (sc *SaslClient) Start() (string, []byte, error) { return mechName, nil, sc.getError("unable to initialize client") } - payload, err := sc.Next(nil) + payload, err := sc.Next(nil, nil) return mechName, payload, err } -func (sc *SaslClient) Next(challenge []byte) ([]byte, error) { +func (sc *SaslClient) Next(_ context.Context, challenge []byte) ([]byte, error) { var outBuf C.PVOID var outBufLen C.ULONG diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbaws.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbaws.go index 7ae4b08..679c54e 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbaws.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbaws.go @@ -9,57 +9,62 @@ package auth import ( "context" "errors" + "net/http" "go.mongodb.org/mongo-driver/internal/aws/credentials" "go.mongodb.org/mongo-driver/internal/credproviders" + "go.mongodb.org/mongo-driver/x/mongo/driver" "go.mongodb.org/mongo-driver/x/mongo/driver/auth/creds" ) // MongoDBAWS is the mechanism name for MongoDBAWS. const MongoDBAWS = "MONGODB-AWS" -func newMongoDBAWSAuthenticator(cred *Cred) (Authenticator, error) { - if cred.Source != "" && cred.Source != "$external" { +func newMongoDBAWSAuthenticator(cred *Cred, httpClient *http.Client) (Authenticator, error) { + if cred.Source != "" && cred.Source != sourceExternal { return nil, newAuthError("MONGODB-AWS source must be empty or $external", nil) } + if httpClient == nil { + return nil, errors.New("httpClient must not be nil") + } return &MongoDBAWSAuthenticator{ - source: cred.Source, credentials: &credproviders.StaticProvider{ Value: credentials.Value{ - ProviderName: cred.Source, AccessKeyID: cred.Username, SecretAccessKey: cred.Password, SessionToken: cred.Props["AWS_SESSION_TOKEN"], }, }, + httpClient: httpClient, }, nil } // MongoDBAWSAuthenticator uses AWS-IAM credentials over SASL to authenticate a connection. type MongoDBAWSAuthenticator struct { - source string credentials *credproviders.StaticProvider + httpClient *http.Client } // Auth authenticates the connection. func (a *MongoDBAWSAuthenticator) Auth(ctx context.Context, cfg *Config) error { - httpClient := cfg.HTTPClient - if httpClient == nil { - return errors.New("cfg.HTTPClient must not be nil") - } - providers := creds.NewAWSCredentialProvider(httpClient, a.credentials) + providers := creds.NewAWSCredentialProvider(a.httpClient, a.credentials) adapter := &awsSaslAdapter{ conversation: &awsConversation{ credentials: providers.Cred, }, } - err := ConductSaslConversation(ctx, cfg, a.source, adapter) + err := ConductSaslConversation(ctx, cfg, sourceExternal, adapter) if err != nil { return newAuthError("sasl conversation error", err) } return nil } +// Reauth reauthenticates the connection. +func (a *MongoDBAWSAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("AWS authentication does not support reauthentication", nil) +} + type awsSaslAdapter struct { conversation *awsConversation } @@ -74,7 +79,7 @@ func (a *awsSaslAdapter) Start() (string, []byte, error) { return MongoDBAWS, step, nil } -func (a *awsSaslAdapter) Next(challenge []byte) ([]byte, error) { +func (a *awsSaslAdapter) Next(_ context.Context, challenge []byte) ([]byte, error) { step, err := a.conversation.Step(challenge) if err != nil { return nil, err diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go index 6e2c2f4..1861956 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/mongodbcr.go @@ -10,6 +10,7 @@ import ( "context" "fmt" "io" + "net/http" // Ignore gosec warning "Blocklisted import crypto/md5: weak cryptographic primitive". We need // to use MD5 here to implement the MONGODB-CR specification. @@ -28,9 +29,13 @@ import ( // MongoDB 4.0. const MONGODBCR = "MONGODB-CR" -func newMongoDBCRAuthenticator(cred *Cred) (Authenticator, error) { +func newMongoDBCRAuthenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + source := cred.Source + if source == "" { + source = "admin" + } return &MongoDBCRAuthenticator{ - DB: cred.Source, + DB: source, Username: cred.Username, Password: cred.Password, }, nil @@ -97,6 +102,11 @@ func (a *MongoDBCRAuthenticator) Auth(ctx context.Context, cfg *Config) error { return nil } +// Reauth reauthenticates the connection. +func (a *MongoDBCRAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("MONGODB-CR does not support reauthentication", nil) +} + func (a *MongoDBCRAuthenticator) createKey(nonce string) string { // Ignore gosec warning "Use of weak cryptographic primitive". We need to use MD5 here to // implement the MONGODB-CR specification. diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/oidc.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/oidc.go new file mode 100644 index 0000000..13fd10e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/oidc.go @@ -0,0 +1,556 @@ +// Copyright (C) MongoDB, Inc. 2024-present. +// +// 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 + +package auth + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "regexp" + "strings" + "sync" + "time" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/x/mongo/driver" +) + +// MongoDBOIDC is the string constant for the MONGODB-OIDC authentication mechanism. +const MongoDBOIDC = "MONGODB-OIDC" + +// EnvironmentProp is the property key name that specifies the environment for the OIDC authenticator. +const EnvironmentProp = "ENVIRONMENT" + +// ResourceProp is the property key name that specifies the token resource for GCP and AZURE OIDC auth. +const ResourceProp = "TOKEN_RESOURCE" + +// AllowedHostsProp is the property key name that specifies the allowed hosts for the OIDC authenticator. +const AllowedHostsProp = "ALLOWED_HOSTS" + +// AzureEnvironmentValue is the value for the Azure environment. +const AzureEnvironmentValue = "azure" + +// GCPEnvironmentValue is the value for the GCP environment. +const GCPEnvironmentValue = "gcp" + +// TestEnvironmentValue is the value for the test environment. +const TestEnvironmentValue = "test" + +const apiVersion = 1 +const invalidateSleepTimeout = 100 * time.Millisecond + +// The CSOT specification says to apply a 1-minute timeout if "CSOT is not applied". That's +// ambiguous for the v1.x Go Driver because it could mean either "no timeout provided" or "CSOT not +// enabled". Always use a maximum timeout duration of 1 minute, allowing us to ignore the ambiguity. +// Contexts with a shorter timeout are unaffected. +const machineCallbackTimeout = time.Minute +const humanCallbackTimeout = 5 * time.Minute + +var defaultAllowedHosts = []*regexp.Regexp{ + regexp.MustCompile(`^.*[.]mongodb[.]net(:\d+)?$`), + regexp.MustCompile(`^.*[.]mongodb-qa[.]net(:\d+)?$`), + regexp.MustCompile(`^.*[.]mongodb-dev[.]net(:\d+)?$`), + regexp.MustCompile(`^.*[.]mongodbgov[.]net(:\d+)?$`), + regexp.MustCompile(`^localhost(:\d+)?$`), + regexp.MustCompile(`^127[.]0[.]0[.]1(:\d+)?$`), + regexp.MustCompile(`^::1(:\d+)?$`), +} + +// OIDCCallback is a function that takes a context and OIDCArgs and returns an OIDCCredential. +type OIDCCallback = driver.OIDCCallback + +// OIDCArgs contains the arguments for the OIDC callback. +type OIDCArgs = driver.OIDCArgs + +// OIDCCredential contains the access token and refresh token. +type OIDCCredential = driver.OIDCCredential + +// IDPInfo contains the information needed to perform OIDC authentication with an Identity Provider. +type IDPInfo = driver.IDPInfo + +var _ driver.Authenticator = (*OIDCAuthenticator)(nil) +var _ SpeculativeAuthenticator = (*OIDCAuthenticator)(nil) +var _ SaslClient = (*oidcOneStep)(nil) +var _ SaslClient = (*oidcTwoStep)(nil) + +// OIDCAuthenticator is synchronized and handles caching of the access token, refreshToken, +// and IDPInfo. It also provides a mechanism to refresh the access token, but this functionality +// is only for the OIDC Human flow. +type OIDCAuthenticator struct { + mu sync.Mutex // Guards all of the info in the OIDCAuthenticator struct. + + AuthMechanismProperties map[string]string + OIDCMachineCallback OIDCCallback + OIDCHumanCallback OIDCCallback + + allowedHosts *[]*regexp.Regexp + userName string + httpClient *http.Client + accessToken string + refreshToken *string + idpInfo *IDPInfo + tokenGenID uint64 +} + +// SetAccessToken allows for manually setting the access token for the OIDCAuthenticator, this is +// only for testing purposes. +func (oa *OIDCAuthenticator) SetAccessToken(accessToken string) { + oa.mu.Lock() + defer oa.mu.Unlock() + oa.accessToken = accessToken +} + +func newOIDCAuthenticator(cred *Cred, httpClient *http.Client) (Authenticator, error) { + if cred.Source != "" && cred.Source != sourceExternal { + return nil, newAuthError("MONGODB-OIDC source must be empty or $external", nil) + } + if cred.Password != "" { + return nil, fmt.Errorf("password cannot be specified for %q", MongoDBOIDC) + } + if cred.Props != nil { + if env, ok := cred.Props[EnvironmentProp]; ok { + switch strings.ToLower(env) { + case AzureEnvironmentValue: + fallthrough + case GCPEnvironmentValue: + if _, ok := cred.Props[ResourceProp]; !ok { + return nil, fmt.Errorf("%q must be specified for %q %q", ResourceProp, env, EnvironmentProp) + } + fallthrough + case TestEnvironmentValue: + if cred.OIDCMachineCallback != nil || cred.OIDCHumanCallback != nil { + return nil, fmt.Errorf("OIDC callbacks are not allowed for %q %q", env, EnvironmentProp) + } + } + } + } + oa := &OIDCAuthenticator{ + userName: cred.Username, + httpClient: httpClient, + AuthMechanismProperties: cred.Props, + OIDCMachineCallback: cred.OIDCMachineCallback, + OIDCHumanCallback: cred.OIDCHumanCallback, + } + err := oa.setAllowedHosts() + return oa, err +} + +func createPatternsForGlobs(hosts []string) ([]*regexp.Regexp, error) { + var err error + ret := make([]*regexp.Regexp, len(hosts)) + for i := range hosts { + hosts[i] = strings.ReplaceAll(hosts[i], ".", "[.]") + hosts[i] = strings.ReplaceAll(hosts[i], "*", ".*") + hosts[i] = "^" + hosts[i] + "(:\\d+)?$" + ret[i], err = regexp.Compile(hosts[i]) + if err != nil { + return nil, err + } + } + return ret, nil +} + +func (oa *OIDCAuthenticator) setAllowedHosts() error { + if oa.AuthMechanismProperties == nil { + oa.allowedHosts = &defaultAllowedHosts + return nil + } + + allowedHosts, ok := oa.AuthMechanismProperties[AllowedHostsProp] + if !ok { + oa.allowedHosts = &defaultAllowedHosts + return nil + } + globs := strings.Split(allowedHosts, ",") + ret, err := createPatternsForGlobs(globs) + if err != nil { + return err + } + oa.allowedHosts = &ret + return nil +} + +func (oa *OIDCAuthenticator) validateConnectionAddressWithAllowedHosts(conn driver.Connection) error { + if oa.allowedHosts == nil { + // should be unreachable, but this is a safety check. + return newAuthError(fmt.Sprintf("%q missing", AllowedHostsProp), nil) + } + allowedHosts := *oa.allowedHosts + if len(allowedHosts) == 0 { + return newAuthError(fmt.Sprintf("empty %q specified", AllowedHostsProp), nil) + } + for _, pattern := range allowedHosts { + if pattern.MatchString(string(conn.Address())) { + return nil + } + } + return newAuthError(fmt.Sprintf("address %q not allowed by %q: %v", conn.Address(), AllowedHostsProp, allowedHosts), nil) +} + +type oidcOneStep struct { + userName string + accessToken string +} + +type oidcTwoStep struct { + conn driver.Connection + oa *OIDCAuthenticator +} + +func jwtStepRequest(accessToken string) []byte { + return bsoncore.NewDocumentBuilder(). + AppendString("jwt", accessToken). + Build() +} + +func principalStepRequest(principal string) []byte { + doc := bsoncore.NewDocumentBuilder() + if principal != "" { + doc.AppendString("n", principal) + } + return doc.Build() +} + +func (oos *oidcOneStep) Start() (string, []byte, error) { + return MongoDBOIDC, jwtStepRequest(oos.accessToken), nil +} + +func (oos *oidcOneStep) Next(context.Context, []byte) ([]byte, error) { + return nil, newAuthError("unexpected step in OIDC authentication", nil) +} + +func (*oidcOneStep) Completed() bool { + return true +} + +func (ots *oidcTwoStep) Start() (string, []byte, error) { + return MongoDBOIDC, principalStepRequest(ots.oa.userName), nil +} + +func (ots *oidcTwoStep) Next(ctx context.Context, msg []byte) ([]byte, error) { + var idpInfo IDPInfo + err := bson.Unmarshal(msg, &idpInfo) + if err != nil { + return nil, fmt.Errorf("error unmarshaling BSON document: %w", err) + } + + accessToken, err := ots.oa.getAccessToken(ctx, + ots.conn, + &OIDCArgs{ + Version: apiVersion, + // idpInfo is nil for machine callbacks in the current spec. + IDPInfo: &idpInfo, + // there is no way there could be a refresh token when there is no IDPInfo. + RefreshToken: nil, + }, + // two-step callbacks are always human callbacks. + ots.oa.OIDCHumanCallback) + + return jwtStepRequest(accessToken), err +} + +func (*oidcTwoStep) Completed() bool { + return true +} + +func (oa *OIDCAuthenticator) providerCallback() (OIDCCallback, error) { + env, ok := oa.AuthMechanismProperties[EnvironmentProp] + if !ok { + return nil, nil + } + + switch env { + case AzureEnvironmentValue: + resource, ok := oa.AuthMechanismProperties[ResourceProp] + if !ok { + return nil, newAuthError(fmt.Sprintf("%q must be specified for Azure OIDC", ResourceProp), nil) + } + return getAzureOIDCCallback(oa.userName, resource, oa.httpClient), nil + case GCPEnvironmentValue: + resource, ok := oa.AuthMechanismProperties[ResourceProp] + if !ok { + return nil, newAuthError(fmt.Sprintf("%q must be specified for GCP OIDC", ResourceProp), nil) + } + return getGCPOIDCCallback(resource, oa.httpClient), nil + } + + return nil, fmt.Errorf("%q %q not supported for MONGODB-OIDC", EnvironmentProp, env) +} + +// getAzureOIDCCallback returns the callback for the Azure Identity Provider. +func getAzureOIDCCallback(clientID string, resource string, httpClient *http.Client) OIDCCallback { + // return the callback parameterized by the clientID and resource, also passing in the user + // configured httpClient. + return func(ctx context.Context, _ *OIDCArgs) (*OIDCCredential, error) { + resource = url.QueryEscape(resource) + var uri string + if clientID != "" { + uri = fmt.Sprintf("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=%s&client_id=%s", resource, clientID) + } else { + uri = fmt.Sprintf("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=%s", resource) + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, newAuthError("error creating http request to Azure Identity Provider", err) + } + req.Header.Add("Metadata", "true") + req.Header.Add("Accept", "application/json") + resp, err := httpClient.Do(req) + if err != nil { + return nil, newAuthError("error getting access token from Azure Identity Provider", err) + } + defer resp.Body.Close() + var azureResp struct { + AccessToken string `json:"access_token"` + ExpiresOn int64 `json:"expires_on,string"` + } + + if resp.StatusCode != http.StatusOK { + return nil, newAuthError(fmt.Sprintf("failed to get a valid response from Azure Identity Provider, http code: %d", resp.StatusCode), nil) + } + err = json.NewDecoder(resp.Body).Decode(&azureResp) + if err != nil { + return nil, newAuthError("failed parsing result from Azure Identity Provider", err) + } + expireTime := time.Unix(azureResp.ExpiresOn, 0) + return &OIDCCredential{ + AccessToken: azureResp.AccessToken, + ExpiresAt: &expireTime, + }, nil + } +} + +// getGCPOIDCCallback returns the callback for the GCP Identity Provider. +func getGCPOIDCCallback(resource string, httpClient *http.Client) OIDCCallback { + // return the callback parameterized by the clientID and resource, also passing in the user + // configured httpClient. + return func(ctx context.Context, _ *OIDCArgs) (*OIDCCredential, error) { + resource = url.QueryEscape(resource) + uri := fmt.Sprintf("http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=%s", resource) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, newAuthError("error creating http request to GCP Identity Provider", err) + } + req.Header.Add("Metadata-Flavor", "Google") + resp, err := httpClient.Do(req) + if err != nil { + return nil, newAuthError("error getting access token from GCP Identity Provider", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, newAuthError(fmt.Sprintf("failed to get a valid response from GCP Identity Provider, http code: %d", resp.StatusCode), nil) + } + accessToken, err := io.ReadAll(resp.Body) + if err != nil { + return nil, newAuthError("failed parsing reading response from GCP Identity Provider", err) + } + return &OIDCCredential{ + AccessToken: string(accessToken), + ExpiresAt: nil, + }, nil + } +} + +func (oa *OIDCAuthenticator) getAccessToken( + ctx context.Context, + conn driver.Connection, + args *OIDCArgs, + callback OIDCCallback, +) (string, error) { + oa.mu.Lock() + defer oa.mu.Unlock() + + if oa.accessToken != "" { + return oa.accessToken, nil + } + + // Attempt to refresh the access token if a refresh token is available. + if args.RefreshToken != nil { + cred, err := callback(ctx, args) + if err == nil && cred != nil { + oa.accessToken = cred.AccessToken + oa.tokenGenID++ + conn.SetOIDCTokenGenID(oa.tokenGenID) + oa.refreshToken = cred.RefreshToken + return cred.AccessToken, nil + } + oa.refreshToken = nil + args.RefreshToken = nil + } + // If we get here this means there either was no refresh token or the refresh token failed. + cred, err := callback(ctx, args) + if err != nil { + return "", err + } + // This line should never occur, if go conventions are followed, but it is a safety check such + // that we do not throw nil pointer errors to our users if they abuse the API. + if cred == nil { + return "", newAuthError("OIDC callback returned nil credential with no specified error", nil) + } + + oa.accessToken = cred.AccessToken + oa.tokenGenID++ + conn.SetOIDCTokenGenID(oa.tokenGenID) + oa.refreshToken = cred.RefreshToken + // always set the IdPInfo, in most cases, this should just be recopying the same pointer, or nil + // in the machine flow. + oa.idpInfo = args.IDPInfo + + return cred.AccessToken, nil +} + +// invalidateAccessToken invalidates the access token, if the force flag is set to true (which is +// only on a Reauth call) or if the tokenGenID of the connection is greater than or equal to the +// tokenGenID of the OIDCAuthenticator. It should never actually be greater than, but only equal, +// but this is a safety check, since extra invalidation is only a performance impact, not a +// correctness impact. +func (oa *OIDCAuthenticator) invalidateAccessToken(conn driver.Connection) { + oa.mu.Lock() + defer oa.mu.Unlock() + tokenGenID := conn.OIDCTokenGenID() + // If the connection used in a Reauth is a new connection it will not have a correct tokenGenID, + // it will instead be set to 0. In the absence of information, the only safe thing to do is to + // invalidate the cached accessToken. + if tokenGenID == 0 || tokenGenID >= oa.tokenGenID { + oa.accessToken = "" + conn.SetOIDCTokenGenID(0) + } +} + +// Reauth reauthenticates the connection when the server returns a 391 code. Reauth is part of the +// driver.Authenticator interface. +func (oa *OIDCAuthenticator) Reauth(ctx context.Context, cfg *Config) error { + oa.invalidateAccessToken(cfg.Connection) + return oa.Auth(ctx, cfg) +} + +// Auth authenticates the connection. +func (oa *OIDCAuthenticator) Auth(ctx context.Context, cfg *Config) error { + var err error + + if cfg == nil { + return newAuthError(fmt.Sprintf("config must be set for %q authentication", MongoDBOIDC), nil) + } + conn := cfg.Connection + + oa.mu.Lock() + cachedAccessToken := oa.accessToken + cachedRefreshToken := oa.refreshToken + cachedIDPInfo := oa.idpInfo + oa.mu.Unlock() + + if cachedAccessToken != "" { + err = ConductSaslConversation(ctx, cfg, sourceExternal, &oidcOneStep{ + userName: oa.userName, + accessToken: cachedAccessToken, + }) + if err == nil { + return nil + } + // this seems like it could be incorrect since we could be inavlidating an access token that + // has already been replaced by a different auth attempt, but the TokenGenID will prevernt + // that from happening. + oa.invalidateAccessToken(conn) + time.Sleep(invalidateSleepTimeout) + } + + if oa.OIDCHumanCallback != nil { + return oa.doAuthHuman(ctx, cfg, oa.OIDCHumanCallback, cachedIDPInfo, cachedRefreshToken) + } + + // Handle user provided or automatic provider machine callback. + var machineCallback OIDCCallback + if oa.OIDCMachineCallback != nil { + machineCallback = oa.OIDCMachineCallback + } else { + machineCallback, err = oa.providerCallback() + if err != nil { + return fmt.Errorf("error getting built-in OIDC provider: %w", err) + } + } + + if machineCallback != nil { + return oa.doAuthMachine(ctx, cfg, machineCallback) + } + return newAuthError("no OIDC callback provided", nil) +} + +func (oa *OIDCAuthenticator) doAuthHuman(ctx context.Context, cfg *Config, humanCallback OIDCCallback, idpInfo *IDPInfo, refreshToken *string) error { + // Ensure that the connection address is allowed by the allowed hosts. + err := oa.validateConnectionAddressWithAllowedHosts(cfg.Connection) + if err != nil { + return err + } + subCtx, cancel := context.WithTimeout(ctx, humanCallbackTimeout) + defer cancel() + // If the idpInfo exists, we can just do one step + if idpInfo != nil { + accessToken, err := oa.getAccessToken(subCtx, + cfg.Connection, + &OIDCArgs{ + Version: apiVersion, + // idpInfo is nil for machine callbacks in the current spec. + IDPInfo: idpInfo, + RefreshToken: refreshToken, + }, + humanCallback) + if err != nil { + return err + } + return ConductSaslConversation( + subCtx, + cfg, + sourceExternal, + &oidcOneStep{accessToken: accessToken}, + ) + } + // otherwise, we need the two step where we ask the server for the IdPInfo first. + ots := &oidcTwoStep{ + conn: cfg.Connection, + oa: oa, + } + return ConductSaslConversation(subCtx, cfg, sourceExternal, ots) +} + +func (oa *OIDCAuthenticator) doAuthMachine(ctx context.Context, cfg *Config, machineCallback OIDCCallback) error { + subCtx, cancel := context.WithTimeout(ctx, machineCallbackTimeout) + accessToken, err := oa.getAccessToken(subCtx, + cfg.Connection, + &OIDCArgs{ + Version: apiVersion, + // idpInfo is nil for machine callbacks in the current spec. + IDPInfo: nil, + RefreshToken: nil, + }, + machineCallback) + cancel() + if err != nil { + return err + } + return ConductSaslConversation( + ctx, + cfg, + sourceExternal, + &oidcOneStep{accessToken: accessToken}, + ) +} + +// CreateSpeculativeConversation creates a speculative conversation for OIDC authentication. +func (oa *OIDCAuthenticator) CreateSpeculativeConversation() (SpeculativeConversation, error) { + oa.mu.Lock() + defer oa.mu.Unlock() + accessToken := oa.accessToken + if accessToken == "" { + return nil, nil // Skip speculative auth. + } + + return newSaslConversation(&oidcOneStep{accessToken: accessToken}, sourceExternal, true), nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go index 532d43e..fb0645a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/plain.go @@ -8,12 +8,30 @@ package auth import ( "context" + "net/http" + + "go.mongodb.org/mongo-driver/x/mongo/driver" ) // PLAIN is the mechanism name for PLAIN. const PLAIN = "PLAIN" -func newPlainAuthenticator(cred *Cred) (Authenticator, error) { +func newPlainAuthenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + // TODO(GODRIVER-3317): The PLAIN specification says about auth source: + // + // "MUST be specified. Defaults to the database name if supplied on the + // connection string or $external." + // + // We should actually pass through the auth source, not always pass + // $external. If it's empty, we should default to $external. + // + // For example: + // + // source := cred.Source + // if source == "" { + // source = "$external" + // } + // return &PlainAuthenticator{ Username: cred.Username, Password: cred.Password, @@ -28,12 +46,17 @@ type PlainAuthenticator struct { // Auth authenticates the connection. func (a *PlainAuthenticator) Auth(ctx context.Context, cfg *Config) error { - return ConductSaslConversation(ctx, cfg, "$external", &plainSaslClient{ + return ConductSaslConversation(ctx, cfg, sourceExternal, &plainSaslClient{ username: a.Username, password: a.Password, }) } +// Reauth reauthenticates the connection. +func (a *PlainAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("Plain authentication does not support reauthentication", nil) +} + type plainSaslClient struct { username string password string @@ -46,7 +69,7 @@ func (c *plainSaslClient) Start() (string, []byte, error) { return PLAIN, b, nil } -func (c *plainSaslClient) Next([]byte) ([]byte, error) { +func (c *plainSaslClient) Next(context.Context, []byte) ([]byte, error) { return nil, newAuthError("unexpected server challenge", nil) } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go index 2a84b53..1ef67f0 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/sasl.go @@ -19,7 +19,7 @@ import ( // SaslClient is the client piece of a sasl conversation. type SaslClient interface { Start() (string, []byte, error) - Next(challenge []byte) ([]byte, error) + Next(ctx context.Context, challenge []byte) ([]byte, error) Completed() bool } @@ -118,7 +118,7 @@ func (sc *saslConversation) Finish(ctx context.Context, cfg *Config, firstRespon return nil } - payload, err = sc.client.Next(saslResp.Payload) + payload, err = sc.client.Next(ctx, saslResp.Payload) if err != nil { return newError(err, sc.mechanism) } @@ -156,7 +156,6 @@ func (sc *saslConversation) Finish(ctx context.Context, cfg *Config, firstRespon func ConductSaslConversation(ctx context.Context, cfg *Config, authSource string, client SaslClient) error { // Create a non-speculative SASL conversation. conversation := newSaslConversation(client, authSource, false) - saslStartDoc, err := conversation.FirstMessage() if err != nil { return newError(err, conversation.mechanism) diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go index c1238cd..0d7deae 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/scram.go @@ -14,10 +14,12 @@ package auth import ( "context" + "net/http" "github.com/xdg-go/scram" "github.com/xdg-go/stringprep" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/x/mongo/driver" ) const ( @@ -35,7 +37,11 @@ var ( ) ) -func newScramSHA1Authenticator(cred *Cred) (Authenticator, error) { +func newScramSHA1Authenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + source := cred.Source + if source == "" { + source = "admin" + } passdigest := mongoPasswordDigest(cred.Username, cred.Password) client, err := scram.SHA1.NewClientUnprepped(cred.Username, passdigest, "") if err != nil { @@ -44,12 +50,16 @@ func newScramSHA1Authenticator(cred *Cred) (Authenticator, error) { client.WithMinIterations(4096) return &ScramAuthenticator{ mechanism: SCRAMSHA1, - source: cred.Source, + source: source, client: client, }, nil } -func newScramSHA256Authenticator(cred *Cred) (Authenticator, error) { +func newScramSHA256Authenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + source := cred.Source + if source == "" { + source = "admin" + } passprep, err := stringprep.SASLprep.Prepare(cred.Password) if err != nil { return nil, newAuthError("error SASLprepping password", err) @@ -61,7 +71,7 @@ func newScramSHA256Authenticator(cred *Cred) (Authenticator, error) { client.WithMinIterations(4096) return &ScramAuthenticator{ mechanism: SCRAMSHA256, - source: cred.Source, + source: source, client: client, }, nil } @@ -84,6 +94,11 @@ func (a *ScramAuthenticator) Auth(ctx context.Context, cfg *Config) error { return nil } +// Reauth reauthenticates the connection. +func (a *ScramAuthenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("SCRAM does not support reauthentication", nil) +} + // CreateSpeculativeConversation creates a speculative conversation for SCRAM authentication. func (a *ScramAuthenticator) CreateSpeculativeConversation() (SpeculativeConversation, error) { return newSaslConversation(a.createSaslClient(), a.source, true), nil @@ -112,7 +127,7 @@ func (a *scramSaslAdapter) Start() (string, []byte, error) { return a.mechanism, []byte(step), nil } -func (a *scramSaslAdapter) Next(challenge []byte) ([]byte, error) { +func (a *scramSaslAdapter) Next(_ context.Context, challenge []byte) ([]byte, error) { step, err := a.conversation.Step(string(challenge)) if err != nil { return nil, err diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go index 03a9d75..1b84e00 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go @@ -8,6 +8,7 @@ package auth import ( "context" + "net/http" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "go.mongodb.org/mongo-driver/x/mongo/driver" @@ -17,7 +18,10 @@ import ( // MongoDBX509 is the mechanism name for MongoDBX509. const MongoDBX509 = "MONGODB-X509" -func newMongoDBX509Authenticator(cred *Cred) (Authenticator, error) { +func newMongoDBX509Authenticator(cred *Cred, _ *http.Client) (Authenticator, error) { + // TODO(GODRIVER-3309): Validate that cred.Source is either empty or + // "$external" to make validation uniform with other auth mechanisms that + // require Source to be "$external" (e.g. MONGODB-AWS, MONGODB-OIDC, etc). return &MongoDBX509Authenticator{User: cred.Username}, nil } @@ -65,7 +69,7 @@ func (a *MongoDBX509Authenticator) Auth(ctx context.Context, cfg *Config) error requestDoc := createFirstX509Message() authCmd := operation. NewCommand(requestDoc). - Database("$external"). + Database(sourceExternal). Deployment(driver.SingleConnectionDeployment{cfg.Connection}). ClusterClock(cfg.ClusterClock). ServerAPI(cfg.ServerAPI) @@ -76,3 +80,8 @@ func (a *MongoDBX509Authenticator) Auth(ctx context.Context, cfg *Config) error return nil } + +// Reauth reauthenticates the connection. +func (a *MongoDBX509Authenticator) Reauth(_ context.Context, _ *driver.AuthConfig) error { + return newAuthError("X509 does not support reauthentication", nil) +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batch_cursor.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batch_cursor.go index 23b4a65..2aa0aca 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batch_cursor.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/batch_cursor.go @@ -108,12 +108,12 @@ func NewCursorResponse(info ResponseInfo) (CursorResponse, error) { if !ok { return CursorResponse{}, fmt.Errorf("ns should be a string but is a BSON %s", elem.Value().Type) } - index := strings.Index(ns, ".") - if index == -1 { + database, collection, ok := strings.Cut(ns, ".") + if !ok { return CursorResponse{}, errors.New("ns field must contain a valid namespace, but is missing '.'") } - curresp.Database = ns[:index] - curresp.Collection = ns[index+1:] + curresp.Database = database + curresp.Collection = collection case "id": curresp.ID, ok = elem.Value().Int64OK() if !ok { @@ -314,7 +314,7 @@ func (bc *BatchCursor) KillCursor(ctx context.Context) error { } return Operation{ - CommandFn: func(dst []byte, desc description.SelectedServer) ([]byte, error) { + CommandFn: func(dst []byte, _ description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendStringElement(dst, "killCursors", bc.collection) dst = bsoncore.BuildArrayElement(dst, "cursors", bsoncore.Value{Type: bsontype.Int64, Data: bsoncore.AppendInt64(nil, bc.id)}) return dst, nil @@ -369,7 +369,7 @@ func (bc *BatchCursor) getMore(ctx context.Context) { } bc.err = Operation{ - CommandFn: func(dst []byte, desc description.SelectedServer) ([]byte, error) { + CommandFn: func(dst []byte, _ description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendInt64Element(dst, "getMore", bc.id) dst = bsoncore.AppendStringElement(dst, "collection", bc.collection) if numToReturn > 0 { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/connstring/connstring.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/connstring/connstring.go index 686458e..fd69eb4 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/connstring/connstring.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/connstring/connstring.go @@ -24,6 +24,7 @@ import ( "go.mongodb.org/mongo-driver/internal/randutil" "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/x/mongo/driver/auth" "go.mongodb.org/mongo-driver/x/mongo/driver/dns" "go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage" ) @@ -258,6 +259,16 @@ func (u *ConnString) Validate() error { } } + // Check for OIDC auth mechanism properties that cannot be set in the ConnString. + if u.AuthMechanism == auth.MongoDBOIDC { + if _, ok := u.AuthMechanismProperties[auth.AllowedHostsProp]; ok { + return fmt.Errorf( + "ALLOWED_HOSTS cannot be specified in the URI connection string for the %q auth mechanism, it must be specified through the ClientOptions directly", + auth.MongoDBOIDC, + ) + } + } + return nil } @@ -285,7 +296,7 @@ func (u *ConnString) setDefaultAuthParams(dbName string) error { u.AuthMechanismProperties["SERVICE_NAME"] = "mongodb" } fallthrough - case "mongodb-aws", "mongodb-x509": + case "mongodb-aws", "mongodb-x509", "mongodb-oidc": if u.AuthSource == "" { u.AuthSource = "$external" } else if u.AuthSource != "$external" { @@ -781,6 +792,10 @@ func (u *ConnString) validateAuth() error { if u.AuthMechanismProperties != nil { return fmt.Errorf("SCRAM-SHA-256 cannot have mechanism properties") } + case "mongodb-oidc": + if u.Password != "" { + return fmt.Errorf("password cannot be specified for MONGODB-OIDC") + } case "": if u.UsernameSet && u.Username == "" { return fmt.Errorf("username required if URI contains user info") @@ -887,15 +902,16 @@ func (p *parser) parse(original string) (*ConnString, error) { uri := original var err error - if strings.HasPrefix(uri, SchemeMongoDBSRV+"://") { + switch { + case strings.HasPrefix(uri, SchemeMongoDBSRV+"://"): connStr.Scheme = SchemeMongoDBSRV // remove the scheme uri = uri[len(SchemeMongoDBSRV)+3:] - } else if strings.HasPrefix(uri, SchemeMongoDB+"://") { + case strings.HasPrefix(uri, SchemeMongoDB+"://"): connStr.Scheme = SchemeMongoDB // remove the scheme uri = uri[len(SchemeMongoDB)+3:] - } else { + default: return nil, errors.New(`scheme must be "mongodb" or "mongodb+srv"`) } @@ -906,9 +922,9 @@ func (p *parser) parse(original string) (*ConnString, error) { username := userInfo var password string - if idx := strings.Index(userInfo, ":"); idx != -1 { - username = userInfo[:idx] - password = userInfo[idx+1:] + if u, p, ok := strings.Cut(userInfo, ":"); ok { + username = u + password = p connStr.PasswordSet = true } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go index 900729b..363f4d6 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/driver.go @@ -24,6 +24,63 @@ import ( "go.mongodb.org/mongo-driver/x/mongo/driver/session" ) +// AuthConfig holds the information necessary to perform an authentication attempt. +// this was moved from the auth package to avoid a circular dependency. The auth package +// reexports this under the old name to avoid breaking the public api. +type AuthConfig struct { + Description description.Server + Connection Connection + ClusterClock *session.ClusterClock + HandshakeInfo HandshakeInformation + ServerAPI *ServerAPIOptions +} + +// OIDCCallback is the type for both Human and Machine Callback flows. RefreshToken will always be +// nil in the OIDCArgs for the Machine flow. +type OIDCCallback func(context.Context, *OIDCArgs) (*OIDCCredential, error) + +// OIDCArgs contains the arguments for the OIDC callback. +type OIDCArgs struct { + Version int + IDPInfo *IDPInfo + RefreshToken *string +} + +// OIDCCredential contains the access token and refresh token. +type OIDCCredential struct { + AccessToken string + ExpiresAt *time.Time + RefreshToken *string +} + +// IDPInfo contains the information needed to perform OIDC authentication with an Identity Provider. +type IDPInfo struct { + Issuer string `bson:"issuer"` + ClientID string `bson:"clientId"` + RequestScopes []string `bson:"requestScopes"` +} + +// Authenticator handles authenticating a connection. The implementers of this interface +// are all in the auth package. Most authentication mechanisms do not allow for Reauth, +// but this is included in the interface so that whenever a new mechanism is added, it +// must be explicitly considered. +type Authenticator interface { + // Auth authenticates the connection. + Auth(context.Context, *AuthConfig) error + Reauth(context.Context, *AuthConfig) error +} + +// Cred is a user's credential. +type Cred struct { + Source string + Username string + Password string + PasswordSet bool + Props map[string]string + OIDCMachineCallback OIDCCallback + OIDCHumanCallback OIDCCallback +} + // Deployment is implemented by types that can select a server from a deployment. type Deployment interface { SelectServer(context.Context, description.ServerSelector) (Server, error) @@ -79,6 +136,8 @@ type Connection interface { DriverConnectionID() uint64 // TODO(GODRIVER-2824): change type to int64. Address() address.Address Stale() bool + OIDCTokenGenID() uint64 + SetOIDCTokenGenID(uint64) } // RTTMonitor represents a round-trip-time monitor. diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/errors.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/errors.go index 177c2d4..59c3992 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/errors.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/errors.go @@ -140,7 +140,7 @@ func (wce WriteCommandError) Retryable(wireVersion *description.VersionRange) bo if wce.WriteConcernError == nil { return false } - return (*wce.WriteConcernError).Retryable() + return wce.WriteConcernError.Retryable() } // HasErrorLabel returns true if the error contains the specified label. diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/mongocrypt.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/mongocrypt.go index 20f6ff0..c5044f8 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/mongocrypt.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/mongocrypt.go @@ -278,7 +278,12 @@ func (m *MongoCrypt) createExplicitEncryptionContext(opts *options.ExplicitEncry if opts.RangeOptions.Precision != nil { mongocryptDoc = bsoncore.AppendInt32Element(mongocryptDoc, "precision", *opts.RangeOptions.Precision) } - mongocryptDoc = bsoncore.AppendInt64Element(mongocryptDoc, "sparsity", opts.RangeOptions.Sparsity) + if opts.RangeOptions.Sparsity != nil { + mongocryptDoc = bsoncore.AppendInt64Element(mongocryptDoc, "sparsity", *opts.RangeOptions.Sparsity) + } + if opts.RangeOptions.TrimFactor != nil { + mongocryptDoc = bsoncore.AppendInt32Element(mongocryptDoc, "trimFactor", *opts.RangeOptions.TrimFactor) + } mongocryptDoc, err := bsoncore.AppendDocumentEnd(mongocryptDoc, idx) if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go index 325777e..81805e7 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/mongocrypt/options/mongocrypt_context_options.go @@ -61,10 +61,11 @@ type ExplicitEncryptionOptions struct { // ExplicitRangeOptions specifies options for the range index. type ExplicitRangeOptions struct { - Min *bsoncore.Value - Max *bsoncore.Value - Sparsity int64 - Precision *int32 + Min *bsoncore.Value + Max *bsoncore.Value + Sparsity *int64 + TrimFactor *int32 + Precision *int32 } // ExplicitEncryption creates a new ExplicitEncryptionOptions instance. diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation.go index db5367b..ec6f69e 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation.go @@ -315,6 +315,10 @@ type Operation struct { // [Operation.MaxTime]. OmitCSOTMaxTimeMS bool + // Authenticator is the authenticator to use for this operation when a reauthentication is + // required. + Authenticator Authenticator + // omitReadPreference is a boolean that indicates whether to omit the // read preference from the command. This omition includes the case // where a default read preference is used when the operation @@ -573,8 +577,7 @@ func (op Operation) Execute(ctx context.Context) error { // Set the previous indefinite error to be returned in any case where a retryable write error does not have a // NoWritesPerfomed label (the definite case). - switch err := err.(type) { - case labeledError: + if err, ok := err.(labeledError); ok { // If the "prevIndefiniteErr" is nil, then the current error is the first error encountered // during the retry attempt cycle. We must persist the first error in the case where all // following errors are labeled "NoWritesPerformed", which would otherwise raise nil as the @@ -912,6 +915,28 @@ func (op Operation) Execute(ctx context.Context) error { operationErr.Labels = tt.Labels operationErr.Raw = tt.Raw case Error: + // 391 is the reauthentication required error code, so we will attempt a reauth and + // retry the operation, if it is successful. + if tt.Code == 391 { + if op.Authenticator != nil { + cfg := AuthConfig{ + Description: conn.Description(), + Connection: conn, + ClusterClock: op.Clock, + ServerAPI: op.ServerAPI, + } + if err := op.Authenticator.Reauth(ctx, &cfg); err != nil { + return fmt.Errorf("error reauthenticating: %w", err) + } + if op.Client != nil && op.Client.Committing { + // Apply majority write concern for retries + op.Client.UpdateCommitTransactionWriteConcern() + op.WriteConcern = op.Client.CurrentWc + } + resetForRetry(tt) + continue + } + } if tt.HasErrorLabel(TransientTransactionError) || tt.HasErrorLabel(UnknownTransactionCommitResult) { if err := op.Client.ClearPinnedResources(); err != nil { return err @@ -1173,18 +1198,12 @@ func (Operation) decompressWireMessage(wm []byte) (wiremessage.OpCode, []byte, e if !ok { return 0, nil, errors.New("malformed OP_COMPRESSED: missing compressor ID") } - compressedSize := len(wm) - 9 // original opcode (4) + uncompressed size (4) + compressor ID (1) - // return the original wiremessage - msg, _, ok := wiremessage.ReadCompressedCompressedMessage(rem, int32(compressedSize)) - if !ok { - return 0, nil, errors.New("malformed OP_COMPRESSED: insufficient bytes for compressed wiremessage") - } opts := CompressionOpts{ Compressor: compressorID, UncompressedSize: uncompressedSize, } - uncompressed, err := DecompressPayload(msg, opts) + uncompressed, err := DecompressPayload(rem, opts) if err != nil { return 0, nil, err } diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/abort_transaction.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/abort_transaction.go index 9413727..aeee533 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/abort_transaction.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/abort_transaction.go @@ -21,6 +21,7 @@ import ( // AbortTransaction performs an abortTransaction operation. type AbortTransaction struct { + authenticator driver.Authenticator recoveryToken bsoncore.Document session *session.Client clock *session.ClusterClock @@ -66,6 +67,7 @@ func (at *AbortTransaction) Execute(ctx context.Context) error { WriteConcern: at.writeConcern, ServerAPI: at.serverAPI, Name: driverutil.AbortTransactionOp, + Authenticator: at.authenticator, }.Execute(ctx) } @@ -199,3 +201,13 @@ func (at *AbortTransaction) ServerAPI(serverAPI *driver.ServerAPIOptions) *Abort at.serverAPI = serverAPI return at } + +// Authenticator sets the authenticator to use for this operation. +func (at *AbortTransaction) Authenticator(authenticator driver.Authenticator) *AbortTransaction { + if at == nil { + at = new(AbortTransaction) + } + + at.authenticator = authenticator + return at +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/aggregate.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/aggregate.go index 44467df..df6b8fa 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/aggregate.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/aggregate.go @@ -25,6 +25,7 @@ import ( // Aggregate represents an aggregate operation. type Aggregate struct { + authenticator driver.Authenticator allowDiskUse *bool batchSize *int32 bypassDocumentValidation *bool @@ -115,6 +116,7 @@ func (a *Aggregate) Execute(ctx context.Context) error { Timeout: a.timeout, Name: driverutil.AggregateOp, OmitCSOTMaxTimeMS: a.omitCSOTMaxTimeMS, + Authenticator: a.authenticator, }.Execute(ctx) } @@ -433,3 +435,13 @@ func (a *Aggregate) OmitCSOTMaxTimeMS(omit bool) *Aggregate { a.omitCSOTMaxTimeMS = omit return a } + +// Authenticator sets the authenticator to use for this operation. +func (a *Aggregate) Authenticator(authenticator driver.Authenticator) *Aggregate { + if a == nil { + a = new(Aggregate) + } + + a.authenticator = authenticator + return a +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/command.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/command.go index 3528379..64c98ba 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/command.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/command.go @@ -22,6 +22,7 @@ import ( // Command is used to run a generic operation. type Command struct { + authenticator driver.Authenticator command bsoncore.Document database string deployment driver.Deployment @@ -78,7 +79,7 @@ func (c *Command) Execute(ctx context.Context) error { } return driver.Operation{ - CommandFn: func(dst []byte, desc description.SelectedServer) ([]byte, error) { + CommandFn: func(dst []byte, _ description.SelectedServer) ([]byte, error) { return append(dst, c.command[4:len(c.command)-1]...), nil }, ProcessResponseFn: func(info driver.ResponseInfo) error { @@ -107,6 +108,7 @@ func (c *Command) Execute(ctx context.Context) error { ServerAPI: c.serverAPI, Timeout: c.timeout, Logger: c.logger, + Authenticator: c.authenticator, }.Execute(ctx) } @@ -219,3 +221,13 @@ func (c *Command) Logger(logger *logger.Logger) *Command { c.logger = logger return c } + +// Authenticator sets the authenticator to use for this operation. +func (c *Command) Authenticator(authenticator driver.Authenticator) *Command { + if c == nil { + c = new(Command) + } + + c.authenticator = authenticator + return c +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/commit_transaction.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/commit_transaction.go index 11c6f69..6b402bd 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/commit_transaction.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/commit_transaction.go @@ -22,6 +22,7 @@ import ( // CommitTransaction attempts to commit a transaction. type CommitTransaction struct { + authenticator driver.Authenticator maxTime *time.Duration recoveryToken bsoncore.Document session *session.Client @@ -68,6 +69,7 @@ func (ct *CommitTransaction) Execute(ctx context.Context) error { WriteConcern: ct.writeConcern, ServerAPI: ct.serverAPI, Name: driverutil.CommitTransactionOp, + Authenticator: ct.authenticator, }.Execute(ctx) } @@ -201,3 +203,13 @@ func (ct *CommitTransaction) ServerAPI(serverAPI *driver.ServerAPIOptions) *Comm ct.serverAPI = serverAPI return ct } + +// Authenticator sets the authenticator to use for this operation. +func (ct *CommitTransaction) Authenticator(authenticator driver.Authenticator) *CommitTransaction { + if ct == nil { + ct = new(CommitTransaction) + } + + ct.authenticator = authenticator + return ct +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/count.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/count.go index 8de1e9f..eaafc9a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/count.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/count.go @@ -25,6 +25,7 @@ import ( // Count represents a count operation. type Count struct { + authenticator driver.Authenticator maxTime *time.Duration query bsoncore.Document session *session.Client @@ -128,6 +129,7 @@ func (c *Count) Execute(ctx context.Context) error { ServerAPI: c.serverAPI, Timeout: c.timeout, Name: driverutil.CountOp, + Authenticator: c.authenticator, }.Execute(ctx) // Swallow error if NamespaceNotFound(26) is returned from aggregate on non-existent namespace @@ -311,3 +313,13 @@ func (c *Count) Timeout(timeout *time.Duration) *Count { c.timeout = timeout return c } + +// Authenticator sets the authenticator to use for this operation. +func (c *Count) Authenticator(authenticator driver.Authenticator) *Count { + if c == nil { + c = new(Count) + } + + c.authenticator = authenticator + return c +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create.go index 45b26cb..4878e2c 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create.go @@ -20,6 +20,7 @@ import ( // Create represents a create operation. type Create struct { + authenticator driver.Authenticator capped *bool collation bsoncore.Document changeStreamPreAndPostImages bsoncore.Document @@ -77,6 +78,7 @@ func (c *Create) Execute(ctx context.Context) error { Selector: c.selector, WriteConcern: c.writeConcern, ServerAPI: c.serverAPI, + Authenticator: c.authenticator, }.Execute(ctx) } @@ -399,3 +401,13 @@ func (c *Create) ClusteredIndex(ci bsoncore.Document) *Create { c.clusteredIndex = ci return c } + +// Authenticator sets the authenticator to use for this operation. +func (c *Create) Authenticator(authenticator driver.Authenticator) *Create { + if c == nil { + c = new(Create) + } + + c.authenticator = authenticator + return c +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_indexes.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_indexes.go index 77daf67..464c176 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_indexes.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_indexes.go @@ -24,21 +24,22 @@ import ( // CreateIndexes performs a createIndexes operation. type CreateIndexes struct { - commitQuorum bsoncore.Value - indexes bsoncore.Document - maxTime *time.Duration - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - writeConcern *writeconcern.WriteConcern - result CreateIndexesResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + commitQuorum bsoncore.Value + indexes bsoncore.Document + maxTime *time.Duration + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + writeConcern *writeconcern.WriteConcern + result CreateIndexesResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // CreateIndexesResult represents a createIndexes result returned by the server. @@ -119,6 +120,7 @@ func (ci *CreateIndexes) Execute(ctx context.Context) error { ServerAPI: ci.serverAPI, Timeout: ci.timeout, Name: driverutil.CreateIndexesOp, + Authenticator: ci.authenticator, }.Execute(ctx) } @@ -278,3 +280,13 @@ func (ci *CreateIndexes) Timeout(timeout *time.Duration) *CreateIndexes { ci.timeout = timeout return ci } + +// Authenticator sets the authenticator to use for this operation. +func (ci *CreateIndexes) Authenticator(authenticator driver.Authenticator) *CreateIndexes { + if ci == nil { + ci = new(CreateIndexes) + } + + ci.authenticator = authenticator + return ci +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_search_indexes.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_search_indexes.go index cb0d807..8185d27 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_search_indexes.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/create_search_indexes.go @@ -22,18 +22,19 @@ import ( // CreateSearchIndexes performs a createSearchIndexes operation. type CreateSearchIndexes struct { - indexes bsoncore.Document - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - result CreateSearchIndexesResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + indexes bsoncore.Document + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + result CreateSearchIndexesResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // CreateSearchIndexResult represents a single search index result in CreateSearchIndexesResult. @@ -116,6 +117,7 @@ func (csi *CreateSearchIndexes) Execute(ctx context.Context) error { Selector: csi.selector, ServerAPI: csi.serverAPI, Timeout: csi.timeout, + Authenticator: csi.authenticator, }.Execute(ctx) } @@ -237,3 +239,13 @@ func (csi *CreateSearchIndexes) Timeout(timeout *time.Duration) *CreateSearchInd csi.timeout = timeout return csi } + +// Authenticator sets the authenticator to use for this operation. +func (csi *CreateSearchIndexes) Authenticator(authenticator driver.Authenticator) *CreateSearchIndexes { + if csi == nil { + csi = new(CreateSearchIndexes) + } + + csi.authenticator = authenticator + return csi +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/delete.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/delete.go index bf95cf4..4b520a5 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/delete.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/delete.go @@ -25,25 +25,26 @@ import ( // Delete performs a delete operation type Delete struct { - comment bsoncore.Value - deletes []bsoncore.Document - ordered *bool - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - writeConcern *writeconcern.WriteConcern - retry *driver.RetryMode - hint *bool - result DeleteResult - serverAPI *driver.ServerAPIOptions - let bsoncore.Document - timeout *time.Duration - logger *logger.Logger + authenticator driver.Authenticator + comment bsoncore.Value + deletes []bsoncore.Document + ordered *bool + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + writeConcern *writeconcern.WriteConcern + retry *driver.RetryMode + hint *bool + result DeleteResult + serverAPI *driver.ServerAPIOptions + let bsoncore.Document + timeout *time.Duration + logger *logger.Logger } // DeleteResult represents a delete result returned by the server. @@ -59,8 +60,7 @@ func buildDeleteResult(response bsoncore.Document) (DeleteResult, error) { } dr := DeleteResult{} for _, element := range elements { - switch element.Key() { - case "n": + if element.Key() == "n" { var ok bool dr.N, ok = element.Value().AsInt64OK() if !ok { @@ -116,6 +116,7 @@ func (d *Delete) Execute(ctx context.Context) error { Timeout: d.timeout, Logger: d.logger, Name: driverutil.DeleteOp, + Authenticator: d.authenticator, }.Execute(ctx) } @@ -328,3 +329,13 @@ func (d *Delete) Logger(logger *logger.Logger) *Delete { return d } + +// Authenticator sets the authenticator to use for this operation. +func (d *Delete) Authenticator(authenticator driver.Authenticator) *Delete { + if d == nil { + d = new(Delete) + } + + d.authenticator = authenticator + return d +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/distinct.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/distinct.go index b7e675c..0c39027 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/distinct.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/distinct.go @@ -24,6 +24,7 @@ import ( // Distinct performs a distinct operation. type Distinct struct { + authenticator driver.Authenticator collation bsoncore.Document key *string maxTime *time.Duration @@ -58,8 +59,7 @@ func buildDistinctResult(response bsoncore.Document) (DistinctResult, error) { } dr := DistinctResult{} for _, element := range elements { - switch element.Key() { - case "values": + if element.Key() == "values" { dr.Values = element.Value() } } @@ -107,6 +107,7 @@ func (d *Distinct) Execute(ctx context.Context) error { ServerAPI: d.serverAPI, Timeout: d.timeout, Name: driverutil.DistinctOp, + Authenticator: d.authenticator, }.Execute(ctx) } @@ -311,3 +312,13 @@ func (d *Distinct) Timeout(timeout *time.Duration) *Distinct { d.timeout = timeout return d } + +// Authenticator sets the authenticator to use for this operation. +func (d *Distinct) Authenticator(authenticator driver.Authenticator) *Distinct { + if d == nil { + d = new(Distinct) + } + + d.authenticator = authenticator + return d +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_collection.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_collection.go index 8c65967..5a32c2f 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_collection.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_collection.go @@ -23,18 +23,19 @@ import ( // DropCollection performs a drop operation. type DropCollection struct { - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - writeConcern *writeconcern.WriteConcern - result DropCollectionResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + writeConcern *writeconcern.WriteConcern + result DropCollectionResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // DropCollectionResult represents a dropCollection result returned by the server. @@ -104,6 +105,7 @@ func (dc *DropCollection) Execute(ctx context.Context) error { ServerAPI: dc.serverAPI, Timeout: dc.timeout, Name: driverutil.DropOp, + Authenticator: dc.authenticator, }.Execute(ctx) } @@ -222,3 +224,13 @@ func (dc *DropCollection) Timeout(timeout *time.Duration) *DropCollection { dc.timeout = timeout return dc } + +// Authenticator sets the authenticator to use for this operation. +func (dc *DropCollection) Authenticator(authenticator driver.Authenticator) *DropCollection { + if dc == nil { + dc = new(DropCollection) + } + + dc.authenticator = authenticator + return dc +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_database.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_database.go index a8f9b45..1995621 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_database.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_database.go @@ -21,15 +21,16 @@ import ( // DropDatabase performs a dropDatabase operation type DropDatabase struct { - session *session.Client - clock *session.ClusterClock - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - writeConcern *writeconcern.WriteConcern - serverAPI *driver.ServerAPIOptions + authenticator driver.Authenticator + session *session.Client + clock *session.ClusterClock + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + writeConcern *writeconcern.WriteConcern + serverAPI *driver.ServerAPIOptions } // NewDropDatabase constructs and returns a new DropDatabase. @@ -55,6 +56,7 @@ func (dd *DropDatabase) Execute(ctx context.Context) error { WriteConcern: dd.writeConcern, ServerAPI: dd.serverAPI, Name: driverutil.DropDatabaseOp, + Authenticator: dd.authenticator, }.Execute(ctx) } @@ -154,3 +156,13 @@ func (dd *DropDatabase) ServerAPI(serverAPI *driver.ServerAPIOptions) *DropDatab dd.serverAPI = serverAPI return dd } + +// Authenticator sets the authenticator to use for this operation. +func (dd *DropDatabase) Authenticator(authenticator driver.Authenticator) *DropDatabase { + if dd == nil { + dd = new(DropDatabase) + } + + dd.authenticator = authenticator + return dd +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_indexes.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_indexes.go index 0c3d459..a22496b 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_indexes.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_indexes.go @@ -23,20 +23,21 @@ import ( // DropIndexes performs an dropIndexes operation. type DropIndexes struct { - index *string - maxTime *time.Duration - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - writeConcern *writeconcern.WriteConcern - result DropIndexesResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + index any + maxTime *time.Duration + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + writeConcern *writeconcern.WriteConcern + result DropIndexesResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // DropIndexesResult represents a dropIndexes result returned by the server. @@ -52,8 +53,7 @@ func buildDropIndexesResult(response bsoncore.Document) (DropIndexesResult, erro } dir := DropIndexesResult{} for _, element := range elements { - switch element.Key() { - case "nIndexesWas": + if element.Key() == "nIndexesWas" { var ok bool dir.NIndexesWas, ok = element.Value().AsInt32OK() if !ok { @@ -65,9 +65,9 @@ func buildDropIndexesResult(response bsoncore.Document) (DropIndexesResult, erro } // NewDropIndexes constructs and returns a new DropIndexes. -func NewDropIndexes(index string) *DropIndexes { +func NewDropIndexes(index any) *DropIndexes { return &DropIndexes{ - index: &index, + index: index, } } @@ -101,25 +101,33 @@ func (di *DropIndexes) Execute(ctx context.Context) error { ServerAPI: di.serverAPI, Timeout: di.timeout, Name: driverutil.DropIndexesOp, + Authenticator: di.authenticator, }.Execute(ctx) } func (di *DropIndexes) command(dst []byte, _ description.SelectedServer) ([]byte, error) { dst = bsoncore.AppendStringElement(dst, "dropIndexes", di.collection) - if di.index != nil { - dst = bsoncore.AppendStringElement(dst, "index", *di.index) + + switch t := di.index.(type) { + case string: + dst = bsoncore.AppendStringElement(dst, "index", t) + case bsoncore.Document: + if di.index != nil { + dst = bsoncore.AppendDocumentElement(dst, "index", t) + } } + return dst, nil } // Index specifies the name of the index to drop. If '*' is specified, all indexes will be dropped. -func (di *DropIndexes) Index(index string) *DropIndexes { +func (di *DropIndexes) Index(index any) *DropIndexes { if di == nil { di = new(DropIndexes) } - di.index = &index + di.index = index return di } @@ -242,3 +250,13 @@ func (di *DropIndexes) Timeout(timeout *time.Duration) *DropIndexes { di.timeout = timeout return di } + +// Authenticator sets the authenticator to use for this operation. +func (di *DropIndexes) Authenticator(authenticator driver.Authenticator) *DropIndexes { + if di == nil { + di = new(DropIndexes) + } + + di.authenticator = authenticator + return di +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_search_index.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_search_index.go index 3992c83..94e4ddf 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_search_index.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/drop_search_index.go @@ -21,18 +21,19 @@ import ( // DropSearchIndex performs an dropSearchIndex operation. type DropSearchIndex struct { - index string - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - result DropSearchIndexResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + index string + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + result DropSearchIndexResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // DropSearchIndexResult represents a dropSearchIndex result returned by the server. @@ -47,8 +48,7 @@ func buildDropSearchIndexResult(response bsoncore.Document) (DropSearchIndexResu } dsir := DropSearchIndexResult{} for _, element := range elements { - switch element.Key() { - case "ok": + if element.Key() == "ok" { var ok bool dsir.Ok, ok = element.Value().AsInt32OK() if !ok { @@ -93,6 +93,7 @@ func (dsi *DropSearchIndex) Execute(ctx context.Context) error { Selector: dsi.selector, ServerAPI: dsi.serverAPI, Timeout: dsi.timeout, + Authenticator: dsi.authenticator, }.Execute(ctx) } @@ -212,3 +213,13 @@ func (dsi *DropSearchIndex) Timeout(timeout *time.Duration) *DropSearchIndex { dsi.timeout = timeout return dsi } + +// Authenticator sets the authenticator to use for this operation. +func (dsi *DropSearchIndex) Authenticator(authenticator driver.Authenticator) *DropSearchIndex { + if dsi == nil { + dsi = new(DropSearchIndex) + } + + dsi.authenticator = authenticator + return dsi +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/end_sessions.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/end_sessions.go index 52f300b..8b24b3d 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/end_sessions.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/end_sessions.go @@ -20,15 +20,16 @@ import ( // EndSessions performs an endSessions operation. type EndSessions struct { - sessionIDs bsoncore.Document - session *session.Client - clock *session.ClusterClock - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - serverAPI *driver.ServerAPIOptions + authenticator driver.Authenticator + sessionIDs bsoncore.Document + session *session.Client + clock *session.ClusterClock + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + serverAPI *driver.ServerAPIOptions } // NewEndSessions constructs and returns a new EndSessions. @@ -61,6 +62,7 @@ func (es *EndSessions) Execute(ctx context.Context) error { Selector: es.selector, ServerAPI: es.serverAPI, Name: driverutil.EndSessionsOp, + Authenticator: es.authenticator, }.Execute(ctx) } @@ -161,3 +163,13 @@ func (es *EndSessions) ServerAPI(serverAPI *driver.ServerAPIOptions) *EndSession es.serverAPI = serverAPI return es } + +// Authenticator sets the authenticator to use for this operation. +func (es *EndSessions) Authenticator(authenticator driver.Authenticator) *EndSessions { + if es == nil { + es = new(EndSessions) + } + + es.authenticator = authenticator + return es +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find.go index 8950fde..c71b7d7 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find.go @@ -25,6 +25,7 @@ import ( // Find performs a find operation. type Find struct { + authenticator driver.Authenticator allowDiskUse *bool allowPartialResults *bool awaitData *bool @@ -112,6 +113,7 @@ func (f *Find) Execute(ctx context.Context) error { Logger: f.logger, Name: driverutil.FindOp, OmitCSOTMaxTimeMS: f.omitCSOTMaxTimeMS, + Authenticator: f.authenticator, }.Execute(ctx) } @@ -575,3 +577,13 @@ func (f *Find) Logger(logger *logger.Logger) *Find { f.logger = logger return f } + +// Authenticator sets the authenticator to use for this operation. +func (f *Find) Authenticator(authenticator driver.Authenticator) *Find { + if f == nil { + f = new(Find) + } + + f.authenticator = authenticator + return f +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find_and_modify.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find_and_modify.go index 7faf561..ea365cc 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find_and_modify.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/find_and_modify.go @@ -25,6 +25,7 @@ import ( // FindAndModify performs a findAndModify operation. type FindAndModify struct { + authenticator driver.Authenticator arrayFilters bsoncore.Array bypassDocumentValidation *bool collation bsoncore.Document @@ -145,6 +146,7 @@ func (fam *FindAndModify) Execute(ctx context.Context) error { ServerAPI: fam.serverAPI, Timeout: fam.timeout, Name: driverutil.FindAndModifyOp, + Authenticator: fam.authenticator, }.Execute(ctx) } @@ -477,3 +479,13 @@ func (fam *FindAndModify) Timeout(timeout *time.Duration) *FindAndModify { fam.timeout = timeout return fam } + +// Authenticator sets the authenticator to use for this operation. +func (fam *FindAndModify) Authenticator(authenticator driver.Authenticator) *FindAndModify { + if fam == nil { + fam = new(FindAndModify) + } + + fam.authenticator = authenticator + return fam +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/hello.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/hello.go index 16f2ebf..60c99f0 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/hello.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/hello.go @@ -36,6 +36,7 @@ const driverName = "mongo-go-driver" // Hello is used to run the handshake operation. type Hello struct { + authenticator driver.Authenticator appname string compressors []string saslSupportedMechs string @@ -649,3 +650,13 @@ func (h *Hello) GetHandshakeInformation(ctx context.Context, _ address.Address, func (h *Hello) FinishHandshake(context.Context, driver.Connection) error { return nil } + +// Authenticator sets the authenticator to use for this operation. +func (h *Hello) Authenticator(authenticator driver.Authenticator) *Hello { + if h == nil { + h = new(Hello) + } + + h.authenticator = authenticator + return h +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/insert.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/insert.go index 7da4b8b..a65a489 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/insert.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/insert.go @@ -25,6 +25,7 @@ import ( // Insert performs an insert operation. type Insert struct { + authenticator driver.Authenticator bypassDocumentValidation *bool comment bsoncore.Value documents []bsoncore.Document @@ -58,8 +59,7 @@ func buildInsertResult(response bsoncore.Document) (InsertResult, error) { } ir := InsertResult{} for _, element := range elements { - switch element.Key() { - case "n": + if element.Key() == "n" { var ok bool ir.N, ok = element.Value().AsInt64OK() if !ok { @@ -115,6 +115,7 @@ func (i *Insert) Execute(ctx context.Context) error { Timeout: i.timeout, Logger: i.logger, Name: driverutil.InsertOp, + Authenticator: i.authenticator, }.Execute(ctx) } @@ -306,3 +307,13 @@ func (i *Insert) Logger(logger *logger.Logger) *Insert { i.logger = logger return i } + +// Authenticator sets the authenticator to use for this operation. +func (i *Insert) Authenticator(authenticator driver.Authenticator) *Insert { + if i == nil { + i = new(Insert) + } + + i.authenticator = authenticator + return i +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/listDatabases.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/listDatabases.go index c70248e..3df171e 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/listDatabases.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/listDatabases.go @@ -24,6 +24,7 @@ import ( // ListDatabases performs a listDatabases operation. type ListDatabases struct { + authenticator driver.Authenticator filter bsoncore.Document authorizedDatabases *bool nameOnly *bool @@ -165,6 +166,7 @@ func (ld *ListDatabases) Execute(ctx context.Context) error { ServerAPI: ld.serverAPI, Timeout: ld.timeout, Name: driverutil.ListDatabasesOp, + Authenticator: ld.authenticator, }.Execute(ctx) } @@ -327,3 +329,13 @@ func (ld *ListDatabases) Timeout(timeout *time.Duration) *ListDatabases { ld.timeout = timeout return ld } + +// Authenticator sets the authenticator to use for this operation. +func (ld *ListDatabases) Authenticator(authenticator driver.Authenticator) *ListDatabases { + if ld == nil { + ld = new(ListDatabases) + } + + ld.authenticator = authenticator + return ld +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_collections.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_collections.go index 6fe68fa..1e39f5b 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_collections.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_collections.go @@ -22,6 +22,7 @@ import ( // ListCollections performs a listCollections operation. type ListCollections struct { + authenticator driver.Authenticator filter bsoncore.Document nameOnly *bool authorizedCollections *bool @@ -83,6 +84,7 @@ func (lc *ListCollections) Execute(ctx context.Context) error { ServerAPI: lc.serverAPI, Timeout: lc.timeout, Name: driverutil.ListCollectionsOp, + Authenticator: lc.authenticator, }.Execute(ctx) } @@ -259,3 +261,13 @@ func (lc *ListCollections) Timeout(timeout *time.Duration) *ListCollections { lc.timeout = timeout return lc } + +// Authenticator sets the authenticator to use for this operation. +func (lc *ListCollections) Authenticator(authenticator driver.Authenticator) *ListCollections { + if lc == nil { + lc = new(ListCollections) + } + + lc.authenticator = authenticator + return lc +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_indexes.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_indexes.go index 79d50ec..433344f 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_indexes.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/list_indexes.go @@ -21,19 +21,20 @@ import ( // ListIndexes performs a listIndexes operation. type ListIndexes struct { - batchSize *int32 - maxTime *time.Duration - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - database string - deployment driver.Deployment - selector description.ServerSelector - retry *driver.RetryMode - crypt driver.Crypt - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + batchSize *int32 + maxTime *time.Duration + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + database string + deployment driver.Deployment + selector description.ServerSelector + retry *driver.RetryMode + crypt driver.Crypt + serverAPI *driver.ServerAPIOptions + timeout *time.Duration result driver.CursorResponse } @@ -85,6 +86,7 @@ func (li *ListIndexes) Execute(ctx context.Context) error { ServerAPI: li.serverAPI, Timeout: li.timeout, Name: driverutil.ListIndexesOp, + Authenticator: li.authenticator, }.Execute(ctx) } @@ -233,3 +235,13 @@ func (li *ListIndexes) Timeout(timeout *time.Duration) *ListIndexes { li.timeout = timeout return li } + +// Authenticator sets the authenticator to use for this operation. +func (li *ListIndexes) Authenticator(authenticator driver.Authenticator) *ListIndexes { + if li == nil { + li = new(ListIndexes) + } + + li.authenticator = authenticator + return li +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update.go index 881b1bc..1070e7c 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update.go @@ -26,6 +26,7 @@ import ( // Update performs an update operation. type Update struct { + authenticator driver.Authenticator bypassDocumentValidation *bool comment bsoncore.Value ordered *bool @@ -167,6 +168,7 @@ func (u *Update) Execute(ctx context.Context) error { Timeout: u.timeout, Logger: u.logger, Name: driverutil.UpdateOp, + Authenticator: u.authenticator, }.Execute(ctx) } @@ -414,3 +416,13 @@ func (u *Update) Logger(logger *logger.Logger) *Update { u.logger = logger return u } + +// Authenticator sets the authenticator to use for this operation. +func (u *Update) Authenticator(authenticator driver.Authenticator) *Update { + if u == nil { + u = new(Update) + } + + u.authenticator = authenticator + return u +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update_search_index.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update_search_index.go index 64f2da7..c63e048 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update_search_index.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/operation/update_search_index.go @@ -21,19 +21,20 @@ import ( // UpdateSearchIndex performs a updateSearchIndex operation. type UpdateSearchIndex struct { - index string - definition bsoncore.Document - session *session.Client - clock *session.ClusterClock - collection string - monitor *event.CommandMonitor - crypt driver.Crypt - database string - deployment driver.Deployment - selector description.ServerSelector - result UpdateSearchIndexResult - serverAPI *driver.ServerAPIOptions - timeout *time.Duration + authenticator driver.Authenticator + index string + definition bsoncore.Document + session *session.Client + clock *session.ClusterClock + collection string + monitor *event.CommandMonitor + crypt driver.Crypt + database string + deployment driver.Deployment + selector description.ServerSelector + result UpdateSearchIndexResult + serverAPI *driver.ServerAPIOptions + timeout *time.Duration } // UpdateSearchIndexResult represents a single index in the updateSearchIndexResult result. @@ -48,8 +49,7 @@ func buildUpdateSearchIndexResult(response bsoncore.Document) (UpdateSearchIndex } usir := UpdateSearchIndexResult{} for _, element := range elements { - switch element.Key() { - case "ok": + if element.Key() == "ok" { var ok bool usir.Ok, ok = element.Value().AsInt32OK() if !ok { @@ -95,6 +95,7 @@ func (usi *UpdateSearchIndex) Execute(ctx context.Context) error { Selector: usi.selector, ServerAPI: usi.serverAPI, Timeout: usi.timeout, + Authenticator: usi.authenticator, }.Execute(ctx) } @@ -225,3 +226,13 @@ func (usi *UpdateSearchIndex) Timeout(timeout *time.Duration) *UpdateSearchIndex usi.timeout = timeout return usi } + +// Authenticator sets the authenticator to use for this operation. +func (usi *UpdateSearchIndex) Authenticator(authenticator driver.Authenticator) *UpdateSearchIndex { + if usi == nil { + usi = new(UpdateSearchIndex) + } + + usi.authenticator = authenticator + return usi +} diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/session/client_session.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/session/client_session.go index 8dac093..eff27bf 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/session/client_session.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/session/client_session.go @@ -90,6 +90,8 @@ type LoadBalancedTransactionConnection interface { DriverConnectionID() uint64 // TODO(GODRIVER-2824): change type to int64. Address() address.Address Stale() bool + OIDCTokenGenID() uint64 + SetOIDCTokenGenID(uint64) // Functions copied over from driver.PinnedConnection that are not part of Connection or Expirable. PinToCursor() error @@ -158,13 +160,14 @@ func MaxClusterTime(ct1, ct2 bson.Raw) bson.Raw { epoch1, ord1 := getClusterTime(ct1) epoch2, ord2 := getClusterTime(ct2) - if epoch1 > epoch2 { + switch { + case epoch1 > epoch2: return ct1 - } else if epoch1 < epoch2 { + case epoch1 < epoch2: return ct2 - } else if ord1 > ord2 { + case ord1 > ord2: return ct1 - } else if ord1 < ord2 { + case ord1 < ord2: return ct2 } @@ -476,11 +479,12 @@ func (c *Client) UpdateCommitTransactionWriteConcern() { // CheckAbortTransaction checks to see if allowed to abort transaction and returns // an error if not allowed. func (c *Client) CheckAbortTransaction() error { - if c.TransactionState == None { + switch { + case c.TransactionState == None: return ErrNoTransactStarted - } else if c.TransactionState == Committed { + case c.TransactionState == Committed: return ErrAbortAfterCommit - } else if c.TransactionState == Aborted { + case c.TransactionState == Aborted: return ErrAbortTwice } return nil diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go index 649e87b..e00363a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/connection.go @@ -9,10 +9,12 @@ package topology import ( "context" "crypto/tls" + "encoding/binary" "errors" "fmt" "io" "net" + "os" "strings" "sync" "sync/atomic" @@ -54,7 +56,7 @@ type connection struct { nc net.Conn // When nil, the connection is closed. addr address.Address idleTimeout time.Duration - idleDeadline atomic.Value // Stores a time.Time + idleStart atomic.Value // Stores a time.Time readTimeout time.Duration writeTimeout time.Duration desc description.Server @@ -79,9 +81,13 @@ type connection struct { driverConnectionID uint64 generation uint64 - // awaitingResponse indicates that the server response was not completely + // awaitRemainingBytes indicates the size of server response that was not completely // read before returning the connection to the pool. - awaitingResponse bool + awaitRemainingBytes *int32 + + // oidcTokenGenID is the monotonic generation ID for OIDC tokens, used to invalidate + // accessTokens in the OIDC authenticator cache. + oidcTokenGenID uint64 } // newConnection handles the creation of a connection. It does not connect the connection. @@ -111,12 +117,6 @@ func newConnection(addr address.Address, opts ...ConnectionOption) *connection { return c } -// DriverConnectionID returns the driver connection ID. -// TODO(GODRIVER-2824): change return type to int64. -func (c *connection) DriverConnectionID() uint64 { - return c.driverConnectionID -} - // setGenerationNumber sets the connection's generation number if a callback has been provided to do so in connection // configuration. func (c *connection) setGenerationNumber() { @@ -138,6 +138,39 @@ func (c *connection) hasGenerationNumber() bool { return c.desc.LoadBalanced() } +func configureTLS(ctx context.Context, + tlsConnSource tlsConnectionSource, + nc net.Conn, + addr address.Address, + config *tls.Config, + ocspOpts *ocsp.VerifyOptions, +) (net.Conn, error) { + // Ensure config.ServerName is always set for SNI. + if config.ServerName == "" { + hostname := addr.String() + colonPos := strings.LastIndex(hostname, ":") + if colonPos == -1 { + colonPos = len(hostname) + } + + hostname = hostname[:colonPos] + config.ServerName = hostname + } + + client := tlsConnSource.Client(nc, config) + if err := clientHandshake(ctx, client); err != nil { + return nil, err + } + + // Only do OCSP verification if TLS verification is requested. + if !config.InsecureSkipVerify { + if ocspErr := ocsp.Verify(ctx, client.ConnectionState(), ocspOpts); ocspErr != nil { + return nil, ocspErr + } + } + return client, nil +} + // connect handles the I/O for a connection. It will dial, configure TLS, and perform initialization // handshakes. All errors returned by connect are considered "before the handshake completes" and // must be handled by calling the appropriate SDAM handshake error handler. @@ -313,6 +346,10 @@ func (c *connection) closeConnectContext() { } } +func (c *connection) cancellationListenerCallback() { + _ = c.close() +} + func transformNetworkError(ctx context.Context, originalError error, contextDeadlineUsed bool) error { if originalError == nil { return nil @@ -335,10 +372,6 @@ func transformNetworkError(ctx context.Context, originalError error, contextDead return originalError } -func (c *connection) cancellationListenerCallback() { - _ = c.close() -} - func (c *connection) writeWireMessage(ctx context.Context, wm []byte) error { var err error if atomic.LoadInt64(&c.state) != connConnected { @@ -419,15 +452,10 @@ func (c *connection) readWireMessage(ctx context.Context) ([]byte, error) { dst, errMsg, err := c.read(ctx) if err != nil { - if nerr := net.Error(nil); errors.As(err, &nerr) && nerr.Timeout() && csot.IsTimeoutContext(ctx) { - // If the error was a timeout error and CSOT is enabled, instead of - // closing the connection mark it as awaiting response so the pool - // can read the response before making it available to other - // operations. - c.awaitingResponse = true - } else { - // Otherwise, use the pre-CSOT behavior and close the connection - // because we don't know if there are other bytes left to read. + if c.awaitRemainingBytes == nil { + // If the connection was not marked as awaiting response, use the + // pre-CSOT behavior and close the connection because we don't know + // if there are other bytes left to read. c.close() } message := errMsg @@ -444,6 +472,26 @@ func (c *connection) readWireMessage(ctx context.Context) ([]byte, error) { return dst, nil } +func (c *connection) parseWmSizeBytes(wmSizeBytes [4]byte) (int32, error) { + // read the length as an int32 + size := int32(binary.LittleEndian.Uint32(wmSizeBytes[:])) + + if size < 4 { + return 0, fmt.Errorf("malformed message length: %d", size) + } + // In the case of a hello response where MaxMessageSize has not yet been set, use the hard-coded + // defaultMaxMessageSize instead. + maxMessageSize := c.desc.MaxMessageSize + if maxMessageSize == 0 { + maxMessageSize = defaultMaxMessageSize + } + if uint32(size) > maxMessageSize { + return 0, errResponseTooLarge + } + + return size, nil +} + func (c *connection) read(ctx context.Context) (bytesRead []byte, errMsg string, err error) { go c.cancellationListener.Listen(ctx, c.cancellationListenerCallback) defer func() { @@ -457,6 +505,15 @@ func (c *connection) read(ctx context.Context) (bytesRead []byte, errMsg string, } }() + isCSOTTimeout := func(err error) bool { + // If the error was a timeout error and CSOT is enabled, instead of + // closing the connection mark it as awaiting response so the pool + // can read the response before making it available to other + // operations. + nerr := net.Error(nil) + return errors.As(err, &nerr) && nerr.Timeout() && csot.IsTimeoutContext(ctx) + } + // We use an array here because it only costs 4 bytes on the stack and means we'll only need to // reslice dst once instead of twice. var sizeBuf [4]byte @@ -464,29 +521,27 @@ func (c *connection) read(ctx context.Context) (bytesRead []byte, errMsg string, // We do a ReadFull into an array here instead of doing an opportunistic ReadAtLeast into dst // because there might be more than one wire message waiting to be read, for example when // reading messages from an exhaust cursor. - _, err = io.ReadFull(c.nc, sizeBuf[:]) + n, err := io.ReadFull(c.nc, sizeBuf[:]) if err != nil { + if l := int32(n); l == 0 && isCSOTTimeout(err) { + c.awaitRemainingBytes = &l + } return nil, "incomplete read of message header", err } - - // read the length as an int32 - size := (int32(sizeBuf[0])) | (int32(sizeBuf[1]) << 8) | (int32(sizeBuf[2]) << 16) | (int32(sizeBuf[3]) << 24) - - // In the case of a hello response where MaxMessageSize has not yet been set, use the hard-coded - // defaultMaxMessageSize instead. - maxMessageSize := c.desc.MaxMessageSize - if maxMessageSize == 0 { - maxMessageSize = defaultMaxMessageSize - } - if uint32(size) > maxMessageSize { - return nil, errResponseTooLarge.Error(), errResponseTooLarge + size, err := c.parseWmSizeBytes(sizeBuf) + if err != nil { + return nil, err.Error(), err } dst := make([]byte, size) copy(dst, sizeBuf[:]) - _, err = io.ReadFull(c.nc, dst[4:]) + n, err = io.ReadFull(c.nc, dst[4:]) if err != nil { + remainingBytes := size - 4 - int32(n) + if remainingBytes > 0 && isCSOTTimeout(err) { + c.awaitRemainingBytes = &remainingBytes + } return dst, "incomplete read of full message", err } @@ -507,25 +562,65 @@ func (c *connection) close() error { return err } +// closed returns true if the connection has been closed by the driver. func (c *connection) closed() bool { return atomic.LoadInt64(&c.state) == connDisconnected } +// isAlive returns true if the connection is alive and ready to be used for an +// operation. +// +// Note that the liveness check can be slow (at least 1ms), so isAlive only +// checks the liveness of the connection if it's been idle for at least 10 +// seconds. For frequently in-use connections, a network error during an +// operation will be the first indication of a dead connection. +func (c *connection) isAlive() bool { + if c.nc == nil { + return false + } + + // If the connection has been idle for less than 10 seconds, skip the + // liveness check. + // + // The 10-seconds idle bypass is based on the liveness check implementation + // in the Python Driver. That implementation uses 1 second as the idle + // threshold, but we chose to be more conservative in the Go Driver because + // this is new behavior with unknown side-effects. See + // https://github.com/mongodb/mongo-python-driver/blob/e6b95f65953e01e435004af069a6976473eaf841/pymongo/synchronous/pool.py#L983-L985 + idleStart, ok := c.idleStart.Load().(time.Time) + if !ok || idleStart.Add(10*time.Second).After(time.Now()) { + return true + } + + // Set a 1ms read deadline and attempt to read 1 byte from the connection. + // Expect it to block for 1ms then return a deadline exceeded error. If it + // returns any other error, the connection is not usable, so return false. + // If it doesn't return an error and actually reads data, the connection is + // also not usable, so return false. + // + // Note that we don't need to un-set the read deadline because the "read" + // and "write" methods always reset the deadlines. + err := c.nc.SetReadDeadline(time.Now().Add(1 * time.Millisecond)) + if err != nil { + return false + } + var b [1]byte + _, err = c.nc.Read(b[:]) + return errors.Is(err, os.ErrDeadlineExceeded) +} + func (c *connection) idleTimeoutExpired() bool { - now := time.Now() - if c.idleTimeout > 0 { - idleDeadline, ok := c.idleDeadline.Load().(time.Time) - if ok && now.After(idleDeadline) { - return true - } + if c.idleTimeout == 0 { + return false } - return false + idleStart, ok := c.idleStart.Load().(time.Time) + return ok && idleStart.Add(c.idleTimeout).Before(time.Now()) } -func (c *connection) bumpIdleDeadline() { +func (c *connection) bumpIdleStart() { if c.idleTimeout > 0 { - c.idleDeadline.Store(time.Now().Add(c.idleTimeout)) + c.idleStart.Store(time.Now()) } } @@ -533,10 +628,6 @@ func (c *connection) setCanStream(canStream bool) { c.canStream = canStream } -func (c initConnection) supportsStreaming() bool { - return c.canStream -} - func (c *connection) setStreaming(streaming bool) { c.currentlyStreaming = streaming } @@ -550,6 +641,12 @@ func (c *connection) setSocketTimeout(timeout time.Duration) { c.writeTimeout = timeout } +// DriverConnectionID returns the driver connection ID. +// TODO(GODRIVER-2824): change return type to int64. +func (c *connection) DriverConnectionID() uint64 { + return c.driverConnectionID +} + func (c *connection) ID() string { return c.id } @@ -558,6 +655,14 @@ func (c *connection) ServerConnectionID() *int64 { return c.serverConnectionID } +func (c *connection) OIDCTokenGenID() uint64 { + return c.oidcTokenGenID +} + +func (c *connection) SetOIDCTokenGenID(genID uint64) { + c.oidcTokenGenID = genID +} + // initConnection is an adapter used during connection initialization. It has the minimum // functionality necessary to implement the driver.Connection interface, which is required to pass a // *connection to a Handshaker. @@ -595,7 +700,7 @@ func (c initConnection) CurrentlyStreaming() bool { return c.getCurrentlyStreaming() } func (c initConnection) SupportsStreaming() bool { - return c.supportsStreaming() + return c.canStream } // Connection implements the driver.Connection interface to allow reading and writing wire @@ -606,6 +711,8 @@ type Connection struct { refCount int cleanupPoolFn func() + oidcTokenGenID uint64 + // cleanupServerFn resets the server state when a connection is returned to the connection pool // via Close() or expired via Expire(). cleanupServerFn func() @@ -827,37 +934,14 @@ func (c *Connection) DriverConnectionID() uint64 { return c.connection.DriverConnectionID() } -func configureTLS(ctx context.Context, - tlsConnSource tlsConnectionSource, - nc net.Conn, - addr address.Address, - config *tls.Config, - ocspOpts *ocsp.VerifyOptions, -) (net.Conn, error) { - // Ensure config.ServerName is always set for SNI. - if config.ServerName == "" { - hostname := addr.String() - colonPos := strings.LastIndex(hostname, ":") - if colonPos == -1 { - colonPos = len(hostname) - } - - hostname = hostname[:colonPos] - config.ServerName = hostname - } - - client := tlsConnSource.Client(nc, config) - if err := clientHandshake(ctx, client); err != nil { - return nil, err - } +// OIDCTokenGenID returns the OIDC token generation ID. +func (c *Connection) OIDCTokenGenID() uint64 { + return c.oidcTokenGenID +} - // Only do OCSP verification if TLS verification is requested. - if !config.InsecureSkipVerify { - if ocspErr := ocsp.Verify(ctx, client.ConnectionState(), ocspOpts); ocspErr != nil { - return nil, ocspErr - } - } - return client, nil +// SetOIDCTokenGenID sets the OIDC token generation ID. +func (c *Connection) SetOIDCTokenGenID(genID uint64) { + c.oidcTokenGenID = genID } // TODO: Naming? diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/fsm.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/fsm.go index 2acf527..1d097b6 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/fsm.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/fsm.go @@ -22,7 +22,7 @@ var ( MinSupportedMongoDBVersion = "3.6" // SupportedWireVersions is the range of wire versions supported by the driver. - SupportedWireVersions = description.NewVersionRange(6, 21) + SupportedWireVersions = description.NewVersionRange(6, 25) ) type fsm struct { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go index 52461eb..e956542 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/pool.go @@ -9,6 +9,7 @@ package topology import ( "context" "fmt" + "io" "net" "sync" "sync/atomic" @@ -166,8 +167,11 @@ type reason struct { // connectionPerished checks if a given connection is perished and should be removed from the pool. func connectionPerished(conn *connection) (reason, bool) { switch { - case conn.closed(): - // A connection would only be closed if it encountered a network error during an operation and closed itself. + case conn.closed() || !conn.isAlive(): + // A connection would only be closed if it encountered a network error + // during an operation and closed itself. If a connection is not alive + // (e.g. the connection was closed by the server-side), it's also + // considered a network error. return reason{ loggerConn: logger.ReasonConnClosedError, event: event.ReasonError, @@ -788,17 +792,27 @@ var ( // // It calls the package-global BGReadCallback function, if set, with the // address, timings, and any errors that occurred. -func bgRead(pool *pool, conn *connection) { - var start, read time.Time - start = time.Now() - errs := make([]error, 0) - connClosed := false +func bgRead(pool *pool, conn *connection, size int32) { + var err error + start := time.Now() defer func() { + read := time.Now() + errs := make([]error, 0) + connClosed := false + if err != nil { + errs = append(errs, err) + connClosed = true + err = conn.close() + if err != nil { + errs = append(errs, fmt.Errorf("error closing conn after reading: %w", err)) + } + } + // No matter what happens, always check the connection back into the // pool, which will either make it available for other operations or // remove it from the pool if it was closed. - err := pool.checkInNoEvent(conn) + err = pool.checkInNoEvent(conn) if err != nil { errs = append(errs, fmt.Errorf("error checking in: %w", err)) } @@ -808,34 +822,28 @@ func bgRead(pool *pool, conn *connection) { } }() - err := conn.nc.SetReadDeadline(time.Now().Add(BGReadTimeout)) + err = conn.nc.SetReadDeadline(time.Now().Add(BGReadTimeout)) if err != nil { - errs = append(errs, fmt.Errorf("error setting a read deadline: %w", err)) - - connClosed = true - err := conn.close() - if err != nil { - errs = append(errs, fmt.Errorf("error closing conn after setting read deadline: %w", err)) - } - + err = fmt.Errorf("error setting a read deadline: %w", err) return } - // The context here is only used for cancellation, not deadline timeout, so - // use context.Background(). The read timeout is set by calling - // SetReadDeadline above. - _, _, err = conn.read(context.Background()) - read = time.Now() - if err != nil { - errs = append(errs, fmt.Errorf("error reading: %w", err)) - - connClosed = true - err := conn.close() + if size == 0 { + var sizeBuf [4]byte + _, err = io.ReadFull(conn.nc, sizeBuf[:]) if err != nil { - errs = append(errs, fmt.Errorf("error closing conn after reading: %w", err)) + err = fmt.Errorf("error reading the message size: %w", err) + return } - - return + size, err = conn.parseWmSizeBytes(sizeBuf) + if err != nil { + return + } + size -= 4 + } + _, err = io.CopyN(io.Discard, conn.nc, int64(size)) + if err != nil { + err = fmt.Errorf("error discarding %d byte message: %w", size, err) } } @@ -886,19 +894,22 @@ func (p *pool) checkInNoEvent(conn *connection) error { // means that connections in "awaiting response" state are checked in but // not usable, which is not covered by the current pool events. We may need // to add pool event information in the future to communicate that. - if conn.awaitingResponse { - conn.awaitingResponse = false - go bgRead(p, conn) + if conn.awaitRemainingBytes != nil { + size := *conn.awaitRemainingBytes + conn.awaitRemainingBytes = nil + go bgRead(p, conn, size) return nil } - // Bump the connection idle deadline here because we're about to make the connection "available". - // The idle deadline is used to determine when a connection has reached its max idle time and - // should be closed. A connection reaches its max idle time when it has been "available" in the - // idle connections stack for more than the configured duration (maxIdleTimeMS). Set it before - // we call connectionPerished(), which checks the idle deadline, because a newly "available" - // connection should never be perished due to max idle time. - conn.bumpIdleDeadline() + // Bump the connection idle start time here because we're about to make the + // connection "available". The idle start time is used to determine how long + // a connection has been idle and when it has reached its max idle time and + // should be closed. A connection reaches its max idle time when it has been + // "available" in the idle connections stack for more than the configured + // duration (maxIdleTimeMS). Set it before we call connectionPerished(), + // which checks the idle deadline, because a newly "available" connection + // should never be perished due to max idle time. + conn.bumpIdleStart() r, perished := connectionPerished(conn) if !perished && conn.pool.getState() == poolClosed { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go index a29eea4..0623632 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/server.go @@ -730,7 +730,7 @@ func (s *Server) createConnection() *connection { WithWriteTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }), // We override whatever handshaker is currently attached to the options with a basic // one because need to make sure we don't do auth. - WithHandshaker(func(h Handshaker) Handshaker { + WithHandshaker(func(Handshaker) Handshaker { return operation.NewHello().AppName(s.cfg.appname).Compressors(s.cfg.compressionOpts). ServerAPI(s.cfg.serverAPI) }), diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology_options.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology_options.go index b5eb4a9..2c0518a 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology_options.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/topology/topology_options.go @@ -7,10 +7,10 @@ package topology import ( + "context" "crypto/tls" "fmt" "net/http" - "strings" "time" "go.mongodb.org/mongo-driver/event" @@ -71,9 +71,80 @@ func newLogger(opts *options.LoggerOptions) (*logger.Logger, error) { return log, nil } -// NewConfig will translate data from client options into a topology config for building non-default deployments. -// Server and topology options are not honored if a custom deployment is used. +// convertOIDCArgs converts the internal *driver.OIDCArgs into the equivalent +// public type *options.OIDCArgs. +func convertOIDCArgs(args *driver.OIDCArgs) *options.OIDCArgs { + if args == nil { + return nil + } + return &options.OIDCArgs{ + Version: args.Version, + IDPInfo: (*options.IDPInfo)(args.IDPInfo), + RefreshToken: args.RefreshToken, + } +} + +// ConvertCreds takes an [options.Credential] and returns the equivalent +// [driver.Cred]. +func ConvertCreds(cred *options.Credential) *driver.Cred { + if cred == nil { + return nil + } + + var oidcMachineCallback auth.OIDCCallback + if cred.OIDCMachineCallback != nil { + oidcMachineCallback = func(ctx context.Context, args *driver.OIDCArgs) (*driver.OIDCCredential, error) { + cred, err := cred.OIDCMachineCallback(ctx, convertOIDCArgs(args)) + return (*driver.OIDCCredential)(cred), err + } + } + + var oidcHumanCallback auth.OIDCCallback + if cred.OIDCHumanCallback != nil { + oidcHumanCallback = func(ctx context.Context, args *driver.OIDCArgs) (*driver.OIDCCredential, error) { + cred, err := cred.OIDCHumanCallback(ctx, convertOIDCArgs(args)) + return (*driver.OIDCCredential)(cred), err + } + } + + return &auth.Cred{ + Source: cred.AuthSource, + Username: cred.Username, + Password: cred.Password, + PasswordSet: cred.PasswordSet, + Props: cred.AuthMechanismProperties, + OIDCMachineCallback: oidcMachineCallback, + OIDCHumanCallback: oidcHumanCallback, + } +} + +// NewConfig will translate data from client options into a topology config for +// building non-default deployments. func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, error) { + var authenticator driver.Authenticator + var err error + if co.Auth != nil { + authenticator, err = auth.CreateAuthenticator( + co.Auth.AuthMechanism, + ConvertCreds(co.Auth), + co.HTTPClient, + ) + if err != nil { + return nil, fmt.Errorf("error creating authenticator: %w", err) + } + } + return NewConfigWithAuthenticator(co, clock, authenticator) +} + +// NewConfigWithAuthenticator will translate data from client options into a +// topology config for building non-default deployments. Server and topology +// options are not honored if a custom deployment is used. It uses a passed in +// authenticator to authenticate the connection. +func NewConfigWithAuthenticator( + co *options.ClientOptions, + clock *session.ClusterClock, + authenticator driver.Authenticator, +) (*Config, error) { var serverAPI *driver.ServerAPIOptions if err := co.Validate(); err != nil { @@ -135,11 +206,11 @@ func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, for _, comp := range comps { switch comp { case "zlib": - connOpts = append(connOpts, WithZlibLevel(func(level *int) *int { + connOpts = append(connOpts, WithZlibLevel(func(*int) *int { return co.ZlibLevel })) case "zstd": - connOpts = append(connOpts, WithZstdLevel(func(level *int) *int { + connOpts = append(connOpts, WithZstdLevel(func(*int) *int { return co.ZstdLevel })) } @@ -156,35 +227,8 @@ func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, } // Handshaker - var handshaker = func(driver.Handshaker) driver.Handshaker { - return operation.NewHello().AppName(appName).Compressors(comps).ClusterClock(clock). - ServerAPI(serverAPI).LoadBalanced(loadBalanced) - } - // Auth & Database & Password & Username - if co.Auth != nil { - cred := &auth.Cred{ - Username: co.Auth.Username, - Password: co.Auth.Password, - PasswordSet: co.Auth.PasswordSet, - Props: co.Auth.AuthMechanismProperties, - Source: co.Auth.AuthSource, - } - mechanism := co.Auth.AuthMechanism - - if len(cred.Source) == 0 { - switch strings.ToUpper(mechanism) { - case auth.MongoDBX509, auth.GSSAPI, auth.PLAIN: - cred.Source = "$external" - default: - cred.Source = "admin" - } - } - - authenticator, err := auth.CreateAuthenticator(mechanism, cred) - if err != nil { - return nil, err - } - + var handshaker func(driver.Handshaker) driver.Handshaker + if authenticator != nil { handshakeOpts := &auth.HandshakeOptions{ AppName: appName, Authenticator: authenticator, @@ -192,16 +236,15 @@ func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, ServerAPI: serverAPI, LoadBalanced: loadBalanced, ClusterClock: clock, - HTTPClient: co.HTTPClient, } - if mechanism == "" { + if co.Auth.AuthMechanism == "" { // Required for SASL mechanism negotiation during handshake - handshakeOpts.DBUser = cred.Source + "." + cred.Username + handshakeOpts.DBUser = co.Auth.AuthSource + "." + co.Auth.Username } if co.AuthenticateToAnything != nil && *co.AuthenticateToAnything { // Authenticate arbiters - handshakeOpts.PerformAuthentication = func(serv description.Server) bool { + handshakeOpts.PerformAuthentication = func(description.Server) bool { return true } } @@ -209,7 +252,17 @@ func NewConfig(co *options.ClientOptions, clock *session.ClusterClock) (*Config, handshaker = func(driver.Handshaker) driver.Handshaker { return auth.Handshaker(nil, handshakeOpts) } + } else { + handshaker = func(driver.Handshaker) driver.Handshaker { + return operation.NewHello(). + AppName(appName). + Compressors(comps). + ClusterClock(clock). + ServerAPI(serverAPI). + LoadBalanced(loadBalanced) + } } + connOpts = append(connOpts, WithHandshaker(handshaker)) // ConnectTimeout if co.ConnectTimeout != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage/wiremessage.go b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage/wiremessage.go index 2199f85..987ae16 100644 --- a/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage/wiremessage.go +++ b/vendor/go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage/wiremessage.go @@ -381,16 +381,9 @@ func ReadMsgSectionSingleDocument(src []byte) (doc bsoncore.Document, rem []byte // ReadMsgSectionDocumentSequence reads an identifier and document sequence from src and returns the document sequence // data parsed into a slice of BSON documents. func ReadMsgSectionDocumentSequence(src []byte) (identifier string, docs []bsoncore.Document, rem []byte, ok bool) { - length, rem, ok := readi32(src) - if !ok || int(length) > len(src) { - return "", nil, rem, false - } - - rem, ret := rem[:length-4], rem[length-4:] // reslice so we can just iterate a loop later - - identifier, rem, ok = readcstring(rem) + identifier, rem, ret, ok := ReadMsgSectionRawDocumentSequence(src) if !ok { - return "", nil, rem, false + return "", nil, src, false } docs = make([]bsoncore.Document, 0) @@ -403,7 +396,7 @@ func ReadMsgSectionDocumentSequence(src []byte) (identifier string, docs []bsonc docs = append(docs, doc) } if len(rem) > 0 { - return "", nil, append(rem, ret...), false + return "", nil, src, false } return identifier, docs, ret, true @@ -413,8 +406,8 @@ func ReadMsgSectionDocumentSequence(src []byte) (identifier string, docs []bsonc // sequence data. func ReadMsgSectionRawDocumentSequence(src []byte) (identifier string, data []byte, rem []byte, ok bool) { length, rem, ok := readi32(src) - if !ok || int(length) > len(src) { - return "", nil, rem, false + if !ok || int(length) > len(src) || length-4 < 0 { + return "", nil, src, false } // After these assignments, rem will be the data containing the identifier string + the document sequence bytes and @@ -423,7 +416,7 @@ func ReadMsgSectionRawDocumentSequence(src []byte) (identifier string, data []by identifier, rem, ok = readcstring(rem) if !ok { - return "", nil, rem, false + return "", nil, src, false } return identifier, rem, rest, true @@ -546,14 +539,6 @@ func ReadCompressedCompressorID(src []byte) (id CompressorID, rem []byte, ok boo return CompressorID(src[0]), src[1:], true } -// ReadCompressedCompressedMessage reads the compressed wiremessage to dst. -func ReadCompressedCompressedMessage(src []byte, length int32) (msg []byte, rem []byte, ok bool) { - if len(src) < int(length) { - return nil, src, false - } - return src[:length], src[length:], true -} - // ReadKillCursorsZero reads the zero field from src. func ReadKillCursorsZero(src []byte) (zero int32, rem []byte, ok bool) { return readi32(src) diff --git a/vendor/modules.txt b/vendor/modules.txt index 7f0e9e6..5f1dd42 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -107,7 +107,7 @@ github.com/youmark/pkcs8 # github.com/yusufpapurcu/wmi v1.2.4 ## explicit; go 1.16 github.com/yusufpapurcu/wmi -# go.mongodb.org/mongo-driver v1.16.1 +# go.mongodb.org/mongo-driver v1.17.1 ## explicit; go 1.18 go.mongodb.org/mongo-driver/bson go.mongodb.org/mongo-driver/bson/bsoncodec