Hack 48. Control Access to Remote Objects


Enforce access control to your objects.

Perl's idea of access control and privacy is politeness. Sometimes this is usefulyou don't have to spend a lot of time and energy figuring out what to hide and how. Sometimes you need to rifle through someone else's code to get your job done quickly.

Other times, security is more important than ease of codingespecially when you have to deal with the cold, hostile world at large. Though you may need to make your code accessible to the wilds of the Internet, you don't want to let just anyone do anything.

Modules and frameworks such as SOAP::Lite make it easy to provide web service access to plain old Perl objects. Here's one way to make them somewhat safer.

The Hack

First, decide what kinds of operations you need to support on your object. Take a standard web-enabled inventory system. You need to fetch an item, insert an item, update an item, and delete an item. Then identify the types of access: creating, reading, writing, and deleting.

You could maintain a list in code or a configuration file somewhere mapping all the access controls to all the methods of the objects in your system. That would be silly, though; this is Perl! Instead, consider using a subroutine attribute [Hack #45].

package Proxy::AccessControl; use strict; use warnings; use Attribute::Handlers; my %perms; sub UNIVERSAL::perms {     my ($package, $symbol, $referent, $attr, $data) = @_;     my $method                                      = *{ $symbol }{NAME};     for my $permission (split(/\\s+/, $data))     {         push @{ $perms{ $package }{ $method } }, $permission;     } } sub dispatch {     my ($user, $class, $method, @args) = @_;     return unless $perms{ $class }{ $method } and $class->can( $method );     for my $perm (@{ $perms{ $class }{ $method } })     {       die "Need permission '$perm\\n'" unless $user->has_permission( $perm );     }     $class->$method( @args ); } 1;

Declaring permissions is easy:

package Inventory; use Proxy::AccessControl; sub insert :perms( 'create' ) {     my ($self, $attributes) = @_;     # ... } sub delete :perms( 'delete' ) {     my ($self, $id) = @_;     # ... } sub update :perms( 'write' ) {     my ($self, $id, $attributes) = @_;     # ... } sub fetch :perms( 'read' ) {     my ($self, $id) = @_;     # ... }

You can also mix and match permissions:

sub clone :perms( 'read create' ) {     my ($self, $id, $attributes) = @_;     # ... }

Proxy::AccessControl provides an attribute handler perms that registers a space-separated list of permissions for each marked method. It also provides a dispatch( ) methodthe barrier point into the system between the controller routing incoming requests and the actual Perl objects handling the requests.

The only thing left to do (besides actually writing the business logic code) is to make your controller run everything through Proxy::AccessControl::dispatch( ). This function takes three parameters. The first is a $user object that represents the access capabilities of the external user somehow. (Your code needs to allow authentication and creation of this object.) The $class and $method parameters identify the proper class and method to call, if the user has permission to do so.

Hacking the Hack

dispatch( ) is a coarsely-grained approach to proxying. Perhaps creating dedicated proxies that speak web services or remote object protocols natively would be useful. Behind the scenes, they could take only one extra parameter (the user object) and, for each proxied method, provide their own implementation that performs the access checks before delegating or denying the request as necessary.

There's no reason to limit access control to permissions alone, either. You could control access to objects based on the number of concurrent accesses, the phase of the moon, the remote operating system, the time of day, or whatever mechanism you desire. Anything you can put in an attribute's data is fair game.



Perl Hacks
Perl Hacks: Tips & Tools for Programming, Debugging, and Surviving
ISBN: 0596526741
EAN: 2147483647
Year: 2004
Pages: 141

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net