Composición de Autorizaciones en Ruby usando Walruz

24
Composici ´ on de Autorizaciones en Ruby usando Walruz Rom´ an Gonz ´ alez LATAM on Rails November 7, 2010

Transcript of Composición de Autorizaciones en Ruby usando Walruz

Composicion de Autorizaciones en Rubyusando Walruz

Roman Gonzalez

LATAM on Rails

November 7, 2010

Definiciones

→ Autenticacion != Autorizacion

→ Autenticacion: Es el proceso de verificar algo o alguiencomo autentico

→ Autorizacion: Es el proceso de verificar los privilegios deuna entidad

Plugins existentes en Rails

→ Autenticaciondevisewardenacts as authenticated

→ Autorizaciondeclarative authorizationwalruz

Definamos un escenario

c l a s s User < ActiveRecord : : Base# a t t r i b u t e : admin , : b o o l e a nhas many : f r i e n d s h i p shas many : albums

end

c l a s s Friendship < ActiveRecord : : Basebe longs to : f r i e n d , : c lass name => ’ User ’be longs to : befr iend , : c lass name => ’ User ’

end

c l a s s Album < ActiveRecord : : Basebe longs to : owner , : c lass name => ’ User ’

end

AlbumsController

c l a s s AlbumsController < A p p l i c a t i o n C o n t r o l l e rb e f o r e f i l t e r : f i n d u s e r

def show@album = user . albums . f ind ( params [ : id ] )render : a c t i o n => ’ show ’

end

protec ted : f i n d u s e rdef f i n d u s e r

@user = User . f ind ( params [ : u s e r i d ] )end

end

Solo el creador del Album

1 def show2 i f c u r r e n t u s e r == user3 @album = user . albums . f ind ( params [ : id ] )4 render : a c t i o n => ’ show ’5 e l s e6 unauthorized7 end8 end

+ Admin

1 def show2 i f c u r r e n t u s e r . admin? | | c u r r e n t u s e r == user3 @album = user . albums . f ind ( params [ : id ] )4 render : a c t i o n => ’ show ’5 e l s e6 unauthorized7 end8 end

+ Amigos

1 def show2 allowed = c u r r e n t u s e r . admin? | |3 c u r r e n t u s e r == user | |4 user . f r i e n d ? ( c u r r e n t u s e r )5 i f allowed6 @album = user . albums . f ind ( params [ : id ] )7 render : a c t i o n => ’ show ’8 e l s e9 unauthorized

10 end11 end

- Amigos que esten autorizados

1 def show2 @album = user . albums . f ind ( params [ : id ] )3 allowed = c u r r e n t u s e r . admin? | |4 c u r r e n t u s e r == user | |5 ( ( f = user . f r i e n d s h i p w i t h ( c u r r e n t u s e r ) ) &&6 f . a l low to see album ? ( @album ) )7 i f allowed8 render : a c t i o n => ’ show ’9 e l s e

10 unauthorized11 end12 end

+ Verifica que el Album sea publico

1 allowed = album . i s p u b l i c ? | |2 c u r r e n t u s e r . admin? | |3 c u r r e n t u s e r == user | |4 ( ( f = user . f r i e n d s h i p w i t h ( c u r r e n t u s e r ) ) &&5 f . a l low to see album ? ( @album ) )

Observaciones

→ Estamos implementando una logica que puede nopertenecer a un solo controlador (Copy-Paste)

→ Los controladores dejan de ser skinny por tener codigo quese encarga de las autorizaciones

Posibles Soluciones

→ ¿Mover la logica de validacion de autorizaciones alModelo?

→ NO. El codigo estarıa esparcido en distintos modelos,haciendo casi imposible mantener rastro de las distintasautorizaciones que existen en proyectos de mediano a grantamano.

Usando Walruz

1 def show2 @album = user . albums . f ind ( params [ : id ] )3 # a c t o r . can ?( a c t i o n , s u b j e c t )4 i f c u r r e n t u s e r . can ? ( : read , @album )5 render : a c t i o n => ’ show ’6 e l s e7 unauthorized8 end9 end

Removemos toda la logica de autorizacion

→ Los controladores pasan a ser Open For Extension/ClosedFor Modification

→ El codigo sigue siendo legible y claro en sus intenciones

¿Como funciona?

c l a s s User < ActiveRecord : : Baseinclude Walruz : : Actor

end

c l a s s Album < ActiveRecord : : Baseinclude Walruz : : S u b j e c tc h e c k a u t h o r i z a t i o n s

# a c t i o n => p o l i c y: read => P o l i c i e s : : AlbumReadAuthorization

end

¿Que es Policies::AlbumReadAuthorization?

Policies File

# l i b / walruz / p o l i c i e s . rbmodule P o l i c i e s

requi re ” p o l i c i e s /a c t or i s a d mi n ”requi re ” p o l i c i e s /a c t o r i s o w n e r ”requi re ” p o l i c i e s / a c t o r i s f r i e n d ”requi re ” p o l i c i e s /fr iendship al low read albums ”

AlbumReadAuthorization =orP ( ActorIsAdmin ,

ActorIsOwner ,andP ( Actor IsFr iend . f o r s u b j e c t ( : owner ) ,

FriendshipAllowReadAlbums ))

end

ActorIsAdmin

c l a s s ActorIsAdmin < Walruz : : Po l i cy

# c u r r e n t u s e r . can ? ( : r ead , @album )# a c t o r −> c u r r e n t u s e r# s u b j e c t −> @album

def authorized ? ( actor , s u b j e c t )a c t o r . admin?

end

end

ActorIsOwner

c l a s s ActorIsOwner < Walruz : : Po l i cy

# c u r r e n t u s e r . can ? ( : r ead , @album )# a c t o r −> c u r r e n t u s e r# s u b j e c t −> @album

def authorized ? ( actor , s u b j e c t )a c t o r == s u b j e c t . owner

end

end

ActorIsFriend

# A c t o r I s F r i e n d . f o r s u b j e c t ( : owner )

c l a s s ActorIsFr iend < Walruz : : Po l i cy

# c u r r e n t u s e r . can ? ( : r ead , @album )# a c t o r −> c u r r e n t u s e r# s u b j e c t −> @album . owner

def authorized ? ( user , o t h e r u s e r )f r i e n d s h i p = o t h e r u s e r . f r i e n d s h i p w i t h ( user )i f f r i e n d s h i p

[ true , : f r i e n d s h i p => f r i e n d s h i p ]e l s e

f a l s eend

end

end

FriendshipAllowReadAlbum

# andP ( A c t o r I s F r i e n d . f o r s u b j e c t ( : owner ) ,# Fr i endsh ipAl lowReadAlbum )

c l a s s FriendshipAllowReadAlbum < Walruz : : Po l i cy

def authorized ? ( actor , album )params [ : f r i e n d s h i p ] . a l low to see album ? ( album )

end

end

Observaciones

→ Las diferentes polıticas que se implementan se mantienenbien aisladas y simples

→ Mediante la composicion de estas polıticas podemosdefinir facilmente polıticas con mayor complejidad

→ Todo el sistema de seguridad se mantiene en un solo sitioen el proyecto

→ El problema deja de ser, invocar las autorizaciones en elproyecto, y pasa a ser manejar el archivo de polıticasautorizaciones

Desventajas

→ Esto es Ruby, no SQL

→ A medida que las polıticas son mas complejas, mas tiempose va a tomar en ejecutar la verificaciones

→ Las colecciones de objetos no son el mejor caso de uso, peroen el caso de que sea requerido, memcache es tu amigo

→ Por ahora, walruz-rails solo soporta rails 2

¿Preguntas?

¡Gracias!+ Informacion:

Comunidad:http://ruby.org.ve

Twitter:@romanandreg

Proyecto:http://github.com/noomii/walruzhttp://github.com/noomii/walruz-rails