How do I get ELMAH to work with SQL Server (permission problems) - asp.net

I've got ELMAH working on my (Cassini) development server, and was quite happy with it, but now that I'm trying to move everything to my production server (IIS7), the honeymoon looks like being over.
I've got past the "gotcha" with IIS7, which frankly could have been better highlighted in the documentation, and if I just use the in-memory log then it works.
However, I'm trying to get it to use the SQL Server log (as I do on my development system), and I'm getting an error along the lines of:
The EXECUTE permission was denied on the object ELMAH_GetErrorsXml
Well, fine. I know how to grant database permissions, but I'm really struggling to understand which user and which stored procs/tables I need to grant access to.
The thing that's really confusing me is that I didn't have to do anything like this to get it to work on my development server. The only difference I can see is that on my development server it seems to connect as NT AUTHORITY\IUSR, whereas on my production server it seems to connect as NT AUTHORITY\NETWORK SERVICE. (It's just using a trusted connection so I've not explicitly configured it to do that - I presume it's to do with the web server). UPDATE: I've since established that because I'm using Cassini, it was actually logging in as me (an admin) and not IUSR, which explains why I didn't get any permission problems.
On my development server, the IUSR account is a member of the public database role, and has access to the required database (again as "public"). There's no explicit granting of object-level permissions. [See update above - this is irrelevant].
On my production server, I've added NETWORK SERVICE in exactly the same way (public database role, explicit access to the database as "public"). Yet, I get this permission error. Why?!! [See update above - the only reason I don't get a permission error is because I'm running as an admin].
And, of course, if the fact that it works locally is just "luck", I will need to know which SPs/tables to grant access to. My guess would be all 3 SPs and not the table, but it would be good (again) to see some documentation that makes this explicit.

example of sql needed to give execute permission to the user USER_NAME:
GRANT EXECUTE ON ELMAH_GetErrorsXml TO USER_NAME
GRANT EXECUTE ON ELMAH_GetErrorXml TO USER_NAME
GRANT EXECUTE ON ELMAH_LogError TO USER_NAME

Are you providing ELMAH with a full connectionstring in the web.config? If so, you should know exactly what db user to grant permissions to, right? And yes, permission would be to execute the three ELMAH stored procedures...
Here's a configuration that I've used:
<elmah>
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="elmah" />
</elmah>
<connectionStrings>
<add name="elmah" connectionString="Data Source=XXX;Initial Catalog=XXX;User Id=XXX;Password=XXX;" providerName="System.Data.SqlClient" />
</connectionStrings>

Related

Unable to find username and password fields for ASP.Net (not in webconfig)

My office recently did some migration of servers, and as a result our webpages now use different data sources. For our environment, we typically use SQL Server, though we also have a linked server to an Oracle database. I am having difficulty finding out where I need to update the username and password for one of our web pages.
Generally speaking, the process has been pretty easy: go to Web.Config, find the connection string that the page is using, and update it with the relevant data source, username, and password. This page, however, is different. First, I get this error when visiting the page:
ERROR [28000] [Oracle][ODBC][Ora]ORA-01017: invalid username/password;
logon denied
ERROR [IM006][Microsoft][ODBC Driver Manager] Driver's
SQLSetConnectAttr failed
ERROR [28000] [Oracle][ODBC][Ora]ORA-01017: invalid username/password;
login failed
Okay, so obviously I need to update the password somewhere. I go to Web.Config, and I don't see any connection strings. This is a first for me, so I start looking around, and the only thing I see (worth mentioning) is this line:
<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1; Trusted_Connection=yes" cookieless="false" timeout="20"/>
To me, this indicates that the database is local, or at the very least my problem lies on the webserver itself. So I remote in, and I check both the ODBC connections for Oracle and SQL Server; no issues. Each of them work. I even check the 32-bit and 64-bit connections.
Googling "Driver's SQLSetConnectAttr failed" tells me it's the ODBC issues, but again...I can't find anything.
Does anyone have any ideas on why I keep getting these errors and what I can do to fix it?
I (well, technically my coworker) found the answer. The answer lied within IIS. Basically, we were missing two connection strings. The first one references the driver, and the second one (I believe) contains the username/password that is passed to the ODBC driver through the first connection string. Whereas normally the connection strings are stored in the program (web.config file), in this case it was on the actual server. The program looked for the connection strings there, but couldn't find it.

log4Net eventlog permissions issue using non-administrator account

This probably isnt an issue with SiteCore per se but I've included it for completeness. I have sitecore 6.3 running under IIS7 using a custom identity for the app pool. I cant get Sitecore to write its logging information (using the default log4net settings) to the eventlog. I've followed the advice here: http://logging.apache.org/log4net/release/faq.html#Why%20doesn%27t%20the%20EventLogAppender%20work? and although it works fine when I make the custom identity a member of the administrator's group I need to find a way to get it working in production without such a security hack.
The weird thing is that I have a MSI that installs it (running under an account which IS a member of the administrator's group) and creates the correct registry keys in the eventlog for me and yet despite that, I am still getting the following error when I run the application using the custom identity (without it being a member of administrators).
log4net:ERROR DOMConfigurator: Could not create Appender [EventLogAppender] of type [log4net.Appender.EventLogAppender]. Reported error follows.
System.Security.SecurityException: Requested registry access is not allowed.
at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
at System.Diagnostics.EventLog.GetEventLogRegKey(String machine, Boolean writable)
at System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)
at System.Diagnostics.EventLog.DeleteEventSource(String source, String machineName)
at log4net.Appender.EventLogAppender.ActivateOptions()
at log4net.Repository.Hierarchy.DOMHierarchyConfigurator.ParseAppender(XmlElement appenderElement)
The Zone of the assembly that failed was:
MyComputer
log4net:ERROR DOMConfigurator: Appender named [EventLogAppender] not found.
Thinking I could narrow it down to a registry permission issue I granted Everyone full permissions to the following registry key and subkeys but it didnt work either: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog
The custom identity is a member of the following groups:
Event Log Readers
IIS_USERS
Performance Monitor Users
I've also seen the following question which seems to ask the same thing. The Microsoft article seems to suggest it might be a problem with ACLs on an event log and gives examples on how you can change SSDLs but I'd rather avoid that if at all possible.
EDIT:
I have another server running where the log is being populated fine. The custom identity was a member of administrators so I revoked that and rebooted, trying to purposely break it but I cant. Config is identical on both boxes and same identity used to run the MSI which creates the registry keys. Have run procmon on both (after doing a IISReset and spinning up the app pool again) to examine registry activity. Strange thing is - on the box that works you get 477 name not found records for my event source in the wrong places (Application, and a different Custom EventLog "MyCompany"). No hits for the place where it is logging which is "MyCompany\MyCompany.SiteCore". Whilst on the box which is broken, it does appear to be requesting to read the right key (albeit only 6 times) but you then get the Log4Net registry access error.
As I understand it EventStores are stored in the registry, so you only need write permission to registry to create or delete an EventStore. This is usually only needed once and most applications create this as part of the install procedure so that the application does not need to be run as Administrator during normal execution.
However your error message (in the question) includes the method DeleteEventSource from which I would deduce/guess that the EventSource does exist but is wrong in some way. So perhaps this is currently registered as writing to the event log named MyCompany and you are now trying to change it to "MyCompany\MyCompany.SiteCore" which requires you to delete the old eventsource and create a new one.
So it sounds like your installation routine is creating a different EventSource from the one that your application is actually using.
If that doesn't help, then I would suggest enabling internal logging for Log4net (but obviously not to the eventlog) which will probably give you more information.
Giving full permission to the registry key is not enough.
According to Microsoft
To create an event source in Windows Vista and later or Windows Server 2003, you must have administrative privileges.
The reason for this requirement is that all event logs, including security, must be searched to determine whether the event source is unique. Starting with Windows Vista, users do not have permission to access the security log; therefore, a SecurityException is thrown.
Starting with Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. To execute the code that accesses the security log, you must first elevate your privileges from standard user to administrator. You can do this when you start an application by right-clicking the application icon and indicating that you want to run as an administrator.
I think, contrary to the Apache documentation, log4net DOES need write access to the registry – or at least it does in my case. To prove this, I backed up the registry on the server where it wasnt working and granted IIS administrator privileges before spinning up sitecore. Sure enough it started logging away to the eventlog nicely and then when I exported the registry again to run a diff, there WAS a difference.
The value for the eventlogmessage file on my event source had been updated from:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll
To
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\EventLogMessages.dll
So I assumed that merely changing this value in the registry by hand would work.
But it didn’t.
So I ran procmon on the two servers I have: A=the working one, B=the failing one. Sure enough, on server B I have a line which says:
Operation: RegOpenKey, Path: HKLM\System\CurrentControlSet\Services\EventLog, Desired Access:Read/Write, Result: ACCESS DENIED.
I’ve traced through with Server A and in exactly the same place, the key is requested with Desired Access:Read.
Conclusion:
It seems unavoidable that I will need to grant my app pool identity administrator privileges in production for at least enough time to programatically do the necessary registry writes the first time from within log4net. I dont know why administrator; I have tried granting Full permissions to the entire eventlog node in the registry for my custom app to no avail. It seems to do something which I cannot identify or pin down. I will then revoke this privilege immediately after it starts to log and monitor whether subsequent installs knock out the functionality afterwards. (Hopefully not).
If anyone has any insight into this behaviour it would be greatly appreciated.

My SQL Server Express has gone nuts it seems, at times mounting db and others not

I am not sure what's going on exactly as I can't establish a strict linear correlation between
events. But below you'll find my connection string, at times it works, other times when I open the app/project I am building (no changes made) it doesn't and gives me various errors and reasons.
<add name="EFDbContext"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\EFDbContext.mdf;MultipleActiveResultSets=true;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
Errors include:
Unable to complete operation. The supplied SqlConnection does not specify an initial catalog.
or
saying Amin-PC\Admin has no access rights (I am logged in admin)
Also when I try to add a new connection at times it will tell me I have no access rights or database already exists or just adds it normally!
I tried explicitly starting visual studio as administrator and this seemed to help with the denied access to the db issue.
Basically I don't know what the heck's going on.
Have recently started with .net and it has been easy coding for asp.net mvc framework until I got to interacting with underlying asp.net infrastructure, connection strings, outdated (noon-entity framework ready) membership provider etc.
And now don't know what's going on with the SQL Server Express edition that gets installed a long with VS2010.
My recommendation would be: since you already have a server instance (.\SQLEXPRESS) installed - attach your databases to the SQL Server Express instance, and then use them under their database name (instead of using the shaky AttachDbFileName= method).
So:
launch your SQL Server Management Studio Express
find your MDF files you want
use Server > Attach Database to attach the MDF/LDF to the server - give it meaningful name
from that point on - use the database on the server and don't attach MDF's on the fly....
Your connection string would then look something like:
server=.\SQLEXPRESS;Database=YourEFDatabaseName;Integrated Security=True
I find this method is typically much more reliable and predictable - the AttachdbFileName= and User Instance=true are supposed to be easier, but tend to be more confusing that anything else....
Refer to SQL Server connection string samples here.

ASP.NET ASPNETDB.MDF Cannot open database

I am using membership class for my user management, and it created a database called ASPNETDB.MDF.. I decided to use the same database to handle my other data, and so I added some of my own tables in there...
When I try to access it:
<connectionStrings>
<add name="connString" connectionString="Initial Catalog=MyProject;Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\MyName\Documents\Visual Studio 2008\Projects\Project\MyProject\App_Data\ASPNETDB.MDF;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
</connectionStrings>
Using this:
Dim conn As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("connString").ToString)
It gives me this error after I log in through Membership class:
Cannot open database "MyProject" requested by the login. The login failed.
Login failed for user 'My-PC\Myuser'.
I am not sure what's going on?
Edit: If i don't use Membership class, I can use the database fine.. but when after I login using the membership class, it stops to work..
Make sure My-Pc\MyUser has access appropriate permissions to 'MyProject' database. For the test environment that my local projects run on, i generally assign myself as the database owner to the database i want to access. That is if i am the only user accessing it. You can do so by running EXEC sp_changedbowner 'My-Pc\MyUser'. Obviously, you want to dedicate a separate account with limited access for your production environment.
You'll probably need to make sure that the user the web server is running as has read/write access to the db file and directory.
Try removing "connString" from web.config and using "LocalSqlServer" connection string instead (it is defined in machine.config):
Dim conn As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
I also encountered this problem, and I noticed that it does indeed work if I changed the owner of the database to 'My-Pc\MyUser' (via EXEC sp_changedbowner 'My-Pc\MyUser') as pointed out above.
You might also try running this on your database:
exec sp_grantlogin 'My-PC\MyUser2'
This is certainly useful if you want MyUser AND MyUser2 having access to your database. I encountered this scenario when I have to execute aspnet_regsql.exe using MyUser2 credentials (as the owner of my database is ASPNET, which does NOT have login/runas capabilities).
Hope this helps someone :)

working with sql server 2008

I am not used to work with SQL Server(usually I just use express). I run it on windows server 2008, iis7.
I have attached the database to my sql server. I made a web site in iis7 but I get this error message.
Cannot open database "Phaeton.mdf" requested by the login. The login failed.
Login failed for user 'NT AUTHORITY\NETWORK SERVICE'.
Connectionstring I use
<add key="PhaetonConnectionString" value="Data Source=.;Initial Catalog=Phaeton.mdf;Integrated Security=True"/>
Thanks
Since you are using Integrated Security the SQL connection will use the windows identity which is passed from ASP.NET.
You can either change your security to mixed-mode which will involve removing the integrated security. Or use impersonation (check IIS and your web.config) and grant that user access to the database.
Hope that helps
You need to configure your application in IIS to turn off anonymous access and turn on Windows authentication(If yoy want to use integrated security).
Access SQL Server Using Windows Integrated Security
The other way, you can use a connection string with user/password ... with the appropriate login
Problem was that the database I tried to attach was sql express
The problem is here:
Initial Catalog=Phaeton.mdf
In SQL Server Express, you can attach a filename as a local database. That's not how it works on a production SQL Server. In non-Express versions you attach a database permanently, which it looks like you've already done, and you give it a logical name, which is not the same as the primary file name.
I would guess that if the file name was "Phaeton.mdf" then you probably named the database "Phaeton". In which case that part of the connection string should simply be:
Initial Catalog=Phaeton
If that's not the right name, you can get a list of database names from the server using the following script:
USE master;
SELECT name FROM sys.databases

Resources