Modelli di controllo di accessi come tipi Haskell

By abell on 2009-10-11-20:53:48 | In haskell access control controllo accessi

Prendendo spunto dalla lettura di uno dei miei blog preferiti, mi è capitato di dare una scorsa al documento intitolato A Survey of Access Control Models, che descrive modelli di controllo di accessi di complessità crescente. Questa complessità crescente si manifesta nella dipendenza da fattori intermedi sempre più ricchi e mi è venuta la tentazione di esprimere queste dipendenze come signature di funzioni in Haskell. Ecco cosa ne è uscito fuori.

Per chi fosse digiuno di Haskell, basta sapere che:

data NuovoTipo = A | B | C
definisce un nuovo tipo che contiene solo i tre oggetti A, B e C. Ad esempio, il tipo Permission può essere definito così:
data Permission = Read | Write | Execute | Delete | Modify
Si possono definire type alias, ad esempio
type UserPermissions = [ ( User, [ Permission ] ) ]
definisce un tipo UserPermissions che consiste in liste ([ ... ]) di coppie con primo elemento uno User e secondo elemento una lista di Permission.

Un'espressione di questo tipo

funzione :: TipoPar1 -> TipoPar2 -> TipoPar3 -> TipoRisultato
è la type-signature di una funzione con parametri di tipo TipoPar1, TipoPar2, TipoPar3 e risultato di tipo TipoRisultato.

Per ogni modello, l'unica implementazione è quella della funzione getUserPerms che restituisce i permessi di un utente per una certa risorsa.

ACL (Access Control Lists)

Un modello molto semplice: i permessi dipendono solamente dall'utente e dalla risorsa.

data ACL = [ ( User, [ Permission ] ) ]
getResourceACL :: Resource -> ACL
getPerms :: ACL -> User -> [ Permission ]
getUserPerms :: User -> Resource -> [ Permission ]
getUserPerms user resource = getPerms ( getResourceACL resource ) user

L'associazione tra risorsa e ACL (la funzione getResourceACL) può essere implementata con metadati associati alla risorsa. Una possibile implementazione di getPerms consiste nel filtrare gli elementi dell'ACL che hanno l'utente di interesse e prendere poi i permessi corrispondenti, nel caso semplificato che le ACL siano implementate come array, come definito sopra.

getPerms :: ACL -> User -> [ Permission ]
getPerms acl user = map snd $ filter ( ( == user ) . fst ) acl

RBAC (Role-Based Access Control)

In questo modello, ad ogni utente sono associati ruoli e i permessi dipendono solo da questi ruoli (ad esempio con ACL applicate ai ruoli e non direttamente agli utenti).

getRoles :: User -> [ Role ]
getPerms :: [ Role ] -> Resource -> [ Permission ]
getUserPerms :: User -> Resource -> [ Permission ]
getUserPerms user resource = getPerms ( getRoles user ) resource

ABAC (Attribute-Based Access Control)

Il modello basato sugli attributi utilizza una struttura intermedia più ricca, basata su attributi che possono essere associati agli utenti (ad esempio area, qualifica, data di assunzione), alle risorse (ad esempio area, sensibilità dei dati) e all'ambiente.

data Attribute = Attribute AttrKey AttrValue
getUserAttrs :: User -> [ Attribute ]
getResourceAttrs :: Resource -> [ Attribute ]
getEnvironmentAttrs :: [ Attribute ]
getPerms :: [ Attribute ] -> [ Attribute ] -> [ Attribute ] -> Resource -> [ Permission ]
getUserPerms :: User -> Resource -> [ Permission ]
getUserPerms user resource = getPerms userAttrs resourceAttrs environmentAttrs resource
  where
    userAttrs = getUserAttrs user
    resourceAttrs = getResourceAttrs resource
    environmentAttrs = getEnvironmentAttrs

PBAC (Policy-Based Access Control)

In questo modello c'è un ulteriore elemento: la presenza di policy che entrano nel momento decisionale della concessione degli accessi.

data Attribute = Attribute AttrKey AttrValue
getUserAttrs :: User -> [ Attribute ]
getResourceAttrs :: Resource -> [ Attribute ]
getEnvironmentAttrs :: [ Attribute ]
getPerms :: [ Attribute ] -> [ Attribute ] -> [ Attribute ] -> Resource -> [ Policy ] -> [ Permission ]
getPolicies :: [ Policy ]
getUserPerms :: User -> Resource -> [ Policy ] -> [ Permission ]
getUserPerms user resource = getPerms userAttrs resourceAttrs environmentAttrs resource policies
  where
    userAttrs = getUserAttrs user
    resourceAttrs = getResourceAttrs resource
    environmentAttrs = getEnvironmentAttrs
    policies = getPolicies

RAAC (Risk-Adaptive Access Control)

Un ulteriore elemento entra in gioco: una valutazione del rischio, che modifica dinamicamente le policy. Questo permette di avere regole più restrittive in momenti particolari (attacco hacker, fase delicata dello sviluppo di un nuovo prodotto, possibile fuga di informazioni).

data Attribute = Attribute AttrKey AttrValue
getUserAttrs :: User -> [ Attribute ]
getResourceAttrs :: Resource -> [ Attribute ]
getEnvironmentAttrs :: IO [ Attribute ]
getPerms :: [ Attribute ] -> [ Attribute ] -> [ Attribute ] -> Resource -> [ Policy ] -> [ Permission ]
getPolicies :: RiskCondition -> [ Policy ]
getRisk :: RiskCondition
getUserPerms user resource = getPerms userAttrs resourceAttrs environmentAttrs resource policies
  where
    userAttrs = getUserAttrs user
    resourceAttrs = getResourceAttrs resource
    environmentAttrs = getEnvironmentAttrs
    risk = getRisk
    policies = getPolicies risk