Class: Mongo::Server::PendingConnection Private

Inherits:
ConnectionBase show all
Extended by:
Forwardable
Defined in:
lib/mongo/server/pending_connection.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

This class encapsulates connections during handshake and authentication.

Since:

  • 2.0.0

Constant Summary

Constants inherited from ConnectionBase

ConnectionBase::DEFAULT_MAX_BSON_OBJECT_SIZE, ConnectionBase::MAX_BSON_COMMAND_OVERHEAD, ConnectionBase::REDUCED_MAX_BSON_SIZE

Constants included from Loggable

Loggable::PREFIX

Instance Attribute Summary collapse

Attributes inherited from ConnectionBase

#description, #options, #server

Attributes included from Monitoring::Publishable

#monitoring

Attributes inherited from ConnectionCommon

#compressor, #pid

Instance Method Summary collapse

Methods inherited from ConnectionBase

#app_metadata, #dispatch, #generation, #service_id

Methods included from Monitoring::Publishable

#publish_cmap_event, #publish_event, #publish_sdam_event

Methods included from Loggable

#log_debug, #log_error, #log_fatal, #log_info, #log_warn, #logger

Methods inherited from ConnectionCommon

#connected?, #handshake_command, #handshake_document

Constructor Details

#initialize(socket, server, monitoring, options = {}) ⇒ PendingConnection

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of PendingConnection.

Since:

  • 2.0.0



27
28
29
30
31
32
33
# File 'lib/mongo/server/pending_connection.rb', line 27

def initialize(socket, server, monitoring, options = {})
  @socket = socket
  @options = options
  @server = server
  @monitoring = monitoring
  @id = options[:id]
end

Instance Attribute Details

#idInteger (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The ID for the connection. This is the same ID as that of the regular Connection object for which this PendingConnection instance was created.

Returns:

  • (Integer)

    The ID for the connection. This is the same ID as that of the regular Connection object for which this PendingConnection instance was created.

Since:

  • 2.0.0



38
39
40
# File 'lib/mongo/server/pending_connection.rb', line 38

def id
  @id
end

Instance Method Details

#handshake_and_authenticate!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.0.0



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/mongo/server/pending_connection.rb', line 40

def handshake_and_authenticate!
  speculative_auth_doc = nil
  if options[:user] || options[:auth_mech]
    # To create an Auth instance, we need to specify the mechanism,
    # but at this point we don't know the mechanism that ultimately
    # will be used (since this depends on the data returned by
    # the handshake, specifically server version).
    # However, we know that only 4.4+ servers support speculative
    # authentication, and those servers also generally support
    # SCRAM-SHA-256. We expect that user accounts created for 4.4+
    # servers would generally allow SCRAM-SHA-256 authentication;
    # user accounts migrated from pre-4.4 servers may only allow
    # SCRAM-SHA-1. The use of SCRAM-SHA-256 by default is thus
    # sensible, and it is also mandated by the speculative auth spec.
    # If no mechanism was specified and we are talking to a 3.0+
    # server, we'll send speculative auth document, the server will
    # ignore it and we'll perform authentication using explicit
    # command after having defaulted the mechanism later to CR.
    # If no mechanism was specified and we are talking to a 4.4+
    # server and the user account doesn't allow SCRAM-SHA-256, we will
    # authenticate in a separate command with SCRAM-SHA-1 after
    # going through SCRAM mechanism negotiation.
    default_options = Options::Redacted.new(:auth_mech => :scram256)
    speculative_auth_user = Auth::User.new(default_options.merge(options))
    speculative_auth = Auth.get(speculative_auth_user, self)
    speculative_auth_doc = speculative_auth.conversation.speculative_auth_document
  end

  result = handshake!(speculative_auth_doc: speculative_auth_doc)

  if description.unknown?
    raise Error::InternalDriverError, "Connection description cannot be unknown after successful handshake: #{description.inspect}"
  end

  begin
    if speculative_auth_doc && (speculative_auth_result = result['speculativeAuthenticate'])
      unless description.features.scram_sha_1_enabled?
        raise Error::InvalidServerAuthResponse, "Speculative auth succeeded on a pre-3.0 server"
      end
      case speculative_auth_user.mechanism
      when :mongodb_x509
        # Done
      # We default auth mechanism to scram256, but if user specified
      # scram explicitly we may be able to authenticate speculatively
      # with scram.
      when :scram, :scram256
        authenticate!(
          speculative_auth_client_nonce: speculative_auth.conversation.client_nonce,
          speculative_auth_mech: speculative_auth_user.mechanism,
          speculative_auth_result: speculative_auth_result,
        )
      else
        raise Error::InternalDriverError, "Speculative auth unexpectedly succeeded for mechanism #{speculative_auth_user.mechanism.inspect}"
      end
    elsif !description.arbiter?
      authenticate!
    end
  rescue Mongo::Error, Mongo::Error::AuthError => exc
    exc.service_id = service_id
    raise
  end

  if description.unknown?
    raise Error::InternalDriverError, "Connection description cannot be unknown after successful authentication: #{description.inspect}"
  end

  if server.load_balancer? && !description.mongos?
    raise Error::BadLoadBalancerTarget, "Load-balanced operation requires being connected a mongos, but the server at #{address.seed} reported itself as #{description.server_type.to_s.gsub('_', ' ')}"
  end
end