Securing Indigo Applications


One major improvement in Indigo applications as compared to prior managed- communications technologies is that Indigo applications allow you to create secure communications. Indigo provides common security services such as confidentiality (also known as encryption), integrity, authentication, and authorization. By default, the Indigo performs many security tasks (such as encryption and digital signing) for you, greatly easing the job of building a secure application.

Effectively securing your Indigo application primarily consists of the following steps:

  1. Securing access to the methods your application publishes or exposes.

  2. Securing the content of messages sent to and from nodes of your application.

Let s look at securing access to published methods. Often you need to restrict access to your Indigo application to only a select group of predefined users. To do so, Indigo must determine the identity of a client using an authentication service. Indigo provides the following built-in authentication services:

  • Microsoft Windows authentication

  • X.509 certificate authentication

  • Basic user name and password authentication

When writing an application, the developer determines which roles can access a method. When deploying a Message Bus application, an administrator assigns user and group memberships to one or more roles. When Indigo authenticates a client, it determines the client s identity and maps that identity to a role.

An Indigo application might need to communicate across a network where anyone can monitor the messages. In many applications, you will not want third parties to read the messages during transmission or to alter or replace messages during transmission. You can use encryption to protect the confidentiality of your messages. Indigo supports encryption using both symmetric and asymmetric algorithms. Similarly, you can use digital signatures to protect the integrity of your messages and to verify the authenticity of the message sender.

Indigo provides most of the security you need by default. Message Bus applications automatically adapt to meet the security requirements specified by receiving nodes as defined by the WS-SecurityPolicy specification. For example, if you write a client and use the default configuration schemes, your client will automatically conform to the encryption and authentication requirements of most servers to which it might connect. In many cases, security requirements need to be explicitly specified only on the server side. Indigo provides many default security schemes that you can easily control through code attributes and configuration.

The Indigo security system automatically implements most security details when you add security attributes to your communications methods. For example, when you need to encrypt a message, you specify that you want to perform encryption by decorating your methods with descriptive attributes. When the method is accessed, Indigo automatically encrypts the message for you. You request Web method access control similarly.

Indigo provides two mechanisms to define and modify security requirements. A developer can define security requirements in a configuration file or explicitly in code, similar to the way you can define the communications transports and ports in a configuration file or code. However, system administrators might also want to define or modify the security requirements for a deployed application. They would use the configuration files to specify the new requirements.

Security Manager

The SecurityManager is the primary component of the Indigo security system. It defines the security requirements that are applied to incoming and outgoing messages of a specified port. Typically, every port has one SecurityManager .

You can easily create a new SecurityManager automatically when you create a new ServiceEnvironment . When you create a ServiceEnvironment by loading a configuration file, the Indigo framework automatically creates a SecurityManager if a definition of a SecurityManager is present in the configuration file. The SecurityManager contains three important properties: Scopes , Bindings , and EndpointSettings .

Scopes Property

The Scopes property contains a collection of security scope objects.

Security Scope

A security scope defines the security requirements you want associated with a service method. For example, if you want to specify that a method needs to use encryption, you would define it in a security scope. If you want to specify that a method requires an access check, you would also define it in a security scope.

You use a security scope to specify the following requirements for a Web service method:

  • It must encrypt its message bodies.

  • It requires an access check (and that implicitly involves message integrity and sender authentication)

Security Profile

A security profile defines how to implement a security requirement. It specifies how the encryption, integrity and sender authentication requirements can be met. For example, most systems support a variety of encryption algorithms. One security profile can specify that the DES3 encryption should be used, while a different profile specifies RSA encryption.

The following security requirement implementations can be defined using security profiles:

  • Algorithms to use for encryption

  • Keys or X.509 certificates to use for encryption

  • The type of authentication to use (such as Windows, basic user name and password, or X.509 certificate authorization)

  • How to use licensing

Bindings Property

Security scopes are not associated with a security profile until the two are explicitly bound by a security binding. Generally, your application will have one or more scopes associated with every service method or remote object. A system will typically have numerous profiles available. When an administrator configures or deploys an application, the administrator decides which implementation ”for example, authentication type ”to use by binding a scope to a profile. The SecurityManager Bindings property contains these bindings and is populated by configuration information in the Machine.config and Application.config files when you create a new SecurityManager .

EndpointSettings Property

The EndpointSettings property encapsulates security capabilities of the current endpoint. All cryptographic algorithms, keys, X.509 certificates, and authentication providers are enumerated here. Like the Bindings property, the EndpointSettings property is typically populated by information from Machine.config and Application.config files when you create a new SecurityManager . These values are usually configured during application deployment and administration rather than during development.

Design-Time vs. Deploy-Time

While this design initially seems complicated, the distinction between security scopes and security profiles allow you to separate your security requirements from your security implementation. Typically, you will specify your security requirements in code (for example, this method restricts access control to users in role X). However, you typically specify the implementation of that security requirement in a configuration file (for example, that Windows authentication should be used). This separation allows you to change the implementation of a security requirement (type of authentication, type of encryption, and so forth) that your application uses without having to recompile.

Creating an Authenticated Web Service

Let s add authentication to my original Web service example from this chapter. In the following example, I ve simply added the two lines in bold: a using declaration, and a ServiceSecurity attribute that indicates Indigo should secure access to the GetUtcTimeAndDate method.

 using System; 
using System.Globalization;
using System.MessageBus;
using System.MessageBus.Services;
using System.MessageBus.Security;

namespace WiseOwl {
[DatagramPortType(Name="Time",
Namespace="http://www.wiseowl.com/WebServices")]
public class Time {
[ServiceSecurity(Name="GetUtcDateAndTimeScope", Role="StandardUserRole")]
[ServiceMethod]
public string GetUtcTimeAndDate(string culture) {
Console.WriteLine ("Client requested UTC time for culture {0}", culture);
CultureInfo ci = new CultureInfo (culture);
return DateTime.UtcNow.ToString ("F", ci);
}
}
}

I didn t change the host application at all, so I won t list it again here. However, I did add a securityManager element to the host s application configuration file, host.exe.config. Note that the securityManager element contains an applicationSecurity element with a binding that maps the scope named GetUtcDateAndTimeScope to the profile named windows .

 <configuration> 
<system.messagebus>
<serviceEnvironments>
<serviceEnvironment name="main">
<port>
<identityRole>soap.tcp://localhost:46000/TimeService/</identityRole>
</port>
<!-- Bind the scope defined using ServiceSecurityAttribute to a profile that uses
Windows Authentication. -->
<securityManager>
<applicationSecurity>
<binding scope="GetUtcDateAndTimeScope" profile="windows" />
</applicationSecurity>
</securityManager>
<policyManager>
<!-- CAUTION: Security disabled for demonstration purposes only. -->
<!-- Permits unsigned policy statements. Default requires signed policy statements -->
<areUntrustedPolicyAttachmentsAccepted>
true
</areUntrustedPolicyAttachmentsAccepted>
<isPolicyReturned>true</isPolicyReturned>
</policyManager>
<serviceManager>
<activatableServices>
<add type="WiseOwl.Time, TimeService" />
</activatableServices>
</serviceManager>
</serviceEnvironment>
</serviceEnvironments>
</system.messagebus>
</configuration>

The ServiceSecurity attribute on my Web service method states that access to the method is constrained by the scope named GetUtcDateAndTimeScope. Conceptually, an administrator has bound that scope name to the windows profile ”a system-defined profile that specifies that the desired implementation is the Windows authentication implementation.

Indigo will now require a client to authenticate using Windows authentication. The method s ServiceSecurity attribute requires the authenticated user to be in the role named StandardUserRole to access the method. The mapping between users and roles resides in the application s security configuration file, which in this example, is named host.exe.security. In my WiseOwl domain, I ve created a new group named Indigo Users and added my user account to that group. Then in the application s security configuration file, I specify that an authenticated user in the Indigo Users group is in the StandardUserRole role and, therefore, has access to my Web service method.

 <securityData> 
<authorizationData>
<memoryMapping id="mainAuthorizationData">
<globalEntries>
<windowsRoleAssignment domain="WiseOwl" group="Indigo Users"
roles = "StandardUserRole"/>
</globalEntries>
</memoryMapping>
</authorizationData>
</securityData>

Calling an Authenticated Web Service Method

You can use the original Web service client listed previously in this chapter to call the authenticated version of the Web service method. Run the client while logged in using an account that is currently authenticated by the domain that the Web service recognizes. You don t need to make any changes to the client code to call an authenticated Web service. However, I did need to make one small change to the client s configuration file. The original version removed the security manager from the service environment as follows :

 <remove name="securityManager" /> 

Now I need the default security manager in the service environment, so I deleted the preceding line from the client.exe.config file for my authenticated Web service client.

Variations on Authentication

Now that I ve enabled authentication for my Web service method, I can easily change the type and manner of authentication by editing the configuration files. For example, if I want to switch from Windows authentication to requiring a user name and password, I need to make only two changes at the server and one at the client. First, I change the securityManager in my host.exe.config application configuration file so that my security code now binds to the standard userNamePassword profile as follows:

 <securityManager> 
<applicationSecurity>
<binding scope="GetUtcDateAndTimeScope" profile="userNamePassword" />
</applicationSecurity>
</securityManager>

Then I change my application security file, host.exe.security, so that it specifies the allowed user names and their respective passwords, and maps the user names to the appropriate roles.

 <securityData> 
<credentials>
<username id="mainUsers" nonceLength="24">
<memoryPasswordResolver>
<add user="Brent" password="password1" />
<add user="Lisa" password="password2" />
</memoryPasswordResolver>
</username>
</credentials>
<authorizationData>
<memoryMapping id="mainAuthorizationData">
<globalEntries>
<userNameRoleAssignment user="Brent" roles = "StandardUserRole"/>
<userNameRoleAssignment user="Lisa" roles = "StandardUserRole"/>
</globalEntries>
</memoryMapping>
</authorizationData>
</securityData>

I feel obliged to point out that you can replace the memoryPasswordResolver used in the prior example with your own custom mechanism to retrieve user names and passwords from some more secure and presumably encrypted source.

Because the service application requires a user name and password, I must now change the client application so that it provides the user name and password. The easiest way is to use my original client application and specify the user name and password in the client application s security configuration file. Here s the original client application. The following code is a client application:

 // client.cs 
using System;
using System.MessageBus;
using System.MessageBus.Services;
using www_wiseowl_com.WebServices; // The imported service namespace

public class Client {
public static void Main(string[] args) {
string culture = "en-US";
if (args.Length > 0) culture = args[0];

// Load the default service environment, called "main".
ServiceEnvironment se = null;

try {
se = ServiceEnvironment.Load();

// Retrieve the ServiceManager from the default environment
ServiceManager sm =
se[typeof(ServiceManager)] as ServiceManager;
if (sm == null)
throw new Exception ("ServiceManager is not available.");

// Start the service environment.
se.Open();

// Create a proxy channel that points to the service to call.
Uri uri = new Uri("soap.tcp://localhost:46000/TimeService/");
ITimeChannel channel = (ITimeChannel)
sm.CreateChannel(typeof(ITimeChannel), uri);

Console.WriteLine(channel.GetUtcTimeAndDate (culture));
}
catch (Exception e) {
Console.WriteLine (e);
}
finally {
if (se != null) se.Close();
}
}
}

Because the prior client application loads its configuration from the default service environment, I can specify my security settings using a security configuration file. My client application is named client.exe ”therefore my client application security file is client.exe.security and looks like this:

 <securityData> 
<tokens>
<tokenCache id="mainTokenCache">
<userNameToken user="Brent" password="password"/>
<userNameToken user="Lisa" password="wordpass"/>
</tokenCache>
</tokens>
</securityData>

Rather than specifying the user name and password pairs in the configuration file, I can alternatively initialize the security token cache programmatically before I open the security environment:

 // Retrieve the SecurityManager from the default environment 
SecurityManager secMan = se [typeof(SecurityManager)] as SecurityManager;

if (secMan == null) {
throw new ApplicationException("Security Manager not present.");
}

// Create a new UserName Token and add password and user information.
UserNameToken t = new UserNameToken (userName, password, 24);
secMan.EndpointSettings.TokenCache.AddToken(t);

se.Open ();

Message Confidentiality

When you enable confidentiality on a Web service method, Indigo encrypts the body of your messages automatically. When a client calls your encrypted Web service, Indigo automatically acquires the appropriate keys and encrypts the messages to meet the requirements of the service. An administrator typically decides encryption requirements during deployment by using configuration files.

You enable confidentiality by passing the true Confidentiality property of the ServiceSecurityAttribute . Therefore, using following attribute in place of the one listed previously requires authentication and authorization to access the method. It also encrypts the SOAP message body of the message sent to the method.

  [ServiceSecurity(Name="GetUtcDateAndTimeScope",  
Role="StandardUserRole", Confidentiality = true )]

As with the prior example, you typically select the specific encryption implementation using configuration file entries.




Introducing Microsoft WinFX
Introducing WinFX(TM) The Application Programming Interface for the Next Generation of Microsoft Windows Code Name Longhorn (Pro Developer)
ISBN: 0735620857
EAN: 2147483647
Year: 2004
Pages: 83
Authors: Brent Rector

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net