Question

Y at-il possibilité de chiffrer toutes les procédures existantes stockées d'une base de données SQL Server 2008 après qu'ils ont été créés par un script SQLCMD?

La raison pour laquelle je veux faire est la suivante:
Je voudrais 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 chiffrer, donc je pensais que peut-être que je pourrais écrire un script qui les encrypte seulement après leur création. Pour les systèmes de dev je simplement n'exécuter le script alors que sur les systèmes utilisateur final le script sera exécuté.

Était-ce utile?

La solution

J'ai le même problème.

Ma solution est de mettre « - AVEC CRYPTAGE » dans toutes mes procédures stockées. Cette version est utilisée par les développeurs et stockés dans le contrôle source.

Je puis utiliser un outil (comme sed) dans ma construction pour remplacer « - AVEC CRYPTAGE ». Avec « WITH ENCRYPTION » sur les fichiers avant de les envoyer à installer

Pour une solution pure SQL, vous pouvez utiliser REPLACE.

Autres conseils

Vous pouvez consulter Encrypting toutes les procédures stockées d'une base de données :

  

Si vous décidez que vous devez protéger votre SQL Stored   Procédures, et la pensée encryptage était une bonne idée, être très prudent !!!   Base de données des procédures stockées Crypter les NE DOIVENT PAS se faire sans   ayant des fichiers de sauvegarde ou une sorte de contrôle de code source pour le stockées   procédures. La raison pour laquelle je dis cela parce que, une fois qu'ils sont cryptés,   il n'y a pas tournant autour. (Oui, il existe des outils tiers qui   déchiffrera votre code, mais pourquoi passer par ce problème.)

     

Cette astuce est quelque chose que je développé parce que mon entreprise avait besoin pour héberger l'application sur un serveur différent, et nous étions concernés   notre code étant compromise. Donc, pour livrer la base de données, nous   a décidé de chiffrer toutes les procédures stockées. Avoir plus d'une centaine   procédures écrites, je ne voulais pas ouvrir chaque procédure et coller   « AVEC CRYPTAGE » dans chaque procédure stockée. (Pour ceux   vous qui ne savent pas comment chiffrer, reportez-vous Comment puis-je protéger mon Stored   Code de procédure [^]). J'ai donc décidé de faire mon propre petit C # application   qui fait la même chose.

     

Cette application est une application console faite   en utilisant Visual Studio 2005 et SQL Server 2005. Les paramètres d'entrée sont   nom de base de données, l'adresse du serveur, nom d'utilisateur et mot de passe de la base de données. Une fois que   vous êtes en mesure de fournir ces détails, vous êtes prêt à avoir tous vos   procédures stockées cryptées.

     

J'ai mis le code de ma demande   ici est. Pour que ce code fonctionne, vous devrez ajouter un   « Microsft.SQlserver.SMO » refrence à l'application, de sorte que la   classes telles que "base de données" et "StoredProcedure" sont 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;
      }
   }
}

WITH ENCRYPTION signifie que le code derrière le proc ne sont pas stockées 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 des procédures multilignes / grandes 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

Cela permet de masquer tout le code pour la procédure stockée sur le serveur de production.

Vous pouvez mettre ceci dans un LOOP ou un CURSOR (pas vraiment une IMHO opération à base de jeu) pour tous les objets d'un type particulier et / ou convention de nommage que vous souhaitez chiffrer, et l'exécuter à chaque fois que vous déployez.

Je recommande la création de la procédure stockée dans une variable de chaîne multi-ligne, puis d'insérer ou de modifier à l'aide sp_executesql. Le seul inconvénient gênant de cette approche est 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 aussi un fichier batch pour appeler le script et les variables de ligne de commande SQLCMD-mode pour sélectionner divers comportements, ce qui le rend reproductible et facile à tester.

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

J'ai écrit un curseur, par étapes et encrypte 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

1) exporter Créer un code pour SP et les fonctions. Gardez-le sauvegardé. par exemple D: \ SP2.sql "

2) ce transact code SQL, générer le script existant supprimer sP et fonctions

SELECT 'DROP PROCEDURE  [' + SCHEMA_NAME(p.schema_id) + '].[' + p.NAME + ']'  as A
FROM sys.procedures p
union
SELECT  'DROP FUNCTION ' + [name]  
FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0
order by a

3) Ce code Poweshell remplacer

AS
BEGIN

par

WITH ENCRYPTION 
AS
BEGIN

Le code

$File = "D:\SP2.sql"
$File2 = $File.Replace("SP2.sql","SP-WithEncrypt.sql")
$sortie=""
$SP = get-content -path $file
echo $SP.Count
For ($i = 0 ; $i -le $SP.Count)
{ if ($sp[$i] -eq "AS" -and $sp[$i+1] -eq "BEGIN")
   { $AEcrire = "`nWITH ENCRYPTION `n AS `n BEGIN"
   $i+=1 
          }
   else
   {$AEcrire =$sp[$i]
   }
   $sortie += "`n$AEcrire"

 $i+=1 
 $SP.Count-$i
}

$sortie| out-file $File2

Ce serait plus rapide avec un .replace (,), mais le problème avec la fin des lignes ...

4) exécuter le SP-WithEncrypt.sql dans SSMS

Je l'ai fait une mise à jour à l'une des réponses ci-dessus en supprimant la dépendance à la première balise de début. J'ai eu une situation où pas toutes mes procédures stockées avaient BEGIN et END.

I utilisé à la place de la clause AS et également utilisé un cas la version sensible du charindex (en ajoutant une collation)

Son pas une solution parfaite, mais aidé à obtenir plus de mes procédures stockées cryptées.

Voici mon code mis à jour:

            IF OBJECT_ID('tempdb..#backup', 'U') IS NOT NULL 

             BEGIN

             DROP TABLE #backup

             END

            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] = 'CaseSensitiveIndex'

             AND xtype = 'FN' ) 

             BEGIN
                

             EXEC (
             'CREATE FUNCTION dbo.CaseSensitiveIndex(@source nvarchar(max), @pattern VARCHAR(50))
            RETURNS int
            BEGIN  
                return   CHARINDEX(@pattern COLLATE Latin1_General_CS_AS, @source COLLATE Latin1_General_CS_AS) 
            END; '
            )
            end


             IF NOT EXISTS ( SELECT [name]

             FROM sysobjects

             WHERE [name] = 'ce_LastIndexOf'

             AND xtype = 'FN' ) 

             BEGIN

                

             EXEC

             ( 'CREATE FUNCTION ce_LastIndexOf 

                (@strValue VARCHAR(max),

                @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=(select dbo.CaseSensitiveIndex(@tempproc, 'AS'))


             if(@beginindex=0) begin set @beginindex=( SELECT dbo.ce_lastindexof(@tempproc, 'AS'))end
             SELECT @header = SUBSTRING(@tempproc, @procindex,

             @beginindex )

             SELECT @asindex = ( SELECT dbo.ce_lastindexof(@header, 'AS')

             - 2

             )

             SELECT @replacetext = STUFF(@header, @asindex, 3,

             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 MAKE 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 where encryptstatus =0
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top