EventHub connection using Python libraries azure-eventhub 5.0.0 - python-3.x

All,
I inadvertently uninstalled EventHub V1.3.3 and installed the latest V5.0.0. I had to change the code that I had but I never got it to work. Below is the code:
from azure.eventhub import EventHubProducerClient, EventData
connection_str = 'Endpoint=sb://eventhubns20.servicebus.windows.net/;SharedAccessKeyName=eventhub20_pol;SharedAccessKey=xxxxxxxxxx=;EntityPath=eventhub20' eventhub_name = 'eventhub20'
client = EventHubProducerClient.from_connection_string(connection_str, eventhub_name=eventhub_name)
event_data_batch = client.create_batch()
Below is the error:
Traceback:
File "C:\Users\grajee\AppData\Local\Programs\Python\Python38-32\lib\site-packages\uamqp\authentication\cbs_auth.py", line 69, in create_authenticator
self._cbs_auth = c_uamqp.CBSTokenAuth(
File ".\src/cbs.pyx", line 73, in uamqp.c_uamqp.CBSTokenAuth.__cinit__
ValueError: Unable to open CBS link.
The error is on this line - event_data_batch = client.create_batch().
Has anyone experienced this error. If it is too much of work I might have to rollback to V1.3.3. The Python version is V3.8.1 on Windows.

Your connection string is incorrect. The one you are using is EventHub instance connection string, but you should use Eventhub Namespace connection string.
The correct Eventhub Namespace connection string looks like this: Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=policyName;SharedAccessKey=xxxx.
Please follow the step below to get the Event hub NameSpace connection string(not the event hub instance connection string).
Nav to azure portal -> your Azure EventHub NameSpace -> Shared access policies -> click the policy you want to use -> then copy the connection string from Connection string–primary key.
The screenshot as blow:

Your hostname doesn't resolve. Please make sure you are using an active Event hubs namespace.
>ping eventhubns20.servicebus.windows.net
Ping request could not find host eventhubns20.servicebus.windows.net. Please check the name and try again.

Related

EventHub Golang client error: amqp:internal-error

I try to use EventHub Go client to send a simple "hello world" event but got this error message:
*Error{Condition: amqp:internal-error, Description: The service was unable to process the request; please retry the operation. For more information on exception types and proper exception handling, please refer to http://go.microsoft.com/fwlink/?LinkId=761101 TrackingId:be0c66437a1447b7accdc113c84955dd_G5, SystemTracker:gateway5, Timestamp:2021-07-10T21:28:48, Info: map[]}
The code is exactly the same as this sample code here: https://github.com/Azure/azure-event-hubs-go
The SO thread I found which somehow has similar error message is here Getting "amqp:internal-error" when peeking messages from Azure Service Bus Queue using AMQP, rhea and Node, but it is for Service Bus and Node client.
Any idea why this issue occured?
This error is pretty non-descriptive.
One way to trigger is to specify an EventHubs connection string without an EntityPath=<event hub name> in it.
So if you're using a broker level connection string you'll need to specify the EventHub you're attempting to connect to by adding EntityPath=eventHubName. The readme snippet does list this, but the error is admittedly not great in that situation.
I've filed this issue to at least improve the error message in that case, as it doesn't really lead you to what's wrong.
https://github.com/Azure/azure-event-hubs-go/issues/222

Connection to Entity Framework works locally, Was working in Azure but now I get "Invalid object name..."

I have looked through various posts related to this problem, but none provide an answer. I created a .Net 5.0 app that accesses an Azure SQL DB using EF 6.4.4 which works with .Net standard libraries. I modified the EF by adding a function that creates the connection string from appsettings.json since .Net 5 apps don't use a web.config file. This also works well in Azure with the configuration settings in an app service.
The connection string looks like this:
metadata=res://*/EF.myDB.csdl|res://*/EF.myDB.ssdl|res://*/EF.myDB.msl;provider=System.Data.SqlClient;provider connection string='Data Source=tcp:mydb.database.windows.net,1433;Initial Catalog=myDB;Integrated Security=False;Persist Security Info=False;User ID=myuserid#mydb;Password="password";MultipleActiveResultSets=True;Connect Timeout=120;Encrypt=True;TrustServerCertificate=True'
I also have a deployment pipeline that will deploy the code after a check-in instead of using the Visual Studio publish feature, but the pipeline deployed code has the same problem.
When I first created the app and published it to the app service, it worked. Recently I updated the app with no changes to the EF connection. Now I get the "Invalid Object name when I reference any table in the model. If I run the same code locally and connect to the Azure SQL DB, the DB is accessed as expected. This problem only occurs when running in the Azure app service. Note that there are no connection strings configured for the app service since the EF string is built from the config settings. I saw this post, but I don't think it applies:
Local works. Azure give error: Invalid object name 'dbo.AspNetUsers'. Why?
even though the problem is the same. I have also read various posts about the format of the EF connection string. Since my model is database first, (and the connection used to work), I'm confident the string has the correct format. I don't think the problem is in the code since it works when running locally with a connection to the Azure SQL DB. It must have something to do with the Azure app service configuration, but I'm not sure what to look for at this point. Unfortunately I don't have a copy of the code and publish files that did work to compare to, but it the pipeline build doesn't work either and that it how the code would normally be deployed. Thanks for any insight you might have!
UPDATE
metadata=res://*/EF.myDB.csdl|res://*/EF.myDB.ssdl|res://*/EF.myDB.msl;provider=System.Data.SqlClient;provider connection string='Data Source=tcp:yourdbsqlserver.database.windows.net,1433;Initial Catalog=yourdb;Persist Security Info=False;User ID=userid;Password=your_password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30'
When the troubleshooting problem is not on the string, our easiest way is to use vs2019 to re-use the generated string.
Your connection string should be like below.
<connectionStrings>
<add name="SchoolDBEntities" connectionString="metadata=res://*/SchoolDB.csdl|res://*/SchoolDB.ssdl|res://*/SchoolDB.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;initial catalog=SchoolDB;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient"/>
</connectionStrings>
For more details, you can refer my answer in the post and the tutorial.
1. Timeout period elasped prior to obtaining a connection from the pool - Entity Framework
2. Entity Framework Tutorial
The problem was one of my config settings in Azure. The catalog parameter was missing. A simple fix, but the error message was misleading, so I thought I would note that here in case anyone else gets the same "Invalid object name" message when referencing an Azure SQL DB with EF. It would have been more helpful if the message was "catalog name invalid" or "unable to connect to database".
For those who are curious about building an EF connection string, here is example code:
public string BuildEFConnectionString(SqlConnectionStringModel sqlModel, EntityConnectionStringModel entityModel)
{
SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
{
DataSource = sqlModel.DataSource,
InitialCatalog = sqlModel.InitialCatalog,
PersistSecurityInfo = sqlModel.PersistSecurityInfo,
UserID = sqlModel.UserID, // Blank if using Windows authentication
Password = sqlModel.Password, // Blank if using Windows authentication
MultipleActiveResultSets = sqlModel.MultipleActiveResultSets,
Encrypt = sqlModel.Encrypt,
TrustServerCertificate = sqlModel.TrustServerCertificate,
IntegratedSecurity = sqlModel.IntegratedSecurity,
ConnectTimeout = sqlModel.ConnectTimeout
};
//Build an Entity Framework connection string
EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
{
Provider = entityModel.Provider, // "System.Data.SqlClient",
Metadata = entityModel.Metadata,
ProviderConnectionString = sqlString.ToString()
};
return entityString.ConnectionString;
}
Given what I have learned, the properties should be validated before the string is returned. If the string is created this way, all of the connection string properties can be added to the config settings in the app service. I used the options pattern to get them at runtime. Thanks to everyone for your suggestions.

Azure IoT SDK C: Error 401 when connecting to Blob Storage

OS and version used: Ubuntu 18.04
SDK version used: Release Dec. 13, 2018
Target: ESP32.
Description of the issue:
I am trying to connect the ESP32 to my Blob storage. I am getting an HTTP error 401 (unauthorized access).
I am using the example: iothub_client_sample_upload_to_blob_mb.
I tried connecting using just the Shared Access Key in my connection string, but this did not work (no connection). After that I generated an SAS token in Azure (Storage Accounts -> -> Shared Access Signature) and plugged that in into my connection string.
My connection string looks like this:
static const char* connectionString = "HostName=<Host name>;DeviceId=<Device ID>;SharedAccessSignature=<inserted here without the "?" at the beginning>";
Q1: Why is there a "?" in front of the token? When I look at the connection string, at SharedAccessSignature=.. I don't see the "?".
I also set up the Endpoint in Azure under IoT Hub -> Upload files.
In the example, I am using the option SET_TRUSTED_CERT_IN_SAMPLES.
Q2: What does that mean? I am not so familiar with basic encryption and should probably read up on that.
Q3: Why am I getting an 401 error? What could be a possible solution?
Log:
Initializing SNTP
ESP platform sntp inited!
Time is not set yet. Connecting to WiFi and getting time over NTP. timeinfo.tm_year:70
Waiting for system time to be set... tm_year:0[times:1]
Starting the IoTHub client sample upload to blob with multiple blocks...
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Info: Waiting for TLS connection
Error: Time:Thu Jan 17 22:06:00 2019 File:/home/julian/eclipse-workspace/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:send_http_request Line:142 HTTP code was 401
Error: Time:Thu Jan 17 22:06:00 2019 File:/home/julian/eclipse-workspace/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:IoTHubClient_LL_UploadToBlob_step1and2 Line:494 unable to HTTPAPIEX_ExecuteRequest
Error: Time:Thu Jan 17 22:06:00 2019 File:/home/julian/eclipse-workspace/chaze-esp32/components/esp-azure/azure-iot-sdk-c/iothub_client/src/iothub_client_ll_uploadtoblob.c Func:IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl Line:768 error in IoTHubClient_LL_UploadToBlob_step1
Received unexpected result FILE_UPLOAD_ERROR
hello world failed to upload
Press any key to continue
Here is the link to the GitHub Repo.
The example can be found here.
I generated an SAS token in Azure (Storage Accounts -> -> Shared Access Signature) and plugged that in into my connection string. My connection string looks like this:
static const char* connectionString = "HostName=<Host name>;DeviceId=<DeviceID>;SharedAccessSignature=<inserted here without the "?" at the beginning>";
Q1: Why is there a "?" in front of the token? When I look at the connection string, at SharedAccessSignature=.. I don't see the "?".
After registering a device on IoTHub you will need to retrieve it's connection string to use on this example. See here an example on how to register and retrieve the connection string from a device on IoTHub.
I also set up the Endpoint in Azure under IoT Hub -> Upload files. In the example, I am using the option SET_TRUSTED_CERT_IN_SAMPLES.
Q2: What does that mean? I am not so familiar with basic encryption and should probably read up on that.
That Flag is used when compiling the SDK for your device. See the CMake File:
#Conditionally use the SDK trusted certs in the samples
if(${use_sample_trusted_cert})
add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES)
include_directories(${PROJECT_SOURCE_DIR}/certs)
set(iothub_client_sample_upload_to_blob_mb_c_files ${iothub_client_sample_upload_to_blob_mb_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c)
endif()
Q3: Why am I getting an 401 error? What could be a possible solution?
Make sure you configure file upload on Azure IoTHub correctly - https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-file-upload and use the correct connection string on the sample. Also leverage the ESP8266 sample that should have similar steps as the ESP32 configuration.
To get rid of the 401 error: Use MSFT Baltimore certificate in the code.
To get rid of the panic on the ESP: Look at this GitHub issue.

An unhandled exception of type 'System.FormatException' occurred in Microsoft.Azure.Devices.dll

I'm referring this tutorial to create a device identity. However, getting an exception as below:
Here is my config file:
Edit:
What is this Instrumentation key and value in App.Config? I just copied from the sample code. However, from where can I get it, in case I'm using a real device?
Am I missing any SDK or anything else?
Do I need to download something extra? the tutorial does not suggest anything.
Even when I'm running sample code from GiTHub getting the same error.
the following screen snippet shows a reason of this error, such as connectionString.
Use the connectionString from your Azure IoT Hub - see the tutorial section Create an IoT Hub step 6.
Can you check that the connection string you're using is in the correct format. It should look like:
"HostName={your hub name}.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey={your key}"
You can copy the complete connection string from the portal as described in the tutorial.
Issue resolve: I was missing my connection string.Which I got from "IoTHubOwner" from Azure portal login. :)

Proton connection to azure iothub amqps endpoints

I'm trying to use python 2.7 qpid proton (0.17.0) on Debian 4.8.4-1 on google cloud to connect to the service AMQPS 1.0 endpoints on an Azure IoT hub.
I'm using a shared access policy and a SAS token pair (which successfully work in ampq net lite under C#) for SASL PLAIN. For azure iothub, you reference the shared access policy as the username in the format policyName#sas.root.IoTHubName
When I use these (obfuscated) credentials with qpid proton as follows
import sys
from proton import Messenger, Message
base = "amqps://iothubowner#sas.root.HubName:SharedAccessSignature sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=1490861529&skn=iothubowner#HubName.azure-devices.net:5671"
entityName = "/messages/servicebound/feedback"
messenger = Messenger()
messenger.subscribe("%s%s" % ( base, entityName))
messenger.start()
I get the following error
(debug print of connection string being passed) amqps://iothubowner#sas.root.HubName:SharedAccessSignature
sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=1490861529&skn=iothubowner#HubName.azure-devices.net:5671
Traceback (most recent call last): File "readProton2.py", line 27,
in
messenger.subscribe("%s%s" % ( base, entityName)) File "/usr/lib/python2.7/dist-packages/proton/__init__.py", line 496, in
subscribe
self._check(pn_error_code(pn_messenger_error(self._mng))) File "/usr/lib/python2.7/dist-packages/proton/__init__.py", line 300, in
_check
raise exc("[%s]: %s" % (err, pn_error_text(pn_messenger_error(self._mng))))
proton.MessengerException: [-2]: CONNECTION ERROR
(sas.root.HubName:SharedAccessSignature
sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=1490861529&skn=iothubowner#HubName.azure-devices.net:5671):
getaddrinfo(sas.root.HubName, SharedAccessSignature
sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=149086152
9&skn=iothubowner#HubName.azure-devices.net:5671): Servname not
supported for ai_socktype
The final error message looks like parsing of the connection string is being mangled (on a very quick look, pni_default_rewrite in qpid-proton/messenger.c appears to use the first occurrence of # to split the connection string which could be the problem)
However, I'm new to AMQP and proton, so before I raise a bug, want to check whether others have successfully use proton to iothub, or if I've missed something??
You need to encode amqp username and password.
iothubowner#sas.root.HubName
iothubowner%40sas.root.HubName
SharedAccessSignature sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=1490861529&skn=iothubowner
SharedAccessSignature%20sr%3DHubName.azure-devices.net%252fmessages%26sig%3DPERCENT_ENCODED_SIG%26se%3D1493454429%26st%3D1490861529%26skn%3Diothubowner
The server name should be HubName.azure-devices.net:5671, but as you can see in error message, server name changed to sas.root.HubName, SharedAccessSignature sr=HubName.azure-devices.net%2fmessages&sig=PERCENT_ENCODED_SIG&se=1493454429&st=149086152 9&skn=iothubowner#HubName.azure-devices.net:5671

Resources