Web service privileges

P

Peter Bradley

Hi,

I'm writing a Web service (the first one I've ever written in anger, by the
way) that has to do some AD manipulation and then has to create some
directories on some remote servers. Doing the AD stuff is fine, because I
can pass in suitable credentials: however this is not the case (AFAIK) with
the folder manipulation code. Here's an example of the kind of thing I want
to do:

....

// Create a new DirectoryInfo object
DirectoryInfo dInfo = new DirectoryInfo(@\\ourserver +
ProfilePathInfix +
"ade" +
@"\" +
_Personal_ID.ToLower());

if (!dInfo.Exists)
{
dInfo.Create();
}

// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();

// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(@"OURDOMAIN\" +
_Personal_ID, FileSystemRights.FullControl, AccessControlType.Allow));

// Set the new access settings.
dInfo.SetAccessControl(dSecurity);

....

It seems to me that I have a couple of options:
* Have the Web service run as a privileged user
* Call a remote service that runs as a privileged user

I'd be glad to get any advice anyone can give on which option would be
better.

Personally, I'm not too worried about having the Web service run as a
privileged user, because it will be running on an internal server,
innaccessible from outside and only ever called from its own local host. So
I should be able to configure it to be pretty secure.

However, on a practical level, VS2005 doesn't create the Web service on the
development box Web server. As far as I can see, you have to publish the
service first. Does that mean that if I opt for the first choice (run as
privileged user) I will not be able to debug it in VS as a privileged user?

Cheers


Peter
 
W

Willy Denoyette [MVP]

Peter Bradley said:
Hi,

I'm writing a Web service (the first one I've ever written in anger, by the way) that has
to do some AD manipulation and then has to create some directories on some remote servers.
Doing the AD stuff is fine, because I can pass in suitable credentials: however this is
not the case (AFAIK) with the folder manipulation code. Here's an example of the kind of
thing I want to do:

...

// Create a new DirectoryInfo object
DirectoryInfo dInfo = new DirectoryInfo(@\\ourserver +
ProfilePathInfix +
"ade" +
@"\" +
_Personal_ID.ToLower());

if (!dInfo.Exists)
{
dInfo.Create();
}

// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();

// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(@"OURDOMAIN\" + _Personal_ID,
FileSystemRights.FullControl, AccessControlType.Allow));

// Set the new access settings.
dInfo.SetAccessControl(dSecurity);

...

It seems to me that I have a couple of options:
* Have the Web service run as a privileged user
* Call a remote service that runs as a privileged user

I'd be glad to get any advice anyone can give on which option would be better.

Personally, I'm not too worried about having the Web service run as a privileged user,
because it will be running on an internal server, innaccessible from outside and only ever
called from its own local host. So I should be able to configure it to be pretty secure.

However, on a practical level, VS2005 doesn't create the Web service on the development
box Web server. As far as I can see, you have to publish the service first. Does that
mean that if I opt for the first choice (run as privileged user) I will not be able to
debug it in VS as a privileged user?

Cheers


Peter


Why a webservice if it's sole purpose is to be called from the same box?
Anyway, you can't access remote resources like file servers from a webservice unless you:
- Run it as a domain user with admin privileges on the remote server.
- impersonate that same user in code.
- drop this part of your code in a COM+ server style application.

The easiest and most secure is the latter, just inherit your class from ComponentServices,
set the required attributes to enable the class to be hosted and register the class with the
COM+ catalog using regsvcs.exe.

Here are the assembly attributes needed, note that you may have to create a new guid for the
ApplicationID and change the version info and the ApplicationName.


[assembly: AssemblyVersion("1.0.0.0")]
[assembly: ApplicationName("MyServer")]
[assembly: ApplicationAccessControl(AccessChecksLevel =
AccessChecksLevelOption.ApplicationComponent)]
[assembly: ApplicationID("ffc4e201-888f-4a15-be54-afe286ef70ac")]
[assembly: ApplicationActivation(ActivationOption.Server)]

following are the interface attributes (preferably in separate assembly, to be used by the
client code).

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("0f743bc7-b28e-4ebe-890f-d2a728da787c")]
public interface ISomeInterface
{
method declarations here...
}

following are the class attributes..

[JustInTimeActivation]
[ObjectPooling(Enabled = false)]
[Guid("17103ddc-d317-48ee-8585-8125c86ac4c5")]
[ProgId("xxxx.yyyyy")]
[ComVisible(true)]
public sealed class SomeClass: ServicedComponent, ISomeInterface
{
// implematation of ISomeInterface...
....

ProgId and Comvisible is required to expose this class to native COM clients too. same
remark as above for the guids.

Please refer to MSDN for more details.

Willy.
 
P

Peter Bradley

Thanks for that.

The reason for the strange configuration is because I'm calling the Web
service from BizTalk using the SOAP adapter. BizTalk send ports can't call
code directly. They do it via adapters. The easiest one we've found to use
for this purpose is the SOAP adapter (which calls a Web service). We did
consider coding our own adapter, but doing so would be far more complex than
using an existing one.

You say:
Anyway, you can't access remote resources like file servers from a
webservice unless you:
- Run it as a domain user with admin privileges on the remote server.
- impersonate that same user in code.
- drop this part of your code in a COM+ server style application.

I'm afraid I don't know how to do any of these things with Web services -
despite some searching on MSDN and elsewhere. However, since you express a
preference for the 3rd option, can you explain how a Web service can be
hosted in a COM+ server? You've lost me there, I think.

Thanks


Peter


Willy Denoyette said:
Peter Bradley said:
Hi,

I'm writing a Web service (the first one I've ever written in anger, by
the way) that has to do some AD manipulation and then has to create some
directories on some remote servers. Doing the AD stuff is fine, because I
can pass in suitable credentials: however this is not the case (AFAIK)
with the folder manipulation code. Here's an example of the kind of
thing I want to do:

...

// Create a new DirectoryInfo object
DirectoryInfo dInfo = new DirectoryInfo(@\\ourserver +
ProfilePathInfix +
"ade" +
@"\" +
_Personal_ID.ToLower());

if (!dInfo.Exists)
{
dInfo.Create();
}

// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();

// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(@"OURDOMAIN\" +
_Personal_ID, FileSystemRights.FullControl, AccessControlType.Allow));

// Set the new access settings.
dInfo.SetAccessControl(dSecurity);

...

It seems to me that I have a couple of options:
* Have the Web service run as a privileged user
* Call a remote service that runs as a privileged user

I'd be glad to get any advice anyone can give on which option would be
better.

Personally, I'm not too worried about having the Web service run as a
privileged user, because it will be running on an internal server,
innaccessible from outside and only ever called from its own local host.
So I should be able to configure it to be pretty secure.

However, on a practical level, VS2005 doesn't create the Web service on
the development box Web server. As far as I can see, you have to publish
the service first. Does that mean that if I opt for the first choice
(run as privileged user) I will not be able to debug it in VS as a
privileged user?

Cheers


Peter


Why a webservice if it's sole purpose is to be called from the same box?
Anyway, you can't access remote resources like file servers from a
webservice unless you:
- Run it as a domain user with admin privileges on the remote server.
- impersonate that same user in code.
- drop this part of your code in a COM+ server style application.

The easiest and most secure is the latter, just inherit your class from
ComponentServices, set the required attributes to enable the class to be
hosted and register the class with the COM+ catalog using regsvcs.exe.

Here are the assembly attributes needed, note that you may have to create
a new guid for the ApplicationID and change the version info and the
ApplicationName.


[assembly: AssemblyVersion("1.0.0.0")]
[assembly: ApplicationName("MyServer")]
[assembly: ApplicationAccessControl(AccessChecksLevel =
AccessChecksLevelOption.ApplicationComponent)]
[assembly: ApplicationID("ffc4e201-888f-4a15-be54-afe286ef70ac")]
[assembly: ApplicationActivation(ActivationOption.Server)]

following are the interface attributes (preferably in separate assembly,
to be used by the client code).

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("0f743bc7-b28e-4ebe-890f-d2a728da787c")]
public interface ISomeInterface
{
method declarations here...
}

following are the class attributes..

[JustInTimeActivation]
[ObjectPooling(Enabled = false)]
[Guid("17103ddc-d317-48ee-8585-8125c86ac4c5")]
[ProgId("xxxx.yyyyy")]
[ComVisible(true)]
public sealed class SomeClass: ServicedComponent, ISomeInterface
{
// implematation of ISomeInterface...
...

ProgId and Comvisible is required to expose this class to native COM
clients too. same remark as above for the guids.

Please refer to MSDN for more details.

Willy.
 
D

DeveloperX

Thanks for that.

The reason for the strange configuration is because I'm calling the Web
service from BizTalk using the SOAP adapter. BizTalk send ports can't call
code directly. They do it via adapters. The easiest one we've found to use
for this purpose is the SOAP adapter (which calls a Web service). We did
consider coding our own adapter, but doing so would be far more complex than
using an existing one.

You say:
Anyway, you can't access remote resources like file servers from a
webservice unless you:
- Run it as a domain user with admin privileges on the remote server.
- impersonate that same user in code.
- drop this part of your code in a COM+ server style application.

I'm afraid I don't know how to do any of these things with Web services -
despite some searching on MSDN and elsewhere. However, since you express a
preference for the 3rd option, can you explain how a Web service can be
hosted in a COM+ server? You've lost me there, I think.

Thanks

Peter



Why a webservice if it's sole purpose is to be called from the same box?
Anyway, you can't access remote resources like file servers from a
webservice unless you:
- Run it as a domain user with admin privileges on the remote server.
- impersonate that same user in code.
- drop this part of your code in a COM+ server style application.
The easiest and most secure is the latter, just inherit your class from
ComponentServices, set the required attributes to enable the class to be
hosted and register the class with the COM+ catalog using regsvcs.exe.
Here are the assembly attributes needed, note that you may have to create
a new guid for the ApplicationID and change the version info and the
ApplicationName.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: ApplicationName("MyServer")]
[assembly: ApplicationAccessControl(AccessChecksLevel =
AccessChecksLevelOption.ApplicationComponent)]
[assembly: ApplicationID("ffc4e201-888f-4a15-be54-afe286ef70ac")]
[assembly: ApplicationActivation(ActivationOption.Server)]
following are the interface attributes (preferably in separate assembly,
to be used by the client code).
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("0f743bc7-b28e-4ebe-890f-d2a728da787c")]
public interface ISomeInterface
{
method declarations here...
}
following are the class attributes..
[JustInTimeActivation]
[ObjectPooling(Enabled = false)]
[Guid("17103ddc-d317-48ee-8585-8125c86ac4c5")]
[ProgId("xxxx.yyyyy")]
[ComVisible(true)]
public sealed class SomeClass: ServicedComponent, ISomeInterface
{
// implematation of ISomeInterface...
...
ProgId and Comvisible is required to expose this class to native COM
clients too. same remark as above for the guids.
Please refer to MSDN for more details.
Willy.- Hide quoted text -

- Show quoted text -

I could be way off base, but I think he's suggesting host the
problematic bit of code in COM+ and call the COM+ component from your
web service.
I have some similar issues at the moment but I'm not as far into the
project as you, so I look forward to seeing what the solution turns
out to be :)
 
W

Willy Denoyette [MVP]

Peter Bradley said:
Thanks for that.

The reason for the strange configuration is because I'm calling the Web service from
BizTalk using the SOAP adapter. BizTalk send ports can't call code directly. They do it
via adapters. The easiest one we've found to use for this purpose is the SOAP adapter
(which calls a Web service). We did consider coding our own adapter, but doing so would
be far more complex than using an existing one.

You say:

I'm afraid I don't know how to do any of these things with Web services - despite some
searching on MSDN and elsewhere. However, since you express a preference for the 3rd
option, can you explain how a Web service can be hosted in a COM+ server? You've lost me
there, I think.

Thanks

You don't host the webservice in a COM+ server, you have to host the "security sensitive"
code in a COM+ hosted process, security sensitive means code that needs admin privileges to
perform it's tasks, so this includes access to the AD as well as other windows resources
like fileservers.
You can keep your webservice as is, all you do is call your method(s) on a class that runs
in a remotely process. You have to configure the process (COM+) such that it runs in the
account of a "domain admin" having the necessary privileges to access the remote servers
resources, while your Webservice keeps running in the account of a less privileged user.
Note that you can apply role based security at the COM+ level, this allows you to apply
"fine grained" access control.

So basically what you have is this:

[Webservice -- 1 --> COM+ process ]---- 2 ----> [Remote servers resource]

1 = cross-process call
2 = cross-machine call
The Webservice call a method on the interface implemented by the class running in the COM+
server.

Willy.
 
P

Peter Bradley

Yeah. What we've decided to do is not to use COM+, but to use a remote
object (Single call SAO over TCP/IP) to do all the AD and file system
manipulations. The remote object will be hosted in a service on our
application server, and that service will run as the privileged user. We'll
try to ensure that the Web service will only accept calls from BizTalk
itself and that the remote service will only accept calls from the BizTalk
server.

It's not a perfect solution, but I think it should be secure enough. I just
hope it turns out to reliable enough. This particular piece of systems
integration needs a highly reliable solution.


Peter


Willy Denoyette said:
Peter Bradley said:
Thanks for that.

The reason for the strange configuration is because I'm calling the Web
service from BizTalk using the SOAP adapter. BizTalk send ports can't
call code directly. They do it via adapters. The easiest one we've
found to use for this purpose is the SOAP adapter (which calls a Web
service). We did consider coding our own adapter, but doing so would be
far more complex than using an existing one.

You say:

I'm afraid I don't know how to do any of these things with Web services -
despite some searching on MSDN and elsewhere. However, since you express
a preference for the 3rd option, can you explain how a Web service can be
hosted in a COM+ server? You've lost me there, I think.

Thanks

You don't host the webservice in a COM+ server, you have to host the
"security sensitive" code in a COM+ hosted process, security sensitive
means code that needs admin privileges to perform it's tasks, so this
includes access to the AD as well as other windows resources like
fileservers.
You can keep your webservice as is, all you do is call your method(s) on a
class that runs in a remotely process. You have to configure the process
(COM+) such that it runs in the account of a "domain admin" having the
necessary privileges to access the remote servers resources, while your
Webservice keeps running in the account of a less privileged user. Note
that you can apply role based security at the COM+ level, this allows you
to apply "fine grained" access control.

So basically what you have is this:

[Webservice -- 1 --> COM+ process ]---- 2 ----> [Remote servers resource]

1 = cross-process call
2 = cross-machine call
The Webservice call a method on the interface implemented by the class
running in the COM+ server.

Willy.
 
W

Willy Denoyette [MVP]

Peter Bradley said:
Yeah. What we've decided to do is not to use COM+, but to use a remote object (Single
call SAO over TCP/IP) to do all the AD and file system manipulations. The remote object
will be hosted in a service on our application server, and that service will run as the
privileged user. We'll try to ensure that the Web service will only accept calls from
BizTalk itself and that the remote service will only accept calls from the BizTalk server.

It's not a perfect solution, but I think it should be secure enough. I just hope it turns
out to reliable enough. This particular piece of systems integration needs a highly
reliable solution.

That's why I suggested to use COM+, you can configure COM+ to run as a Service without you
have to implement a service, and you can take advantage of the COM+ features like transport
security and automatic recovery in case of server failures. Sure you can do this all by
yourself but why re-invent the wheel?, especially when using Biztalk which already
integrates with COM+.

Willy.
 
P

Peter Bradley

You may well be right, Willy. However there are a couple of reason for
doing what we've decided to do. Firstly we understand .NET remoting: we
don't understand COM+. Secondly, I'm not sure that BizTalk 2006 does
integrate all that easily with COM+ any more. Early versions of BizTalk
certainly did, but my impression from the training and our subsequent
experience is that BTS2006 needs to connect to its end points via adapters.
The choice is therefore between using an existing adapter or rolling your
own. Clearly, using an existing one is much easier, and therefore quicker.

Finally, automatic recovery won't necessarily help. Successful recovery may
not be possble. It's avoiding the need for recovery that's important, so
I'm nervous about adding another element to the chain - whether that element
is COM+ or .NET remoting.

But many thanks for your help and constructive suggestions.


Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top