Thursday, April 18, 2013

How to encrypt app settings in a web.config

In a web application I recently developed, I found the need to store credentials for a rather powerful service account in my web.config.  The reason being, I needed to authenticate as that service account user at times, and use normal user credentials at others.  I was able to use the service account details without issue, but incase we ever found the need to update the account name or password, I wanted to make this value part of the web.config, but also have the means to encrypt this value to shield it from prying eyes.  Fortunately, using some web.config transforms and the aspnet_regiis –pef command option, this isn’t all too difficult, and we can have a perfectly normal web.config, but encrypt just one section of the web.config to hide sensitive data.

Step 1, Create a new web.config section

In your web.config, within the configuration\configSections area, add the following XML:

<section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

This XML will allow us to create a new section called secureAppSettings within our config.  You can call this whatever you want of course, but me… I like secureAppSettings.

Still within your config file, after your <appSettings> section, create a new section called secureAppSettings, and within this section add your key\value pairs, like so:

<secureAppSettings>
  <add key="testkey" value="This is a value in secureAppSettings testkey"/>
</secureAppSettings>

Step 2, reference your value’s in your code

Now that you created your values, you reference them in your application *almost* like normal.  Rather than referencing your AppSettings object of the ConfigurationManager class, you need to reference the “secureAppSettings” section instead.  This is simple.. but a minor change nonetheless.  So, find where your code is looking to reference our new secure values and reference the secureAppSettings key like follows:

Dim myVal as String = ConfigurationManager.GetSection("secureAppSettings")("testkey").ToString

Do you see the difference?  Here, we need to use the “GetSection” method, and then specify our “secureAppSettings” section.  Then, we reference our “testkey” value.  As I said, it’s a minor change.  Also take note, we do not need to do anything different to worry about the encryption\decryption of the web.config value, as the .NET Framework will handle that for us.  We simply need to reference the value, the .NET Framework will handle the rest.

Step 3, Encrypt Your Config Section

Here’s the fun part.  Publish your application, so you have a full config file.  (Personally, I like to publish to a local directory on my PC so I can push all files to my staging\production server’s manually when possible).  Once you publish the application, navigate to the publish directory and take a peek at the web.config.  How does it look?  Like normal, right?  Take this file and copy it to your web server, then remote into your web server and open a command prompt (run as admin just to be safe).  The encrypted values are generated based on the server’s machine key, so executing these command’s on a PC that isn’t your web server could cause unintended results.

Once within a cmd prompt, execute the following 2 command’s

1.) cd C:\Windows\Microsoft.NET\Framework64\v4.0.30319

2.) aspnet_regiis -pef "secureAppSettings" "E:\YourPhysicalPathToTheFileLocation" -prov DataProtectionConfigurationProvider

For your physical path to the file location in the 2nd command, you do not need to specify the file name, simply the directory it resides in.  So it would be “E:\mydir\mysubdir”, NOT “E:\mydir\mysubdir\web.config”. Once you complete both commands, take a look at your config now.  You should see something similar to the following:

<secureAppSettings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
    <CipherData>
      <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAxFAcBHLMb0uk5ES0SYgO2AQAAAACAAAAAAA………………………..2fZwOKP8VFg7OW2eMYFnq86TbUhB92EOQk0DhPqxDaA0pnp7MwRq2YR5CjmVAOFAAAAAxzUbeL1Fuij0DFEe0Cb7KEa92/</CipherValue>
    </CipherData>
  </EncryptedData>
</secureAppSettings>

Check it out!  Now, your secureAppSettings config values are encrypted!  As stated earlier, there’s no need to reference these values any differently in your code, other than specifying the secureAppSettings section.

Step 4, Merging these values back within your code

As I stated earlier, I needed to encrypt a username and password, just incase the value needs to change later on.  So in my scenario, I only need to document this process and generate my encrypted values once.  Then, if I ever need to publish a new build, I can still promote the same config values, and only worry about updating these username\password values if they ever change.  To handle this, I just placed my secureAppSettings in a web.config transform.  To do so, within Visual Studio, open your Web.Release.config transform file.  In the appropriate section (for me, this was below connectionStrings and above system.web), place your encrypted values using xdt transform notation:

<secureAppSettings configProtectionProvider="DataProtectionConfigurationProvider" xdt:Transform="SetAttributes">
<add xdt:Transform="RemoveAll" />

  <EncryptedData xdt:Transform="Insert">
    <CipherData>
      <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAxFAcBHLMb0uk5ES0SYgO2AQAAAACAAAAAAA………………………..2fZwOKP8VFg7OW2eMYFnq86TbUhB92EOQk0DhPqxDaA0pnp7MwRq2YR5CjmVAOFAAAAAxzUbeL1Fuij0DFEe0Cb7KEa92/</CipherValue>
    </CipherData>
  </EncryptedData>
</secureAppSettings>

The code above does a few things.

1. The SetAttributes on the secureAppSettings node causes the transform to add the configProtectionProvider attribute.

2. The RemoveAll transform removes any non-encrypted key\value pairs you may have in your web.config prior to performing a publish.  This means that your web.config during local debugging can still have your clear text key\value pairs, but they’ll get removed when you perform your publish.

3. the Insert transform will cause the EncryptedData, CipherData and CipherValue nodes to copy into your transform.

Step 4b – Updating your encrypted values

Should you have the need to recreate a clear text version of your web.config again, so you can update your values and re-encrypt them, just create a new publish profile within Visual Studio that publishes to a directory, but does NOT use your web.release.config transform.  This way, you can publish your config to a local directory and repeat the steps listed above.

Hope this helps!

Wednesday, April 17, 2013

System.Web.Services.Protocols.SoapException: Default value or value provided for the report parameter '<paramName>' is not a valid value

SharePoint has an odd limitation, with reporting services, user's don’t have access to properly subscribe to their own reports.  If you provide users with the ability to subscribe, they must also have access to edit subscriptions, and that means ALL subscriptions, which doesn't bode well, because users will just hate that.

So I took to creating a custom web form that allows users to edit and maintain their own subscriptions.  The form uses the SQL Reporting Services exposed web services via the ReportService2010 class (http://msdn.microsoft.com/en-us/library/reportservice2010.aspx), and uses these methods to read all report subscriptions in for a user, available parameter's for a report, etc.  I plan on doing a separate blog post on this because, frankly, I think it's cool.

Anyway, I was about to launch my afforementioned masterpiece when I receive an error in attempting to subscribe to a report: Default value or value provided for the report parameter '<paramName>' is not a valid value

This was all very confusing, because all along I have been creating subscriptions for myself and others.  The parameter values I am pumping into the report subscription are all supplied by the reportservice method GetItemParameters, which has a ValidValues property that lists what the valid values are.  And sure enough, for my parameter, I was supplying a Valid Value!

After quite a bit of debugging, tweaking some code to test some scenario's and cursing Microsoft, I found out that.. as usual.. it was an end user (me) error.  It's kind of an oddball scenario, but I imagine it could happen to others, which is why I am writing this blog post, which presumably is why you are reading it...

The report parameter that was failing for me was a user drop down list, which is generated based on who is attemping to create the report subscription.  So User A will see different values than User B.  When generating the parameter values for the report subscription, I was using the following code:

'Note, for this web form, Impersonate is set to TRUE
Dim rs As New ReportingService2010
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
……
parameters = rs.GetItemParameters(“A Plethora of Parameters”)

The important line of code is the 2nd one shown above, setting the Credentials to DefaultCredentials.  When this is used to authenticate with the reporting web service, the user's credentials are passed, meaning User A or User B are sent to the server.  The appropriate values are then returned for the report parameters, so they vary properly depending on if the user is User A or User B... all as expected.

With me so far?  OK, Good...

My issue was when I was creating the report, not generating the parameter items.  To give every user the ability to create a report, without granting them access to view\edit subscriptions within SharePoint, I was executing the CreateSubscription method underneath the context of a service account, NOT as User A or User B.  So in the end, my code looked similar to:

Dim rs As New ReportingService2010
rs.Credentials = New System.Net.NetworkCredential _ ("serviceAcctName", "password", "Domain")
……
subscriptionID = rs.CreateSubscription("A plethora of parameters")

What was the issue? 

When the CreateSubscription method was executing, it was executing under the context of my "serviceAcctName" user, not as User A or User B.  This means that, even though I was passing valid values for my parameter for the user, these weren't a valid value for the "serviceAcctName" user, meaing that the exception was accurate.

In the end, I was able to tweak my back end logic that was generating the custom drop down list values to include every value possible for the "serviceAcctName" user, so no matter what user would be using my subscription manager, it would be a valid value for my service account.

I don't know how many other's will run into this particular scenario, but if you're one of them, I hope this helps!

Friday, April 5, 2013

Why Use An IDE?

Artists have a quote that says "A blank canvas is an open opportunity to create whatever your imagination can stir to life". All artists begin with a medium of their choice, and use that medium to bring together their creation. Some artists use paint, some stone, some sand, and some even resort to using natural elements such as ice and snow. As such, all successful artists have a mastery of their tools to maximize their skillset.

I often tell developer’s in the making that using ASP.NET, Visual C# and Visual Basic is a specialized skillset, as the programmer not only develops code to control the application, but design's the interface in which the user uses the program a well. This is an important concept, as the misplacement of a button, or inadvertently hiding certain options can cause an immense amount of disdain from your end-users. It is impossible to overstate how important a toolset is to programmers. Much like artists needs to understand and use their tools appropriately, programmers must do the same. Failure to do so will cause over-complicated code, causing projects to run over time and over budget. Using toolsets properly will only serve to enhance the programmers ability to create enterprise-level applications that provide value to end-users and development teams alike. 

The most important tool a developer will ever use in your programming career is the Integrated Development Environment (IDE). There are many different IDE's available to programmers, but the choice of a programming language depends on the hardware you intend to run your applications. Much in the same vein, the IDE you choose is dependent on the language you want to program with. Some common examples include IBM's Eclipse which support's Java natively, Anjuta which supports a number of Object Oriented languages but runs on a Linux computer, or SharpDevelop, a free and popular IDE that support a number of languages, and is supported by an open source community of software developers. When it comes to programming with Visual C# however, one of the best IDE's available (if not the best) is Visual Studio.

Visual Studio natively supports .NET languages, including C#, VB.NET, ASP.NET, and F#, and supports a wide number of community sourced plugins as well. Visual Studio also has a rich history with programmers, as it's first version of a development platform was made available to users in 1995! Microsoft has continued to upgrade and enhance the tools available for programmers as they have developed their programming languages as well. More recently, as the .NET initiative has taken flight, Microsoft has released a version of Visual Studio to match releases of it's .NET Framework, which has been every 2-3 years or so. Why do this? Simple, as new programming features and upgrades are made available to the .NET Framework, Visual Studio's latest tools will reflect those changes and features, allowing programmers to upgrade both existing applications and new applications to use said features.

You may not be aware, but the .NET SDK (Software Development Toolkit) is available through Microsoft's website. Using this SDK, you can install all features necessary to compile a defined program, review any error's, resolve them, and re-compile to create your very own executable file. Best of all, this SDK is completely free! This means you can actually write programs in any old-fashioned text editor (such as notepad), and run the commands necessary to compile those files into an application.

So you may be asking yourself, why wouldn't we do this? Well, the .NET SDK provides the capabilities listed above, but it is very raw, basic, and obtuse. With Visual Studio however, the programmer has the capability to perform the functions listed above, but is also provided several benefits including the following (for a full list of the options available, visit http://www.microsoft.com/visualstudio/eng/products/compare:

  • IntelliSense (real-time object exploration)
  • Code Formatting
  • Debugging and diagnostics
  • Deployment Options and Code Refactoring
  • Testing Tools
  • Development Platform Support
  • Architecture and Modeling
  • Lab Management
  • Team Collaboration Tools
  • Integration with other Microsoft products (such as SQL Server Databases, or SharePoint powered Internet websites)

Needless to say, there are enough features in Visual Studio to teach an entire course! As you can see, however, an IDE is so much more than code formatting, it is an entire management tool for a programmer to write code, create files, store information, debug an application, write test cases for the program, create documentation and publish, all in one spot.

Wednesday, April 3, 2013

Human’s are so funny (and odd and not like web applications in any way)

We have a kitchen area where I work.  It has a few refrigerator's, a stove, some free coffee, Tylenol, a bunch of empty cabinets and a sink.  It's pretty nice though, as our building is only a few years old.  There are 2 cylindrical receptacles in the countertop next to the sink, and there's a small note between the 2 of them that reads "Recyclable's Only", and underneath that text there are 2 arrows, one for aluminum and the other for plastic.  Wouldn't you know it, no matter how many gripes people may have, people in the building still use those receptacles to throw away normal trash, out of convenience.  The typical garbage thrown in there are empty coffee creamer containers, some napkins, or a Styrofoam cup (ironically in a recyclable container, as Styrofoam cups and cockroaches will undoubtedly live to the end of time).  There are also some trash bins against the wall, no more than 3 feet away from a person at the sink, but those are "behind" them.

In an experiment recently, I took a small trashcan and placed it under the sink (there is no cabinetry underneath, so it was visible).  No signs were posted, nothing was said, the trashcan was just placed there.  Wouldn't you know it, people started using the recycling and trash receptacles properly?  Oddly enough, someone else stole (yes, I'm accusing someone of theft!) the small trashcan about 2 months later, and the all-purpose recycling and garbage dumping started once again, with people just using the receptacles for whatever their refuse needs were at the moment.

This goes to show 3 things.  1, my fellow employees apparently don't care about the environment, 2, I enjoy using co-workers for pointless experimentation, and 3, human's are funny and fickle creatures who tend to take the path of least resistance.

I read a book recently by Dan Ariely (http://danariely.com/), a behavioral economist who studies people, and the more he learns about people the more he realizes how little he knows about people.  In a talk once, he told the audience that asking a person to opt-out of something occurs much less frequently than having people opt-in.  The example he provides is the amount of organ donor's in certain European countries.  The difference between the high and low rate of organ donor's has little to do with morality, upbringing, subsidies or any other influences.  It's only because the countries with the larger\largest organ donation have a form with a box stating "check this box if you do NOT want to donate your organ's after you meet your untimely demise" (yes, I paraphrased).  But do you understand the difference here?  Asking user's on a web form to opt-in to an email campaign is much different than asking them to opt-out.  Furthermore, the implication of the result is HUGE!  A person who has to opt-in for an email message is probably much more interested in your monthly email discussing widgets, rather than the person who happened to sign up for it "by default".

Whenever I'm teaching programming to software developer trainee's, I always tell them "the computer does what you tell it to".  When a trainee creates a loop in their program, or if a font color changes "randomly", I remind them of that phrase, and tell them that it's a bug.  They may not have intended for something to happen (hence it being a bug), but the computer does what it is TOLD to do.  It doesn't ask any questions (unless you tell it to ;), it just runs the code and that's that.  Human beings are so much more complex than that, it's always an interesting world to be between, programming a web application one minute and deigning a user interface where I'm guessing a user will or won't check a checkbox the next.  Such is life...