C# Cumulocity SDK throws "Connecting with MQTT server failed (ConnectionRefusedNotAuthorized)" - c#

I try to generate a new device and publish some random data to it via MQTT.
I follow this official example:
https://cumulocity.com/guides/device-sdk/mqtt-examples/#hello-mqtt-cs
All operations are executed without any error. Even establishing connection. But when I try to publish a message to the device I get the following error
"Connecting with MQTT server failed (ConnectionRefusedNotAuthorized)"
Here is my info to connect to the server
const string serverUrl = "mytenant.eu-latest.cumulocity.com";
const string clientId = "d:testdevice4";
const string device_name = "testdevice4";
const string user = "<mytenant>.eu-latest/<myusername>";
const string password = "XXXXXXXX";
And here are the operations that are executed without throwing any exception or ConnectionFailed event:
Establish Connection
await client.EstablishConnectionAsync();
Create Device
string topic = "s/us";
string payload = $"100,{device_name}, c8y_MQTTDevice";
var message = new MqttMessageRequestBuilder()
.WithTopicName(topic)
.WithQoS(QoS.EXACTLY_ONCE)
.WithMessageContent(payload)
.Build();
The other operations on Cumulocity Example
// set device's hardware information
var deviceMessage = new MqttMessageRequestBuilder()
.WithTopicName("s/us")
.WithQoS(QoS.EXACTLY_ONCE)
.WithMessageContent($"110, {device_name}, MQTT test model, Rev0.1")
.Build();
await client.PublishAsync(deviceMessage);
// add restart operation
await client.SubscribeAsync(new MqttMessageRequest() { TopicName = "s/ds" });
await client.SubscribeAsync(new MqttMessageRequest() { TopicName = "s/e" });
await client.PublishAsync(new MqttMessageRequestBuilder()
.WithTopicName("s/us")
.WithQoS(QoS.EXACTLY_ONCE)
.WithMessageContent("114,c8y_Restart")
.Build());
But when I try to publish a message to the device as follows, ConnectionFailed event is invoked with the error:
"Connecting with MQTT server failed (ConnectionRefusedNotAuthorized)"
Random rnd = new Random();
while (!cToken.IsCancellationRequested)
{
int temp = rnd.Next(10, 20);
Console.WriteLine("Sending temperature measurement (" + temp + "º) ...");
var xx = client.ConnectionDetails;
await client.PublishAsync(new MqttMessageRequestBuilder()
.WithTopicName("s/us")
.WithQoS(QoS.EXACTLY_ONCE)
.WithMessageContent("211," + temp)
.Build());
Thread.Sleep(1000);
}

You get a ConnectionRefusedNotAuthorized error because your credentials are not correct. To be precise, the user:
const string user = "<mytenant>.eu-latest/<myusername>";
The user is formed as tenantID/username
Your tenant domain (<mytenant>.eu-latest) is not the tenant ID. Tenant IDs – in most of the cases – are a number preceded by the letter t, e.g. t123123.
so your string should look like:
const string user = "t123123/mytenant";
More details can be found in the public documentation:
Tenant ID and Tenant domain
GET the current tenant details

There could be more reasons than just authorization issues, as per
https://cumulocity.com/guides/device-sdk/mqtt/
which states for return code 5 - "Connection refused, not authorized"
Mostly a device side related problem, used when the device doesn’t
have permissions or is doing something forbidden. For example, if the
client sends malformed messages or tries to execute an operation
without authenticating first, such as publishing a message. Thrown on
any issue with certificate authentication (for example, wrong common
name, failed auto registration). Also thrown on general issues with
receiving device data or some other authorization problem related to
the device state on the platform. For example, device managed object
problems, or the sudden removal of permissions. In this situation it
may be required to take action on the platform to investigate and
apply a fix. When clientId is too long the user can receive this error
when using 3.1 version of MQTT. This can happen if clientId has 24
characters or more. Lastly, it can also be thrown on unexpected
exceptions like performance issues, especially during connection.
Therefore it is a good approach to repeat the connection a few times
to overcome temporary performance issues.
I had the same issue where all my coded attempts (C#, Node.js) were failing with this same error.
In my case I am using a trial Cumulocity environment where the tenant id differs from all the Cumulocity documentation (which says the tenant id starts with a 't' followed by a number of digits. In my trial environment, the Tenant ID is shown in the Cumulocity Cockpit under the user details (top right), and this is in the format "ENVxxxxxx".
To try to troubleshoot the issue I began testing with an online MQTT client http://www.emqx.io/online-mqtt-client and through this process I mistakenly typed the username with lower case "env" and this resolved my issue. Hope that helps others.

Related

Docusign C# CreateEnvelope error - Could not establish trust relationship for the SSL/TLS secure channel

After the go live process, I created the new keys and I am using them as well. But I got this error
Error calling CreateEnvelope: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I am using a c# application. The exception is thrown in the Create Envelope method:
EnvelopeDefinition Envelope = new EnvelopeDefinition
{
EmailSubject = EmailSubject,
Documents = EnvelopeDocuments,
Recipients = new Recipients { Signers = Signers },
Status = "sent"
};
return GetEnvelopesApi().CreateEnvelope(_AccountId, Envelope).EnvelopeId;
Where GetEnvelopesApi just call the public EnvelopesApi(Configuration configuration = null); of docusign.esign.api :
private EnvelopesApi GetEnvelopesApi()
{
ApiClient Client = new ApiClient("https://docusign.net/restapi");
Client.Configuration.AddDefaultHeader("Authorization", "Bearer " + GetAccessToken());
return new EnvelopesApi(Client.Configuration);
}
If I use my developer demo keys instead of the production ones, and "https://demo.docusign.net/restapi" instead of the production url, it works.
What you did to get to the error message
{"errorCode":"USER_LACKS_MEMBERSHIP",
"message": "The UserID does not have a valid membership in this Account."}
was correct.
Next, you need to solve the problem that causes the USER_LACKS_MEMBERSHIP error. It is probably due to you continuing to use a UserId (guid format) from the developer (demo) account. You need to use a UserId from your production account.
Also note that you must determine what the base url is for your account. That determines if you should use www.docusign.net in production, or na2.docusign.net or something else.
You can determine the base url for your account manually or automatically. But it must be correct... Ask another question if you need help on that subject.
The problem you have is the lack of https, so you need to change the url to https://docusign.net/restapi
UPDATE
I think I found your issue! The url should be https://www.docusign.net/restapi due to the fact the ssl certificate is signed to use www. and gives you a certificate error when you don't have it
UPDATE 2
Add the following line before to make the connection:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
That is in order to force the connection to use TLS 1.2
Also, I would suggest you to debug it inside the function so you know where it breaks within it
UPDATE 3
In case you still receive the SSL/TLS issue, you could try to add the following line before your rest call too:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

C# LDAP SSL Logon issue on F5 VIP name when LdapEnforceChannelBinding=1 or 2

I have C# Windows Form application to test the LDAP SSL authentication.
Here is the code. First, I made a function.
using System.DirectoryServices;
private bool VerifyDomainUserUsignLDAP(string UserName, string Password, string Domain,string mode, out string message)
{
bool retVal = false;
message = null;
DirectoryEntry de;
try
{ if (mode =="Plain")
//plain mode
de = new DirectoryEntry(Domain, UserName, Password);
else
//SSL mode
de = new DirectoryEntry(Domain, UserName, Password,
AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer);
DirectorySearcher ds = new DirectorySearcher(de);
SearchResult sr= ds.FindOne();
lblResult.Text = "Authentication Passed! " + sr.ToString();
retVal = true;
}
catch (Exception ex)
{
retVal = false;
lblResult.Text = ex.Message;
}
return retVal;
}
My problem is the invoke.
Share with some background first.
We have multiple domain control servers (Windows). dcserver001.mydomain.com is one of them. (of course, we have dcserver002.mydomain.com, dcserver003.mydomain.com, etc). each server provides LDAPS service.
And we created a VIP name ldap.mydomain.com in F5 (Load balance), we put all above dc servers into the Load balance. All DC servers are Windows servers.
Days before, if I use following line to invoke above function for LDAP authenticate on the VIP name - ldap.mydomain.com.
For e.g.
VerifyDomainUserUsignLDAP("mydomain\\myuserid", "mypassword",
#"LDAP://ldap.mydomain.com", "SSL" ,out Message);
It always worked fine and the user was authenticated.
However, some days before, our LDAP service team made a registry change (LdapEnforceChannelBinding) on each ldap servers to
enhance the security based on MS suggestion.
In short, they changed following key value from 0 to 2
Path: HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/NTDS/Parameters
Key: LdapEnforceChannelBinding
Here is detail page about the setting on MS web site.
Use the LdapEnforceChannelBinding registry entry to make LDAP authentication over SSL/TLS more secure
https://support.microsoft.com/en-hk/help/4034879/how-to-add-the-ldapenforcechannelbinding-registry-entry
After that, I noticed my above function stop working.
i.e. if I use same line to invoke above function for LDAP authenticate.
For e.g.
VerifyDomainUserUsignLDAP("mydomain\\myuserid", "mypassword",
#"LDAP://ldap.mydomain.com", "SSL" ,out Message);
It always returned exception "Logon failure: unknown user name or password."
(I promise password and user name were correct.)
Then, I did further investigation.
I tried to use following line to invoke above function for LDAP authenticate on any individual dc server, e.g.
dcserver001.mydomain.com.
VerifyDomainUserUsignLDAP("mydomain\\myuserid", "mypassword",
#"LDAP://dcserver001.mydomain.com", "SSL" ,out Message);
It worked fine as well.
I actually tested all individual dc servers one by one, thwy were all working.
So, it looks like the ldap request with same invoke parameters works well on the individual dc server, but it doesn't work on the VIP name.
Then, I asked the ldap server team to rollback to LdapEnforceChannelBinding change to value 0. Then, I re-tested ldap against both individual server and VIP name, both worked.
I checked with our metwork team and got got some more information as follwoing.
They said this won't work with LDAPS VIPs because the SSL channel from client is terminated on F5, and reestablished to DC.
the reason why it works directly to the dc is because its one continuous packet.
The update addresses this vulnerability by incorporating support for Extended Protection for Authentication security feature, which allows the LDAP server to detect and block such forwarded authentication requests once enabled.
What I need help is - is there anyone here encountered the similar ldap ssl logon issue against F5 VIP and with the LdapEnforceChannelBinding registry value = 1 or 2?
If LdapEnforceChannelBinding registry value = 1 or 2 on the LDAP servers, what changes need to be done to resolve above LDAPS logon issue?
Thanks a lot!
Jun

Override the userid send by Websphere MQ Client in C# Windows application

I am trying to connect to a test instance of a Websphere MQ 7.5 server (on a Windows domain) from a C# application using the full MQ Client install, but I've had no luck. I keep getting the error code 2035 MQRC_NOT_AUTHORIZED from the MQ server. Initially I tried the code below:
string QueueManagerName = "myNewQManager";
MQEnvironment.Hostname = "tst-mqsvr";
MQEnvironment.Channel = "test.channel";
MQEnvironment.Port = 1414;
MQEnvironment.UserId = "domainUser";
MQEnvironment.Password = "********";
//set transport properties.
MQEnvironment.properties[MQC.TRANSPORT_PROPERTY] = MQC.TRANSPORT_MQSERIES_CLIENT;
try
{
queueManager = new MQQueueManager(QueueManagerName);
}
catch(MQException mqexp)
{
//I get the error code 2035
log.Error(mqexp)
}
changing to this doesn't work either:
string QueueManagerName = "myNewQManager";
var queueProperties = new Hashtable();
queueProperties[MQC.TRANSPORT_PROPERTY] = MQC.TRANSPORT_MQSERIES_CLIENT;
queueProperties[MQC.HOST_NAME_PROPERTY] = "tst-mqsvr";
queueProperties[MQC.PORT_PROPERTY] = "1414";
queueProperties[MQC.CHANNEL_PROPERTY] = "test.channel";
queueProperties[MQC.USER_ID_PROPERTY] = "domainUser";
queueProperties[MQC.PASSWORD_PROPERTY] = "*********";
try
{
queueManager = new MQQueueManager(QueueManagerName, queueProperties);
}
catch(MQException mqexp)
{
//I still get the error code 2035
log.Error(mqexp)
}
This error goes away and I can connect/put/get messages from my queue if
I manually set the MCAUSER on my channel, or
I run the application as the domain user who set up the MQ server (using RunAs)
However, I will not be able to use either of these two workarounds for the production set up. I am assuming I'm getting the error code 2035 because the MQ client is sending the wrong user-id. I need to be able to override (or at least determine) the flowed userid during server connection. How do I go about this?
Edit: I got the errors below in my AMQERR01.log file
-------------------------------------------------------------------------------
7/6/2016 13:06:14 - Process(1380.10) User(MUSR_MQADMIN) Program(amqzlaa0.exe)
Host(TST-MQSVR) Installation(DefaultInstall)
VRMF(7.5.0.2) QMgr(MYNEWQMANAGER)
AMQ8075: Authorization failed because the SID for entity 'sinistrian' cannot be
obtained.
EXPLANATION:
The Object Authority Manager was unable to obtain a SID for the specified
entity. This could be because the local machine is not in the domain to locate
the entity, or because the entity does not exist.
ACTION:
Ensure that the entity is valid, and that all necessary domain controllers are
available. This might mean creating the entity on the local machine.
----- amqzfubn.c : 2273 -------------------------------------------------------
7/6/2016 13:06:14 - Process(1380.10) User(MUSR_MQADMIN) Program(amqzlaa0.exe)
Host(TST-MQSVR) Installation(DefaultInstall)
VRMF(7.5.0.2) QMgr(MYNEWQMANAGER)
AMQ8073: Authorization failed because SID: ((None)) could not be resolved.
EXPLANATION:
The Object Authority Manager was unable to resolve the specified SID into
entity and domain information.
ACTION:
Ensure that the application provides a SID that is recognized on this system,
that all necessary domain controllers are available, and that the security
policy is set as you required.
----- amqzfubn.c : 4397 -------------------------------------------------------
7/6/2016 13:06:14 - Process(3008.3) User(MUSR_MQADMIN) Program(amqrmppa.exe)
Host(TST-MQSVR) Installation(DefaultInstall)
VRMF(7.5.0.2) QMgr(MYNEWQMANAGER)
AMQ9557: Queue Manager User ID initialization failed.
EXPLANATION:
The call to initialize the User ID failed with CompCode 2 and Reason 2035.
ACTION:
Correct the error and try again.
----- cmqxrsrv.c : 1975 -------------------------------------------------------
7/6/2016 13:06:14 - Process(3008.3) User(MUSR_MQADMIN) Program(amqrmppa.exe)
Host(TST-MQSVR) Installation(DefaultInstall)
VRMF(7.5.0.2) QMgr(MYNEWQMANAGER)
AMQ9999: Channel 'TEST.CHANNEL' to host 'WKS-L450 (192.168.10.23)' ended
abnormally.
EXPLANATION:
The channel program running under process ID 3008(2192) for channel
'TEST.CHANNEL' ended abnormally. The host name is 'WKS-L450 (192.168.10.23)';
in some cases the host name cannot be determined and so is shown as '????'.
ACTION:
Look at previous error messages for the channel program in the error logs to
determine the cause of the failure. Note that this message can be excluded
completely or suppressed by tuning the "ExcludeMessage" or "SuppressMessage"
attributes under the "QMErrorLog" stanza in qm.ini. Further information can be
found in the System Administration Guide.
Until version 7.5, MQ client always flows the logged-in UserId and not the UserId specified by the application, to queue manager for authorization. You will need a security exit for this scenario.
This changed in MQ v8 where UserId specified by the application is flowed to the queue manager for authorization check. More details here: https://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.sec.doc/q113260_.htm
You could use the MQS_REPORT_NOAUTH or MQSAUTHERRORS setting to get more info the authority failure.

Connect hadoop in C#

I want to connect hadoop in c# using HDInsight. I have created a cluster in AZURE and it was created successfully. and also I enabled remote desktop connection in it.
When I entered the credentials in C# and execute the job then I get the connection error. I am confused in providing the parameters. Kindly assist me.
var hadoop = Hadoop.Connect(new Uri("https://clustername.azurehdinsight.net"), "admin", "");
//I have set remote desktop password
var config = new HadoopJobConfiguration();
config.InputPath = "input/CodeFiles";
config.OutputFolder = "output/CodeFiles";
var result = hadoop.MapReduceJob.ExecuteJob<NamespaceCounterJob>();
Last line gives the exception.
Exception message is:
One or more errors occured
And this is the inner exception:
Unable to connect to the remote server
The Uri should be your Cluster Name, not Username, like:
var hadoop = Hadoop.Connect(new Uri("https://clustername.azurehdinsight.net"), "username", "password");
var config = new HadoopJobConfiguration();
config.InputPath = "input/CodeFiles";
config.OutputFolder = "output/CodeFiles";
var result = hadoop.MapReduceJob.ExecuteJob<NamespaceCounterJob>();
The cluster name is shown at the top of the detail page in the Azure portal for your cluster. Also, you don't need to enable RDP to use this method, it's actually the username set for "Hadoop Services" in the configuration tab of the cluster. Launching a job in this manner makes use of the WebHCat/Templeton endpoint, so RDP is not required.

as a Service connecting remote WMI query errors out with wrong user

Ok, first of all here is the error message from WMI-Activity / Operational in EventLog (Windows 8):
Id = ; ClientMachine = machinename; User = machinename\Dev; ClientProcessId = 1440; Component = WMIService; Operation = connect to namespace : root\CIMV2\Security\MicrosoftVolumeEncryption; ResultCode = 0x80041003; PossibleCause = the user was not granted appropriate permission on the namespace.
the thing is User name "Dev" is not the username that I fed to the ConnectionOptions of ManagementScope() when I attempted connection to remote computer.
The machinename(I hide) was correct.
Trying to make a remote connection is a service and most suspicious scenario is service running as local machine somehow overwrites the username..
I need a confirmation with somebody who might know and able to explain what I am doing wrong here..
I see Username and Password are correct until fed into properties of ConnectionOptions and made Scope.Connect() call.

Categories

Resources