Ocelot API gateway fails to establish SSL connection to downstream - asp.net5

I have an Ocelot API gateway in front of all our microservices providing some form of an API. We also have some external services hosted in Azure, one which I figured I wanted to route through our API gateway. However, as the title says, when attempting to connect using https as the downstream scheme I get the following error message:
Error Code: ConnectionToDownstreamServiceError Message: Error connecting to downstream service, exception: System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Cannot determine the frame size or a corrupted frame was received.
at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
Googling the inner exception leads to some posts suggesting that since .net 5.0 preview 6 the default tls version is determined by the operating system default which by now should probably be TLSv1.3. I believe Azure functions does not support TLSv1.3 yet and it appears that the downstream request from Ocelot does not fall back on TLSv1.2 when this is the case.
Attempting to run the request a number of other ways yields only success which leads me to believe that this is an issue specific to Ocelot. Running requests directly to the Azure resource via
Postman: succeeds. TLSv1.2 is used.
curl: succeeds. TLS1.2 is used here too.
GetAsync using HttpClient in C# (.net 5.0): succeeds.
Running curl with -v I can see that it attempts a handshake with TLSv1.3 first but then falls back to TLS1.2.
Can anyone confirm that the tls version is indeed the problem? And in that case is there any way to allow TLSv1.2 in an asp.net 5 ocelot API Gateway project?
Additional information:
Setting "DangerousAcceptAnyServerCertificateValidator": true does not resolve the issue
The gateway has no issues when using http as downstream scheme

I have a similar environement where most of my Ocelot downstream requests are currently pointing to localhost microservices (in development). However i have rigged up an Azure Function (Http Trigger) that i deployed to Azure and therefore need Ocelot to route a downstream request to the external facing url.
What I can confirm is that my Ocelot environment is running on .NET Core 5.0 and am able to succesfully call the Azure Function and return the data to my front end Web App (upstream route)
I havent had to do anything different with Ocelot for it to work. Below is the snippet from the ocelot.json file
"Routes": [
// ---------------------------------------------------
// ---------- Azure Functions HTTP Triggers ----------
// ---------------------------------------------------
// ----------- Logs -----------
{
"DownstreamPathTemplate": "/api/logproperties",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "azurefunction-httpget-logproperties.azurewebsites.net",
"Port": 443
}
],
"UpstreamPathTemplate": "/logs/logproperties",
"UpstreamHttpMethod": [ "Get" ],
"RouteIsCaseSensitive": false,
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": []
}
}
]
The actual url path for my function is shown below (obviously with the api key removed)
https://azurefunction-httpget-logproperties.azurewebsites.net/api/logproperties?code=<MyApiKeyHere>&containerName=ohiAppSource&logPropertyName=OhiAppSource
I was having issues intitially but after removing 'https://' from the string set for the "Host" in the Json config then it went through OK.
My Ocelot environement authenticates upstream requests (Client App --> Ocelot) using Microsoft Identity Web library so calling a function with a simple API key is not a security concern for me. But regardless of how you're securing the inbound side of ocelot, I dont think that would affect the issue you encountered. My solution is not promising a fix to your particular issue but it always helps to see a working configuration.

Related

What is the request that whatsapp cloud api does to verify a webhook?

I'm able to verify the webhook using glitch from the getting started:
https://glitch.com/edit/?fbclid=IwAR2YTjZuGGM9Hi6T_v1eZh_nV6_HY3RYn_8lll4gY1REa_bJy6ZAuq6tkKQ#!/whatsapp-cloud-api-echo-bot
my local server (in a subdomain with https enabled) has the same behavior as glitch and show "WEBHOOK_VERIFIED" on the log for the request:
/webhook?hub.mode=subscribe&hub.verify_token=xpto123&hub.challenge=123
but when try to verify my local server the request from meta does not reach the server.
chrome showing that the connection to the server is secured
After more tests I found that my local server was been blocked by the ISP, understood it after test with another connection.
I made my own server and had tried ngrok and other programs to run it from local host with https redirect but whatsapp doesn't allow the use of those programs.
In the end, my error was that the URL HAS to end in /webhook or else, it won't even send the request. Then it'll send a GET request and you have to return the hub.challenge query param after making sure that the provided token from them is the one you set up. This is my code using NodeJS
if(req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) return res.status(200).send(req.query['hub.challenge'])

How can I forward server response error to client with Jetty proxyservlet.Transparent?

I have implemented a proxy extending jetty's ProxyServlet.Transparent.
However upon testing I noticed there is a difference on error messages the user sees when the server returns an error.
For example, when connecting directly to one of our application server with an invalid user credential, the server should return something more specific with instructions on the auth as we have set it this way. When connecting to the proxy server the error is in its most generic form like Authentication failed: Unauthorized
I suspect at some stage jetty checks on the server response and set the proxy response with minimal information so I am looking into the Transparent class code and its parent classes to find which method I can override to intercept the original server response and forward the information in the proxy response, assuming my understanding on these two responses are correct.
Thanks for the help.

API Gateway WebSocket API postConnection timeout

I'm trying to set up a WebSocket API on API Gateway. I'm following the basic tutorial, and I have everything up and running -> Routes for $connect, $disconnect, "test", $default. I am able to connect to the API, store the connectionId in Redis, and retrieve it when accessing from the test route.
The problem is when I try to send back a message from my lambda (single lambda handling all routes). I'm using the following code
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
});
Then I call
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}`
}).promise()
This is only called on the "test" route.
All of this is as per their guide. I had to add a patch to be able to make postConnection work, again, as per their tutorial. The problem is when the above method is called I get a Internal Server Error message from the API Gateway and the lambda times out after 3 seconds.
There is very little info on this method. I'm not sure what is causing the internal server error. I have checked the endpoint and the connectionId, both are correct.
What am I doing wrong? Any suggestions?
So the problem wasn't the actual lambda but the fact that it wasn't set up in a VPC that had access to the Internet. So if you're lambda has VPC enabled, make sure you it has a NAT gateway and Internet gateway set up.

Cordova ajax call kCFErrorDomainCFNetwork error 311

Anyone encountered this error? kCFErrorDomainCFNetwork error 311?
I wrote a simple cordova application running in iPad (iOS 9 up). This applications calls an HTTPS api but throws this error kCFErrorDomainCFNetwork error 311.
Pleas note that the HTTPS Server has a valid CA Issued SSL Certificate.
I googled a lot on this error but without any luck and only managed to found this cfStreamErrorHTTPSProxyFailureUnexpectedResponseToCONNECTMethod that has an int value of 311 and it says that
The HTTPS proxy returned an unexpected status code, such as a 3xx
redirect
Indeed the resource that i am invoking is returning a 302 which unfortunately i have no control of.
And to access the https server, i have to specifically connect to a wifi proxy where the IP address is whitelisted in the https server.
I hope someone from this great community could provide me some light on this error.
Thank you.
I also have received the same error. The problem is that you are accessing network through a proxy which needs to be authenticated before you send a request.
In your case, generally if you are accessing internet in the system browser, you might have proxy settings(along with authentication) in your browser or system preferences -> network -> Advanced -> Proxies.
In order to address the authentication issues while URL requests, Apple has given documentation in this regard - https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html.
For a simple model implementation just refer to Simple example of NSURLSession with authentication

Invoke worklight SQL adapter procedure using AJAX

Can someone give an example of how to invoke and receive a response from an SQL adapter in worklight using AJAX call? I'm using worklight 6.0
I have security at the app level. I need to invoke a procedure that doesn't need authentication (example: Registering an account) and hence need to invoke the adapter using AJAX
This is my adapter:
var invocationData = {
adapter : 'UserInfo',
procedure : 'addUserInfo',
parameters : [ customerData.firstName,
customerData.lastName, customerData.email,
customerData.province, customerData.zipPostal,
customerData.phoneNumber, customerData.streetName,
customerData.streetNumber, customerData.country,
customerData.city ]
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : insertUserSuccess,
onFailure : insertUserFailure
});
My understanding is that you just want to invoke an Adapter procedure using Ajax from some client.
Is it the same as this other question ?
Calling Worklight adapter from external app
You can check the details of the HTTP API here
http://www-01.ibm.com/support/knowledgecenter/SSZH4A_6.0.0/com.ibm.worklight.help.doc/admin/r_http_interface_of_the_prod_server.html?lang=en
Update:
Also note that if you have any security tests configured, different than "wl_unprotected" (your adapter is 100% public with that, be careful!!) you may need extra steps to handle authentication.
If you have a default adapter, without any security test set, you may receive a 401 unauthorized in your first request, and in the body of the 401 you may find a WL-Instance-ID property, that you must send together with a new request to get authorized to use it.
Update 2:
Worklight/MobileFirst Platform doesn't enable CORS (so you can't "naturally" call adapters using ajax from an external web page). It may be possible to workaround that by using a gateway (IHS maybe) that adds the header "Access-Control-Allow-Origin" to all adapter responses. Note that you are handling a security thing, so make sure you know what you are doing.
Worklight (6.3 and below) adapters can work only with the Worklight Server.
If you plan on using Worklight adapters, you are required to use the API as provided by the Worklight framework - the code mentioned in the question.
You can still use regular AJAX requests - but those won't/cannot be requests sent to/by the Worklight adapter.
WLJQ.ajax( "some-URL" )
.done(function (data) {
console.log(data);
});
If the destination does require going through the Worklight Server, and it is not protected by any realm, what is the problem then? Send the request.
Perhaps you should not protect the app at the environment level but rather at the procedure level (set the security test on the adapter procedure in the adapter XML and not on the environment in application-descriptor.xml).
Perhaps you need to better explain your specific scenario...

Resources