Friday, November 12, 2010

SSRS data processing extension, Windows integrated security, and impersonation

I've been playing around with Craig Martin's SSRS Data Processing Extension for FIM. (Great stuff; thanks for posting it, Craig!) I had to do some troubleshooting with Windows integrated security and Windows credentials stored securely on the server.

I noticed that the IDbConnection.Open method was being called as the impersonated Windows user:

2010-11-11 14:56:37,932 --4-- DEBUG [FimDataProcessingExtension.FimConnection]    

[Microsoft.ReportingServices.DataProcessing.IDbConnection.Open] Current user info:
Name : TEST\joe.zamora
IsAuthenticated : True
AuthenticationType : Kerberos
ImpersonationLevel : Impersonation

However, the IDbCommand.ExecuteReader method was not run under the context of the Windows user:

2010-11-11 14:56:37,934 --4-- DEBUG [FimDataProcessingExtension.FimConnection]    

[GetData] Current user info:
Name : TEST\svc_ssrs
IsAuthenticated : True
AuthenticationType : Kerberos
ImpersonationLevel : None

Well, turns out that this is by design. Here's the official word from Microsoft:

Impersonation and Custom Data Processing Extensions

If your custom data processing extension connects to data sources using impersonation, you must use the Open method on either the IDbConnection orIDbConnectionExtension interfaces to make the request. Alternately, you can store the user identity object (System.Security.Principal.WindowsIdentity) and then reuse it in the other data processing extension APIs.

In previous releases of Reporting Services, all custom data processing extensions were called under user impersonation. In this release, only the Open method will be called while impersonating the user. If you have an existing data processing extension that requires integrated security, you must modify your code to use the Openmethod or store the user identity object.



Thus, you should save the current Windows identity to a local variable in the IDbConnection.Open method:

if (this.integratedSecurity)
{
this.windowsIdentity = WindowsIdentity.GetCurrent();
}

And then you can use it later in the other API calls:

private WindowsImpersonationContext impersonationContext;
internal void MaybeImpersonate()
{
if (this.integratedSecurity)
{
impersonationContext = this.windowsIdentity.Impersonate();
}
}

That'll teach me for not reading the documenation. ;)

No comments:

Post a Comment