I never tried this because there was no point in my particular case, but the WindowsSecurityContext documentation says this in the section on the Credentials property:
" When the mode is set to Process no other properties need to be set. If the calling thread is impersonating then it will be reverted back to the process credentials." In other words, try setting the credentials to ImpersonationMode.Process instead of ImpersonationMode.User, and get rid of the other properties that only apply to user mode. Check out the docs for WindowsSecurityContext. And let me know if it works, I've got a web service or 3 in my near future. I still want to know how a regular ASP.NET can log to adoappender using trusted security and not exposing passwords, though, if anyone has any ideas. What can I say? I'm greedy. :-) -B WILLIAM BARNUM [EMAIL PROTECTED] -----Original Message----- From: Colin Mackie [mailto:[EMAIL PROTECTED] Sent: Tuesday, November 29, 2005 4:41 PM To: Log4NET User Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? The app is a web service and it is calling the config code within the static class constructor, so it is called after the first request but once before anything happens. That way it does have the correct Identity but only affects the very first call. However, it is still the wrong identity, as it is the IIS Process identity and not the anon user, which I need. You can get around this by calling WindowsIdentity.GetCurrent() and using that instead of doing a Logon - which is what log4net does. This was my idea, to change log4net code, WindowsSecurityContext.cs: : public void ActivateOptions() { if (m_impersonationMode == ImpersonationMode.User) { //if (m_userName == null) throw new ArgumentNullException("m_userName"); //if (m_domainName == null) throw new ArgumentNullException("m_domainName"); //if (m_password == null) throw new ArgumentNullException("m_password"); if (m_userName != null) { m_identity = LogonUser(m_userName, m_domainName, m_password); } else { m_identity = WindowsIdentity.GetCurrent(); } } } : i.e. uses the current Identity if you haven't specified one. Alternative you could expose the m_identity property and set it manually, rather than setting username/password. Any reason why this wouldn't work? Colin -----Original Message----- From: Billy Barnum [mailto:[EMAIL PROTECTED] Sent: 29 November 2005 16:29 To: 'Log4NET User' Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? It suddenly occurs to me that if you don't have high traffic volumes you could do something like: if (!IsPostBack) { <do my log4net configgerin'> } That is, configure not once application, but once per page per user. I didn't say it was a great idea, now. I just said you could do it, and I suppose you would then be able to pass through process credentials, as you do to SQL Server. Anyone wanna comment as to how stupid an idea this is? Probably waaaaaay too expensive to call configure() so often, right? Unless there was a way to dump log4net config data in the web cache ...? OK, 'nuff silly ideas for late in the day, but seriously - if anyone has ideas I'd love to hear 'em. This really is a problem, and I can't believe it hasn't come up before, so here's the challenge: How can an ASP.NET app use ADOAppenders with trusted security and NOT expose passwords anywhere, including code? -BillyB WILLIAM BARNUM [EMAIL PROTECTED] -----Original Message----- From: Billy Barnum [mailto:[EMAIL PROTECTED] Sent: Tuesday, November 29, 2005 4:14 PM To: 'Log4NET User' Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? Ah. I see now. I'm afraid you're S.O.L., Colin. (Unless someone else out there has a better idea?) You see, you need to be calling that configureandwatch() or configure() only once per application "session", yes? And for ASP.NET, that point is Application_Start(), when the web site is brought up. However - and this is a big however - there is no current user at that point. CurrentPrincipal is a big fat (thin?) null. Makes sense, right? No one has connected. So you're problem is not that log4net won't let you pass in current process credentials ... it's that there are none to pass at the time that configure() or configureandwatch() are called . Therefore you have to connect as a user, and in turn to do that you need to provide a domain and password, or use a database id. The only way I could see for the keepers of log4net to solve this problem would be to go back and try to re-fetch credentials at the point you log events to adoappenders in your code ... or any point after application startup. Might be possible, dunno. Prolly very expensive in performance, though, if it's even possible. I'd hafta think about it. Myself, I'd love it if this were possible, because I've started to use log4net as more than a debugging and tracing tool, I've made it part of *application* logic in certain areas and like you "logged" to relational databases; saved my clients time and $$$. But this security gotcha seems to be the price. Is there hope? -BillyB WILLIAM BARNUM [EMAIL PROTECTED] -----Original Message----- From: Colin Mackie [mailto:[EMAIL PROTECTED] Sent: Tuesday, November 29, 2005 3:51 PM To: Log4NET User Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? I saw you previous posts, and see that you had cracked the code for the securityContext. I tried that and it works great. I was just trying to take the next step and remove the hard coded username/password from code or the config - especially since the network admins manage IIS and passwords, so really I shouldn't be using it. This is something I have been able to do with my app, where it creates other threads and Impersonates the anon user. And it's something I made work by adding a few lines into the log4net code. The extra login idea for just accessing logging tables is good, but is going to create an admin headache so probably won't be used. I just needed to know if there was better way of doing it, something I missed, or if log4net really should be changed to support this mode? thanks, Colin -----Original Message----- From: Billy Barnum [mailto:[EMAIL PROTECTED] Sent: 29 November 2005 15:27 To: 'Log4NET User' Cc: [EMAIL PROTECTED] Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? Yup. Been there, my friend. I was never completely satisfied with what I found, but it wasn't really log4net's fault; just security choices that have to be made. The following code in Application_Start() of Global.asax.cs did indeed do for me what you're talking about, if I'm understading your request correctly: WindowsSecurityContext securityContext = new log4net.Util.WindowsSecurityContext(); securityContext.Credentials = log4net.Util.WindowsSecurityContext.ImpersonationMode.User; securityContext.DomainName = "mydomain"; securityContext.UserName = "myuser"; securityContext.Password = "mypassword"; securityContext.ActivateOptions(); using (securityContext.Impersonate(this)) { string path = Path.Combine(Server.MapPath("."), ConfigurationSettings.AppSettings["Log4NetConfigFile"]); XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(path)); } It worked with trusted connection specs in the config file (for SQLAppender) as follows <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <connectionString value="Data Source=BBARNUMXP;Database=WIAN;Integrated Security=SSPI;Trusted_Connection=yes;" /> You're still exposing a password, but it's at least it's in code and not in a clear-text ascii file. The only other choice we found acceptable was to create a SQL dbms account that only had access to the logging tables in question. Actually we decided to go with the latter option in the end, opting to expose a password that only risked dbms tables, not domain access. -BillyB WILLIAM BARNUM [EMAIL PROTECTED] -----Original Message----- From: Colin Mackie [mailto:[EMAIL PROTECTED] Sent: Tuesday, November 29, 2005 2:59 PM To: [email protected] Cc: [EMAIL PROTECTED] Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? I have been have a related problem on this and would appreciate any help in getting it configured right. I have 2003/IIS6/ASP.NET application that accesses a remote database. The application in IIS has its 'anonymous access' user set to a service account, which has access to some stored procedures within the database. Within the application, new threads are created to access the database, but this works fine as <identity impersonate="true" /> is set within the web.config and the new threads call Impersonate() on the calling thread's WindowsIdentity.GetCurrent() - otherwise the new threads would take the identity of IIS and not the service account set in our application. Also the application pool identity can't be used in this case. The problem is that when log4net AdoNetAppender tries to write out to the database, it can either use the IIS 'process' identity ("ImpersonationMode.Process"), but that doesn't have access, or could use "ImpersonationMode.User" but in this case the password isn't known - although it has already been set in the IIS application/virtual dir. How can I do the equivalent of using WindowsIdentity.GetCurrent() of the initial thread for the AdoNetAppender's security context? Could I pass my WindowsIdentity down, or get the WindowsSecurityContext to use the current identity rather than have to call Logon? Regards, Colin -----Original Message----- From: Craig Boland [mailto:[EMAIL PROTECTED] Sent: 03 October 2005 16:43 To: [email protected] Cc: 'Georg Jansen'; [EMAIL PROTECTED] Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? Connecting to a database with integrated security from a web app is all about the identity of the process (I know you all are aware of this, I'm just providing context for the message). And the way this is done, well, depends on how the application is configured. I've outlined some steps you'll need to take to get this set up. 1. Create A Domain Service Account Create a service account in your domain for your application. It could be a workgroup or machine account, but domain accounts offer a wider scope on the network. I don't often see this done, but as time goes by I see the value of an application service account more and more. In fact, if you install any server products by Microsoft, the installation guide often recommends doing this. 2. Grant Database Permissions to the Service Account Create a login account in the database for the service account and give appropriate permissions. Nothing special here. 3. Configure Applications to Run Under the Service Account If you're running on Windows Server 2003, you've got it easy. Simply configure the identity of the Application Pool to which your web app is assigned and enable impersonation. The ASP.NET process (w3p.exe) will now run using the credentials of the service account. If you're running on Windows Server 2000, you'll need to jump thru the traditional hoops depending on how the site is configured. If you have an Anonymous-only site, you can set the anonymous identity in the virtual directory to be the service account from above. In all other cases (Windows or Basic authentication), you'll need to configure the <identity> element in web.config to use the username/password of the service account. I know this isn't ideal because the creds are in plain-text, but you can mitigate a security breach by hardening access to the server, applying ACLs to web.config, etc. My current project is configured for the last case above, so if any of the details don't work for you (I'm writing this off the top of my head), reply back and I'll help you get this straightened out. -----Original Message----- From: Georg Jansen [mailto:[EMAIL PROTECTED] Sent: Monday, October 03, 2005 7:33 AM To: 'Log4NET User' Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? Billy, I forgot to mention in my previous response, that I did move the code back into the Application_Start event - but I did not use impersonating. I am no expert on this but as fare as I have understood this; The Application_Start runs under the aspnet process user, no mater if you are using impersonating or not. When it comes to choosing how to login/connect/store login information, well that's actually a question about security policy in the company you are working for. Storing password in clear text in config files is usually never considered as a good choice. Storing it inside a program is safer than a text file, but a program can be reverse engineered. You could use an "anti reverse engineering tool" - to make it harder to break. But you also have a maintenance problem - passwords should be changed from time to time. A couple of additional alternatives you may want to consider: Store the password/user information encrypted a separate config file, the .NET has pretty good support for encryption (as far as I know) and it should be fairly easy to implement. When it comes to logging, you could put the log table in a separate database, and give the ASPNET access only to that database. If you prefer to log to separate tables from different applications you need to define several tables. If you prefer to keep the log table in the same database as the application uses, you could grant the ASPNET user access to (and only to) the log table. Create a stored procedure for inserting rows to the log table, and grant ASPNET access to (only) that procedure is also an alternative. I found a couple of checklist for securing asp.net applications you may find useful: http://channel9.msdn.com/wiki/default.aspx/Channel9.ASPNETSecurityCodeRe view http://channel9.msdn.com/wiki/default.aspx/Channel9.ASPNETSecurityCheckl ist Regards, Georg www.l4ndash.com - Log4Net Dashboard -----Original Message----- From: Billy Barnum [mailto:[EMAIL PROTECTED] Sent: 30. september 2005 23:00 To: 'Log4NET User' Subject: RE: How to pass integrated security credentials to AdoNetAppender from ASP.NET? OK, Georg. I've successfully connected to a local database via a trusted connection that is similar to yours. Thank you, sir. I have also been able to connect to a remote database using a trusted connection that is a windows domain account in what the SDK calls "user mode". Like this in the .config file <securityContext type="log4net.Util.WindowsSecurityContext"> <UserName value="MyUserName" /> <Password value="MyPassword" /> <DomainName value="MyDomain" /> </securityContext> Or like this in code: WindowsSecurityContext securityContext = new log4net.Util.WindowsSecurityContext(); securityContext.DomainName = " MyDomain"; securityContext.UserName = " MyUserName"; securityContext.Password = " MyPassword"; securityContext.ActivateOptions(); adoAppender.SecurityContext = securityContext; Now, I understand that code in Application_Start() runs under the security context of ASPNET, not a user, even an anonymous one. And I understand that we do our lo4net setup work in this method because we don't want to do the config work for every page for every user. I'm just a back-end DBA / database access developer and don't know much about the ASP.NET request/response cycle and security contexts therein. But it seems like my choices are (A) putting passwords in code (B) Giving ASPNET access to all databases at an installation that want to use log4net instead of reducing risk by having a separate account for each database, or (C) doing my log4net config work over and over in Application_BeginRequest() or some spot where I have enough security context to use the "process" mode of log4net.Util.WindowsSecurityContext, therefore hurting performance. Can anyone advise me on this? How secure is putting a password in .NET code? I thought it was a no-no. Or is there a way to use security from the anonymous account without doing a lot of unnecessary work? Whatever, I'm grateful for the help I've gotten so far. Thanks again. -BillyB WILLIAM BARNUM [EMAIL PROTECTED]
