4

Est-il possible de crypter toutes les procédures stockées existantes d'une base de données SQL Server 2008 APRÈS avoir été créées via un script SQLCMD? Je veux développer les procédures stockées sans cryptage afin que je puisse facilement cliquer sur "Modifier" dans SQL Server Management Studio pour vérifier leur contenu.
Cependant, pour le déploiement je voudrais les crypter donc j'ai pensé que peut-être je pourrais écrire un script qui les crypte seulement après leur création. Pour les systèmes de développement, je n'exécuterais tout simplement pas le script alors que sur les systèmes d'utilisateurs finaux, le script serait exécuté.Comment crypter toutes les procédures stockées existantes d'une base de données

Répondre

3

J'ai le même problème.

Ma solution est de mettre "- WITH ENCRYPTION" dans toutes mes procédures stockées. Cette version est utilisée par les développeurs et stockée dans le contrôle de source. Puis j'utilise un outil (comme sed) dans ma construction pour remplacer "- WITH ENCRYPTION" par "WITH ENCRYPTION" sur les fichiers avant de les envoyer pour être installés.

Pour une solution SQL pure, vous pouvez utiliser REPLACE.

+0

Nous faisons quelque chose de similaire, mais nous remplaçons également '-, ENCRYPTION', ce qui nous permet d'avoir des propriétés additionnelles WITH, telles que' WITH SCHEMABINDING -, ENCRYPTION' – Kristen

1

WITH ENCRYPTION signifie que le code derrière la proc n'est pas stocké dans la table SysComments.

Vous pouvez écrire un script qui fait un exec sp_helptext 'MyProcName' et obtient le contenu dans un VARCHAR (MAX) il peut contenir plusieurs lignes/grandes procédures facilement et modifiy la procédure à partir de son état d'origine

CREATE MyProcName AS 

SELECT SecretColumns From TopSecretTable 

changement CREATE-ALTER et AS entouré d'espace ou une tabulation ou saut de ligne (bon endroit pour utiliser les expressions régulières) à WITH ENCRYPTION AS

ALTER MyProcName WITH ENCRYPTION AS 

SELECT SecretColumns From TopSecretTable 

Ceci cachera tout le code pour le proc stocké sur le serveur de production. Vous pouvez mettre ceci dans un LOOP ou un CURSOR (pas vraiment une opération basée sur un ensemble IMHO) pour tous les objets d'un type spécifique et/ou une convention de nommage que vous souhaitez crypter, et exécutez-le chaque fois que vous déployez.

+1

Il y a deux problèmes avec ceci. 1) Les paramètres de la procédure stockée vont entre les commandes ALTER/CREATE et WITH. 2) Les procédures stockées longues peuvent être stockées sur plusieurs lignes. –

+0

réponse aux commentaires modifiés –

+0

Merci pour les informations sur la table 'SysComments'. Je ne le savais pas. – RBT

1

Je vous recommande de créer le sproc dans une variable de chaîne multiligne, puis de l'insérer ou de le modifier à l'aide de sp_executesql. Le seul inconvénient gênant de cette approche est le doublement des guillemets simples pour les chaînes.

DECLARE @action varchar(max); 
SET @action = 'CREATE'; /* or "ALTER" */ 

DECLARE @withEncryption varchar(max); 
SET @withEncryption = ''; /* or "WITH ENCRYPTION" */ 

DECLARE @sql varchar(max); 
SET @sql = @action + ' PROCEDURE dbo.Something' 
    (
     .... 
    ) ' + @withEncryption + 
    ' AS 
    BEGIN 
     DECLARE @bob varchar(10); 
     SET @bob = ''Bob''; 
     .... 
    END; 
    '; 

EXEC sp_executesql @statement = @sql; 

[Notez les espaces autour des variables.]

Tous mes scripts utiliser cette méthode, qui fonctionne bien une fois que vous vous habituez à la citation chose doubler.

J'utilise également un fichier batch pour appeler le script, et des variables de ligne de commande en mode SQLCMD pour sélectionner différents comportements, ce qui le rend répétable et facile à tester.

4

Vous pourriez vouloir vérifier Encrypting all the Stored Procedures of a Database:

Si vous décidez que vous devez protéger votre SQL Stored procédures, et la pensée était une bonne chiffrer idée, TRÈS PRUDENT !!! Cryptage Les procédures stockées dans la base de données NE DEVRAIENT PAS être effectuées sans ayant des fichiers de sauvegarde ou une sorte de contrôle de source pour les procédures mémorisées. La raison pour laquelle je dis cela est parce que, une fois qu'ils sont cryptés, il n'y a pas de demi-tour. (Oui, il existe des outils tiers que va décrypter votre code, mais pourquoi passer par ce problème.)

Cette astuce est quelque chose que j'ai développé parce que mon entreprise devait héberger l'application sur un serveur différent, et nous étions préoccupés à propos de notre code étant compromis. Donc, pour livrer la base de données, nous avons décidé de crypter toutes les procédures stockées. Ayant écrit plus de cent procédures , je n'ai pas voulu ouvrir chaque procédure et coller 'WITH ENCRYPTION' dans chaque procédure stockée. (Pour ceux de vous qui ne savez pas crypter, reportez-vous à Comment puis-je protéger mon code de procédure stocké [^]). J'ai donc décidé de faire ma propre petite application C# qui a fait la même chose.

Cette application est une application de console faite en utilisant Visual Studio 2005 et SQL Server 2005. Les paramètres d'entrée sont nom de base de données, adresse du serveur, nom d'utilisateur de base de données et mot de passe. Une fois que vous êtes en mesure de fournir ces informations, vous êtes prêt à disposer toutes vos procédures stockées cryptées. J'ai mis le code de ma demande ici tel quel. Pour que ce code fonctionne, vous devez ajouter une référence "Microsft.SQlserver.SMO" à l'application, de sorte que les classes telles que "Database" et "StoredProcedure" soient accessibles.

BEFORE YOU DO THIS, TAKE A BACKUP!!!!!!! 
//Connect to the local, default instance of SQL Server. 
string DB = ""; 
ServerConnection objServerCOnnection = new ServerConnection(); 
objServerCOnnection.LoginSecure = false; 
Console.WriteLine("Enter name or IP Address of the Database Server."); 
objServerCOnnection.ServerInstance = Console.ReadLine(); 
Console.WriteLine("Enter name of the Database"); 
DB = Console.ReadLine(); 
Console.WriteLine("Enter user id"); 
objServerCOnnection.Login = Console.ReadLine(); 
Console.WriteLine("Enter Password"); 
objServerCOnnection.Password = Console.ReadLine(); 
Console.WriteLine(" "); 
Server srv = new Server(); 
try // Check to see if server connection details are ok. 
{ 
    srv = new Server(objServerCOnnection); 
    if (srv == null) 
    { 
     Console.WriteLine("Server details entered are wrong," 
     + " Please restart the application"); 
     Console.ReadLine(); 
     System.Environment.Exit(System.Environment.ExitCode); 
    } 
} 
catch 
{ 
    Console.WriteLine("Server details entered are wrong," 
     + " Please restart the application"); 
    Console.ReadLine(); 
    System.Environment.Exit(System.Environment.ExitCode); 
} 
Database db = new Database(); 
try // Check to see if database exists. 
{ 
    db = srv.Databases[DB]; 
    if (db == null) 
    { 
     Console.WriteLine("Database does not exist on the current server," 
     + " Please restart the application"); 
     Console.ReadLine(); 
     System.Environment.Exit(System.Environment.ExitCode); 
    } 
} 
catch 
{ 
    Console.WriteLine("Database does not exist on the current server," 
     + " Please restart the application"); 
    Console.ReadLine(); 
    System.Environment.Exit(System.Environment.ExitCode); 
} 
string allSP = ""; 

for (int i = 0; i < db.StoredProcedures.Count; i++) 
{ 
    //Define a StoredProcedure object variable by supplying the parent database 
    //and name arguments in the constructor. 
    StoredProcedure sp; 
    sp = new StoredProcedure(); 
    sp = db.StoredProcedures[i]; 
    if (!sp.IsSystemObject)// Exclude System stored procedures 
    { 
     if (!sp.IsEncrypted) // Exclude already encrypted stored procedures 
     { 
     string text = "";// = sp.TextBody; 
     sp.TextMode = false; 
     sp.IsEncrypted = true; 
     sp.TextMode = true; 
     sp.Alter(); 

     Console.WriteLine(sp.Name); // display name of the encrypted SP. 
     sp = null; 
     text = null; 
     } 
    } 
} 
+0

Ceci est un très bon extrait de code, merci beaucoup. Juste entrer dans SMO et l'aimer. Merci encore pour le partage. – MikeMalter

0

Utilisez cette requête qui Chiffrer toutes les procédures de base de données

CREATE TABLE #backup 
(
id BIGINT IDENTITY(1, 1), 
sptext NVARCHAR(MAX) NOT NULL, 
spname NVARCHAR(100) NOT NULL, 
encrypttext NVARCHAR(MAX) NULL, 
encryptstatus BIT NOT NULL 
DEFAULT (0) 
) 
DECLARE @sptexttable TABLE 
(
id BIGINT IDENTITY(1, 1), 
sptext NVARCHAR(MAX), 
spname NVARCHAR(100) 
) 
INSERT INTO @sptexttable (sptext, spname) 
SELECT [text], 
[name] 
FROM syscomments 
JOIN sysobjects ON syscomments.id = sysobjects.id 
AND sysobjects.xtype = 'p' 
DECLARE @sptext NVARCHAR(MAX) 
DECLARE @spname NVARCHAR(100) 
DECLARE @counter INT 
SET @counter = 1 
WHILE @counter <= (SELECT MAX(id) 
FROM @sptexttable 
) 
BEGIN 
BEGIN TRY 

INSERT INTO #backup (sptext, spname) 
SELECT sptext, 
spname 
FROM @sptexttable 
WHERE id = @counter 
END TRY 
BEGIN CATCH 
END CATCH 

IF NOT EXISTS (SELECT [name] 
FROM sysobjects 
WHERE [name] = 'ce_LastIndexOf' 
AND xtype = 'FN') 
BEGIN 


EXEC 
('CREATE FUNCTION ce_LastIndexOf 
(
@strValue VARCHAR(4000), 
@strChar VARCHAR(50) 
) 
RETURNS INT 
AS BEGIN 
DECLARE @index INT 


SET @index = 0 


WHILE CHARINDEX(@strChar, @strValue) > 0 
BEGIN 
SET @index = @index 
+ CASE WHEN CHARINDEX(@strChar, @strValue) > 1 
THEN (LEN(@strValue) - LEN(SUBSTRING(@strValue, 
CHARINDEX(@strChar, @strValue) 
+ LEN(@strChar), 
LEN(@strValue)))) 
ELSE 1 
END 
SET @strValue = SUBSTRING(@strValue, 
CHARINDEX(@strChar, @strValue) 
+ LEN(@strChar), LEN(@strValue)) 
END 
RETURN @index 
END' 
) 


END 
DECLARE @tempproc NVARCHAR(MAX) 
DECLARE @procindex INT 
DECLARE @beginindex INT 
DECLARE @header NVARCHAR(MAX) 
DECLARE @asindex INT 
DECLARE @replacetext NVARCHAR(MAX) 

SET @tempproc = (SELECT sptext 
FROM @sptexttable 
WHERE id = @counter 
) 

IF (SELECT CHARINDEX('CREATE PROC', UPPER(@tempproc)) 
) > 0 
BEGIN 
BEGIN TRY 
SELECT @procindex = CHARINDEX('PROC', UPPER(@tempproc)) 
PRINT @procindex 
SELECT @beginindex = CHARINDEX('BEGIN', UPPER(@tempproc)) 
PRINT @beginindex 
SELECT @header = SUBSTRING(@tempproc, @procindex, 
@beginindex - @procindex) 
SELECT @asindex = (SELECT dbo.ce_lastindexof(@header, 'AS') 
- 2 
) 
SELECT @replacetext = STUFF(@header, @asindex, 10, 
CHAR(13) + 'WITH ENCRYPTION' 
+ CHAR(13) + 'AS' + CHAR(13)) 
SET @tempproc = REPLACE(@tempproc, @header, @replacetext) 

END TRY 
BEGIN CATCH 
END CATCH 
END 

UPDATE @sptexttable 
SET sptext = @tempproc 
WHERE id = @counter 


--PLAY HERE TO M AKE SURE ALL PROCS ARE ALTERED 
UPDATE @sptexttable 
SET sptext = (SELECT REPLACE(sptext, 'CREATE PROC', 
'ALTER PROC') 
FROM @sptexttable 
WHERE id = @counter 
) 
WHERE id = @counter 
SELECT @sptext = sptext, 
@spname = spname 
FROM @sptexttable 
WHERE id = @counter 
BEGIN TRY 
EXEC (@sptext 
) 
UPDATE #backup 
SET encrypttext = @sptext, 
encryptstatus = 1 
WHERE id = @counter 
END TRY 
BEGIN CATCH 
PRINT 'the stored procedure ' + @spname 
+ ' cannot be encrypted automatically' 
END CATCH 
SET @counter = @counter + 1 
END 
SELECT * 
FROM #backup 
0

j'ai écrit un curseur, par étapes et Crypte la plupart des objets.

      DECLARE cur_ENCRYPT_ANTHING CURSOR READ_ONLY 
          FOR 
            SELECT STUFF(src.definition, 
                CASE WHEN CHARINDEX('AS' + CHAR(13),src.definition,1) = 0 
                 THEN CASE WHEN CHARINDEX('AS ' + CHAR(13),src.definition,1) = 0 THEN CHARINDEX('AS ',src.definition,1) 
                   ELSE CHARINDEX('AS ' + CHAR(13),src.definition,1) 
                  END 
                 ELSE CHARINDEX('AS' + CHAR(13),src.definition,1) 
                END,3,'WITH ENCRYPTION AS' + CHAR(13)) 
            FROM (SELECT o.name 
              ,  STUFF(RIGHT(sm.definition,LEN(sm.definition) - CHARINDEX('CREATE ',sm.definition,1) + 1),1,6,'ALTER') AS definition 
              FROM sys.sql_modules AS sm 
                JOIN sys.objects AS o ON sm.object_id = o.object_id 
              WHERE CAST(CASE WHEN sm.definition IS NULL THEN 1 
                   ELSE 0 
                 END AS BIT) = 0 
                AND type <> 'TR' 
              ) AS src 








          DECLARE @VLS NVARCHAR(MAX) 
          OPEN cur_ENCRYPT_ANTHING 

          FETCH NEXT FROM cur_ENCRYPT_ANTHING INTO @VLS 
          WHILE (@@fetch_status <> -1) 
            BEGIN 
             IF (@@fetch_status <> -2) 
              BEGIN 
               BEGIN TRY 
                 EXEC (@VLS) 

               END TRY 
               BEGIN CATCH 
                 PRINT ERROR_MESSAGE() 
                 PRINT '' 

                 PRINT @VLS 
               END CATCH 
              END 
             FETCH NEXT FROM cur_ENCRYPT_ANTHING INTO @VLS 
            END 

          CLOSE cur_ENCRYPT_ANTHING 
          DEALLOCATE cur_ENCRYPT_ANTHING 
Questions connexes