Dialog Security

As with any feature that sends data across the network, security is a vital part of the Service Broker infrastructure. Service Broker includes a number of security options that support the level of security appropriate to the network vulnerability and data criticality. Service Broker security must solve the unique issues presented by asynchronous messaging. Because the applications communicating over a Service Broker conversation might never be running at the same time, normal connection-oriented network security won’t provide the full range of security options required by Service Broker. This section describes how dialog security is implemented in the Service Broker and how to configure it.

Dialog security doesn’t make sense if both dialog endpoints are in the same database. To configure dialog security, you’ll need to move one of the endpoints of our sample application to a different database. To keep things simple, you’ll move the initiator to another database in the same SQL Server instance. To set this up, create a database called Manufacturing. Create the message types and contract, as you did in Example 11-1, and then run the two scripts that set up the initiator (which are provided in Example 11-3 and Example 11-4). If this all works correctly, execute AddItemProc in the Manufacturing database to begin a dialog and send a message to the InventoryService. You should find that the message never makes it to the InventoryQueue and instead ends up in the sys.transmission_queue in the Manufacturing database with a message in the transmission_status column that indicated a bad security context. This statement will display the messages in the sys.transmission_queue view.

SELECT * FROM sys.transmission_queue

The security context error is caused by Service Broker impersonating the owner of the Manufacturing service to send the message. Service Broker does this because a number of users can send messages on a dialog. So the send executes in the context of the service owner to ensure consistent security behavior. SQL Server 2005 considers crossing databases with an impersonated user context a security threat. To see why this is an issue, assume that Moe is the database owner (dbo) of the Inventory database and owns the InventoryService. If Larry is the dbo of the Manufacturing database, he can create a user in his database for Moe’s login, make this user the owner of the ManufacturingService, and grant himself impersonation permissions for this user. Because the Moe user in the Manufacturing database is associated with the same login as the Moe user in the Inventory database, Larry has just given himself permission to execute code in the Inventory database without Moe’s knowledge or permission. Although this is a bad thing if Larry isn’t a trustworthy dbo, there are valid reasons for wanting to do this. To allow cross-database permissions with an impersonated security context, the system administrator can mark the impersonating database as "trustworthy." To see how this works, sign on as a system administrator and execute the following:

ALTER DATABASE Manufacturing SET TRUSTWORTHY ON;

If everything is set up correctly, the message in the sys.transmission_queue will be delivered and a response will be received within a minute. Check the InventoryState table in the Manufacturing database with this query to make sure it worked.

SELECT * FROM InventoryState

There is now successful communication with a service in another database, but marking the Manufacturing database as "trustworthy" gives the Manufacturing dbo a lot of power. You wanted to allow him to access the InventoryService in the Inventory database, but you actually gave him the ability to access any service in any database in the instance. If Larry isn’t really that trustworthy, it’s possible to turn off the trustworthy flag and use dialog security to give him access to only the services he really needs. Dialog security uses public key/private key certificates for authentication, so I will start with a brief explanation of asymmetric key encryption and then show how Service Broker uses it for secure message delivery.

Asymmetric Key Authentication

Asymmetric encryption involves two keys–a public key and a private key. These two keys have a special relationship. Data encrypted with the private key can be decrypted only with the public key, and data encrypted with the public key can be decrypted only with the private key. The private key is kept tightly secured on the owner’s system, and the public key is given out to systems that need to communicate with the private key owner. At first glance, it looks like a great way to secure communications. If Larry and Moe need to talk, Larry gives Moe his public key and Moe gives Larry his public key. When Larry wants to send Moe something he encrypts it with Moe’s public key, confident that only Moe can decrypt it. There are two issues that arise with this process. First, Larry knows that only Moe can decrypt the message, but Moe doesn’t know for sure that Larry sent it to him. Larry can solve this problem by signing the message with his private key so that when Moe checks the signature with Larry’s public key he will know that Larry sent it. The other, more critical problem is that asymmetric key encryption and decryption are extremely slow. The processor overhead is so great that using this technique for exchanging data is impractical.

Fortunately, symmetric key encryption is relatively efficient for exchanging large messages. Symmetric key encryption is also called "shared secret" encryption because both the sender and receiver have the same key. The issue with this process is the need to reliably exchange the secret key. This issue is especially important for Service Broker because, for optimal security, every conversation has its own symmetric key.

As you might have guessed, Service Broker combines these techniques for dialog security. The asymmetric key technique is used to securely exchange a symmetric key, and then the symmetric key is used to exchange data. Actually, Service Broker cuts down the asymmetric overhead even further by exchanging a symmetric Key Exchange Key (KEK) with the asymmetric keys and then using the KEK to exchange the session keys for each dialog. The KEK is always sent in the header of the first dialog message, but it is decrypted only if the target has lost the KEK or it has changed. Each pair of Service Broker endpoints uses a different KEK for the dialogs between them. Service Broker generates a new Key Exchange Key periodically to reduce the impact of someone using a brute-force attack to break the key.

Configuring Dialog Security

Now that you know the basics of secure data transmission and authentication with dialog security, I’ll cover how to configure services to use dialog security. For mutual authentication, the initiator will need a private key and the target’s public key. The target needs its private key and the initiator’s public key. To provide these, Service Broker takes advantage of the support SQL Server 2005 provides for storing certificates. It’s important to understand that Service Broker primarily uses a certificate as a convenient container for an asymmetric key. Service Broker never traces the issuer of the certificate. It only checks validity dates to determine a certificate’s validity. For Service Broker’s purposes, a self-signed certificate works just as well as a certificate from a certificate authority. To fit into the SQL Server security infrastructure, certificates need to own services and hold permissions. However, SQL Server certificates are not security principals, so they can’t be assigned ownership or permissions. This means that a certificate must be associated with a user that is a security principal. The user is associated with the certificate through ownership. Certificates are not owned by schemas but are owned directly by users through the AUTHORIZATION parameter of CREATE CERTIFICATE. The other useful SQL Server 2005 feature that Service Broker takes advantage of is the user with no login. If you specify WITHOUT LOGIN in the CREATE USER statement, the user will be created without being associated with a login. This means that you can assign permissions to this user, but no external user can ever log in as this user. This arrangement helps make Service Broker applications more secure.

The BEGIN DIALOG command needs to know which certificates to use to secure the dialog. The private key comes from the owner of the Service object. The public key to use comes from the user specified in the REMOTE SERVICE BINDING for the service. The REMOTE SERVICE BINDING is a Service Broker object that ties a service name to a user who owns the public key associated with the remote service. The certificates corresponding to these two certificates–the public key certificate of the initiating service owner’s certificate, and the private key certificate of the REMOTE SERVICE BINDING user’s certificate–must be present in the target database to establish the dialog.

The private key certificate corresponding to the REMOTE SERVICE BINDING user of the initiator must have CONTROL permission on the target service, and the public key certificate corresponding to the initiator service owner’s certificate must have SEND permissions on the target service. The security header sent with the first message of a dialog contains identifiers of the two certificates used to create the security header so that the target knows which certificates to use. The certificate identifier is the combination of the issuer name and the sequence number, which should be unique. The Key Exchange Key is encrypted with the public key of the REMOTE SERVICE BINDING user’s certificate, and it is signed with the private key of the initiator service owner’s certificate. If the target has the same certificates, it can validate the signature and decrypt the KEK. Once both endpoints have the KEK, dialogs can be established between the endpoints using the KEK to transfer the session key for the dialog without having to use the certificates until the KEK changes or is lost through a database restart. (The KEK is never persisted, so if either endpoint is restarted, a new one must be established.)

Now that you know what’s needed, let’s look at an example of setting up security for our sample application, as shown in Example 11-5. This assumes you created the Manufacturing database in the cross database example.

Example 11-5. Securing the AddItem dialog

/*----------------------------------------------------------------------
-- This script sets up dialog security between the initiator and target
-- of the AddItem dialog
----------------------------------------------------------------------*/

-- First, turn off the trustworthy flag

USE master;
GO
ALTER DATABASE Manufacturing SET TRUSTWORTHY OFF;
GO

/*--------------------------------------------------------------------
-- Set up the Target Service security
--------------------------------------------------------------------*/

USE Inventory;
GO

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pass.word1';

-- Create a user to represent the "Inventory" Service
CREATE USER InventoryServiceUser WITHOUT  LOGIN;
ALTER AUTHORIZATION ON SERVICE::[//microsoft.com/InventoryService]
  TO InventoryServiceUser;

-- Grant control on the Inventory service to this user
GRANT CONTROL ON SERVICE::[//microsoft.com/InventoryService]
  TO InventoryServiceUser;

-- Create a Private Key Certificate associated with this user
CREATE CERTIFICATE InventoryServiceCertPriv
  AUTHORIZATION InventoryServiceUser
   WITH SUBJECT = 'ForInventoryService';

-- Dump the public key certificate to a file for use on the
-- initiating server - no private key
BACKUP CERTIFICATE InventoryServiceCertPriv
  TO FILE = 'C:InventoryServiceCertPub';

/*-------------------------------------------------------------------
-- Set up the Initiator Service security
-------------------------------------------------------------------*/

USE Manufacturing;
GO

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pass.word1';

-- Create a user to own the "Manufacturing" Service
CREATE USER ManufacturingServiceUser WITHOUT LOGIN;

-- Make this user the owner of the FROM service
ALTER AUTHORIZATION ON SERVICE::[//microsoft.com/ManufacturingService]
  TO ManufacturingServiceUser;

-- Create a Private Key Certificate associated with this user
CREATE CERTIFICATE ManufacturingServiceCertPriv
  AUTHORIZATION ManufacturingServiceUser
   WITH SUBJECT = 'ForManufacturingService';

-- Dump the public key certificate to a file for use on
-- the Manufacturing server
BACKUP CERTIFICATE ManufacturingServiceCertPriv
  TO FILE = 'C:ManufacturingServiceCertPub';

-- Create a user to represent the "Inventory" Service
CREATE USER InventoryServiceUser WITHOUT LOGIN;

-- Import the cert we got from the Inventory Service owned
-- by the user we just created
CREATE CERTIFICATE InventoryServiceCertPub
  AUTHORIZATION InventoryServiceUser
   FROM FILE = 'C:InventoryServiceCertPub';

CREATE REMOTE SERVICE BINDING ToInventoryService
  TO SERVICE '//microsoft.com/InventoryService'
   WITH USER = InventoryServiceUser;

/*--------------------------------------------------------------------
-- Finish the Target Service security setup
--------------------------------------------------------------------*/

USE Inventory;
GO

-- Create a user to represent the "Manufacturing" Service
CREATE USER ManufacturingServiceUser WITHOUT LOGIN;

-- Import the cert we got from the Manufacturing Service owned
-- by the user we just created
CREATE CERTIFICATE ManufacturingServiceCertPub
  AUTHORIZATION ManufacturingServiceUser
   FROM FILE = 'C:ManufacturingServiceCertPub';
GRANT SEND ON SERVICE::[//microsoft.com/InventoryService]
  TO ManufacturingServiceUser ;

This looks like a lot of code, but in reality you’ve just created the four certificates used for authentication and assigning permissions. Creating the public key certificates requires a certificate file exported from the private key certificate. This file is exported with the BACKUP CERTIFICATE command. If the initiator and target are located on different systems, the file must be transferred to the opposite server. However, in this case, the initiator and target are in the same instance, so it is just written out and then read back in from the same file. Also notice the trustworthy flag was set to OFF, so if this service works, it is because of dialog security.

Setting up dialog security seems like a lot of work to avoid setting the trustworthy flag. However, there is another advantage of setting up dialog security to the database–you can now detach either of these databases and attach it to a different SQL Server instance without having to change dialog security. This is what I’ll do in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.105.114