Camilo Orozco's BLOG

Tuesday, September 22, 2009

Add an XML attribute on a specific location of a specific node:

//Look for node MyNode
XmlNode node = doc.SelectSingleNode("//MyNode");
//Create empty attribute
XmlAttribute attribute = doc.CreateAttribute("MyAttrib2");
//Remove any existing attribute with that name just in case
node.Attributes.Remove(attribute);
//Set the value of the attribute
attribute.Value = "1";
//Add the attribute to the node
XmlAttribute attributeBefore = node.Attributes["MyAttrib1"];
node.Attributes.InsertAfter(attribute, attributeBefore);

Monday, June 16, 2008

Customize web.config Sections and Compile from Command Line


It is always important to being able to customize a software project build steps. Always there is the need to support at least two configurations: Debug and Release, but for some other projects you might need more configuration types. For instance you might need to support more than one database username depending on the data schema forcing you to come up with a different connectionStrings section in the web.config file depending on the username being used, you could also need to compile the XML documentation using a tool like SandCastle and come up with an automated MSDN-like help site or any other documentation style, but you might not want to do that always since the those documentation tools’ build process takes a bit of extra time to execute.
The project file (.csproj) is compiled by default using msbuild which is shipped by default with .NET 2.0 and higher and with the latest version of Visual Studio. This project file is nothing more than an XML file that defines the steps and properties msbuild needs to follow in order to come up with the correct build, something like an Ant or NAnt file. One very sensitive part of a build is the ability to replace web.config sections, such as the connectionStrings section. The guys at Microsoft provide the Web Project Deployment tool that implements a task called webConfigReplace, all this task does is pretty simple: it takes a file containing the XML that will replace the existing section in web.config. This works great for ASP .NET projects with the added dependency of an extra project file in the solution, but what if you want to get rid of the extra project in the solution and implement the replacement task in the actual project file (.csproj) containing your project? It’s actually not that complicated, all is needed is to download the Web Project Deployment tool and include the library in the project file as seen here:


<project toolsversion="3.5" defaulttargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><!-- Import WebDeployment.Tasks.dll v9.0 in order to utilize the ReplaceConfigSections task to customize the web.config file --><usingtask taskname="ReplaceConfigSections" assemblyfile="$(MSBuildExtensionsPath)\\Microsoft\\WebDeployment\\v9.0\\Microsoft.WebDeployment.Tasks.dll">

Then it is just a matter of setting the properties for this tool and that’s about it now you can come up with a new web.config file every time you hit compile:

<ItemGroup>
<WebConfigReplacementFiles Include="connectionStrings\connectionStrings.config">
<Section>connectionStrings</Section>
</WebConfigReplacementFiles>
</ItemGroup>
<ReplaceConfigSections RootPath="$(OutputDir)$(Configuration)\" WebConfigReplacementFiles="@(WebConfigReplacementFiles)" UseExternalConfigSource="false" ValidateSectionElements="false" />

Another cool thing is that you can compile your project from a command line which will get rid of the Visual Studio dependency to build, also you can change the value of properties inside the project file with the /p command line argument to msbuild. This method also allows organizations that are working on a mixed environment (unix/Windows, java/.net) to understand each other since msbuild looks a lot more like a tool that can be controlled from command line and XML project files which the java guys are used to, this integration of the teams gives more power and value to the organization since it helps break those mental barriers that java and .net developers often have.

Thursday, June 05, 2008

ADAM and AzMan Nightmares?

In a recent project there was a need to work with active directory users as well as external users that would register to an application. Each type of user would have different permission levels into the app’s data. The security expert told me that I wasn’t allowed to make direct calls to AD from the app which is sitting on the DMZ, that requirement killed the easy approach to just make a direct call to AD and authenticate.

After some searching I found ADAM which stands for Active Directory Application Mode. If you read all ADAM’s documentation, you will find out that ADAM allows maintaining a set of local ADAM users and by using methods such as Windows pass through authentication or AD proxy users you can authenticate AD users via ADAM, basically making ADAM the complete authentication service for an application. The security requirements asked for ADAM to be on the DMZ and to have ADAM making secure simple LDAP calls to the internal AD servers. I thought I could accomplish that by having ADAM deployed on a machine sitting on a specialized DMZ without joining it to the domain, but we were proved wrong. We talked to Microsoft for hours (or days!) on the phone and over newsgroups until one of the guys that helped us at Microsoft finally talked to the correct people and found out that there is no way ADAM could authenticate AD users without having it’s host Windows server being part of the domain. That took us a lot of time to figure out, now I had to convince the security guy that the only solution to the requirement was to have ADAM’s server joined to the domain. We were able to configure ADAM so that on one side it receives the app server’s requests via simple LDAP calls and on the other side it makes the thick secure domain AD queries to authenticate all internal users. Also, we setup ADAM to work using SSL and now we had a secure communication channel from the app server to ADAM and the regular secure AD calls from ADAM to the domain controllers. The security guy wasn’t all happy about the solution but we thought it was the best we could do with ADAM. The next problem to tackle has a name: userProxy.

The method we chose to maintain an AD pointer for internal users was the user proxy method. This method uses a synchronization setting file that synchronizes any number of AD users with ADAM. The problem with the synchronized users in ADAM is that the users’ class when in ADAM is userProxy, this type of user class is not supported by the default ASP .NET MembershipProvider and in order to find out I had lots of communication with Microsoft again and with other AD experts over forums. Then I saw this article that confirmed the theory that the userProxy is not supported by the provider. The only solution left to do was to create our own custom MembershipProvider which I did and by the way I made it a bit more flexible in terms of the LDAP queries it can handle. Now I had an app that was able to make secure LDAP queries using the provider pattern and ADAM as a middle tier to securely connect to AD, all of the ADAM users were supported naturally by ADAM with no special change in the provider code, this was cool and it was putting the app in a better shape to support both types of users. The only problem is that so far we could only authenticate, we needed to maintain different levels of authorization depending on the type of user, so here we go again, the next problem was authorization and specifically the problem had a name: AzMan.
AzMan is a product that helps maintain roles, tasks and operations for any application that might need them, basically manages the authorization part. AzMan can store roles on an XML file or can get hooked to an AD product like ADAM. Naturally you would think that since you have authentication in place using ADAM, AzMan should just use ADAM as it’s store, well we were proven wrong again. After more hours (days?) of endless calls to Microsoft we hit the right guys and they finally pointed out that AzMan requires all servers accessing it to be part of the domain which completely breaks our current implementation of having the app server detached from the domain and only the server hosting ADAM being part of the domain, authorization with AzMan had to be discarded. The quick solution to that was easy, use the database server that was serving the app’s data to maintain the Database Role provider data as well, we used the Oracle Role Provider for .NET between the DBA and myself we were able to set it up in hours, that solved all problems and the security code of the app didn’t need to be changed thanks to the provider model. A good thing is that no Role provider code was needed since Oracle provides the implementation for free.

The lessons learned with this experience are:
  • In order to support internal AD users ADAM must be part of the domain or a more complex solution must be implemented such as ADFS.

  • App servers can use ADAM and being detached from the domain if they are facing the internet.

  • Always setup ADAM to use SSL in order to maintain a secure data flow.

  • AzMan = Domain, you are in a much better place by just using the regular Roles DB providers.
I personally think that ADAM is a great product but Microsoft should open it more so that LDAP simple calls to internal ADs can be made in order to accommodate possible security requirements. Security guys don’t like the amount of communication a server that is part of a domain needs to have with its domain controller. I think that userProxy queries should be part of the MembershipProvider or we will end up with hundreds of MembershipProviders throughout the world. AzMan is a product that is made to work on internal apps only, It looks great, but again it needs that thick level of communication with domain controllers.
If you ever need more details on the implementation I made for this project do not hesitate to comment on this blog.

Wednesday, May 28, 2008

Visual Studio 2008, TFS and VisualSVN

In the organization I work for most of the development has been done in Java and therefore a lot of the IT personnel are unix/linux experts. In my group we are developing in .NET 3.5 and VS2008 using TFS as our development core system. I saw the possibility to move our development core system from TFS to SVN, Tracs and Cruise Control .Net and in order to start the whole process the first thing needed was to have VS2008 talk to SVN.

VS2008 can talk to SVN via Tortoise SVN but that method will not bind to VS interface as a plugin just like Team Explorer does. After reading a bunch of blogs, I found out Visual SVN (which is not free, but is cheap $49pu) and started the whole testing process and this is what we found out:

  1. The new solution files that will organize the working projects for the current project must be under svn in the root folder for all projects. Create blank solution(s) at the root of the svn-controlled directory.
  2. Manually copy each project directory from the TFS location in your hard drive to the svn location in order to have two working copies of the same project, one working with TFS and the other one working with svn.
  3. In the svn directories, delete all files with the extension .vspscc from all project directories, this is a file needed by TFS only and not needed by svn.
  4. Inside each project's directory open the corresponding project file e.g. .csproj for edit and delete the following properties: SccProjectName, SccLocalPath, SccAuxPath, SccProvider. This step will get rid of any link to TFS source control.
  5. Open the new solution and add all projects you just copied and edited.
  6. Right click the root solution and select Commit to svn, this will launch Tortoise svn and allow to commit the changes, now all traffic lights should be green.

Now that all code is under svn, Tracs will easily integrate to the project and CC.Net will also easily be deployed and connected to svn for automated builds.

I got help from these blogs which might give you more insight on MS source control settings files: