May 2006 - Posts

Introduction to Microsoft® Windows Communication Foundation™ (saArchitect TFS/VSTS Community Events)

We are pleased to announce saArchitect "technology readiness" community events, focused on interoperability and especially Windows Communication Foundation (WCF). The following 1-day events are scheduled at this stage:

Introduction to Windows Communication Foundation™   24 June 2006
Introduction to Windows Communication Foundation™   29 July 2006 

Please refer to www.drp.co.za for more details or to book a seat on this exciting program.

The events are sponsored by IT Intellect (facilities), Barone, Budge and Dominick (DRP material) and DRP mentor community members who will run with these events.

Introduction to Microsoft® Visual Studio Team System™ (saArchitect TFS/VSTS Community Events)

We are pleased to announce saArchitect "technology readiness" community events, focused on Team Foundation Server (TFS) and Visual Studio Team System (VSTS). The following 1-day events are scheduled at this stage:

  • Introduction to Microsoft® Visual Studio Team System™   8 July 2006
  • Introduction to Microsoft® Visual Studio Team System™   12 August 2006

Please refer to www.drp.co.za for more details or to book a seat on this exciting program.

The events are sponsored by IT Intellect (facilities), Barone, Budge and Dominick (DRP material and DRP mentor community members who will run with these events.

Posted by willy with 1 comment(s)

Microsoft® XNA™

If you are serious about Games and interested in VSTS, you must visit http://www.microsoft.com/xna/.
Posted by willy with no comments
Filed under: ,

VSTS RTM:Recommended options for Web Applications to gel with TFS Build

1: CREATING WEB SERVICE PROJECT

By default web projects created with Visual Studio have a misalignment between the project file structure on the file system and that created in Team Foundation Server version control system. The result are build failures as those outlined in the support request SRQ060424600014, which can be addressed by (1) modifying the solution file, (2) using web deployment projects or (3) be proactive following the steps as outlines in this document.

For web deployment projects refer to http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx).


symbol indicates the areas of concern and the recommended resolutions.


To be proactive let us create a typical web service and highlight the key areas:


  • Instead of placing the solutions and projects in the default location, we should create a distinct solution location on the file system, i.e. “c:\Blog” as shown.


  • Next we create an empty solution, such as “BlogSolution”, in the file location as created in the previous step. The recommendation is to first create an empty solution and the add new or existing projects to the solution, rather than allowing the project wizard to create bothg a project and hosting solution.



  • For those wondering why Visual Studio is no longer displaying the solution anmd would like to avoid the confusion that normally reigns after creating a web service and then wanting to add other projects to the same solution. Select tools, options and check the “Always show solution” option, within General under Projects and Solutions.


  • Next we create a web project within the solution, selecting the location as “File System” and Language as “C#”, whereby the latter selection is irrelevant in this case. The key is the actual location, which by default points at the MyDocuments location and not the location within which we created the hosting solution.


  • If we select OK at this point, we will have a problem within TFS Build, because the structure created within TFS Version Control will not match the structure on the file system, which means that the files cannot be located by the build server.



  • Instead we need to browse to the solution location, in this case c:\Blog\BlogSolution and specifying the web service project, i.e. BlobWebService.



  • By default there is no Release configuration for the web project, which implies that the TFS Build would not be in a position to build the project in a release environment. To resolve this issue we select the solution, right click on the solution node and select Configuration Manager as shown.


  • Create a new configuration, called release, and copying the settings from the Debug configuration.


  • Finally we add the solution to source control, in our case to the WebServiceBlog Team Project.


2: CREATING TEAM BUILD


  • This is the next area of caution. When creating a team build for a solution containing only web applications and/or services you have to define “.NET” as the build platform. If the solution, however, contains other projects types such as class libraries, you must change the build type to “Mixed Platform”, else the solution files will not be built and subsequently not found when running test lists as part of composite builds.


  • Select the newly created build and execute the build.


  • The following illustrations shows a successful build.



  • If we go back to the file system and have a look at the build directory, we will notice that the TFS Build has built both the Debug and Release based files.



3: SUMMARY

As shown we have two steps to remember when creating a solution containing web projects and one step when creating the TFS Build, i.e.

  1. Correct the project path to match the structure created in source control.

  2. Create an additional build configuration to include the release build configuration.

  3. Select .NET or Mixed Platform build platform when dealing with pure web solutions and web solutions with other project types, respectively.




Posted by willy with 4 comment(s)
Filed under: ,

Developer Readiness Schedule Is Finally Posted

http://www.drp.co.za/default.asp?id=training/content_training finally lists the forthcoming developer readiness events for the next few months.

Appologies if you get "Service Unavailable" error when accessing this link ... we are seriously struggling with bandwidth as there is currently huge, yet welcome, traffic on our drp site.

Posted by willy with no comments
Filed under: , ,

VSTS RTM: The Journey, Part 7 – Team Project (Eco 1 - 16 Complete) - "Un"stuck on the Composite Build Trenches (Update)

Below is the resolution to the build incident SRQ060424600014 as per Microsoft Support. We disagree with the editing of solution files, as we are trying to keep our solutions teams from changing wizard generated or VS IDE managed files, such as project and solution files. By making use the of the Web Deployment Project (http://msdn.microsoft.com/asp.net/reference/infrastructure/wdp/default.aspx), changing the AspNetDevelopmentServer attribute and specifying the build type (“mixed platform”), as documented herein, we have managed to come to the same resolution without having to make low-level “system/solution” specific files.

We are hoping that future versions of VSTS/TFS will simplify this process, as it is currently an area of concern for most product teams who are not and/or do not want to specialise in the solution files and TFS.Thanks to Microsoft Support (especially Chris) for helping us resolve this beastie.


As agreed, please find below the steps you will need to follow to reach a solution:


The root causes of the problem that you are experiencing are:

  • The solution file contains incorrect paths
  • There is an incorrect configuration of the Build Type

The first changes that were required were to modify the test methods so that they align to our recommendation described in http://msdn2.microsoft.com/en-us/library/ms243399.aspx and http://msdn2.microsoft.com/en-us/library/ms243136.aspx. We have changed the AspNetDevelopmentServer to contain the %PathToWebRoot% environment variable. At the moment it looks like this:


[AspNetDevelopmentServer("CalculatorServer", @"%PathToWebRoot%\CalculatorService")]


This variable needs to be set on the development machine to point to the folder containing the Solution. The inconvenience is that this variable is per machine so it needs to be adjusted every time local tests are executed. This variable does not need to be set on the Team Build machine since it will be automatically generated. In case you do not want to use the %PathToWebRoot% then you can use a relative path in the AspNetDevelopmentServer attribute:


[AspNetDevelopmentServer("CalculatorServer", "CalculatorService")]


When developing ASP.NET or Web Services projects in a Team Environment you also need to be aware of some issues related to source control. These issues are detailed in the following articles which are a must read if you want to build and test ASP.NET or Web Services project using Team Build:



After following these materials we have changed the solution file so that the Physical Path properties match the structure from the source control. Due to this problem, the Web Service was not precompiled during Team Build and the necessary files were not placed in the _PublishedWebsites folder.


Another important detail that is documented in the blogs is the Build Type configuration. In case you have a project that contains only ASP.NET or Web Service projects you need to use the “.NET” configuration for your build when creating a build type. If the project contains any other type of project like a Class Library you need to use the “Mixed Platforms” configuration for your build type.


After following through these steps, please let me know if you are able to complete a successful build. As I mentioned before, I am more than happy to arrange a Live Meeting with our Visual Studio engineer so that we can take you through this step by step,


Kind Regards,


Microsoft Customer Service and Support


Posted by willy with no comments

WCF and VSTS Community Workshops

We decided at last minute not to present at DevDays, primarily due to an acute lack of time to prepare professional and effective sessions, but also to be in a position to focus on our WCF WebCast in June and forthcoming community sessions covering WCF and VSTS.

At this stage we are planning one community WCF workshop in June and one in July, as well as one community VSTS workshop in July and one in August.

The community workshops will be hosted on a Saturday, during which we are planning to introduce the relevant technology and allow us as a group to experiment with the technology, ensuring that we are in a position to formulate the usage and implementation thereof as a community.

The exact dates, location and cost (we are negotiating with sponsors to ensure a ‘zero’ cost for saDeveloper and saArchitect members) will be published on www.drp.co.za during the course of the forthcoming week.

We are excited about this initiative and hope that we will receive support from the community and an understanding for us not presenting at and sharing our early adoption experiences with both WCF and VSTS.


VSTS RTM: The Journey, Part 7 – Team Project (Eco 1 - 16 Complete) - Stuck on the Composite Build Trenches (Update)

As mentioned in http://dotnet.org.za/willy/archive/2006/04/25/51783.aspx we are stuck on a TFS Build issue as per SRQ060424600014.

After DHL'ing a 12GB Virtual Machine Drive, which arrived the next day in the UK, it unfortunately took close to a week for the package to find its way from the receiving desk to the support engineers desk. It therefore took more than a week for support to reproduce our problem, which they are currently investigating.

We will keep you posted.

Ever wondered if and how identities are carried from service to service?

Ever wondered if and how identities are carried from service to service?

Unable to make much progress on VSTS due to the build bug we are investigating, we recently had a discussion around the identity topic. At the time I believed that writing a quick prototype may not be such a bad thing and here is the brief story for those interested. Note that we are trying to show the flow of identities, without getting embroiled in Kerberos, Tickets and other security subsystem features which are documented in detail on MSDN. If you are looking to secure your service we encourage you to have a look at the Web Service Extensions 3 (WSE3) or Windows Communication Foundation (WCF), formely known as Indigo.

Prerequisites

I created two local account, one called Research and the other Impersonator.

Context

In a nutshell I wanted to investigate the following simple steps:

  • WinForms Application attached the credentials to the proxy (P1) and makes a call to Web Service 1.

  • Web Service 1 runs as a trusted account, i.e. does not impersonate calling user.

  • Web Service 1 displays "running as user" and "calling user is".

  • Web Service 1 then impersonates calling user and makes a call to Web Service 2. Should I simply impersonate, or impersonate and then set the credentials on proxy 2 (p2)?

  • Web Service 2 displays "running as user" and "calling user is" ... which should be one and the same.

Web Service 2

Config

The web service was created using VS.NET 2005 and then registered in IIS … virtual directory, setting security as follows … note that anonymous access is turned off.

Additionally the web.config file was updated as follows:

<identity impersonate="true" />

Source

[WebMethod ( EnableSession = false, TransactionOption = System.EnterpriseServices.TransactionOption.Disabled,

Description = "Prototype method which returns the identity of the host and calling thread, optionally calling another webservice with similar functionality" )]

public string RetrieveSecurityInformation ()
{
 
StringBuilder returnInformation = new StringBuilder ();
  
WindowsIdentity identityCurrent = WindowsIdentity.GetCurrent ();
 
IIdentity identityCaller = Thread.CurrentPrincipal.Identity;
 
 
// 1. Build Current Identity Information
 
returnInformation.Append ( "SERVICE B: CURRENT IDENTTITY INFORMATION --> [" );
 
returnInformation.Append ( " User Name: " + identityCurrent.Name );
 
returnInformation.Append ( " Is Anonynmous: " + identityCurrent.IsAnonymous );
 
returnInformation.Append ( " Is Athenticated: " +
                             identityCurrent.IsAuthenticated );
 
returnInformation.Append ( " Is Guest: " + identityCurrent.IsGuest );
 
returnInformation.Append ( " Is System: " + identityCurrent.IsSystem );
 
returnInformation.Append ( " Authentication Type: " +
                             identityCurrent.AuthenticationType );
 
returnInformation.Append ( " ] " );
  r
eturnInformation.Append ( Environment.NewLine );

 
// 2. Build Caller Identity Information
 
returnInformation.Append ( "SERVICE B: CALLER IDENTTITY INFORMATION --> [" );
 
returnInformation.Append ( " User Name: " + identityCaller.Name );
 
returnInformation.Append ( " Is Athenticated: " +
                             identityCaller.IsAuthenticated );
 
returnInformation.Append ( " Authentication Type: "
                             identityCaller.AuthenticationType );
 
returnInformation.Append ( " ] " );
 
returnInformation.Append ( Environment.NewLine );
 
 
// Return the information€
 
return (returnInformation.ToString ());
}

Web Service 1

Config

The web service was created using VS.NET 2005 and then registered in IIS … virtual directory, setting security as follows … note that anonymous access is turned on:


Additionally the web.config file was updated as follows:

<identity impersonate="true" userName="willyxpacer\research" password="nicetry" />

Source

[WebMethod ( EnableSession = false,

TransactionOption = System.EnterpriseServices.TransactionOption.Disabled,

Description = "Prototype method which returns the identity of the host and
calling thread, optionally calling another webservice with
similar functionality"
)]

public string RetrieveSecurityInformation ( bool makeRemoteCall,
                                           
bool impersonateCaller,
                                            bool setProxyCredentials,
                                            bool setOtherUser,
                                            string url )
{
 
StringBuilder returnInformation = new StringBuilder ();
 
WindowsIdentity identityCurrent = WindowsIdentity.GetCurrent ();
 
WindowsIdentity identityCaller = (WindowsIdentity)
                                    T
hread.CurrentPrincipal.Identity;
  // 1. Build Current Identity Information
 
returnInformation.Append ( "SERVICE A: CURRENT IDENTTITY INFORMATION --> [" );
 
returnInformation.Append ( " User Name: " + identityCurrent.Name );
 
returnInformation.Append ( " Is Anonynmous: " + identityCurrent.IsAnonymous );
 
returnInformation.Append ( " Is Athenticated:" +
                             identityCurrent.IsAuthenticated );
  
returnInformation.Append ( " Is Guest: " + identityCurrent.IsGuest );
 
returnInformation.Append ( " Is System: " + identityCurrent.IsSystem );
 
returnInformation.Append ( " Authentication Type: " +
                             identityCurrent.AuthenticationType );
 
returnInformation.Append ( " ] ");
 
returnInformation.Append ( Environment.NewLine );
 
  // 2. Build Caller Identity Information
 
returnInformation.Append ( "SERVICE A: CALLER IDENTTITY INFORMATION --> [" );
 
returnInformation.Append ( " User Name: " + identityCaller.Name );
 
returnInformation.Append ( " Is Athenticated: " +
                             identityCaller.IsAuthenticated );
 
returnInformation.Append ( " Authentication Type: " +
                             identityCaller.AuthenticationType );
 
returnInformation.Append ( " ] ");
 
returnInformation.Append ( Environment.NewLine );
 
if ( makeRemoteCall )
 
{
   
// 3. Call Remote Service
   
ServiceB.ServiceB remoteService = new ServiceB.ServiceB();
   
if ( ( null != url ) && ( 0 != url.Length ) )
   
{
     
remoteService.Url = url;
   
}
   
else
   
{
     
remoteService.Url = http://localhost/ServiceB/Service.asmx;
    }
   
if ( impersonateCaller )
   
{

To impersonate we need to create a WindowsImpersonationContext object, assign the identity and call Impersonate().

      // Impersonate
     
WindowsImpersonationContext impersonation = ((WindowsIdentity
                                
(identityCaller)).Impersonate ();
     
WindowsIdentity identityTemp = WindowsIdentity.GetCurrent ();
     
returnInformation.Append ( "SERVICE A: IMPERSONATED IDENTTITY INFORMATION --> [" );
     
returnInformation.Append ( " User Name: " + identityTemp.Name );
     
returnInformation.Append ( " Is Anonynmous: " +
                                 identityTemp.IsAnonymous );
     
returnInformation.Append ( " Is Athenticated: " +
                                 identityTemp.IsAuthenticated );
      
returnInformation.Append ( " Is Guest: " + identityTemp.IsGuest );
     
returnInformation.Append ( " Is System: " + identityTemp.IsSystem );
      
returnInformation.Append ( " Authentication Type: " +
                                 identityTemp.AuthenticationType );
     
returnInformation.Append ( " ] " );
      
returnInformation.Append ( Environment.NewLine );
     
if ( setProxyCredentials )
     
{
       
remoteService.PreAuthenticate = true;
       
remoteService.Credentials = CredentialCache.DefaultCredentials;
      
}
      
returnInformation.Append ( remoteService.RetrieveSecurityInformation () );

We must Undo the impersonation … this is probably a good place to use the finally{}.

      // Revert
     
impersonation.Undo();
   
}
   
else
   

The “setOtherUser” code simply demonstrats how we can create a network credential object and assign them to the service proxy.

      if ( setOtherUser )
     
{
       
NetworkCredential credential = new NetworkCredential ( "impersonator",
                                                               "password",
                                                               "willyxpacer" );
        r
emoteService.PreAuthenticate = true;
       
remoteService.Credentials = credential;
     
}
     
else
     
if (setProxyCredentials)
     
{
       
remoteService.PreAuthenticate = true;

Normally we would simply want to set the current credentials on the proxy.

        remoteService.Credentials = CredentialCache.DefaultCredentials;
     
}
     
returnInformation.Append ( remoteService.RetrieveSecurityInformation ()); 
   
}
  }
  // Return the information
  return (returnInformation.ToString ());
}

Test Application

No idea why we drew a Win Forms application on the whiteboard and to save time and typing effort, I resorted to the good old console application.

static void CallTest ( string message, bool makeRemoteCall,
                      
bool impersonateCaller,
                      
bool setProxyCredentials,
                      
bool setOtherUser )
{
 
localhost.ServiceA service = new ConsoleApplicationTest.localhost.ServiceA();
 
try
  {
    Console.WriteLine ( message );
   
Console.WriteLine ( service.RetrieveSecurityInformation ( makeRemoteCall,
                                                              impersonateCaller,
                                                             
setProxyCredentials,
                                                             
setOtherUser,
                                                              
null ) );
    
Console.WriteLine ();
 
}
 
catch ( Exception ex )
  {
   
Console.WriteLine ( "Failure: " + ex.ToString() );
   
Console.WriteLine ();
 
}
}

static void Main ( string[] args )
{
 
Program.CallTest ( "Service A call only", false, false, false, false );
 
Program.CallTest ( "Service A and B - No Impersonation - Setting Proxy",
                     true, false, true, false );
 
Program.CallTest ( "Service A and B - No Impersonation - Setting Proxy with other user"
                     true, false, true, true );
 
Program.CallTest ( "Service A and B - Impersonation - Setting Proxy",
                     true, true, true, false );
 
Program.CallTest ( "Service A and B - No Impersonation - Not Setting Proxy",
                     true
, false, false, false );
 
Program.CallTest ( "Service A and B - Impersonation - Not Setting Proxy",
                     true
, true, false, false );
 
Console.ReadLine();
}

Result

The results were as expected as shown in the following copy of the console output, with illustrations inserted.

Service A call only
SERVICE A: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Anonymous: False Is Authenticated:True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE A: CALLER IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Authenticated: True Authentication Type: NTLM ]


Service A and B - No Impersonation - Setting Proxy

SERVICE A: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Anonymous: False Is Authenticated:True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE A: CALLER IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Authenticated: True Authentication Type: NTLM ]

SERVICE B: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Anonymous: False Is Authenticated: True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE B: CALLER IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Authenticated: True Authentication Type: Negotiate ]


Service Aand B - No Impersonation - Setting Proxy with other user

SERVICE A: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Anonymous: False Is Authenticated:True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE A: CALLER IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Authenticated: True Authentication Type: NTLM ]

SERVICE B: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Impersonator Is Anonymous: False Is Authenticated: True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE B: CALLER IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Impersonator Is Authenticated: True Authentication Type: Negotiate ]

Service A and B - Impersonation - Setting Proxy

SERVICE A: CURRENT IDENTTITY INFORMATION --> [ User Name: WILLYXPACER\Research Is Anonymous: False Is Authenticated:True Is Guest: False Is System: False Authentication Type: NTLM ]

SERVICE A: CALLER IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Authenticated: True Authentication Type: NTLM ]

SERVICE A: IMPERSONATED IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Anonymous: False Is Authenticated: True Is Guest: False Is System: False Authentication Type: Kerberos ]

SERVICE B: CURRENT IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Anonymous: False Is Authenticated: True Is Guest: False Is System: False Authentication Type: Kerberos ]

SERVICE B: CALLER IDENTTITY INFORMATION --> [ User Name: BBDNET\bbdnet0388 Is Authenticated: True Authentication Type: Negotiate ]

Service A and B - No Impersonation - Not Setting Proxy

Failure: System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Net.WebException: The request failed with HTTP status 401: Access Denied.

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

at ServiceB.ServiceB.RetrieveSecurityInformation() in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\servicea\2f181cf1\8f3f0660\App_WebReferences.jqkarxx8.0.cs:line 89

at Service.RetrieveSecurityInformation(Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser, String url) in d:\BBD\Working\SecurityPoC\ServiceA\App_Code\Service.cs:line 125

--- End of inner exception stack trace ---

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

at ConsoleApplicationTest.localhost.ServiceA.RetrieveSecurityInformation(Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser, String url) in D:\BBD\Working\SecurityPoC\ConsoleApplicationTest\Web References\localhost\Reference.cs:line 142

at ConsoleApplicationTest.Program.CallTest(String message, Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser) in D:\BBD\Working\SecurityPoC\ConsoleApplicationTest\Program.cs:line 22

 

Service A and B - Impersonation - Not Setting Proxy

Failure: System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Net.WebException: The request failed with HTTP status 401: Access Denied.

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

at ServiceB.ServiceB.RetrieveSecurityInformation() in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\servicea\2f181cf1\8f3f0660\App_WebReferences.jqkarxx8.0.cs:line 89

at Service.RetrieveSecurityInformation(Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser, String url) in d:\BBD\Working\SecurityPoC\ServiceA\App_Code\Service.cs:line 104

--- End of inner exception stack trace ---

at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

at ConsoleApplicationTest.localhost.ServiceA.RetrieveSecurityInformation(Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser, String url) in D:\BBD\Working\SecurityPoC\ConsoleApplicationTest\Web References\localhost\Reference.cs:line 142

at ConsoleApplicationTest.Program.CallTest(String message, Boolean makeRemoteCall, Boolean impersonateCaller, Boolean setProxyCredentials, Boolean setOtherUser) in D:\BBD\Working\SecurityPoC\ConsoleApplicationTest\Program.cs:line 22

In another nutshell … this is ending up to be quite a nutty proof of concept … the tests demonstrate the following:

Test

Notes

Service A call only

We are able to identify the host identity and calling identity.

A and B - No Impersonation - Setting Proxy

We can call another service passing the host identity to the service proxy and service.

Service A and B - No Impersonation - Setting Proxy with other user

We can call another service passing new credentials.

Service A and B - Impersonation - Setting Proxy

We can impersonate the calling user and pass the credentials to the service proxy and service.

Service A and B - No Impersonation - Not Setting Proxy

Not setting the proxy credentials results in unhappiness …

"Service A and B - Impersonation - Not Setting Proxy"

Not setting the proxy credentials results in unhappiness …

To conclude we hosted web service 2 on another machine and the results changed as follows:

  • Service A and B – No Impersonation – Setting Proxy … Test also failed with Access Denied, HTTP Status 401.

  • Service A and B – No Impersonation – Setting Proxy with other user … Test also failed with Access Denied, HTTP Status 401.

We needed to make the following changes, which are actually quite obvious, but often overseen:

  • WILLYXPACER\Research defined for ServiceA is a local user account. As soon as the request leaves the comfort of the WILLYXPACER, the credentials are not going to find much favour on the remote service. Changing the configuration to use a domain account as follows resolved this issue:
    <identity impersonate="true" userName="bbdnet\research" password="password" />
    <!--
    identity impersonate="true" userName="willyxpacer\research" password="nicetry" /-->
    For machine hopping … also refered to as delegation … Kerberos is therefore our ally and NTLM a disgruntled localist. .

  • WILLYXPACER\Impersonator used to create a new network credential is also local and suffered the same fate as the one above. The following change was made:
    NetworkCredential credential = new NetworkCredential ( "impersonate", "password", "bbdnet" );
    //NetworkCredential credential = new NetworkCredential ( "impersonator", "password", "willyxpacer" );


An extract from MSDN in terms of authentication types and delegation as discussed in this PoC.

{ I quote:

Authentication Type

Can Delegate

Notes

Anonymous

Depends

If the anonymous account (by default IUSR_MACHINE) is configured in IIS as a local account, it cannot be delegated unless the local (Web server) and remote computer have identical local accounts (with matching user names and passwords).
If the anonymous account is a domain account it can be delegated.

Basic

Yes

If Basic authentication is used with local accounts, it can be delegated if the local accounts on the local and remote computers are identical. Domain accounts can also be delegated.

Digest

No

Integrated Windows

Depends

Integrated Windows authentication either results in NTLM or Kerberos (depending upon the version of operating system on client and server computer).
NTLM does not support delegation.
Kerberos supports delegation with the appropriate Active Directory configuration. *SEE NOTE

Client Certificates

Depends

Can be delegated if used with IIS certificate mapping and the certificate is mapped to a local account that is duplicated on the remote computer or is mapped to a domain account. This works because the credentials for the mapped account are stored on the local server and are used to create an Interactive logon session (which has network credentials).
Active Directory certificate mapping does not support delegation.


*NOTE

If your application runs under the Network Service account, you need to configure your computer account in Active Directory to be trusted for delegation.

If your application runs under a custom domain account, you need to configure your domain account in Active Directory to be trusted for delegation. You must also register a service principal name in Active Directory to associate the domain account with the HTTP service on your Web server.

end quote. }

Now that the security discussion is concluded, we can take this opportunity to ensure that Middle-Earth settles down once again.

Posted by willy with 3 comment(s)