Aller au contenu principal

Sécurité

La sécurité dans SQL Server repose sur un ensemble de mécanismes visant à protéger les données contre tout accès non autorisé, manipulation indésirable ou fuite d’information. Elle s’appuie principalement sur une gestion fine des connexions (logins), des utilisateurs internes aux bases, des rôles, ainsi que des permissions explicites (GRANT, DENY, REVOKE) accordées sur les objets comme les tables, vues ou procédures. SQL Server permet ainsi d’assurer une séparation des responsabilités, un contrôle des accès et une traçabilité des actions. Une bonne configuration de la sécurité est essentielle pour garantir la confidentialité, l’intégrité et la disponibilité des données dans un environnement multi-utilisateurs.

Prérequis

Dans ce laboratoire, nous allons utiliser une base de données préfaite par Microsoft: AdventureWorks. Pour vous faciliter le travail, nous allons construire une image custom basée sur celle de Microsoft. Téléchargez ce fichier zip, décompressez-le et ouvrez un terminal dans le dossier. Exécutez la commande suivante:

docker build -t adventureworks .

Le build prendra un peu de temps, car Docker va charger le fichier de sauvegarde mis à disposition par Microsoft.

Ensuite, exécutez la commande suivante:

docker run -p 1433:1433 -m 2G adventureworks

La base de données reste accessible avec les mêmes informations qu'auparavant:

  • Adresse : localhost
  • Port : 1433
  • Utilisateur : sa
  • Mot de passe : Password1

Utilisateur

Quand nous créons un utilisateur, nous pouvons le lier à un login pour qu'il puisse se connecter. Pourquoi avoir séparé les deux options ? Après tout, qui veut créer un utilisateur et ne pas pouvoir l'utiliser ? En réalité, les préoccupations ne sont pas les mêmes:

  • Un utilisateur va nous servir à définir les actions qui lui seront autorisées
  • Un login représente un moyen de connexion (mais il en existe d'autres)

C'est pour cette raison qu'il y a une séparation entre les 2. On pourrait imaginer qu'on voudrait avoir un utilisateur X qui se connecte avec sa machine Windows (et donc plus via un login). En plus, en cas de problème de fuites de données, il suffit de révoquer le login pour bloquer l'accès à la personne suspecte.

Il nous suffit d'exécuter les commandes suivantes:

database: AdventureWorks 2022
CREATE LOGIN "Sacha" WITH PASSWORD = 'Password1';
CREATE USER "Sacha" FOR LOGIN "Sacha";

Pour voir si tout fonctionne, vous pouvez ouvrir une nouvelle connexion à la base de données avec cet utilisateur:

Si vous désirez voir les logins et/ou utilisateurs, il vous suffit d'exécuter ceci:

-- Pour les logins
SELECT * FROM sys.sql_logins;
-- Pour les utilisateurs
SELECT * FROM sys.server_principals;

Exercice

  • Créez un utilsateur Jean avec le login Jean. Donnez-lui le mot de passe suivant: Password42

Sources:


Autorisations

Si vous avez essayé d'utiliser ce nouvel utilisateur, vous avez dû remarquer ceci:

Nous ne pouvons pas voir les tables de notre base de données...

Le problème vient des autorisations et en particulier celle qui permet de voir les bases de données. Nous allons donc rajouter cette autorisation à notre utilisateur.

database: AdventureWorks2022
GRANT SELECT ON Database::AdventureWorks2022 TO "Sacha";

Nous allons décortiquer l'instruction GRANT:

  • GRANT permet de donner une autorisation
  • SELECT est l'autorisation (ici, le fait de pouvoir sélectionner)
  • ON ... permet d'indiquer la cible
  • TO l'entité qui reçoit l'autorisation

Maintenant, nous pouvons voir les tables avec notre utilisateur ! Hourra !

Nous allons maintenant essayer de rajouter une ligne dans la table PhoneNumberType:

INSERT INTO Person.PhoneNumberType (Name, ModifiedDate) VALUES ('Satelitte', GETDATE());

Suprise ! Même problème !

En réalité, ce n'est pas si étonnant. Nous avons juste donné les accès pour un SELECT sur la base de données. Nous n'avons pas donné d'autorisation pour un INSERT.

GRANT INSERT ON Person.PhoneNumberType To "Sacha";
remarque

Vous avez sûrement l'habitude d'utiliser uniquement le nom d'une table dans une requête. Cependant, vous voyez qu'on a rajouté Person. devant PhoneNumberType. Person est un schéma de base de données et peut-être vu comme une sorte de dossier. C'est pour cette raison qu'il est nécessaire de préciser Person. pour donner le "chemin d'accès" complet.

Si vous testez à nouveau, vous verrez maintenant qu'on a la possibilité d'ajouter une ligne.

Parfait ! Tout est bon ? Pas exactement... Vous vous rendez bien compte que la tâche risque d'être trèèèèès longue si on souhaitait donner l'accès à toutes les tables. N'oubliez pas que nous avons travaillé par autorisation et par table. Enfin, pas tout à fait... Souvenez-vous de l'autorisation SELECT: en l'attribuant à la base de données, nous avons eu la possibilité de consulter les tables. Il y a un effet "d'écoulement" qui fait qu'une autorisation pour une base de données s'applique aux schémas, puis des schémas aux tables, etc.

Pour nous faciliter la vie, nous allons supposer que Sacha est une personne des ressources humaines. C'est pratique, car nous avons justement un schéma HumanRessources ! Nous allons donc attribuer à Sacha le droit d'effectuer les 4 opérations de base (SELECT, UPDATE, DELETE, INSERT) sur toutes les tables de ce schéma.

GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::HumanResources TO "Sacha";
remarque

Quand vous ajoutez WITH GRANT à la fin d'une autorisation, cela signifie que l'utilisateur pourra à son tour donner les mêmes autorsations à un autre utilisateur. Pratique pour déléguer le travail à des personnes de confiance. À éviter si vous n'êtes pas certain à 100% de ce que vous faites.

Si vous essayez de mettre à jour une ligne d'une table de ce schéma, tout devrait fonctionner !

UPDATE HumanResources.Employee SET CurrentFlag = 0 WHERE BusinessEntityID = 1;

Dernière chose avec les autorisations: la résolution de conflit. Imaginez que Sacha puisse faire les 4 opérations sur les tables, mais qu'on lui interdit de modifier la table Employee. Que se passe-t-il ? Testons pour vérifier:

DENY UPDATE, INSERT, DELETE ON HumanResources.Employee TO "Sacha";

Si nous essayons de remettre l'ancienne valeur de notre employé via cette commande:

UPDATE HumanResources.Employee SET CurrentFlag = 1 WHERE BusinessEntityID = 1;

Nous voyons directement une erreur.

La résolution des autorisations commence du niveau le plus haut (base de données), puis descend dans la hiérarchie.

  • Si aucun DENY ou GRANT: alors, on descend dans la hiérarchie.
  • Si on rencontre un GRANT: alors, l'utilisateur obtient une autorisation MAIS on continue de descendre dans la hiérarchie
  • Si on rencontre un DENY: alors, l'utilisateur ne peut pas exécuter son opération ET on ne descend pas plus bas dans la hiérarchie
  • Si on est au bout de la hiérarchie: alors, si l'utilisateur a une autorisation, il pourra exécuter son action. Dans le cas contraire, il ne pourra pas.
attention

Attention ! Il ne faut pas confondre DENY avec REVOKE ! En effet, REVOKE revient juste à retirer un DENY ou un GRANT de la liste des permissions. Tandis que le DENY est une interdiction.

Par exemple, imaginons que vous êtes un reporter et vous êtes invités à la Maison Blanche. Vous recevez une accréditation presse à l'entrée, cela revient à vous appliquer un GRANT. Une fois la conférence terminée, vous remettez votre accréditation. Cela revient à un REVOKE. Le DENY serait l'équivalent de vous mettre sur la liste noire. Même avec une accréditation, vous ne pourriez pas passer.

Pour vous aider, voici un schéma d'état pour une permission:


Sources:


Exercice

Tout d'abord, créez le login et le user associé:

CREATE LOGIN AppUser1 
WITH PASSWORD = 'AppUser@2025';

CREATE USER User1 FOR LOGIN AppUser1;
  • Autorisez l'utilisateur User1 à lire la table Person.Person.
  • Autorisez User1 à insérer des lignes dans Person.EmailAddress.
  • Interdisez à User1 la suppression dans HumanResources.Department.
  • Supprimez la permission INSERT précédemment accordée sur Person.EmailAddress.
  • Accordez à l’utilisateur User1 la permission de lecture sur la table Production.Product, avec la possibilité de déléguer cette permission à d’autres utilisateurs.

Pour vérifier si les permissions sont bonnes, vous pouvez utiliser cette requête SQL:

SELECT 
class_desc,
major_id AS object_id,
USER_NAME(grantee_principal_id) AS user_name,
permission_name,
state_desc
FROM sys.database_permissions
WHERE grantee_principal_id = USER_ID('User1');

Roles

Tout d'abord, supprimons les droits de Sacha.

REVOKE UPDATE, INSERT, DELETE ON HumanResources.Employee TO "Sacha";
REVOKE SELECT, INSERT, UPDATE, DELETE ON SCHEMA::HumanResources TO "Sacha";

Maintenant, vous gérez les autorisations comme des chefs ! Mais vous dites que si vous avez une armée de RH, vous risquez de passer des jours à faire les requêtes et vérifier que tout est bon. La solution serait d'appliquer une série de règles à un groupe et ensuite d'associer nos RH à ce groupe.

Figurez-vous que les développeurs ont pensé exactement à ce scénario et ont créé les rôles ! Si vous êtes familiers du système Linux, vous ne serez pas perdus. On y retrouve le même pattern: un utilisateur peut appartenir à un ou plusieurs groupes.

Dans un premier temps, nous allons créer un rôle pour nos RH:

CREATE ROLE RH AUTHORIZATION db_owner;
remarque

AUTHORIZATION permet d'indiquer le propriétaire du rôle. Dans notre cas, il s'agit d'un autre rôle db_owner (il s'agit d'un des rôles par défaut en SQL Server). Le propriétaire possède des droits sur l'entité, notamment celui de suppression.

Maintenant, il faut ajouter notre utilisateur à ce rôle:

ALTER ROLE RH ADD MEMBER Sacha;

Si notre utilisateur exécute cette instruction:

SELECT * FROM HumanResources.Employee;

Vous verrez qu'on récupère bien un résultat ! SQL Server vérifie bien les droits de l'utilisateur et de ses groupes !

La résolution de conflits suit exactement le même schéma qu'au point précédent. Testons avec les instructions suivantes:

GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Person TO Sacha; -- Sacha a le droit d'accéder au schéma Person
DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Person TO RH; -- Le groupe RH (dont Sacha fait parti) a interdiction de toucher au schéma Person

Si vous testez avec Sacha, vous verrez qu'il ne peut pas un faire un SELECT sur la table Person.Address.

Enfin, sachez qu'il existe des rôles par défaut en SQL Server, voici la liste:

Liste des rôles pour une base de données SQL Server:
RôleDescription
db_ownerLes membres du rôle de base de données fixe db_owner peuvent effectuer toutes les activités de configuration et de maintenance sur la base de données et peuvent également DROP la base de données dans SQL Server. (Dans SQL Database et Azure Synapse, certaines activités de maintenance nécessitent des autorisations au niveau du serveur et ne peuvent pas être effectuées par le rôle db_owners.)
db_securityadminLes membres du rôle de base de données fixe db_securityadmin peuvent modifier l'appartenance au rôle pour les rôles personnalisés uniquement et gérer les autorisations. Les membres de ce rôle peuvent potentiellement élever leurs privilèges et leurs actions doivent être supervisées.
db_accessadminLes membres du rôle de base de données fixe db_accessadmin peuvent ajouter ou supprimer l'accès à la base de données des connexions Windows, des groupes Windows et des comptes de connexion SQL Server.
db_backupoperatorLes membres du rôle de base de données fixe db_backupoperator peuvent sauvegarder la base de données.
db_ddladminLes membres du rôle de base de données fixe db_ddladmin peuvent exécuter n'importe quelle commande DDL (Data Definition Language) dans une base de données. Les membres de ce rôle peuvent potentiellement élever leurs privilèges en manipulant du code qui peut être exécuté avec des privilèges élevés et leurs actions doivent être surveillées.
db_datawriterLes membres du rôle de base de données fixe db_datawriter peuvent ajouter, supprimer et modifier des données dans toutes les tables utilisateur. Dans la plupart des cas d'usage, ce rôle est combiné avec db_datareader appartenance pour permettre la lecture des données à modifier.
db_datareaderLes membres du rôle de base de données fixe db_datareader peuvent lire toutes les données de toutes les tables et vues utilisateur. Les objets utilisateur peuvent exister dans n'importe quel schéma, sauf sys et INFORMATION_SCHEMA.
db_denydatawriterLes membres du rôle de base de données fixe db_denydatawriter ne peuvent ajouter, modifier ou supprimer aucune donnée des tables utilisateur d'une base de données.
db_denydatareaderLes membres du rôle de base de données fixe db_denydatareader ne peuvent lire aucune donnée des tables et vues utilisateur d'une base de données.

Source: https://learn.microsoft.com/fr-fr/sql/relational-databases/security/authentication-access/database-level-roles?view=sql-server-ver16

Exercice

  • Créez un rôle nommé ConsultationRH.
  • Autorisez le rôle ConsultationRH à lire toutes les tables du schéma HumanResources.
  • Ajoutez l'utilisateur UserEmp1 au rôle ConsultationRH.
  • Supprimez UserEmp1 du rôle ConsultationRH.
  • Supprimez le rôle ConsultationRH.
  • Supprimez UserEmp1 et Employe1.

Si vous voulez voir les rôles de UserEmp1, vous pouvez utiliser cette requête SQL:

SELECT 
rp.name AS RoleName,
mp.name AS MemberName
FROM
sys.database_role_members drm
JOIN sys.database_principals rp ON drm.role_principal_id = rp.principal_id
JOIN sys.database_principals mp ON drm.member_principal_id = mp.principal_id
WHERE mp.name = 'UserEmp1';

Source:


Vue

Vous allez voir, ce n'est pas la notion la plus compliquée du laboratoire !

Une vue est une "table virtuelle" sur laquelle on peut effectuer un SELECT. Elle est composée d'une requête qui sera exécutée pour récupérer les données. Il y a deux avantages:

  1. Une requête compliquée peut-être stockée dans la vue, ce qui peut faciliter les appels.
  2. Il s'agit d'une entité à part qui a droit à ses propres autorisations. On peut donc ainsi filtrer les données qu'un utilisateur peut voir

Par exemple, créons cette vue:

CREATE VIEW VuePersonne
AS
SELECT
P.BusinessEntityID,
P.FirstName,
P.LastName,
E.MaritalStatus,
E.Gender
FROM Person.Person as P
RIGHT JOIN HumanResources.Employee as E ON E.BusinessEntityID = P.BusinessEntityID;

GRANT SELECT, INSERT, UPDATE, DELETE ON VuePersonne TO Sacha; -- N'oubliez pas de donner l'accès

Notre Sache peut interroger la vue avec la simple instruction suivante:

SELECT * FROM VuePersonne;

Vous noterez que Sacha peut accéder à certaines colonnes de la table Person alors qu'il a reçu un DENY. Le DENY lui interdisait de faire un SELECT sur cette table. Mais c'est la vue qui a fait ce SELECT. C'est pour cette raison que les vues sont utilisées pour limiter l'accès à certaines colonnes pour un utilisateur ou un groupe.

Concernant les INSERT,UPDATE et DELETE: on peut les effectuer, mais sous certaines conditions:

Toutes les modifications, y compris UPDATE, INSERT et DELETE les instructions, doivent référencer des colonnes à partir d’une seule table de base. 1

Exercices

  1. Créez une vue nommée vw_EmployesActifs qui retourne :
    • BusinessEntityID, JobTitle, HireDate
    • Uniquement les employés dont EndDate est NULL (encore en poste)
  2. Affichez toutes les lignes de la vue vw_EmployesActifs
  3. Créez une vue vw_ProduitsCategories listant :
    • ProductID, Name (du produit), ProductSubcategoryID, SubcategoryName, CategoryName
    • En reliant les tables : Production.Product → Production.ProductSubcategory → Production.ProductCategory
  4. En vous basant sur la vue vw_ProduitsCategories, affichez les produits dont la CategoryName est 'Bikes'.
  5. Ajoutez la colonne Color à la vue vw_ProduitsCategories.
  6. Supprimez la vue vw_EmployesActifs.
  7. Créez un login Lecteur1 avec un utilisateur UserLecteur dans la base de données et accordez à UserLecteur le droit SELECT uniquement sur la vue vw_ProduitsCategories.

Sources:


Procédure

Maintenant, on va pouvoir attaquer la partie difficile du laboratoire !

Votre réaction:

Une procédure est une sorte de vue plus complexe, mais qui permet de faire plus de choses. Un des atouts majeurs est de pouvoir utiliser des paramètres.

Tout d'abord, voyons une procédure simple2:

CREATE PROCEDURE HumanResources.uspGetAllEmployees
AS
SET NOCOUNT ON;
SELECT LastName, FirstName, JobTitle, Department
FROM HumanResources.vEmployeeDepartment;
GO

Et pour utiliser cette procédure, nous pouvons faire (au choix):

EXECUTE HumanResources.uspGetAllEmployees;
GO
-- OU
EXEC HumanResources.uspGetAllEmployees;
GO
-- OU (mais doit être la première instruction si utilisée dans une série d'instructions)
HumanResources.uspGetAllEmployees;

Vous aurez automatiquement une erreur, car vous n'avez pas les autorisations nécessaires.

Cette fois-ci, il s'agit de l'autorisation EXECUTE:

GRANT EXECUTE ON Object::HumanResources.uspGetAllEmployees TO Sacha;

Mais quel est l'intérêt par rapport aux vues ? On pourrait faire exactement la même chose avec une vue. Les procédures nous permettent d'utiliser des paramètres contrairement aux vues !

CREATE OR ALTER PROCEDURE HumanResources.uspGetAllEmployees
@LastName NVARCHAR(50),
@FirstName NVARCHAR(50)
AS
SET NOCOUNT ON;
SELECT FirstName, LastName, JobTitle, Department
FROM HumanResources.vEmployeeDepartment
WHERE FirstName = @FirstName AND LastName = @LastName;
GO

Maintenant, pour utiliser cette procédure, vous devez lui passer des paramètres:

EXECUTE HumanResources.uspGetAllEmployees N'Ackerman', N'Pilar';
-- OU
EXEC HumanResources.uspGetAllEmployees @LastName = N'Ackerman', @FirstName = N'Pilar';
GO
-- OU
EXECUTE HumanResources.uspGetAllEmployees @FirstName = N'Pilar', @LastName = N'Ackerman';
GO
-- OU (mais doit être la première instruction si utilisée dans une série d'instructions)
HumanResources.uspGetAllEmployees N'Ackerman', N'Pilar';

Il y a également moyen de mettre des valeurs par défaut à nos paramètres:

CREATE PROCEDURE HumanResources.uspGetEmployees2
@LastName NVARCHAR(50) = N'D%',
@FirstName NVARCHAR(50) = N'%'
AS
SET NOCOUNT ON;
SELECT FirstName, LastName, JobTitle, Department
FROM HumanResources.vEmployeeDepartment
WHERE FirstName LIKE @FirstName AND LastName LIKE @LastName;

Si on ne précise rien pour le LastName, celui-ci prendra comme valeur D% (qui est un pattern utilisé pour LIKE).

Exercices

  1. Créez une procédure GetAllProducts qui affiche tous les produits de la table Production.Product.
  2. Exécutez la procédure créée ci-dessus.
  3. Créez une procédure GetProductsByColor qui prend un paramètre @Color et affichez les produits correspondants.
  4. Affichez les produits dont la couleur est 'Red'.
  5. Ajoutez une clause ORDER BY Name à la procédure GetProductsByColor (modifiez la procédure, ne la supprimez pas).
  6. Supprimez la procédure GetAllProducts.
  7. Créez un login ProcUser, user UserProc et donnez-lui uniquement le droit d'exécuter GetProductsByColor.

Sources:


Trigger

Un trigger est une procédure spéciale qui va s'enclencher suite à un évènement. Souvent, on voudra enclencher un trigger avant ou après une opération sur une table. Cette procédure peut permettre de vérifier des règles complexes ou bien modifier le comportement d'une action.

Prenons un exemple, un client d'une banque (table Client) souhaite ouvrir un prêt (table Pret). Mais pour cela, il doit avoir au moins 10.000 euros sur son compte (table Compte). Donc, on souhaite qu'une erreur soit levée au moment de l'insertion dans la table Pret si l'utilisateur a moins de 10.000 euros. On ne peut pas utiliser un CHECK, car la vérification concerne une autre table. La seule solution consiste à utiliser un trigger au moment de l'insertion de la ligne. Sachez qu'il y a pas mal de possibilités pour les évènements (INSERT, UPDATE, etc) et qu'il est possible d'enclencher le trigger avant ou apès l'évènement.

Un autre exemple pourrait être les factures. La législation oblige de garder les factures pendant 10 ans. On pourrait imaginer que la suppression d'une facture dans la table facture provoquerait une insertion dans une table facture_archive. Cette table aurait des caractéristiques propres comme aucun index.

Quand vous manipulez un DELETE, UPDATE ou INSERT, les triggers ont accès à deux tables spéciales: inserted et deleted. La première concerne les valeurs ajoutées: valeurs insérées grâce à un INSERT et nouvelles valeurs d'un UPDATE. La deuxième concerne les valeurs supprimées: valeurs supprimées suite à un DELETE et les anciennes valeurs d'un UDPATE.

Nous pourrions imaginer le trigger suivant (vérification qu'un produit n'est pas utilisé dans une commande):

CREATE TRIGGER trg_PreventProductDelete
ON Production.Product
INSTEAD OF DELETE
AS
BEGIN
IF EXISTS (
SELECT 1
FROM deleted d
JOIN Sales.SalesOrderDetail s ON d.ProductID = s.ProductID
)
BEGIN
RAISERROR('Impossible de supprimer un produit utilisé dans des commandes.', 16, 1);
ROLLBACK TRANSACTION;
END
ELSE
BEGIN
DELETE FROM Production.Product
WHERE ProductID IN (SELECT ProductID FROM deleted);
END
END;

Enfin, notez une chose importante: les triggers ne sont pas rétroactifs contrairement aux CHECK. Imaginons que nous créons une contrainte prix > 0 via un CHECK. Au moment de la création, la base de données va vérifier si les données de la table valident cette contrainte. Si un enregistrement ne respecte pas la contrainte, la création du CHECK sera refusée. Donc, si la création a réussi, cela signifie que toutes les données de la table respectent la contrainte.

Les triggers ne font pas cette vérification et seules les données après la création du trigger seront affectées par le trigger. Il n'y a donc aucun effet rétroactif.

Exercices

Créez le schéma suivant avec les tables associées:

IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Audit')
BEGIN
EXEC('CREATE SCHEMA Audit');
END;

CREATE TABLE Audit.SalesOrderAudit (
AuditID INT IDENTITY(1,1) PRIMARY KEY,
SalesOrderID INT NOT NULL,
OrderDate DATETIME NOT NULL,
CustomerID INT NOT NULL,
ModifiedDate DATETIME NOT NULL,
AuditTimestamp DATETIME DEFAULT GETDATE()
);

CREATE TABLE Audit.SalaryChangeLog (
LogID INT IDENTITY(1,1) PRIMARY KEY,
BusinessEntityID INT NOT NULL,
OldRate MONEY NOT NULL,
NewRate MONEY NOT NULL,
ChangeDate DATETIME NOT NULL,
LoggedAt DATETIME DEFAULT GETDATE()
);

CREATE TABLE Audit.AddressChangeLog (
LogID INT IDENTITY(1,1) PRIMARY KEY,
AddressID INT NOT NULL,
OldAddressLine1 NVARCHAR(60),
NewAddressLine1 NVARCHAR(60),
OldCity NVARCHAR(30),
NewCity NVARCHAR(30),
OldPostalCode NVARCHAR(15),
NewPostalCode NVARCHAR(15),
ChangeDate DATETIME NOT NULL DEFAULT GETDATE(),
ChangedBy SYSNAME NOT NULL DEFAULT SYSTEM_USER
);

Réalisez les triggers suivants:

  1. Enregistrez chaque nouvelle commande ajoutée.
  2. Tracez les modifications de salaire.
  3. Tracez les changements d'adresse.
Dorénavant, quand on vous parlera de triggers...

Sources:


Conclusion

Ce laboratoire constitue une introduction aux fondamentaux de la sécurité dans SQL Server. Il a permis d'aborder les éléments essentiels pour contrôler l'accès aux données: la création de logins et d'utilisateurs, la gestion des autorisations (GRANT, DENY, REVOKE), ainsi que l'utilisation des vues et des procédures stockées. Les triggers ont également été explorés comme mécanisme d'automatisation et de renforcement des règles métier. Ces concepts forment une base pour mettre en œuvre une stratégie de sécurité. Toutefois, la sécurité en SQL Server ne s'arrête pas là: il existe des fonctionnalités plus avancées telles que la sécurité au niveau des lignes (Row-Level Security), le chiffrement des données, ou encore l'audit des actions utilisateurs. Ces notions, plus poussées, permettent d'aller encore plus loin dans la protection des données, en particulier dans des environnements sensibles ou à hautes contraintes réglementaires.

Notes de bas de page

  1. Source: https://learn.microsoft.com/fr-fr/sql/t-sql/statements/create-view-transact-sql?view=sql-server-ver16#updatable-views

  2. Source: https://learn.microsoft.com/fr-fr/sql/t-sql/statements/create-procedure-transact-sql?view=sql-server-ver16#a-create-a-transact-sql-procedure