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

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).

Related

Chrome run fails in Azure Functions: An attempt was made to access a socket in a way forbidden by its access permissions

I wrote a web bot that uses Selenium framework to crawl. Installed ChromeDriver 72.0.3626.69 and also downloaded Chromium 72.0.3626.121. The app initializes ChromeDriver with this included Chromium binary (and NOT a locally installed Chrome binary). All this perfectly works on my machine locally.
I've been attempting now to port the app to Azure Functions. I wrote a function, tested it, and it works fine locally. But once I publish it to Azure Functions it fails due to about 182 errors of type:
An attempt was made to access a socket in a way forbidden by its
access permissions
I know this happens due to exceeding the TCP connection limits of Azure sandbox, but the only attempt here was to create an instance of ChromeDriver (not even navigate anywhere yet!)
Here is a screenshot of Azure Function call log.
That error appears about 182 times in a row, and that's basically just an attempt to create a browser instance (or ChromeDriver instance, to be precise - can't be sure if that's Chromium or ChromeDriver causing the issue).
The question: Have anyone experienced issues with ChromeDriver/Chromium creating so many (obviously excessive) connections when launching? And what might help to avoid this.
If that's of any help, this is basically a piece of code that crashes on the last line:
ChromeOptions options = new ChromeOptions();
options.BinaryLocation = this.chromePath;
options.AddArgument("no-sandbox");
options.AddArgument("disable-infobars");
options.AddArgument("--disable-extensions");
if (this.headlessMode)
{
options.AddArgument("headless");
}
options.AddUserProfilePreference("profile.default_content_setting_values.images", 2);
Log.LogInformation("Chrome options compiled. Creating ChromeDriverService...");
var driverService = ChromeDriverService.CreateDefaultService(this.driverPath);
driver = new ChromeDriver(driverService, options, timeout);
I believe you are running this function in a Windows Function App which is subject to quite a few limitations as described in this wiki.
But when running on Linux, functions are basically run in a docker container, removing most of these restrictions that windows has. I believe what you are trying should be possible there.
You could either just deploy your function to a Linux Function App or even build a container and use that directly as well.

Random 21/42 seconds timeout in outgoing traffic on Azure Web Sites

I have an ASP.NET MVC 5 application running in the azure german cloud as Azure Web App (single instance - Standard S3 size).
I'm calling a non azure hosted REST/SOAP service on a particular host and the web requests either succeed promptly or timeout after 21 / 42 seconds.
I've load tested the requests and the percentile of requests timing out is between 20 and 80.
One particular remarkable property of the timeout is, that they occur after exactly 21 or 42 seconds (this is serious, no reference to hitchhiker's guide to the galaxy intended).
Calling a different service from the web app works just fine, temporarily at least.
We've already checked the firewall of the non azure service and if the timeout occurs, not a single packet reached the host.
This issue occurred once in the past one year ago and support was unable to tell what the cause was until the issue suddenly went away roughly two weeks after first occuring, so the ticket got closed as fixed itself but now its back.
The code is using https://github.com/canton7/RestEase (uses HttpClient underneath) and looks like
[Header("Content-Type", "application/json")]
public interface IApi
{
[Post("/Login")]
Task<LoginToken> Login([Body]LoginRequest request);
}
private static Dictionary<string, IApi> ApiClientsByHost = new Dictionary<string, IApi>();
private IApi GetApiForHost(string host)
{
if (!ApiClientsByHost.TryGetValue(host, out var client))
{
lock (ApiClientsByHost)
{
if (!ApiClientsByHost.TryGetValue(host, out client))
{
ApiClientsByHost[host] = client = RestClient.For<IApi>(host);
}
}
}
return client;
}
var client = GetApiForHost("https://production/");
var loginToken = await client.Login(new LoginRequest { Username = username, Password = password });
By different service, i mean using "https://testserver/" instead of "https://production/" (testserver is located in a different data center with different IP and all).
The API authentication is passing a token via query but it timeouts already before being able to get a token.
The code is caching the IApi to avoid the TCP starvation problems of disposing HttpClients (but i've never run into port exhaustion).
Restarting the app does not resolve the issue and the issue only occurs to production currently (but a year ago, when this issue occurred on production, we've switched to testserver which worked initially but after some time, ran into the same problem)
EDIT: Found some explanation in the last answer as to where those magical 21 seconds are comming from.
EDIT: One way i've found to workaround is, is to setup a azure vm with a proxy on it and configure defaultProxy to pass through that vm.
That's TCP retransmission timing out. It's odd that you are getting different values though.

SqlDataProvider connection string in Suave on Azure

I can't get SqlDataProvider to work when executed in a fsx script which is running in an Azure Web Site.
I have started from the samples that Tomas Petrecek has here: https://github.com/tpetricek/Dojo-Suave-FsHome.
In short it is a FSX script that is executed using the IIS httpPlatformHandler so that all http requests to my Azure Web site is forwarded to my F# script.
The F# Script use Suave to handle the requests.
When I tried adding some database access to my HTTP handlers I got into problems.
The problematic code looks like this:
[<Literal>]
let connStr = "Server=(localdb)\\v11.0;Initial Catalog=My_Database;Integrated Security=true;"
[<Literal>]
let resolutionFolder = __SOURCE_DIRECTORY__
FSharp.Data.Sql.Common.QueryEvents.SqlQueryEvent |> Event.add (printfn "Executing SQL: %s")
// the following line fails when executing in azure
type db = SqlDataProvider<connStr, Common.DatabaseProviderTypes.MSSQLSERVER, ResolutionPath = resolutionFolder>
let saveData someDataToSave =
let ctx = db.GetDataContext(Environment.GetEnvironmentVariable("SQLAZURECONNSTR_QUERIES"))
.....
/// code using the context here
This works just fine when I run it locally, but when I deploy it to the azure site it will fail at the line where the type dbis created.
The error message is (line 70 is the line that has the type db = ...:
D:\home\site\wwwroot\app.fsx(70,11): error FS3033: The type provider
'FSharp.Data.Sql.SqlTypeProvider' reported an error: A network-related
or instance-specific error occurred while establishing a connection to
SQL Server. The server was not found or was not accessible. Verify
that the instance name is correct and that SQL Server is configured to
allow remote connections. (provider: SQL Network Interfaces, error: 52
- Unable to locate a Local Database Runtime installation. Verify that SQL Server Express is properly installed and that the Local Database
Runtime feature is enabled.)
The design-time database in the connStr is not available in the azure site, but I thought this is why we have the GetDataContext overload that takes a connection string to be used at run-time?
Is it because it is running as a script and not as compiled code that it is trying to access the database when creating the TypeProvider?
If yes, does it mean that my only option is to compile and provide the database code as a compiled assembly that I load and use in my Suave FSX script?
Reading the connection string from a config file does not work very well as this is in a azure site. I really need to get the connection string from an environment variable (which is set in the azure management interface).
Hmm, this is a bit unfortunate - as #Fyodor mentioned in the comments, the problem is that the script-based deployment to Azure actually compiles the script on the Azure machine - and so you need to have a statically-resolved connection string that works on Azure.
There are two options:
Use compiled project instead. If you compile your F# code locally and deploy the compiled code to Azure it will work. Sadly, there are no good samples for that.
Do some clever trick to make the connection string accessible to the script at compile time.
Send a PR to the SQL provider so that you can give it the name of an environment variable and it reads the connection string from there.
I think (3) would actually be quite nice and useful feature.
I'm not necessarily sure what the best way to do (2) would be. But I think you might be able to modify app.azure.fsx so that it creates a file (say connection.fsx) that contains something like:
module Connection
let [<Literal>] ConnString = "<Contents of SQLAZURECONNSTR_QUERIES>"
Then app.fsx could load this script and use Connection.ConnString in the argument of SQL type provider.

Error with Azure service SSL in Development Fabric

I'm running into a problem with getting SSL to work in the Development Fabric. I'm running a clean install of Windows 8 Pro with Visual Studio 2012 Ultimate and the October 2012 Azure SDK for .NET. IIS8 is not installed, only IIS Express, which claims to support HTTPS so I'm hoping that's not the issue.
Running VS 12 as administrator, I've created a blank VS solution, added a new (.NET 4.5) cloud service with a new ASP.NET MVC 4 Internet web application project, and hit F5. Everything works fine. Then, when I add an SSL certificate to the web role and replace the HTTP endpoint (port 80) with an HTTPS endpoint (port 443, with the certificate), hitting F5 produces the following error message:
Windows Azure Tools for Microsoft Visual Studio
There was an error attaching the debugger to the role instance 'deployment18(32).WindowsAzureCloudService.Mvc4WebRole_IN_0' with Process Id: 4892'. Unable to attach. Access is denied.
Note, the last part ("Access is denied") comes in a few variations, a particularly pleasant one being "Catastrophic failure". :)
The only message in the VS Output window ('General' output) is:
Windows Azure Tools: Warning: Remapping private port 443 to 444 in role 'Mvc4WebRole' to avoid conflict during emulation.
The Compute Emulator UI is not much help; just before the instance disappears, this is the only console output that I get consistently (sometimes other messages appear, but sporadically every few runs; I'm not sure how to capture these):
[fabric] Role Instance: deployment18(33).WindowsAzureCloudService.Mvc4WebRole.0
[fabric] Role state Unknown
[fabric] Role state Suspended
[fabric] Role state Busy
[fabric] Role state Unhealthy
[fabric] Role state Stopped
The certificate was obtained from a CA and properly imported into the Local Machine/Personal/Certificates store as a .pfx with private key, extended properties, and marked as exportable, for what it's worth.
When I attempt to publish the service to Azure, I get one build (validation) warning about the database connection string (which I assume is irrelevant):
The connection string 'DefaultConnection' is using a local database '(LocalDb)\v11.0' in project 'Mvc4WebRole'. This connection string will not work when you run this application in Windows Azure. To access a different database, you should update the connection string in the web.config file.
Probably more important, the deployment actually fails with the following history in the Windows Azure Activity Log window:
9:00:25 AM - Warning: There are package validation warnings.
9:00:25 AM - Preparing deployment for WindowsAzureCloudService - 1/3/2013 8:59:55 AM with Subscription ID '<...>' using Service Management URL 'https://management.core.windows.net/'...
9:00:25 AM - Connecting...
9:00:26 AM - Object reference not set to an instance of an object.
9:00:26 AM - Deployment failed with a fatal error
Can someone help me troubleshoot this issue? I've rebooted a few times. ;)
Thanks in advance!
EDIT (Jan. 3, 4:44 PM): I have a few ideas that might help me make progress, but some are pretty drastic so any advice would be appreciated:
Is there a way to capture all the output from the Compute Emulator (Dev Fabric) to a log file so I can review it? (System.Diagnostic.Trace calls from my service won't help, since I don't even get as far as the RoleEntryPoint when using HTTPS!) I figured this out; see next edit.
That null pointer exception during the Azure deployment has me worried. Is it worthwhile to try reinstalling the Azure SDK, and if so, how should I go about doing a clean install of it?
Has anyone seen a problem of this sort disappear when switching to using full IIS for the emulator? (That seems unlikely since IIS vs. IIS Express should have no relevance to the Azure deployment.)
EDIT (Jan. 4, 10:15 AM): Bad news: I tried the suggestion to grant Read access to the certificates, but it didn't help in my case. Good news: I managed to capture one of those sporadic messages in the Compute Emulator UI before it shut down; it was a bit of info from some diagnostics. Not helpful in and of itself, but it revealed where the Development Fabric was storing its temporary files:
[Diagnostics] Information: C:\Users\Lars\AppData\Local\dftmp\Resources\0005155d-4592-40f4-812e-18793b26576c\directory\DiagnosticStore\Monitor
The GUID portion gets recreated for every deployment, and it is deleted when the deployment goes away (as it always does in my case). But in the parent directory ('dftmp'), there are a few helpful directories that I then monitored during a new deployment: DevFCLogs, DFAgentLogs, and IISConfiguratorLogs. I guess that answers the first question I had yesterday! :)
DFAgentLogs\DFAgent.log: (41KB) No useful information. A bunch of "Failure to read pipe" messages and failures to get the role/deployment instance ID, which I assume are just noise.
DevFCLogs\DevFabric--2013.01.04--<...>.log: (510 KB) No useful information. I skimmed the file and also searched for 'error', 'failure', 'not found', 'certificate', and 'Mvc4WebRole_IN_0'; none of those showed any hints of what was going on.
IISConfiguratorLogs\IISConfigurator.log: (6 KB) Now we're making progress!! :) Can someone tell me what this means? (In the meantime, I'm off ILSpy-hunting... fun fun...)
IISConfigurator Information: 0 : [00006356:00000005, 2013/01/04 16:07:08.915] Using IIS Express appdomain
(...)
IISConfigurator Information: 0 : [00006356:00000005, 2013/01/04 16:07:08.936] Adding binding 127.255.0.0:444: to site deployment18(40).WindowsAzureCloudService.Mvc4WebRole_IN_0_Web
IISConfigurator Information: 0 : [00006356:00000005, 2013/01/04 16:07:10.484] Caught exception
IISConfigurator Information: 0 : [00006356:00000005, 2013/01/04 16:07:10.487] Exception:System.Runtime.InteropServices.COMException (0x800401F3): Invalid class string (Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING))
Server stack trace:
at Microsoft.Web.Administration.Interop.IAppHostProperty.get_Value()
at Microsoft.Web.Administration.ConfigurationElement.GetPropertyValue(IAppHostProperty property)
at Microsoft.Web.Administration.Binding.get_CertificateHash()
at Microsoft.Web.Administration.BindingCollection.Add(Binding binding)
at Microsoft.WindowsAzure.ServiceRuntime.IISConfigurator.WasManager.DeploySite(String roleId, WASite roleSite, String appPoolName, String sitePath, String iisLogsRootFolder, String failedRequestLogsRootFolder, List1 bindings, List1 protocols, FileManager fileManager, WAAppPool defaultAppPoolSettings, String roleGuid, String& appPoolSid, List`1 appPoolsAdded, String configPath)
EDIT (Jan. 4, 11 AM): ILSpy wasn't much help; the exception is being thrown at an interop point (we knew that already) while trying to get the hash of a certificate in order to set up the binding (we knew that too). Does anyone know what COM object would need to be registered in order to get a certificate hash for a binding in Microsoft.Web.Administration? Or how I could intercept the interop call to find out? Bonus points if you can tell me why this is happening in the first place. :)
I've had similar problem on two computers. On both cases installing IIS solved the problem.
It seems to be enough to just install the IIS (via add/remove Windows components). You don't need to start using it. The installation changes something and after that my IIS Express started working again with HTTPS from Visual Studio.
There is a discussion on similar issue on MSDN Social:
http://social.msdn.microsoft.com/Forums/nl-NL/windowsazuredevelopment/thread/ad362016-16f6-459a-8022-9307aa5f910e
And the issue has been also raised on Microsoft connect:
https://connect.microsoft.com/VisualStudio/feedback/details/758533
In my case the error in the log files was:
IISConfigurator Information: 0 : [00007644:00000007, 2013.01.17
00:39:18.523] Exception:System.Runtime.InteropServices.COMException
(0x800401F3): Invalid class string (Exception from HRESULT: 0x800401F3
(CO_E_CLASSSTRING))
I found the log files from C:\Users\\AppData\Local\dftmp\IISConfiguratorLogs directory.
When running locally with a private key cert for SSL, you'll need to give the user the emulator app is running under access to the private key. Open mmc.exe and add the Certificates >> Local Computer Snap-In to view your certificate. Right Click on the certificate, then All Tasks >> Manage Private Keys - then add IUSR and Network Service with at least read access.
For deployment to azure, you'll need to upload the certificate to the Cloud Service and make sure the certificate is valid for the domain.
Follow step 11 from http://www.microsoft.com/en-us/download/details.aspx?id=35448. From this SO post

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