github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/x/mongo/driver/auth/x509.go (about)

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package auth
     8  
     9  import (
    10  	"context"
    11  
    12  	"go.mongodb.org/mongo-driver/mongo/description"
    13  	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
    14  	"go.mongodb.org/mongo-driver/x/mongo/driver"
    15  	"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
    16  )
    17  
    18  // MongoDBX509 is the mechanism name for MongoDBX509.
    19  const MongoDBX509 = "MONGODB-X509"
    20  
    21  func newMongoDBX509Authenticator(cred *Cred) (Authenticator, error) {
    22  	return &MongoDBX509Authenticator{User: cred.Username}, nil
    23  }
    24  
    25  // MongoDBX509Authenticator uses X.509 certificates over TLS to authenticate a connection.
    26  type MongoDBX509Authenticator struct {
    27  	User string
    28  }
    29  
    30  var _ SpeculativeAuthenticator = (*MongoDBX509Authenticator)(nil)
    31  
    32  // x509 represents a X509 authentication conversation. This type implements the SpeculativeConversation interface so the
    33  // conversation can be executed in multi-step speculative fashion.
    34  type x509Conversation struct{}
    35  
    36  var _ SpeculativeConversation = (*x509Conversation)(nil)
    37  
    38  // FirstMessage returns the first message to be sent to the server.
    39  func (c *x509Conversation) FirstMessage() (bsoncore.Document, error) {
    40  	return createFirstX509Message(description.Server{}, ""), nil
    41  }
    42  
    43  // createFirstX509Message creates the first message for the X509 conversation.
    44  func createFirstX509Message(desc description.Server, user string) bsoncore.Document {
    45  	elements := [][]byte{
    46  		bsoncore.AppendInt32Element(nil, "authenticate", 1),
    47  		bsoncore.AppendStringElement(nil, "mechanism", MongoDBX509),
    48  	}
    49  
    50  	// Server versions < 3.4 require the username to be included in the message. Versions >= 3.4 will extract the
    51  	// username from the certificate.
    52  	if desc.WireVersion != nil && desc.WireVersion.Max < 5 {
    53  		elements = append(elements, bsoncore.AppendStringElement(nil, "user", user))
    54  	}
    55  
    56  	return bsoncore.BuildDocument(nil, elements...)
    57  }
    58  
    59  // Finish implements the SpeculativeConversation interface and is a no-op because an X509 conversation only has one
    60  // step.
    61  func (c *x509Conversation) Finish(context.Context, *Config, bsoncore.Document) error {
    62  	return nil
    63  }
    64  
    65  // CreateSpeculativeConversation creates a speculative conversation for X509 authentication.
    66  func (a *MongoDBX509Authenticator) CreateSpeculativeConversation() (SpeculativeConversation, error) {
    67  	return &x509Conversation{}, nil
    68  }
    69  
    70  // Auth authenticates the provided connection by conducting an X509 authentication conversation.
    71  func (a *MongoDBX509Authenticator) Auth(ctx context.Context, cfg *Config) error {
    72  	requestDoc := createFirstX509Message(cfg.Description, a.User)
    73  	authCmd := operation.
    74  		NewCommand(requestDoc).
    75  		Database("$external").
    76  		Deployment(driver.SingleConnectionDeployment{cfg.Connection}).
    77  		ClusterClock(cfg.ClusterClock).
    78  		ServerAPI(cfg.ServerAPI)
    79  	err := authCmd.Execute(ctx)
    80  	if err != nil {
    81  		return newAuthError("round trip error", err)
    82  	}
    83  
    84  	return nil
    85  }