MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Verbinden von MongoDB mit Ruby mit selbstsignierten Zertifikaten für SSL

Angesichts der Beliebtheit unseres Beitrags zur Verbindung von MongoDB SSL mit selbstsignierten Zertifikaten in Node.js haben wir uns entschieden, ein Tutorial zur Verbindung von MongoDB mit Ruby zu schreiben. In diesem Blog zeigen wir Ihnen, wie Sie mit dem Ruby MongoDB-Treiber und dem beliebten Object-Document-Mapper (ODM) mongoid eine Verbindung zu einem MongoDB-Server herstellen, der mit selbstsignierten Zertifikaten für SSL konfiguriert ist.

ScaleGrid verwendet derzeit selbstsignierte Zertifikate für SSL, wenn Knoten für einen neuen Cluster erstellt werden. Darüber hinaus bieten wir Ihnen auch die Möglichkeit, Ihre eigenen SSL-Zertifikate zu erwerben und sie auf dem MongoDB-Server zu konfigurieren, und Sie können eine E-Mail an [email protected] senden, um mehr über dieses Angebot zu erfahren.

Herstellen einer Verbindung zu einem Replikatsatz mithilfe des Ruby MongoDB-Treibers

Für dieses Beispiel verwenden wir die neueste stabile Ruby MongoDB-Treiberversion 2.8. Die 2.5.x-Versionen des Treibers haben einen bekannten Fehler, der sie daran hindert, mit ScaleGrid-Bereitstellungen zu arbeiten. Die Ruby-Version, die in den beiden folgenden Beispielen verwendet wird, ist 2.6.3.

Die für den Treiber verfügbaren Verbindungsoptionen sind hier dokumentiert, und die Optionen, die wir benötigen, sind:

  • :ssl
  • :ssl_verify
  • :ssl_ca_cert .

Suchen und kopieren Sie zuerst Ihre MongoDB-Verbindungszeichenfolge von der Cluster-Detailseite in der ScaleGrid-Konsole:

Die CA-Zertifikatsdatei steht auch auf der Cluster-Detailseite zum Download zur Verfügung. Laden Sie die Zertifikatsdatei herunter und speichern Sie sie an einem Ort, der für die Anwendung verfügbar ist:
Hier ist ein Ausschnitt, der zeigt, wie man von Ruby aus eine Verbindung zu einem MongoDB-Replikatsatz herstellt:

require 'mongo'Mongo::Logger.logger.level =::Logger::DEBUGMONGODB_CA_CERT ="/path/to/ca_cert.pem"MONGODB_CONN_URL ="mongodb://testuser:@SG-example- 17026.servers.mongodirector.com:27017,SG-example-17027.servers.mongodirector.com:27017,SG-example-17028.servers.mongodirector.com:27017/test?replicaSet=RS-example-0&ssl=true" options ={ ssl:true, ssl_verify:true, :ssl_ca_cert => MONGODB_CA_CERT }client =Mongo::Client.new(MONGODB_CONN_URL, options)db =client.databasecollections =db.collection_namesputs "db #{db.name} hat Sammlungen # {Sammlungen}"client.close

Um das Beispiel einfach zu halten, haben wir die Verbindungszeichenfolge und den Pfad der Zertifikatsdatei direkt im Code-Snippet angegeben – Sie würden sie im Allgemeinen entweder in eine YAML-Datei einfügen oder als angeben Umgebungsvariablen. Außerdem legt das Beispiel die Protokollebene auf DEBUG fest damit Verbindungsprobleme behoben werden können. Es sollte auf eine weniger ausführliche Ebene geändert werden, sobald Verbindungsprobleme behoben wurden.

So verbinden Sie MongoDB mit einer Ruby-Anwendung mit SSLClick To Tweet

Verbindung mit Mongoid herstellen

Die mongoide Version, die wir in unserem Beispiel verwenden werden, ist die neueste stabile Version – 7.0.2. Wir werden eine yaml-Datei verwenden, um Mongoid zu konfigurieren, und die Details einer solchen Konfigurationsdatei sind hier dokumentiert. Die SSL-spezifischen Konfigurationsoptionen, die wir benötigen, um eine Verbindung zu unserem Replikatsatz herzustellen, sind:

  • ssl
  • ssl_verify
  • ssl_ca_cert

Unsere yml-Datei:

development:# Verfügbare Datenbankclients konfigurieren. (erforderlich) Clients:# Definieren Sie den Standardclient. (erforderlich) default:# Ein uri kann für einen Client definiert werden:# uri:'mongodb://user:[email protected]:27017/my_db' # Einzelheiten finden Sie in der Treiberdokumentation. Alternativ können Sie Folgendes definieren:# # Definieren Sie den Namen der Standarddatenbank, mit der sich Mongoid verbinden kann. # (erforderlich). database:test # Geben Sie die Hosts an, mit denen sich der Standardclient verbinden kann. Muss ein Array # von Host:Port-Paaren sein. (erforderlich) Hosts:- SG-example-17026.servers.mongodirector.com:27017 - SG-example-17027.servers.mongodirector.com:27017 - SG-example-17028.servers.mongodirector.com:47100  Optionen:# Der Name des Benutzers für die Authentifizierung. Benutzer:'Testbenutzer' # Das Passwort des Benutzers zur Authentifizierung. Passwort:'pwd' # Die Datenbankrollen des Benutzers. roles:- 'readWrite' # Ändern Sie den Standard-Authentifizierungsmechanismus. Gültige Optionen sind::scram, # :mongodb_cr, :mongodb_x509 und :plain. (Standard bei 3.0 ist :scram, Standard # bei 2.4 und 2.6 ist :plain) auth_mech::scram # Die Datenbank oder Quelle, gegen die der Benutzer authentifiziert wird. (Standard:admin) auth_source:test # Zwingen Sie den Treiber dazu, sich auf eine bestimmte Weise zu verbinden, anstatt # automatisch zu erkennen. Kann eines sein von::direct, :replica_set, :sharded. Auf :direct # setzen, wenn eine Verbindung zu verborgenen Mitgliedern eines Replikatsatzes hergestellt wird. connect::replica_set ... ... # Der Name des Replikatsatzes, zu dem eine Verbindung hergestellt werden soll. Als Seeds bereitgestellte Server, die # nicht zu diesem Replikatsatz gehören, werden ignoriert. replica_set:RS-Beispiel-0 # Ob eine Verbindung zu den Servern über SSL hergestellt werden soll. (Standard:falsch) ssl:wahr # Ob Peer-Zertifizierungsvalidierung durchgeführt werden soll oder nicht. (Standard:wahr) ssl_verify:wahr # Die Datei, die einen Satz verketteter Zertifizierungsstellen-Zertifizierungen # enthält, die verwendet werden, um Zertifikate zu validieren, die vom anderen Ende der Verbindung übergeben werden. ssl_ca_cert:/path/to/ca_cert.pem # Mongoid-spezifische Optionen konfigurieren. (optionale) Optionen:# Legen Sie die Protokollebenen der Mongoid- und Ruby-Treiber fest. (Standard::info) log_level::debug

Verbindungsbeispiel:

Gem 'mongoid', '7.0.2'require 'mongoid'Mongoid.load!("/path/to/mongoid.yml", :development)# Keine der ODM-Funktionen verwenden - einfach den zugrunde liegenden Mongo abrufen Client und Verbindungsversuchclient =Mongoid::Clients.defaultdb =client.databasecollections =db.collection_namesputs "db #{db.name} hat Sammlungen #{collections}"Mongoid::Clients.disconnect

Auch hier würde in Produktionsanwendungen von Ruby on Rails der yaml-Dateipfad aus den Umgebungsvariablen übernommen.

Failover-Verhalten testen

Wie andere MongoDB-Treiber ist auch der Ruby MongoDB-Treiber darauf ausgelegt, Änderungen in der Topologie aufgrund von Ereignissen wie Failover intern zu erkennen. Es empfiehlt sich jedoch, das Verhalten des Treibers während Failovers zu testen und zu validieren, um Überraschungen in der Produktion zu vermeiden.

Wie in meinem vorherigen Beitrag zu MongoDB PyMongo können wir ein Testprogramm für den Dauerschreiber schreiben, um das Failover-Verhalten des Treibers zu beobachten.

Der einfachste Weg, ein Failover herbeizuführen, ist die Ausführung des Befehls rs.stepDown():

RS-example-0:PRIMARY> rs.stepDown()2019-04-18T19:44:42.257+0530 E QUERY [thread1] Fehler:Fehler beim Ausführen der Abfrage:Fehlgeschlagen:Netzwerkfehler beim Versuch, den Befehl „replSetStepDown“ auszuführen auf dem Host „SG-example-1.servers.mongodirector.com:27017“ :DB.prototype.runCommand@src/mongo/shell/db.js:168:1DB.prototype.adminCommand@src/mongo/shell/db. js:185:1rs.stepDown@src/mongo/shell/utils.js:1305:12@(shell):1:12019-04-18T19:44:42.261+0530 I NETZWERK [thread1] versucht, sich wieder mit SG-Beispiel zu verbinden -1.servers.mongodirector.com:27017 (X.X.X.X) fehlgeschlagen2019-04-18T19:44:43.267+0530 I NETZWERK [thread1] SG-Beispiel erneut verbinden-1.servers.mongodirector.com:27017 (X.X.X.X) okRS-Beispiel- 0:SEKUNDÄRE 

Hier sind die relevanten Teile unseres Testcodes:

erfordert 'mongo'...logger =Logger.new(STDOUT)logger.level =Logger::INFOMONGODB_CA_CERT ="/path/to/ca_cert.pem"MONGODB_CONN_URL ="mongodb://testuser:@ SG-Beispiel-17026.servers.mongodirector.com:27017,SG-Beispiel-17027.servers.mongodirector.com:27017,SG-Beispiel-17028.servers.mongodirector.com:27017/test?replicaSet=RS-Beispiel- 0&ssl=true"options ={ ssl:true, ssl_verify:true, :ssl_ca_cert => MONGODB_CA_CERT }begin logger.info("Attempting to connect...") client =Mongo::Client.new(MONGODB_CONN_URL, options) i =0 loop do db =client.database collection =db[:test] begin doc ={"idx":i, "date":DateTime.now, "text":SecureRandom.base64(3) } result =collection.insert_one( doc) logger.info("Datensatz eingefügt - ID:#{result.inserted_id}") i +=1 sleep(3) rescue Mongo::Error => e logger.error("Mong-Fehler gesehen:#{e.message }") logger.error(e.backtrace) logger.i nfo("Erneuter Versuch...") end end logger.info("Fertig")rescue => err logger.error("Exception seen:#{err.message}") logger.error(err.backtrace)ensure client. Schließen, es sei denn, client.nil?end

Dies schreibt kontinuierlich Einträge wie diese in die Testsammlung in der Testdatenbank:

RS-test-0:PRIMARY> db.test.find(){ "_id" :ObjectId("5cf50ff1896cd172a4f7c6ee"), "idx" :0, "date" :ISODate("2019-06-03T12:17 :53.008Z"), "text" :"HTvd" }{ "_id" :ObjectId("5cf50ff6896cd172a4f7c6ef"), "idx" :1, "date" :ISODate("2019-06-03T12:17:58.697Z" ), „text“ :„/e5Z“ }{ „_id“ :ObjectId(“5cf50ff9896cd172a4f7c6f0“), „idx“ :2, „date“ :ISODate(“2019-06-03T12:18:01.940Z“), „ text“ :„quuw“ }{ „_id“ :ObjectId(“5cf50ffd896cd172a4f7c6f1“), „idx“ :3, „date“ :ISODate(“2019-06-03T12:18:05.194Z“), „text“ :„ gTyY“ }{ „_id“ :ObjectId(“5cf51000896cd172a4f7c6f2“), „idx“ :4, „date“ :ISODate(“2019-06-03T12:18:08.442Z“), „text“ :„VDXX“ }{ „_id“ :ObjectId(“5cf51003896cd172a4f7c6f3“), „idx“ :5, „date“ :ISODate(“2019-06-03T12:18:11.691Z“), „text“ :„UY87“ }... 

Sehen wir uns das Verhalten während eines Failovers an:

I, [2019-06-03T17:53:25.079829 #9464] INFO -- :Verbindungsversuch...I, [2019-06-03T17:53:30.577099 #9464] INFO -- :Datensatz eingefügt - id:5cf5113f896cd124f8f31062I, [2019-06-03T17:53:33.816528 #9464] INFO -- :Datensatz eingefügt - id:5cf51145896cd124f8f31063I, [2019-06-03T17:53:37.0463I, [2019-06-03T17:53:37.0464] 5CF51148896CD124F8F31064I, [2019-06-03T17:53:40.281537 #9464] Info-:Aufnahme eingefügt-ID:5CF5114C896CD124F8F31065I, [2019-06-03t17:53199965):[2019-06-03t17:53:43.5200106. [2019-06-03T17:53:46.747080 #9464] INFO -- :Datensatz eingefügt - ID:5cf51152896cd124f8f31067I, [2019-06-03T17:53:49.978077 #9464] INFO -- :Datensatz eingefügt - ID:5cf511155 Failover initiiert hereE, [2019-06-03T17:53:52.980434 #9464] FEHLER -- :Mong-Fehler gesehen:EOFError:Dateiende erreicht (für x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017 , TLS))E, [2019-06-03T17:53:52.980533 #9464] FEHLER -- :["C:/Ruby 26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:300:in `rescue in handle_errors'", "C:/Ruby26-x64/lib/ ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:294:in `handle_errors'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/ gems/mongo-2.8.0/lib/mongo/socket.rb:126:in `read'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/ lib/mongo/protocol/message.rb:139:in `deserialize'",......I, [2019-06-03T17:53:52.980688 #9464] INFO -- :Retrying...W, [ 2019-06-03T17:53:52.981575 #9464] WARN -- :Wiederholung von ismaster auf sg-example-17026.servers.mongodirector.com:27017 wegen:Mongo::Error::SocketError EOFError:Dateiende erreicht (for x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS))I, [2019-06-03T17:54:06.293100 #9464] INFO -- :Datensatz eingefügt - ID:5cf51163896cd124f8f3106aI, [2019- 06-03T17:54:09.547716 #9464] INFO -- :Datensatz eingefügt - ID:5cf51169896cd124f8f3106bI, [2019-06-03T17:54:12.806636 #9464] INFO -- :Datensatz eingefügt - ID:5cf5116c896cd1 wieder> 

Es ist offensichtlich, dass der Treiber automatisch die Topologieänderung erkennt und sich wieder mit dem neuen Master verbindet, wenn korrekte Fehler abgefangen und Lese-/Schreibvorgänge wiederholt werden. Für Schreibvorgänge die Option :retry_writes Stellen Sie sicher, dass der Treiber es einmal selbst versucht, bevor er die Anwendung über einen Fehler benachrichtigt.

Es gibt auch mehrere Treiber-Timeouts, die basierend auf dem genauen Verhalten und der Latenz, die Sie in Ihrem Setup sehen, angepasst werden können. Diese sind hier dokumentiert.

Fehlerbehebung

Wenn Sie Probleme haben, eine Verbindung zu Ihrer SSL-fähigen MongoDB-Bereitstellung herzustellen, finden Sie hier einige Tipps zum Debuggen:

  • Vergewissern Sie sich zunächst, dass Sie von dem Server, auf dem Ihre Anwendung ausgeführt wird, tatsächlich eine Verbindung zum MongoDB-Server herstellen können. Der einfachste Weg, dies zu tun, besteht darin, die Mongo-Shell auf dem Client-Computer zu installieren. Unter Linux müssten Sie nicht den gesamten MongoDB-Server installieren – Sie können die Shell einfach separat installieren. Sobald die Shell verfügbar ist, versuchen Sie, die von uns bereitgestellte „Befehlszeilensyntax“ zu verwenden, um zu versuchen, eine Verbindung zum Server herzustellen.
  • Wenn Sie keine Verbindung über die Mongo-Shell herstellen können, bedeutet dies, dass der Client-Computer den Port 27017 der MongoDB-Server nicht erreichen kann. Überprüfen Sie Ihre Sicherheitsgruppen-, VPC- und ScaleGrid-Firewalleinstellungen, um sicherzustellen, dass eine Verbindung zwischen den Client- und Servercomputern besteht.
  • Wenn die Netzwerkkonnektivität korrekt ist, müssen Sie als nächstes überprüfen, ob Sie Versionen von Ruby, mongoid und mongo gem verwenden, die mit der Version kompatibel sind Ihres MongoDB-Servers.
  • Wenn Sie bestätigt haben, dass die Treiberversionen korrekt sind, versuchen Sie, ein Beispiel-Ruby-Skript ähnlich dem oben bereitgestellten Beispiel auf dem IRB auszuführen. Eine schrittweise Ausführung könnte darauf hinweisen, wo das Problem liegt.
  • Wenn das Testskript gut läuft, Sie aber immer noch keine Verbindung mit mongoid herstellen können, versuchen Sie, ein einfaches Testskript auszuführen, wie in dem Beispiel, das wir oben bereitgestellt haben .
  • Wenn Sie immer noch Probleme haben, sich mit Ihrer Instanz zu verbinden, schreiben Sie uns bitte unter [email protected] mit detaillierten Ergebnissen der oben genannten Schritte zur Fehlerbehebung und mit die genauen Versionen von Ruby, Mongoid und Mongo-Treiber, die Sie verwenden. Die Gemfile.lock liefert Ihnen die genauen Versionen.

Wenn Sie neu bei ScaleGrid sind und dieses Tutorial ausprobieren möchten, melden Sie sich für eine kostenlose 30-Tage-Testversion an, um die Plattform zu erkunden und auszuprobieren Verbindung von MongoDB mit Ihrer Ruby-Anwendung.