The Question:
How do I get my Web Application to use my connection string login and not the Application Pool Identity?
The Background:
I have started up a .net mvc project and currently use Arvixe for hosting. I made a simple page using a form to communicate with the SQL database. Here is the site.
Just type anything into the text boxes and hit the button. If the communication is successful, it should just return a message.
The error:
Cannot open database "jfphotography" requested by the login. The login failed.
Login failed for user 'SEAWEED\photosbyjoefor_web6'.
My database user is jfphoto_dbadmin. I have tried making it photosbyjoefor_web6, but with no luck. No where in my code do I use, or set anything to, photosbyjoefor_web6. I have tried using photosbyjoefor_web6 in my connection string.
My connection string is correct, and I have been chatting with support for a week now. We believe that the application is using the Application Pool identity, and, using basic services, I am not allowed/Arvixe will not make any custom Application Pool Identities (which makes sense for shared hosting). Unfortunately, I do not want to be paying 40 bucks a month for their private hosting to be able to edit the Application Pools.
My project is using a Code-First approach, data service layers, context layer, all the fun stuff. I have never encountered this type of error before, and I am unsure of how to approach it. I really do not want to re-build my project in a different manner, but if I have to so-be-it.
Connection string:
add name="PhotographyContext" connectionString="Data Source=seaweed.arvixe.com;Initial Catalog=jfphotography;Integrated Security=True;user id=jfphoto_dbadmin;password=**" providerName="System.Data.SqlClient"
Related
I'm working on an old webpage which the client is trying to migrate to Azure. The app has worked forever, so it's not a question of "maybe the code is broken". Instead, it's the migration to Azure that's been throwing up issues. The differences between a localhost build and the Azure build are significant, since I don't have a Managed Identity local. But the differences are primarily configuration, other than bits of code to add an Access Token to SQL connections.
The app uses dozens of asp:SqlDataSource objects defined in .aspx pages to do all sorts of work. But that's fine, they use a standard connection string, pulled from the web.config, to talk to the database:
<add name="MyConnectionString"
connectionString="Server=tcp:MyDatabaseServer.database.windows.net,1433;
Initial Catalog=MyDatabaseName;
Persist Security; Info=False; MultipleActiveResultSets=False;
Encrypt=True; TrustServerCertificate=False;
Connection Timeout=30" providerName="System.Data.SqlClient"/>
For security reasons, the client now has to use a Managed Identity to talk to the database, rather than our previous service account model.
I added an OnSelecting event to the SqlDataSource where I set an access token on the connection. I'm not getting any exceptions or complaints about that code, so either it's running fine or it's not running at all. The managed identity is created, and it has reader, writer, and executor roles on the database, but this bit of code is the first time that the managed identity is being put through its paces.
What I get is an error
[SqlException (0x80131904): Login failed for user ''.]
Is there some other permissions or flags I need to set on the managed identity, or some missing configuration? Should I be using a different event than the OnSelecting event? Is the URL for an access token different in this situation? Is there a place to find more detailed error logs?
First note that I haven't seen any possible way to use SQL-based session state with a managed identity. Switch your Session storage to InProc and see if your login problem goes away.
Second, I've found that making a web request to 169.254.169.254 to obtain a token doesn't work in a sovereign Azure environment. Instead, do this:
var credential = new Azure.Identity.DefaultAzureCredential();
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://database.windows.net/.default" }));
connection.AccessToken = token.Token;
Using the OnSelecting event to assign the access token to the connection will work fine for a SqlDataSource. Instead of creating credentials and getting a token every time a stored procedure is called, store the token in the app and just re-use it; and make sure to purge the token when the user logs out.
I have database mirroring setup to work with the production database for my asp.net application. When the system fails over to the mirrored database, the application crashes because the connection string is invalid.
If the failover is dependent on a connection string, what kinds of changes do I need to make to my application in order to ensure that it can fail over without my manually changing the connection string?
Do I put exception handling behavior around the EF code where it automatically changes its connection string?
Depending on the type of failover you have set up, I believe there is a connection string property that you can specify the failover DB.
Data Source=myServerAddress;Failover Partner=myMirrorServerAddress;Initial Catalog=myDataBase;Integrated Security=True;
From here: http://www.connectionstrings.com/sql-server-2008
I've been researching for days and I've gotten to the point where my WCF service creates an Access object via com/interop. I've ran the OpenCurrentDatabase call for the Access object without an error but Application.CurrentDB is still nothing/null. If the CurrentDB is nothing then I surely can't call Application.Run "myFunction" I realize WCF services aren't meant to be user interactive, but it's a long story why I'm trying to go this route. Basically I need to have a proof of concept ready sooner rather than later and the alternative (correct) route involves the complete re-writing of a large complex access VBA application. It's not a permissions issue, I have the IIS user names added to the security tab. What I really need is a way to set Environment.UserInteractive to true so my WCF service can create an instance of Access on my server machine, run the VBA functions, close out, return true. I'm using VS 2010 for the WCF, IIS 7 for my server, Access 2010 for the VBA application. Please help!
The answer is to have the WCF service write the access macro name to a database and have a desktop application on the server machine monitor the database. The desktop application loads access, performs the actions, and writes back to the database upon completion. The WCF service monitors the database waiting for an "operation complete" status and returns the result.
I modified the ASP.NET login control to also allow specifying UserRole ('Employee' or 'Volunteer'). Users are authenticated via a call to a webservice written by our client, which accepts username/password/role and returns true or false.
If role is 'Employee' it represents an active directory user. The application should impersonate the user with the given username/password.
If role is 'Volunteer' the application should run under a set Windows account whose username/password are known in advance (i.e. hard-coded in web.config file).
The server runs on Windows Server 2003. I am confused by the myriad of configuration choices and trying to understand my options;
Is it possible to have multiple scenarios as described?
Should I specify the impersonation programmatically or can it be done through the config file? If so, is it required to use LogonUser or WindowsIdentity?
What config file setup should I use? (i.e. Forms authentication, impersonate=true, etc..)
Thank you in advance.
Because the decision about which identity to impersonate is based on run-time data, you'll likely have to deal with impersonation programmatically.
I use a combination of interop and WindowsIdentity to handle impersonation. The steps I follow are:
Log on using the interop LogonUserA(), which fills a handle to an IntPtr (token).
Duplicate the token with the interop DuplicateToken().
Create a new windows identity, a la: var identity = new WindowsIdentity(tokenDuplicate);.
Create an impersonation context via: var context = identity.Impersonate();
Close both tokens with the interop CloseHandle()
When finished impersonating, undo the impersonation context via: context.Undo();
I keep a disposable class around to handle the details. Steps 1-5 occur in a constructor, and step 6 occurs in the dispose routine. This helps ensure that I properly revert even in the face of an exception.
With this approach, since you are passing credentials via a service method, the web.config authentication scheme is not entirely forced. If, however, you are using integrated Windows auth, you could programmatically impersonate the current user from HttpContext.Current.User.Identity.Impersonate(), without passing credentials in a service method.
On an aside, and you may already know, PInvoke.net is a valuable resource for configuring signatures for interop methods.
I'm trying to start a Windows service on Windows Server 2003
from an ASP.NET page:
the code of line 35 is:
32. Dim controller As New ServiceController
33. controller.MachineName = System.Environment.MachineName
34. controller.ServiceName = "WindowsServiceRealName"
35. controller.Start()
The error code is
System.InvalidOperationException: Cannot open WindowsServiceRealName service on computer 'DARWIN'. ---> System.ComponentModel.Win32Exception: Access is denied --- End of inner exception stack trace --- at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess) at System.ServiceProcess.ServiceController.Start(String[] args) at System.ServiceProcess.ServiceController.Start() at AfconParking.Import.StartService() in E:\ProjectsNet\AfconParking\AfconParking\system\Import.aspx.vb:line 35
The account used for the identity of your ASP.NET application pool ("Network Service" by default) does not have the permissions required to start a service.
To fix this issue, you have a few options:
Re-architect your site to not require interactions between ASP.NET pages and the service control manager. I really can't think of a good reason to require this (the service can simply be started at boot time, and remain running: if the service crashes, you should fix the cause of that, and/or use the corrective actions provided by the SCM. If a service restart is needed to kick of some kind of processing, use an IPC mechanism, such as sockets or named pipes, to communicate between your web app and the service instead).
Create a service account with the appropriate permissions (basically, membership of the local Administrators group) as described in detail here. Do note that this has several security implications, none of them particularly good.
Its a permissions issue, try to run the application pool with an Identity that has permissions to perform service control operations.
Read this kb to find out how to grant user such a permissions:
http://support.microsoft.com/kb/325349
Services have Access Control Lists (like files etc.). By default most normal and restricted user accounts (including the default account used by ASP.NET workers) do not have permissions to control or see the status any services.
You can either set an ACL on the service that allows the IIS worker to control the service, or run the web application with an account that already has rights.
The latter option would probably give the web application a dangerous level of access (e.g. what would happen if a web user found a security vulnerability), but is a quick approach to confirming that it is a service access permission.
Setting an ACL is the better solution, but I don't think there is a UI to set the ACL (except in group policy) which makes things harder. You'll need to use the command line tools (e.g. SUBINACL.exe)