Sybase ASE, gestion de la sécurité avec les vues inter-bases (cross database)

Introduction

Sybase ASE possède un mécanisme de gestion des autorisations d'accès aux objets en cascade à la fois strict et souple.

  • Strict car le propriétaire de chaque objet définit explicitement les permissions qu'il souhaite accorder.
  • Souple car la cascade permet de gérer la sécurité d'accès via des vues ou procédures de manière simple, y compris sur des objets situés sur des bases différentes.

Autrement dit, un utilisateur peut se voir attribuer des permissions d'accès à une vue ou une procédure sans pour autant détenir les autorisations sur les objets sous-jacents.

Néanmoins, dans le cadre particulier de liens inter-bases (ou cross database en anglais) , cet 'ownership chain' doit être défini de manière précise.

Cross database : les règles

Le chaînage de droits fonctionne selon les 3 règles suivantes :

  1. Les droits sont contrôlés sur l'objet parent.
  2. Le user appelant la vue doit être un utilisateur de ou des bases référencées dans la vue.
  3. Les droits sont contrôlés à chaque fois qu'un objet sous-jacent a un propriétaire différent de l'objet courant.

Cas pratique

Soit la situation suivante dans laquelle deux bases sont impliquées, chaque base ayant un propriétaire (dbowner) différent. Dans l'une on crée une table, dans l'autre on crée une vue référençant les données de cette table.

schema cross database

Les bases de données base1 et base2 ont pour proriétaire respectif base1_dbo et base2_dbo

Dans la base base2 est créée une table, table qu'un utilisateur de la base base1 (user: base1_usr) va interroger.

Connexion base1 base2
base2_dbo
create table t2 (a int) 
go
insert t2 values (1) 
insert t2 values (2) 
insert t2 values (3) 
go
Le propriétaire de la table t2 dans la base base2 est 'dbo', soit base2_dbo.
Connexion base1 base2
base1_dbo
create view v1 
as 
select a 
from base2.dbo.t2
where a >= 2
go
Le propriétaire de la vue v1 dans la base base1 est dbo, soit base1_dbo.
Connexion base1 base2
base1_usr
select a 
from v1
go
SELECT permission denied
on object v1, 
database base1, 
owner dbo.
Erreur 'normale', la règle n°1 n'est pas respectée
Connexion base1 base2
base1_dbo
grant select on v1 
to base1_usr
Attribution des droits sur la vue v1 au compte base1_usr, il s'agit ici d'une définition de sécurité standard
Connexion base1 base2
base1_usr
select a 
from v1
go
Server user id 14 
is not a valid user 
in database 'base2'
Erreur 'normale', la règle n°2 n'est pas respectée
Connexion base1 base2
base2_dbo
exec sp_adduser base1_usr
Le compte base1_usr est ajoutée dans la base base2. Le propriétaire garantit ainsi l'accès aux données de sa base.
Connexion base1 base2
base1_usr
select a 
from v1
go
SELECT permission denied 
on object t2, 
database base2, 
owner dbo
Normal, la règle n° 3 n'est pas respectée (la vue v1 a pour propriétaire base1_dbo, et la table t2, objet sous-jacent est détenu par base2_dbo, donc lors du contrôle : le compte base1_usr n'a pas d'autorisation sur la table t2
Connexion base1 base2
base2_dbo
grant select 
on t2
to base1_usr
Attribution des permissions sur la table t2 au compte base1_usr
Connexion base1 base2
base2_usr
select a 
from v1
go

a
--
2
3
=> OK

La situation est certes réglée d'un point de vue fonctionnel, mais une faille de sécurité est désormais ouverte : l'utilisateur base1_usr dispose d'un accès direct sur la table t2 de la base2. Cette situation n'est pas souhaitable pour le contrôle d'accès à la donnée.

Les données doivent certes être accessibles, mais sous contrôle des définitions et règles de gestion mises en place à travers la vue ou la procédure.

Connexion base1 base2
base1_usr
select a from t2
go

a
--
1
2
3
=> l'utilisateur voit TOUTES les données de la table, contournant ainsi le filtre sur la vue

À noter que si les deux bases ont le même propriétaire (dbowner), naturellement la règle 3 ne s'applique pas et la gestion du cross database n'est en rien différente d'une gestion de droits en cascade classique.

La règle 3 indique que le contrôle de sécurité est réalisé à chaque changement de propriétaire d'objet. Il faut donc faire en sorte d'éviter ce contrôle en autorisant l'un des dbo à créer un objet dans la base partenaire.

Connexion base1 base2
base2_dbo
revoke select 
on t2 to base1_usr
Suppression des permissions accordées à l'utilisateur base1_usr
Connexion base1 base2
base1_dbo
exec sp_adduser base2_dbo
go

grant create view 
to base2_dbo
go
Autorisation du propriétaire base2_dbo de la base partenaire à venir présenter ses données dans la base base1
Connexion base1 base2
base2_dbo
create view v2
as
select a 
from base2.dbo.t2
where a >=2
go

grant select 
on v2 
to base1_usr
go
Une vue v2 est créée dans la base base1, ayant comme propriétaire non pas dbo mais base2_dbo. Le droit SELECT est donné au compte base1_usr sur la vue v2.
Connexion base1 base2
base1_usr
select a
from base2_dbo.v2
go

a
--
2
3
Le chaînage et les permissions sont donc maitrisés : entre base2_dbo.v2 et t2, le propriétaire ne change pas, donc pas de contrôle. Le contrôle est réalisé en amont, dans la base base1, sur la vue v2.
Connexion base1 base2
base1_usr
select a 
from t2
go
SELECT permission denied on
object t2, 
database base2, 
owner dbo
L'accès aux données est ainsi sécurisé, l'utilisateur base1_usr n'a plus la possibilité de requêter directement la table t2.
Connexion base1 base2
base1_dbo
create view v3
as
select a
from base2_dbo.v2
go
Pour ceux que la notation de type Oracle ( schéma.objet ) rebute ou déroute, Il est possible de définir un synonyme (une vue) sans impact sur les performances sinon à la compilation
Connexion base1 base2
base1_usr
select a
from v3
go

a
--
2
3

Remarques

Elément notable, si c'est le compte 'sa' qui compile le vue v3, alors les droits chaînés sont accordés de manière implicite :

create view v3 as select * from base2_dbo.t2
go

grant select on v4 to base1_usr
go

Dans ce contexte, base1_usr devra certes être créé en tant que user dans la base2, mais il n'est pas nécessaire d'autoriser le dbo partenaire à créer des objets locaux.

La table système sysobjects indique dans quel contexte a été compilée une vue :

select isnull(loginame,'dbo') + '.' + name from sysobjects where type ='V';
-------------
dbo.v1
base2_dbo.v2
dbo.v3
sa.v4