2017-10-24 3 views
0

Ich möchte den Electron Golong Wrapper für die QPid Proton-C-Bibliothek verwenden, um eine Verbindung zum Azure EventHub herzustellen.Verbinden mit dem AMQP 1.0 Azure EventHub mit QPid und dem Golong-Wrapper Elektron

Ich bin die folgenden SASL-Details in Kombination mit dem Host/Port/Namespace/Pfad erforderlich, um die Verbindungszeichenfolge zu erstellen, aber aus irgendeinem Grund bekomme ich immer die Fehlermeldung: connection reset by peer.

package main 

import (
    "fmt" 
    "os" 
    "strings" 
    "qpid.apache.org/amqp" 
    "qpid.apache.org/electron" 
) 

var (
    eventHubNamespaceName = "<MY_CUSTOM_NAMESPACE>" 
    eventHubName = "<MY_CUSTOM_NAME>" 
    eventHubSasKeyName = "<MY_CUSTOM_SAS_KEY_NAME>" 
    eventHubSasKey = "<MY_CUSTOM_SAS_KEY>" // this is the base64 encoded stuff 
) 

func main() { 

    sentChan := make(chan electron.Outcome) // Channel to receive acknowledgements. 
    container := electron.NewContainer(fmt.Sprintf("send[%v]", os.Getpid())) 

    urlStr := fmt.Sprintf("amqp://%s.servicebus.windows.net:5671/%s", eventHubNamespaceName, eventHubName) 
    fmt.Printf("The URL connection string: '%v'\n", urlStr) 

    // parse URL 
    url, err := amqp.ParseURL(urlStr) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Printf("The AMQP parsed URL: %v\n", url) 

    // TCP dial 
    amqpHost := url.Host 
    fmt.Printf("The AMQP host used in the connection is: '%v'\n", amqpHost) 
    c, err := container.Dial(
     "tcp", amqpHost, 
     electron.SASLEnable(), 
     electron.Password([]byte(eventHubSasKey)), 
     electron.User(eventHubSasKeyName), 
    ) 
    if err != nil { 
     panic(err) 
    } 
    defer c.Close(nil) 

    // AMQP send 
    addr := strings.TrimPrefix(url.Path, "/") 
    s, err := c.Sender(electron.Target(addr)) 
    if err != nil { 
     panic(err) 
    } 
    m := amqp.NewMessage() 
    body := fmt.Sprintf("bla bla bla %v", 42) 
    m.Marshal(body) 
    fmt.Printf("The AMQP message body: '%v'\n", m.Body()) 

    go s.SendAsync(m, sentChan, body) // Outcome will be sent to sentChan 

    // AMQP ACK receive 
    fmt.Printf("Waiting for ACKs...\n") 
    for { 
     fmt.Printf("Waiting for an ACK coming out of the channel...\n") 
     out := <-sentChan // Outcome of async sends. 
     fmt.Printf("Received something: '%v'\n", out) 
    } 
} 

Beim Kompilieren, dann den Code ausgeführt wird, ist dies die Ausgabe:

The URL connection string: 'amqp://<MY_CUSTOM_NAMESPACE>.servicebus.windows.net:5671/<MY_CUSTOM_NAME>' 
The AMQP parsed URL: 'amqp://<MY_CUSTOM_NAMESPACE>.servicebus.windows.net:5671/<MY_CUSTOM_NAME>' 
The AMQP host used in the connection is: '<MY_CUSTOM_NAMESPACE>.servicebus.windows.net:5671' 
The AMQP message body: 'bla bla bla 42' 
Waiting for ACKs... 
Waiting for an ACK coming out of the channel... 
Received something: '{unsent : read tcp <MY_PRIVATE_IP_IN_LAN>:<SOME_PORT>-><THE_NSLOOKUP_IP_OF_THE_AZURE_EVENTHUB>:5671: read: connection reset by peer bla bla bla 42}' 
Waiting for an ACK coming out of the channel... 

mir, dass Nachricht connection reset by peer wie ein gültiges ACK sieht nicht sagen, empfangen und ich bin nicht sicher, was mit falsch ist der Verbindungsversuch?

  • Die kompilierte Version von proton-c ist 0.18.0, ich bin mit go1.7.4 linux/amd64.
  • Wenn ich electron.SASLAllowedMechs("EXTERNAL") zu den Verbindungsoptionen hinzufügen, bekomme ich die gleiche Fehlermeldung.
  • Wenn ich den Port zu 5672 ändern, dann bekomme ich einen Panik-Fehler connection refused nach dem Versuch der Wahl über TCP.
  • Wenn ich das Base64-Passwort-Feld mit base64.StdEncoding.DecodeString(eventHubSasKey) entschlüsseln und die Bytes an die Verbindungsoptionen übergeben, bekomme ich den gleichen Fehler connection reset by peer.
  • Wenn ich diese Verbindungsoption hinzufügen electron.SASLAllowedMechs("ANONYMOUS"), dann bekomme ich immer noch die gleiche Fehlermeldung connection reset by peer. Der Grund dafür ist, dass ich kein SSL-Zertifikat verwende und der von Microsoft bereitgestellte Java-Wrapper zu AMQP scheint dieses "anonyme" Ding anstelle des Zertifikats zu verwenden (tatsächlich wird kein Zertifikat benötigt, um mit dem EventHub eine Verbindung herzustellen Java-Connector).

Ich bin nicht sicher, wie hier verfahren, wie ich in dem Verbindungsteil stecken bin, und ich glaube, dass die Details SASL in der richtigen Art und Weise übergeben nach dem docs hier: https://godoc.org/qpid.apache.org/electron#ConnectionOption

Ich bin noch nicht sicher, Der Grund für den Fehler liegt nicht in den SSL-Zertifikaten. Wenn dies der Fall ist, kämpfe ich darum, sie in den Prozess einzubeziehen.

Edit:

ich, dass ich eine TLS-Verbindung über TCP zu etablieren später herausgefunden hatte, auch wenn ich kein privates/öffentliches Schlüsselpaar an Bereitstellung, auch einen „virtuellen Host“ spezifiziere (sonst war AMQP beschwerte sich über den Host nicht erkennen):

// TLS connection details 
    tlsConfig := &tls.Config{} 
    eventHubDomainPort := fmt.Sprintf("%s.servicebus.windows.net:5671", eventHubNamespaceName) 
    tlsConn, err := tls.Dial("tcp", eventHubDomainPort, tlsConfig) 
    if err != nil { 
     panic(err) 
    } 

    // AMPQ container connection on top of TLS via TCP 
    eventHubDomain := fmt.Sprintf("%s.servicebus.windows.net", eventHubNamespaceName) 
    amqpConn, err := container.Connection(
     tlsConn, 
     electron.SASLEnable(), 
     electron.User(eventHubSasKeyName), 
     electron.Password([]byte(eventHubSasKey)), 
     electron.VirtualHost(eventHubDomain), 
     // electron.SASLAllowedMechs(<SOME_MECHANISM>), 
    ) 
    if err != nil { 
     panic(err) 
    } 
    defer amqpConn.Close(nil) 

    // AMQP sender (a AMQP link with target the name defined on the Azure portal) 
    s, err := amqpConn.Sender(electron.Target(eventHubName)) 
    if err != nil { 
     panic(err) 
    } 

jedoch, wenn die App mit der Umgebungsvariablen läuft PN_TRACE_FRM=true (die mir einige ausführliche Protokollierung auf der proton-c Ebene) jetzt der Fehler gibt, ist:

[handle=0, closed=true, [email protected](29) [condition=:"amqp:unauthorized-access", description="Unauthorized access. 'Send' claim(s) are required to perform this operation. Resource: 'sb://<MY_CUSTOM_NAMESPACE>.servicebus.windows.net/<MY_CUSTOM_NAME>'. TrackingId:<SOME_UUID-ISH_HERE>, SystemTracker:<A_LABEL_HERE>, Timestamp:10/25/2017 4:02:58 PM"]]

Diese afaik bedeutet, dass die SASL Details (Benutzername/Passwort) vom Typ „Sender“ sein muss, weil ich versuche, etwas an den Event-Hub zu senden. Ich habe diese Details im Azure-Portal geprüft (klicken Sie auf "Richtlinien für den gemeinsamen Zugriff"> und verwenden Sie die Richtlinie mit "Anspruch" als "Senden") und sie sind korrekt. Ich bin also nicht sicher, warum ich diesen Fehler bekomme.

Ich habe tatsächlich versucht, diese SASL-Richtlinien auf dem Azure-Portal auf verschiedenen Ebenen, <MY_CUSTOM_NAMESPACE> und <MY_CUSTOM_NAME>, aber immer die gleiche Fehlermeldung.

Ich habe auch versucht, verschiedene SASL Mechanismen, z. Bei Verwendung von electron.SASLAllowedMechs("PLAIN") dann bekomme ich diesen Fehler: no mechanism available: No worthy mechs found (Authentication failed [mech=none]).

+0

Der nicht autorisierte Zugriffsfehler bedeutet, dass der Client SASL PLAIN nicht ausführt oder die in sasl-init gesendeten SAS-Schlüsselinformationen nicht im erwarteten Format vorliegen. Was ist der Mechanismus in der sasl-init-Ablaufverfolgung? –

Antwort

0

Ich konnte eine Verbindung mit der "Claims-based Authorization" (CBS) über AMQP herstellen. Es scheint etwas spezifisch für Microsoft zu sein. Einige Details finden Sie unten auf dieser Seite finden: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-amqp-protocol-guide

Im Grunde ist dies die Liste der Schritte:

  • TLS-Verbindung mit electron.VirtualHost(eventHubDomain) und der ANONYMOUS SASL Mechanismus electron.SASLAllowedMechs("ANONYMOUS") (keine Notwendigkeit zu geben SASL-Benutzername und das Passwort). Überprüfen Sie die Details in der Edit Teil meiner Frage hier oben ^.
  • AMQP Link für den speziellen $cbs Event-Hub Namen: cbsLink, err := amqpConnection.Sender(electron.Target("$cbs"))
  • eine AMQP Nachricht mit den Anforderungen von Microsoft für den Handshake CBS vorbereiten:

Die Nachrichteneigenschaften (lesen Sie in diesem C# -Code https://github.com/Azure/amqpnetlite/blob/master/Examples/ServiceBus/Scenarios/CbsAsyncExample.cs zum Vergleich):

appProps := make(map[string]interface{}) 
appProps["operation"] = "put-token" 
appProps["type"] = "servicebus.windows.net:sastoken" 
appProps["name"] = "amqp://<MY_CUSTOM_NAMESPACE>.servicebus.windows.net/<MY_CUSTOM_NAME>" 

Das Token SAS in der Art und Weise formatiert Microsoft will, habe ich dieses Stück Code angepasst: https://github.com/michaelbironneau/asbclient/blob/master/azure.go auf diese Weise:

aqClient := newClient(Queue, "<MY_CUSTOM_NAMESPACE>", "<MY_CUSTOM_SAS_KEY_NAME>", "<MY_CUSTOM_SAS_KEY>") 
sasToken := aqClient.authHeader("amqp://<MY_CUSTOM_NAMESPACE>.servicebus.windows.net/<MY_CUSTOM_NAME>", aqClient.signatureExpiry(time.Now())) 

Das Stück Code^ist hier auf dem Python-SDK basiert: https://github.com/Azure/azure-sdk-for-python/blob/master/azure-servicebus/azure/servicebus/servicebusservice.py enthalten viele Dinge wie Groß-/Kleinschreibung URL-Kodierungen, gemischt mit Zeitstempel für den Verfall Zwecke und die SASL-Benutzername und Passwort ein.

Erstellen Sie das AMQP Nachricht "qpid.apache.org/amqp" importieren:

cbsHandshakeMsg := amqp.NewMessage() 
cbsHandshakeMsg.SetApplicationProperties(appProps) 
cbsHandshakeMsg.Marshal(sasToken) 
  • diese AMQP Nachricht mit outcome := cbsLink.SendSync(cbsHandshakeMsg) und dann auf magische Weise sollten Sie für eine Weile an den Event Hub authentifiziert werden.
  • -Setup des AMQP Link zum Event-Hub Namen, den Sie in erster Linie verbinden wollte: msgSender, err := amqpConnection.Sender(electron.Target("<MY_CUSTOM_NAME>"))

Jetzt können Sie die Nachricht senden Sie wollen auf diese Weise mit diesem letzten AMQP-Link senden:

m := amqp.NewMessage() 
m.Marshal("my message: bla bla bla, foo bar baz!") 
outcome := msgSender.SendSync(m) 

Fertig :)

diesen Code mit der Umwelt Laufvariable PN_TRACE_FRM=true hilft viel bei der AMQP zur Fehlerbehebung, da die proton-c Bibliothek Protokolle vieler nützlichen Debug-Meldungen.

Aus irgendeinem Grund funktioniert der Mechanismus AMQP PLAIN, der den SASL-Benutzernamen und das Kennwort während des Verbindungsversuchs direkt übermittelt, nicht mit dem Event Hub. Es kann ein Problem mit ihnen oder mit den Electron/Qpid-Bibliotheken sein, ich bin mir nicht sicher, aber jetzt ist zumindest jemand in der Lage, Nachrichten mit Hilfe von Golang und dem Microsoft-Protokoll, das sie zur Verfügung gestellt haben, zu senden.

1

Verwenden Sie "amqps" -Schema in URLStr mit Port 5671. Event Hubs ermöglicht keine einfache TCP-Verbindung. Außerdem müssen Sie SASL PLAIN aktivieren, um einen SAS-Schlüssel (Benutzername = Schlüsselname, Kennwort = Schlüssel) zu senden, der für den Namespace oder die Event-Hub-Entität konfiguriert ist (sieht so aus, als ob Sie es bereits tun). Ich bin nicht sicher über Golang, aber mit der Python-Bindung kann man alles so in einen Uri setzen "amqps: // sas-key-name: [email protected]: 5671". Die Portnummer ist optional.

Die zugrunde liegende proton-c-Engine verwendet möglicherweise SASL PLAIN nicht, wenn sie einen anderen unterstützten SASL-Mechanismus sieht. Um PLAIN zu erzwingen, können Sie den zulässigen Mechanismus für den Container festlegen. In der Folge scheint die Funktion SASLAlowedMechs Ihnen eine Verbindungsoption zu geben, die Sie beim Erstellen der Verbindung angeben können.

Dies ist die Python code, die gut mit den Event Hubs funktioniert.

+0

Danke, aber nichts funktioniert. Ich habe eine Azure Linux VM ausprobiert, um einige Firewall-Probleme auszuschließen: selbe Ausgabe: 'connection reset by peer'. Ich habe 'amqps' anstelle von' amqp' versucht, ich habe auch versucht, den PLAIN-Mechanismus zu verwenden, aber bisher kein Glück, d. H. Immer noch 'Verbindung durch Peer zurückgesetzt'. Ich muss sagen, dass, wenn ich Telnet benutze, ich eine Verbindung herstellen kann: 'telnet .servicebus.windows.net 5671' antwortet mit dem Aufbau einer TCP-Verbindung. – TPPZ

+0

Die Verbindung wird vom Dienst zurückgesetzt, weil einige Anforderungen nicht erfüllt sind, z. B. 1. Nicht-SSL-Verbindung, 2. keine SASL-Verhandlung, 3. falsche Anmeldeinformationen. Hast du proton-c kompiliert? Stellen Sie sicher, dass alle Abhängigkeiten installiert sind, insbesondere openssl (falls nicht, wird das Build-System fortfahren und eine lib ohne ssl-Unterstützung erstellen). Damit SASL funktionieren kann, müssen Sie die Benutzer/Pwd-Verbindungsoptionen festlegen und SASL PLAIN erzwingen, indem Sie die Option allowed_mechanisms festlegen. –

Verwandte Themen