Firma del modulo (Motore di database)

Le applicazioni di database spesso richiedono che l'accesso a oggetti e tabelle sottostanti nello schema dell'applicazione avvenga tramite viste o procedure Entry Level. Lo scopo è concedere l'accesso agli utenti finali agli oggetti Entry Level che quindi accedono agli oggetti sottostanti per conto dell'utente. Non è pertanto necessario concedere l'accesso agli utenti finali a tutti gli oggetti nello schema dell'applicazione. Questo approccio consente di conseguire due obiettivi:

  • Semplifica la gestione delle autorizzazioni in quanto le autorizzazioni possono essere gestite unicamente in un subset ridotto di oggetti e non in tutti gli oggetti dello schema dell'applicazione.

  • È possibile nascondere all'utente il layout dello schema sottostante poiché solo i punti di ingresso sono esposti.

MicrosoftSQL Server ha un numero di funzionalità che consentono di realizzare questi scenari, ad esempio il concatenamento della proprietà e l'utilizzo dell'istruzione EXECUTE AS. Iniziando con SQL Server 2005, SQL Server si dispone inoltre della facoltà di firmare moduli all'interno del database. La firma dei moduli offre funzionalità simili, ma non modifica il contesto dell'esecuzione. In questo contesto un modulo fa riferimento a una stored procedure, a una funzione, a un trigger o a un assembly. Per ulteriori informazioni, vedere CREATE ROLE (Transact-SQL) e Utilizzo di EXECUTE AS per la creazione di set di autorizzazioni personalizzati.

Firme dei moduli

In SQL Server 2005 viene introdotta la funzionalità di firma dei moduli all'interno del database, ad esempio stored procedure, funzioni, trigger o assembly. Si noti che i trigger DDL (Data Definition Language) non possono essere firmati. Un firma digitale è un digest di dati crittografato con la chiave privata del firmatario. Tramite la chiave privata, la firma digitale è univoca per il titolare o il proprietario.

Per firmare i dati, il firmatario esegue il digest dei dati, li crittografa con una chiave privata e associa il valore del digest crittografato ai dati. Per verificare la firma, viene utilizzata la chiave pubblica del firmatario per decrittografare il valore del digest crittografato associato ai dati, dopodiché questo valore viene confrontato al valore del digest calcolato in base ai dati complementari. È importante che sia il firmatario sia colui che esegue la verifica utilizzino la stessa funzione hash per eseguire il digest dei dati.

Nota di attenzioneAttenzione

La firma dei moduli deve essere utilizzata unicamente per concedere autorizzazioni, mai per negarle o revocarle.

Scenario

Si supponga che l'accesso alla vista sys.sysprocesses avvenga tramite la stored procedure usp_sysprocesses. Gli utenti possono accedere alle informazioni sys.sysprocesses solo quando si esegue la procedura usp_sysprocesses. Poiché gli oggetti usp_sysprocesses e sys.sysprocesses hanno proprietari diversi, il concatenamento della proprietà non è applicabile.

È innanzitutto necessario creare un certificato nel server da una coppia di chiavi utilizzando l'istruzione CREATE CERTIFICATE. È quindi necessario concedere al certificato le autorizzazioni a eseguire selezioni nella tabella sys.sysprocesses. Poiché, tuttavia, in SQL Server vengono concesse autorizzazioni solo a entità, è innanzitutto necessario creare un account di accesso dal certificato utilizzando l'istruzione CREATE LOGIN. Per questo account di accesso non sono necessarie autorizzazioni di connessione nel server, in quanto si tratta solo di un segnaposto per autorizzazioni e non viene utilizzato per la connessione all'istanza del server. A questo accesso mappato del certificato possono quindi essere concesse le autorizzazioni SELECT nella tabella sys.sysprocesses tramite l'istruzione GRANT VIEW SERVER STATE TO. Dopo la creazione della stored procedure usp_sysprocesses, è possibile firmarla con il certificato, ovvero la chiave privata corrispondente a questo certificato, tramite l'istruzione ADD SIGNATURE. Viene creato un nuovo ruolo al quale viene concessa l'autorizzazione di esecuzione nella stored procedure usp_sysprocesses. Qualsiasi utente membro di questo ruolo avrà quindi l'autorizzazione ad eseguire la stored procedure usp_sysprocesses e l'istruzione SELECT dalla vista sys.sysprocess. Quando si esegue un modulo firmato, le autorizzazioni concesse tramite l'istruzione GRANT all'entità associata al certificato di firma vengono temporaneamente unite (UNION) nel token di protezione di run-time per la durata della chiamata. Non appena il controllo di esecuzione restituisce un risultato, queste autorizzazioni vengono rimosse dal token di protezione. Solo per la durata dell'esecuzione del modulo, si dispone pertanto di fatto di un set aggiuntivo di autorizzazioni. Qualsiasi altro utente o ruolo a cui sono concesse le autorizzazioni EXECUTE in questa procedura disporrà inoltre delle stesse funzionalità.

Esempio

Lo script Transact-SQL seguente costituisce un esempio dello scenario precedente. Un certificato viene creato da una coppia di chiavi e mappato a un nuovo account di accesso. È innanzitutto necessario creare una coppia di chiavi di prova utilizzando lo strumento MakeCert incluso in .NET Framework SDK. Le autorizzazioni Select per la vista sys.sysproceses vengono quindi concesse all'account di accesso associato al certificato. La stored procedure gestita usp_sysprocesses viene creata nel nuovo database e firmata con il certificato. Viene creato il ruolo SysProcRole a cui verranno concesse le autorizzazioni di esecuzione nella stored procedure usp_sysprocesses. Un utente di prova viene creato e aggiunto al ruolo SysProcRole. A scopo di confronto, l'utente di prova esegue un'istruzione SELECT in sys.sysprocess e quindi esegue la stored procedure usp_sysprocesses. Tramite lo script viene quindi eseguita l'eliminazione dell'ambiente di prova.

use master
go

-- Create a test database.
CREATE DATABASE db_Demo
go

-- Create a certificate on the server. A test key pair can be created
-- using the MakeCert tool that ships with the .NET Framework SDK.
CREATE CERTIFICATE SysProcCert FROM FILE = 'e:\programming\testCert.cer'
go

-- Create a login and map it to the certificate.
CREATE LOGIN login_SysProcCert FROM CERTIFICATE SysProcCert
Go

-- Revoke the connect permission.
REVOKE CONNECT SQL FROM login_SysProcCert ;
go 
 
-- Grant the certificate, through the login, permission to select from sys.sysprocesses view.
GRANT VIEW SERVER STATE TO login_SysProcCert
go

-- Create a test login.
CREATE LOGIN bob WITH PASSWORD = '<enterStrongPasswordHere>'
go

-- Connect to the test database.
use db_Demo
go

-- Create the master key for the test database (used to protect 
-- private keys and certificates in the database).
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>' 

-- Create a certificate from a private key.
CREATE CERTIFICATE SysProcCert FROM FILE = 'e:\programming\testCert.cer'
WITH PRIVATE KEY
(FILE = 'e:\programming\testCert.pvk', 
 DECRYPTION BY PASSWORD= '<enterStrongPasswordHere>', 
 ENCRYPTION BY PASSWORD='<enterStrongPasswordHere>')
go 

-- Create the assembly on the server. The assembly DLL must be signed.
CREATE ASSEMBLY SysStoredProcedures
FROM 'E:\programming\SysStoredProcs.dll'
WITH PERMISSION_SET = SAFE
go 

-- Create the managed stored procedure on the server.
CREATE PROCEDURE usp_sysprocesses
AS EXTERNAL NAME SysStoredProcedures.StoredProcedures.usp_sysprocesses
go 

-- Add the signature to the stored procedure.
ADD SIGNATURE TO [dbo].[usp_sysprocesses] 
BY CERTIFICATE SysProcCert WITH PASSWORD = '<enterStrongPasswordHere>'
go 

-- Create a role.
CREATE ROLE SysProcRole
go

-- Create a test user
CREATE USER bob
go

-- Add the test user to the role.
EXEC sp_addrolemember 'SysProcRole', 'bob'
go

-- Grant execute permissions on the stored procedure to the new role.
GRANT EXECUTE ON [dbo].[usp_sysprocesses] TO SysProcRole
go
 
-- Connect as the test user.
EXECUTE AS LOGIN = 'bob'
use db_Demo
go
 
-- User only has permission to see their own processes.
SELECT * FROM sys.sysprocesses
go

-- Execute the stored procedure, which has been signed.
exec usp_sysprocesses
go

-- REVERT
REVERT
----------------------------------------------------------------------
-- Cleanup

use db_Demo
go

use master
go

DROP DATABASE db_Demo
go 

DROP login login_SysProcCert
DROP login bob
go

DROP CERTIFICATE SysProcCert
go

Di seguito è riportato il codice sorgente per la stored procedure usp_sysprocesses che esegue un'istruzione SELECT * nella vista sys.sysprocesses. Dopo la creazione, è necessario firmare l'assembly.

C#

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void usp_sysprocesses()
{
    using(SqlConnection connection = new SqlConnection("context connection=true"))
    {
        connection.Open();
        SqlCommand command = new SqlCommand("SELECT * FROM sys.sysprocesses", connection);
        SqlContext.Pipe.ExecuteAndSend(command);
    }
}
};

Visual Basic

Imports System
Imports System.Data.SqlClient
Imports Microsoft.SqlServer.Server

Partial Public Class StoredProcedures
<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub  usp_sysprocesses ()
    Using connection As New SqlConnection("context connection=true")
        connection.Open()

        Dim command As New SqlCommand("SELECT * FROM sys.sysprocesses", connection)
        SqlContext.Pipe.ExecuteAndSend(command)
    End Using
End Sub
End Class