Med tanke på populariteten för vårt inlägg om att ansluta MongoDB SSL med självsignerade certifikat i Node.js, bestämde vi oss för att skriva en handledning om att ansluta MongoDB med Ruby. I den här bloggen visar vi dig hur du ansluter till en MongoDB-server konfigurerad med självsignerade certifikat för SSL med både Ruby MongoDB-drivrutinen och den populära Object-Document-Mapper (ODM)-mongoiden.
ScaleGrid använder för närvarande självsignerade certifikat för SSL när man skapar noder för ett nytt kluster. Dessutom ger vi dig också möjligheten att köpa dina egna SSL-certifikat och konfigurera dem på MongoDB-servern, och du kan maila [email protected] för att lära dig mer om detta erbjudande.
Ansluta till en replikuppsättning med Ruby MongoDB-drivrutin
Vi kommer att använda den senaste stabila Ruby MongoDB-drivrutinen version 2.8 för detta exempel. 2.5.x-versionerna av drivrutinen har en känd bugg som hindrar dem från att arbeta med ScaleGrid-distributioner. Ruby-versionen som används i båda exemplen nedan är 2.6.3.
De tillgängliga anslutningsalternativen för drivrutinen dokumenteras här, och alternativen vi behöver är:
- :ssl
- :ssl_verify
- :ssl_ca_cert .
Först, hitta och kopiera din MongoDB-anslutningssträng från klusterinformationssidan på ScaleGrid-konsolen:
CA-certifikatfilen är också tillgänglig för nedladdning från klustrets informationssida. Ladda ner och lagra certifikatfilen på en plats som är tillgänglig för applikationen:
Här är ett utdrag som visar hur man ansluter till en MongoDB-replikuppsättning från Ruby:
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&sl" 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} has collections #name} {collections}"client.close
För att hålla exemplet enkelt har vi specificerat anslutningssträngen och cert-filsökvägen direkt i kodavsnittet – du skulle vanligtvis antingen lägga dem i en yaml-fil eller ange dem som Miljövariabler. Exemplet ställer också in loggnivån till DEBUG
så att eventuella anslutningsproblem kan felsökas. Den bör ändras till en mindre utförlig nivå när anslutningsproblem har lösts.
Hur man ansluter MongoDB till en Ruby-applikation med SSLClick To Tweet
Ansluter med Mongoid
Mongoidversionen vi kommer att använda i vårt exempel är den senaste stabila versionen – 7.0.2. Vi kommer att använda en yaml-fil för att tillhandahålla konfiguration till mongoid, och detaljerna för en sådan konfigurationsfil dokumenteras här. De SSL-specifika konfigurationsalternativen vi behöver för att ansluta till vår replikuppsättning är:
- ssl
- ssl_verify
- ssl_ca_cert
Vår yml-fil:
utveckling:# Konfigurera tillgängliga databasklienter. (obligatoriskt) klienter:# Definiera standardklienten. (obligatoriskt) standard:# En uri kan definieras för en klient:# uri:'mongodb://user:[email protected]:27017/my_db' # Se drivrutinsdokumentationen för detaljer. Alternativt kan du definiera följande:# # Definiera namnet på standarddatabasen som Mongoid kan ansluta till. # (obligatoriskt). databas:test # Ange de värdar som standardklienten kan ansluta till. Måste vara en array # av värd:port-par. (obligatoriskt) värdar:- SG-example-17026.servers.mongodirector.com:27017 - SG-example-17027.servers.mongodirector.com:27017 - SG-example-17028.servers.mongodirector.com:471000 alternativ:# Namnet på användaren för autentisering. användare:'testanvändare' # Användarens lösenord för autentisering. lösenord:'pwd' # Användarens databasroller. roller:- 'readWrite' # Ändra standardautentiseringsmekanismen. Giltiga alternativ är::scram, # :mongodb_cr, :mongodb_x509 och :plain. (standard på 3.0 är :scram, standard # på 2.4 och 2.6 är :plain) auth_mech::scram # Databasen eller källan att autentisera användaren mot. (standard:admin) auth_source:test # Tvinga föraren att ansluta på ett specifikt sätt istället för att automatiskt upptäcka. Kan vara en av::direkt, :replica_set, :sharded. Ställ in på :direct # när du ansluter till dolda medlemmar i en replikuppsättning. connect::replica_set ... ... # Namnet på replikuppsättningen att ansluta till. Servrar som tillhandahålls som frön som # inte tillhör denna replikuppsättning kommer att ignoreras. replikuppsättning:RS-exempel-0 # Om man ska ansluta till servrarna via ssl. (standard:falskt) ssl:sant # Om man ska göra peer-certifiering eller inte. (standard:sant) ssl_verify:sant # Filen som innehåller en uppsättning sammanlänkade certifieringsmyndighetscertifieringar # används för att validera certifikat som skickas från den andra änden av anslutningen. ssl_ca_cert:/path/to/ca_cert.pem # Konfigurera Mongoid-specifika alternativ. (valfritt) alternativ:# Ställ in Mongoid- och Ruby-drivrutinsloggnivåerna. (standard::info) log_level::debug
Anslutningsexempel:
gem 'mongoid', '7.0.2'require 'mongoid'Mongoid.load!("/path/to/mongoid.yml", :development)# Använder inte någon av ODM-funktionerna - bara hämta den underliggande mongo klient och försök att ansluta klient =Mongoid::Clients.defaultdb =client.databasecollections =db.collection_namesputs "db #{db.name} har samlingar #{collections}"Mongoid::Clients.disconnect
Återigen, i produktion av Ruby on Rails-applikationer, skulle yaml-filsökvägen plockas upp från miljövariablerna.
Testar failover-beteende
Precis som andra MongoDB-drivrutiner är Ruby MongoDB-drivrutinen också utformad för att internt känna igen förändringar i topologi på grund av händelser som failover. Det är dock bra att testa och validera förarens beteende under failovers för att undvika överraskningar i produktionen.
Precis som mitt tidigare inlägg på MongoDB PyMongo kan vi skriva ett evigt skribenttestprogram för att observera förarens failover-beteende.
Det enklaste sättet att framkalla failover är att köra kommandot rs.stepDown():
RS-example-0:PRIMARY> rs.stepDown()2019-04-18T19:44:42.257+0530 E QUERY [thread1] Fel:fel när fråga gjordes:misslyckades:nätverksfel vid försök att köra kommandot 'replSetStepDown' på värd '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 NETWORK [thread1] försöker återansluta till SG-exempel -1.servers.mongodirector.com:27017 (X.X.X.X) failed2019-04-18T19:44:43.267+0530 JAG NÄTVERK [tråd1] ansluter SG-example-1.servers.mongodirector.com:27017 (X)-ok.ex. 0:SECONDARY>
Här är de relevanta delarna av vår testkod:
require 'mongo'...logger =Logger.new(STDOUT)logger.level =Logger::INFOMONGODB_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 }begin logger.info("Försöker ansluta...") klient =Mongo::Client.new(MONGODB_CONN_URL, alternativ) i =0 loop do db =client.databas collection =db[:test] start doc ={"idx":i, "date":DateTime.now, "text":SecureRandom.base64(3) } result =collection.insert_one( doc) logger.info("Record inserted - id:#{result.inserted_id}") i +=1 sleep(3) rescue Mongo::Error => e logger.error("Mong Error sett:#{e.message }") logger.error(e.backtrace) logger.i nfo("Försöker igen...") end end logger.info("Klar")rescue => err logger.error("Undantag sett:#{err.meddelande}") logger.error(err.backtrace)ensure client. stäng om inte client.nil?end
Detta skriver kontinuerligt sådana här poster till testsamlingen på testdatabasen:
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, "datum" :ISODate("2019-06-03T12:697:58". ), "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" }... före>Låt oss se beteendet under en failover:
Jag, [2019-06-03T17:53:25.079829 #9464] INFO -- :Försöker ansluta...Jag, [2019-06-03T17:53:30.577099 #9464] INFO -- :Posten infogat - id:5cf5113f896cd124f8f31062I, [2019-06-03T17:53:33.816528 #9464] INFO -- :Record inserted - id:5cf51145896cd124f8f31063I, [2019-06-03T17:53:37.047043 #9464] INFO -- :Record inserted - id:5cf51148896cd124f8f31064I, [2019-06-03T17:53:40.281537 #9464] INFO -- :Record inserted - id:5cf5114c896cd124f8f31065I, [2019-06-03T17:53:43.520010 #9464] INFO -- :Record inserted - id:5cf5114f896cd124f8f31066I,; Failover initierad härE, [2019-06-03T17:53:52.980434 #9464] FEL -- :Mong Fel sett:EOFerror:slutet på filen nått (för x.x.x.x:27017 (sg-example-17026.directorservers.com:2go70directorservers.com:2go70directorservers. , TLS))E, [2019-06-03T17:53:52.980533 #9464] FEL -- :["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 -- :Försöker igen...W, [ 2019-06-03T17:53:52.981575 #9464] VARNA -- :Försöker ismaster igen på sg-example-17026.servers.mongodirector.com:27017 på grund av:Mongo::Error::SocketError EOFError nådd (för slutet av filen) x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS))I, [2019-06-03T17:54:06.293100 #9464] INFO -- :Post infogat - 5916cf id:5916cf-id:5911605-5916059111600000000 06-03T17:54:09.547716 #9464] INFO -- :Posten infogat - id:5cf51169896cd124f8f3106bI, [2019-06-03T17:54:12.8046636 insedd 6cd 6cd 1cd 2019:12.8046646] id 6cf 1cd 1cd 6cf 1cf 1cf 5f 1cf 2019. re>Det är uppenbart att om korrekta fel fångas upp och läs-/skrivförsöket görs om, kommer drivrutinen automatiskt att upptäcka topologiändringen och återansluta till den nya mastern. För skrivningar, alternativet :retry_writes se till att föraren försöker igen en gång på egen hand innan han meddelar tillämpningen av ett fel.
Det finns också flera drivrutiner som kan justeras baserat på det exakta beteendet och fördröjningen du ser i din installation. Dessa dokumenteras här.
Felsökning
Om du har problem med att ansluta till din SSL-aktiverade MongoDB-distribution, här är några tips för felsökning:
- Verifiera först att du faktiskt kan ansluta till MongoDB-servern från servern där din applikation körs. Det enklaste sättet att göra detta är att installera mongo shell på klientdatorn. På Linux skulle du inte behöva installera hela MongoDB-servern - du kan välja att bara installera skalet separat. När skalet är tillgängligt, försök att använda "Kommandoradssyntaxen" som vi tillhandahåller för att försöka ansluta till servern.
- Om du inte kan ansluta via mongo-skalet betyder det att klientdatorn inte kan nå port 27017 på MongoDB-servrarna. Titta på brandväggsinställningarna för säkerhetsgrupp, VPC och ScaleGrid för att säkerställa att det finns anslutning mellan klient- och serverdatorerna.
- Om nätverksanslutningen är korrekt är nästa sak att kontrollera att du använder versioner av Ruby, mongoid och mongo gem som är kompatibla med versionen på din MongoDB-server.
- Om du har bekräftat att drivrutinsversionerna är korrekta, prova att köra ett exempel på Ruby-skript, liknande exemplet vi gav ovan, på IRB. En steg-för-steg körning kan peka ut var problemet ligger.
- Om testskriptet fungerar bra, men du fortfarande inte kan ansluta till mongoid, försök att köra ett enkelt testskript, som exemplet vi gav ovan .
- Om du fortfarande har problem med att ansluta till din instans, skriv till oss på [email protected] med detaljerade resultat av ovanstående felsökningssteg och med de exakta versionerna av Ruby-, mongoid- och mongodrivrutinen du använder. Gemfile.lock ger dig de exakta versionerna.
Om du är ny på ScaleGrid och vill ge den här handledningen ett försök, registrera dig för en gratis 30-dagars provperiod för att utforska plattformen och testa ansluter MongoDB till din Ruby-applikation.