ECONNREFUSED when attempting to POST to emulator from within local Docker container - node.js

TLDR:
Can't post to local Cosmos Emulator. Can post to Azure Cosmos, but not with #azure/cosmos-sign, only with #azure/cosmos (which seems utterly bizare as the latter is supposedly built upon the former.) This is not ideal (as the message signing portion alone is very lightweight with REST API directly). Bug, or user error? Why do the instructions for enabling networking/https not seem to work?
Details:
I have a Node.js based app, and am using the Azure/cosmos-sign package to generate the correct headers via the generateHeaders method to save a JSON object in the local Cosmos Emulator.
Upon trying to post from the Node app to the URI provided in the Emulator Quickstart (https://localhost:8081), the error returned is...
Error: connect ECONNREFUSED 127.0.0.1:8081 : https://localhost:8081
As per these instructions...
Enable access to emulator on a local network
If you have multiple machines using a single network, and if you set
up the emulator on one machine and want to access it from other
machine. In such case, you need to enable access to the emulator on a
local network.
You can run the emulator on a local network. To enable network access,
specify the /AllowNetworkAccess option at the command-line, which
also requires that you specify /Key=key_string or
/KeyFile=file_name. You can use /GenKeyFile=file_name to generate
a file with a random key upfront. Then you can pass that to
/KeyFile=file_name or /Key=contents_of_file.
To enable network access for the first time, the user should shut down
the emulator and delete the emulator's data directory
%LOCALAPPDATA%\CosmosDBEmulator.
-https://learn.microsoft.com/en-us/azure/cosmos-db/local-emulator?tabs=cli%2Cssl-netstd21#enable-access-to-emulator-on-a-local-network
...I thought perhaps I needed to enable the networking functionality. It is all on the same (Windows) host (with the Node.js application running in Docker on the same host as the Emulator is installed). But this caused more problems with no benefit. With the generated key, I can load the included UI for managing the local emulator instance, but I then can't create Databases or Containers (without resetting the emulator and starting it again normally, eg: without the AllowNetworkAccess and related settings).
Attempting to use the included Explorer to create a Database returns...
Error while creating database SampleDb:
{
"code": 401,
"body": {
"code": "Unauthorized",
"message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'post\ndbs\n\nmon, 29 mar 2021 23:33:45 gmt\n\n'\r\nActivityId: 29e4e700-d1b7-4d59-bdea-5931e4d6622d, Microsoft.Azure.Documents.Common/2.11.0"
},
"headers": {
"access-control-allow-credentials": "true",
"access-control-allow-origin": "https://localhost:8081",
"access-control-expose-headers": "Access-Control-Allow-Origin,Access-Control-Allow-Credentials,Content-Type,x-ms-activity-id,x-ms-gatewayversion",
"content-type": "application/json",
"date": "Mon, 29 Mar 2021 23:33:45 GMT",
"server": "Microsoft-HTTPAPI/2.0",
"x-firefox-spdy": "h2",
"x-ms-activity-id": "29e4e700-d1b7-4d59-bdea-5931e4d6622d",
"x-ms-gatewayversion": "version=2.11.0",
"x-ms-throttle-retry-count": 0,
"x-ms-throttle-retry-wait-time-ms": 0
},
"activityId": "29e4e700-d1b7-4d59-bdea-5931e4d6622d"
}
I did see this somewhat similar SO question, but it was abandoned.
This one, however seems to imply they simply reverted the KeyFile steps mentioned in the MS Docs. It seems odd that I am getting the same error from the Node.js POST regardless of if I use the AllowNetworkAccess switch or not.
Using the /NoFirewall switch as recommended here didnt resolve POSTs but did allow the Explorer UI to still work properly. The upvoted answer for that question is what I have already tried (/AllowNetworkAccess /KeyFile=...., and is not working, as explained above).
The docs here indicate that TLS (https) is in fact required...
"The Azure Cosmos DB Emulator supports only secure communication via TLS"
However, here they seem to indicate that, in the Node SDK (which relies on the same cosmos-sign library I am using)...
"TLS verification is disabled. By default the Node.js SDK(version 1.10.1 or higher) for the SQL API will not try to use the TLS/SSL certificate when connecting to the local emulator."
I tried adjusting the start script for my Node Docker image as suggested here...
If connecting to the Cosmos DB Emulator, disable TLS verification
for your node process:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
const client = new CosmosClient({ endpoint, key });
...and changed the start script in my package.json from...
"start": "node $NODE_OPTIONS node_modules...."
...to...
"start": "NODE_TLS_REJECT_UNAUTHORIZED=0 node $NODE_OPTIONS node_modules...."
...and rebuilt my images, but still receive the same ECONNREFUSED error from the Node client/app.
As I was reading the documentation for the REST API I was reminded that, as opposed to using the CosmosClient (which just needs the base URL), to do a post to the API the url needs to be fully formed as indicated here...
Method: POST
Request URI: https://{databaseaccount}.documents.azure.com/dbs/{db-id}/colls/{coll-id}/docs
Description: The {databaseaccount} is the name of the Azure Cosmos DB account created under your subscription. The {db-id} value is the
user generated name/ID of the database, not the system generated ID
(rid). The {coll-id} value is the name of the collection that contains
the document.
After appending /dbs/SampleDB/colls/SampleCollection/docs (yes, my entities are CamelCase) to the base url offered by the Emulator UI's Quickstart URI (https://localhost:8081)... I am still getting the ECONNREFUSED error to http posts.
Hmm... retargeted the Node app to point to a collection in my Azure Cosmos DB, and I am still having no luck.
400: Invalid API version. Ensure a valid x-ms-version header value is
passed. Please update to the latest version of Azure Cosmos DB
SDK.ActivityId: bfdeb339-8fef-4ba9-a03d-444a8664c02b,
Microsoft.Azure.Documents.Common/2.11.0
Added x-ms-version and set it to 2018-12-31 (latest, as per here).
Now I am getting (after trying both my secondary, and primary keys... just in case)...
401: The input authorization token can't serve the request. Please
check that the expected payload is built as per the protocol, and
check the key being used. Server used the following payload to sign:
'postdocsdbs/TopHand/colls/SampleTbltue, 30 mar 2021 02:54:25
gmt'ActivityId: bb258bb4-f5a8-4495-b0b5-b54fa8b7c46f,
Microsoft.Azure.Documents.Common/2.11.0
I verified that the required headers are all present. What can possibly be left?!
Base URI for Azure Cosmos had a trailing /, which ended up duplicated when the rest of the path was appended. Fixing the url string, still getting the 401.
A github issue pointed me to what may have been an error in the URL/REST path I was posting to. Rather than posting to (what I had previously)...
dbs/SampleDb/colls/SampleTbl/docs
...I changed it to...
dbs/SampleDb/colls/SampleTbl
...and am now getting error 405, MethodNotAllowed, RequestHandler.Post. 405 isn't listed as code returned by the Cosmos REST service.
This example in the MS docs definitely uses the /docs string at the end of the url/REST path.
Example
POST https://querydemo.documents.azure.com/dbs/1KtjAA==/colls/1KtjAImkcgw=/docs HTTP/1.1
x-ms-documentdb-partitionkey: ["Andersen"]
x-ms-date: Tue, 29 Mar 2016 02:28:29 GMT
authorization: type%3dmaster%26ver%3d1.0%26sig%3d92WMAkQv0Zu35zpKZD%2bcGSH%2b2SXd8HGxHIvJgxhO6%2fs%3d
Cache-Control: no-cache
User-Agent: Microsoft.Azure.Documents.Client/1.6.0.0
x-ms-version: 2015-12-16
Accept: application/json
Host: querydemo.documents.azure.com
Cookie: x-ms-session-token#0=602; x-ms-session-token=602
Content-Length: 344
Expect: 100-continue
{
"id": "AndersenFamily",
"LastName": "Andersen",
}

I contacted MS support and was giving some info that unblocked me (but doesn't entirely address the issues noted above).
For my own use-case, simply setting a key and allowing network access to the emulator was sufficient.
Note: This doesn't address the issues of the Emulator's Data Explorer becoming nonfunctional.
The feedback I received from the support personnel in regard to using the command line switches disabling the UI was...
By changing the key to something other than default one, you also
protect your emulator data from being seen via the Data Explorer.
Apparently the key alone isn't enough to protect the data, and disabling the UI is a "feature".
Solution: Simply executing...
.\Microsoft.Azure.Cosmos.Emulator.exe /AllowNetworkAccess /Key={insert your base64 encoded 64+ character string}
...allowed network access to systems on the same host as the emulator. This avoided all the certificate/key generation/importing/etc headache.
You must connect to the non-loopback IP of the host the emulator is running on to connect to it (writes/reads/etc).

Related

Response as undefined after an API call

I am using the request library to fetch a response from an API, everything was working fine but as of recent, I have started to get local issuer certificate error from the API although the same code is working on my colleague's system.
I have already tried updating the node version and all the version changes regarding the request package of node
The exact error is:
unable to get local issuer certificate node
Here is the error snippet in the console
Could u please console only response..After that u can easily see that there is statusCode is available or not.
Or if u get the statusCode then check its defined or not.
Ex: if(res.statusCode)
console.log("print status code", this.res.statusCode);
This is an SSL error and yo need to make sure that your server's certificate is valid.
With your claim that it used to work - but it stopped working recently with the SSL error message, the possibilities are that either your servers certificate is expired in between or the Sectigo AddTrust External CA Root Expiring May 30, 2020.
https://support.sectigo.com/Com_KnowledgeDetailPage?Id=kA03l00000117LT
Updating the certificate is outside the scope of this answer. You may have to do it yourself or contact the admin.

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.

Atlassian-connect: Error on 'installed' event

I'm trying to run example Jira add-on.
I have created credentials.json file and have run npm i and node app.js.
But I have problems with installed event. Here is nodejs log:
Watching atlassian-connect.json for changes
Add-on server running at http://MacBook-Air.local:3000
Initialized sqlite3 storage adapter
Local tunnel established at https://a277dbdf.ngrok.io/
Check http://127.0.0.1:4040 for tunnel status
Registering add-on...
GET /atlassian-connect.json 200 13.677 ms - 784
Saved tenant details for 608ff294-74b9-3edf-8124-7efae2c16397 to database
{ key: 'my-add-on',
clientKey: '608ff294-74b9-3edf-8124-7efae2c16397',
publicKey: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtKxrEBipTMXhRHlv9zcSLR2Y9h5YQgNQ5vpJ40tF9RmuIzByjkKTurCLHFwMAWU6aLQM+H+Z8wAlpL9AVlN5NKrEP8+a3mGFUOj/5nSJ7ZWHjgju0sqUruyEkKLvKuhWkKkd9NqBxogN0hxv7ue5msP5ezwei/nTJXmnmA5qOAQIDAQAB',
sharedSecret: 'LfT9elHM7iHkto5pHr+MnpH0SR1ypunIDoCyt6ugVJ1Q4hWHurG8k5DjVzLcvT2C98DDbiJiA89VNB0e3DiUvQ',
serverVersion: '100075',
pluginsVersion: '1.3.407',
baseUrl: 'https://gleb-olololololo-22.atlassian.net',
productType: 'jira',
description: 'Atlassian JIRA at https://gleb-olololololo-22.atlassian.net ',
eventType: 'installed' }
POST /installed?user_key=admin 204 51.021 ms - -
Failed to register with host https://gleb-olololololo-22%40yopmail.com:gleb-olololololo-22#gleb-olololololo-22.atlassian.net (200)
The add-on host did not respond when we tried to contact it at "https://a277dbdf.ngrok.io/installed" during installation (the attempt timed out). Please try again later or contact the add-on vendor.
{"type":"INSTALL","pingAfter":300,"status":{"done":true,"statusCode":200,"contentType":"application/vnd.atl.plugins.task.install.err+json","errorMessage":"The add-on host did not respond when we tried to contact it at \"https://a277dbdf.ngrok.io/installed\" during installation (the attempt timed out). Please try again later or contact the add-on vendor.","source":"https://a277dbdf.ngrok.io/atlassian-connect.json","name":"https://a277dbdf.ngrok.io/atlassian-connect.json"},"links":{"self":"/rest/plugins/1.0/pending/80928cb9-f64e-42d0-9a7e-a1fe8ba81055","alternate":"/rest/plugins/1.0/tasks/80928cb9-f64e-42d0-9a7e-a1fe8ba81055"},"timestamp":1513692335651,"userKey":"admin","id":"80928cb9-f64e-42d0-9a7e-a1fe8ba81055"}
Add-on not registered; no compatible hosts detected
I have reviewed tons of information in Google, but didn't found an answer.
More details, that can helps you to answer.
It happens suddenly. It worked OK, but about 1 week ago I start to get this error and cannot fix it. So I didn't change anything, just run add-on again, as I did it every day.
If I try to upload add-on manually I got error in terminal
GET / 302 17.224 ms - 0
GET /atlassian-connect.json 200 2.503 ms - 783
Found existing settings for client 608ff294-74b9-3edf-8124-7efae2c16397. Authenticating reinstall request
Authentication verification error: 401 Could not find authentication data on request
POST /installed?user_key=admin 401 22.636 ms - 45
The most possible reason (that I've found in google) is that I have wrong server time. But the time on my local machine is correct (at least for my timezone).
Anyone has any thoughts about this problem?
Thanks!
I kept randomly having this happen to me. It would be working, then run npm start and I would get the error. Since I'm not using a database right now, I simply removed all references to the juggling-sqlite database. This was in package.json, package-lock.json, config.json, and I just removed store.db. That got it working for me. Pretty frustrating that this happens, not sure a better way around it.

ServiceStack Facebook Authentication NullReference Exception on Vagrant Box (Ubuntu/MySql/Mono/nginx)

Long shot I guess, with the lack of real information that I am offering at this stage. I'll gladly offer up some more details on how to reproduce the issue - but wanted some fast feedback to see if there was a gotcha somewhere I was missing.
I've a simple ServiceStack hello world application, in which I'm playing with the Facebook Auth Provider:
Vanilla ServiceStack
Vanilla Facebook Auth Proivider
Vanilla User Session
Vanilla OrmLite User Repository
Vanilla OrmLite MySql Db Factory
When debugging on my local machine - on Windows 7 (and 8); everything works a treat. The service launches, the database tables are created and I can login via Facebook and records are inserted to the relevant tables.
When running the service on Ubuntu inside a Vagrant Box (running in Virtual Box as the provider for virtualization, hosted on nginx with mono-fastcgi) - the service launches correctly and I can see that the tables are created in the MySql database. When I hit /auth/facebook I am correctly forwarded to Facebook - but I hit an error when the callback to the service occurs.
This is the current output:
[Auth: 07/30/2013 13:02:47]: [REQUEST: {provider:facebook}] System.NullReferenceException: Object reference not set to an instance of an object at
ServiceStack.ServiceInterface.Auth.FacebookAuthProvider.Authenticate (ServiceStack.ServiceInterface.IServiceBase,ServiceStack.ServiceInterface.Auth.IAuthSession,ServiceStack.ServiceInterface.Auth.Auth) <0x0061e> at
ServiceStack.ServiceInterface.Auth.AuthService.Authenticate (ServiceStack.ServiceInterface.Auth.Auth,string,ServiceStack.ServiceInterface.Auth.IAuthSession,ServiceStack.ServiceInterface.Auth.IAuthProvider) <0x000a7> at
ServiceStack.ServiceInterface.Auth.AuthService.Post (ServiceStack.ServiceInterface.Auth.Auth) <0x00303> at
ServiceStack.ServiceInterface.Auth.AuthService.Get (ServiceStack.ServiceInterface.Auth.Auth) <0x00013> at (wrapper dynamic-method) object.lambda_method (System.Runtime.CompilerServices.Closure,object,object) <0x0004f> at
ServiceStack.ServiceHost.ServiceRunner`1<ServiceStack.ServiceInterface.Auth.Auth>.Execute (ServiceStack.ServiceHost.IRequestContext,object,ServiceStack.ServiceInterface.Auth.Auth) <0x00416>
It is clearly reaching the Service (which I'm accessing via localhost:8080 which maps through to the guest machine on port 80); as the error is wrapped nicely in ServiceStack output.
I don't suppose anyone has any clues?
Okay after an evening of investigation - I've found the root cause.
Line 51 of FacebookAuthProvider.cs calls off to Line 28 of WebRequestExtensions.cs - which in turn calls Line 227 of WebRequestExtensions.cs.
This method call fails at line 255-ish - essentially because Mono by default doesn't trust any SSL certificates by default: as explained here..
Instead of figuring out the correct configuration for Mono - I've taken the nasty route (for the time being at least); of using the following line in my AppHostBase.Configure implementation:
F#
System.Net.ServicePointManager.ServerCertificateValidationCallback <- new RemoteCertificateValidationCallback(fun _ _ _ _ -> true)
C#
System.Net.ServicePointManager.ServerCertificateValidationCallback += (a, b, c, d) => { return true; };
I am now up and running (like a fully-operational Death Star).

IIS Application pool identity

I am attempting to obtain a data feed from yahoo finance. I am doing this with the following code:
System.Net.WebRequest request = System.Net.WebRequest.Create(http://download.finance.yahoo.com/download/quotes.csv?format=sl&ext=.csv&symbols=^ftse,^ftmc,^ftas,^ftt1x,^dJA);
request.UseDefaultCredentials = true;
// set properties of the request
using (System.Net.WebResponse response = request.GetResponse())
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
I have placed this code into a console application and, using Console.WriteLine on the output I receive the information I require. I have used the 'Run as..' command to execute this using a specific domain account.
When I use this code from within a Page load I receive the following error message "No connection could be made because the target machine actively refused it 76.13.114.90:80".
This seems to suggest that the call is reaching yahoo (is this true?) and that there is something missing.
This would suggest there is an identity difference in the calls between the console application and application pool.
Environment is: Windows Server 2003, IIS 6.0, .net 4.0
"Target machine actively refused it" indicates that the TCP connection itself is not succeeding. This could be due to the fact that the Proxy settings when run under IIS are not the same as those that apply when you run in the console.
You can fix this by setting a WebProxy on your request, that points to the proxy server being used in the environment.
Yes, an active refusal is indication that the target machine is receiving the request and the information in the headers is either incorrect or insufficient to process the request. It is entirely possible that if you had to run this call using a "run as" command in console that the application pool's identity user does not have the appropriate permission or username. You can attempt to change the identity user to this specific domain account to see if that alleviates the problem, but you may have to isolate this particular function into its own application pool in order to protect the rest of the website from having this specification.

Resources