SlideShare a Scribd company logo
1 of 64
Download to read offline
Practical Applications of
       Zend_Acl


           Rowan Merewood
Who is this?

 @rowan_m

 Software Engineer
 Team Lead

 http://merewood.org

                       2
Why do this?

 So you don't have to.

 Problems encountered,
 solutions discovered,
 lessons learned.

                         3
What do you want?

 More concept?

  - or -

 More code?

                    4
What does this solve?

  The “Gold Standard” for
         security.




                            5
Gold Standard
            Gold
             79

           Au thentication
           196.97



            Gold
             79

           Au thorisation
           196.97



            Gold
             79

           Au diting
           196.97




B.W. Lampson. Computer Security in the Real World. Computer, 37(6):37–46, 2004
http://research.microsoft.com/en-us/um/people/blampson/69-SecurityRealIEEE/69-SecurityRealIEEE.htm



                                                                                                6
Gold Standard
            Gold
             79

           Au thentication
           196.97



            Gold
             79

           Au thorisation
           196.97

                                                     You are here.
            Gold
             79

           Au diting
           196.97




B.W. Lampson. Computer Security in the Real World. Computer, 37(6):37–46, 2004
http://research.microsoft.com/en-us/um/people/blampson/69-SecurityRealIEEE/69-SecurityRealIEEE.htm



                                                                                                7
Role-based Access Control

Roles
Resources
Privileges
Assertions
                     Oh my!



                            8
Warning!

 There is no right answer




                            9
Roles

• A named group of privileges for a
  resource.

• A role may inherit from many parent roles

• Build the tree from leaf to root



                                          10
Roles

• A user is a leaf node              Client Contact

        Developer




                    Lead Developer
   Employee




                    Rowan

                                                      11
Roles

• A user is a leaf node              Client Contact

        Developer




                    Lead Developer                Sales
   Employee

                                           Evil


                    Rowan                Rowan

                                                          12
Roles

• Use inheritance sparingly

• Avoid circular dependencies

• Over-complicated relationships

• Difficult to configure

                                   13
Resources

• Objects with which users can interact

• A resource may have one parent

• Build the tree from root to leaf




                                          14
Resources


                                           Ship



                              Federation          Klingon



               Galaxy class




  NCC-1701-D              NCC-1701-E


                                                            15
Resources


                                             Ship



                              Federation            Klingon



               Galaxy class            Allow “bridge crew” role
                                    the “activate cloak” privilege



  NCC-1701-D              NCC-1701-E


                                                                     16
Resources

              Allow “*” role
     the “self destruct” privilege
         asserting “is captain”               Ship



                                 Federation          Klingon



                Galaxy class




  NCC-1701-D                 NCC-1701-E


                                                               17
Privileges

• Simple – just strings

• Qualifies the operation a role may
  perform against a resource

• Shared vocabulary: CRUD



                                       18
Assertions

• An arbitrary condition attached to the ACL
  returning true or false

• Has access to the role, resource, privilege
  and ACL

• Power and flexibility open to abuse


                                            19
Assertions

• "user" can "view" a "group photo" if "user is
  a member of the group"


• "user" can "create" an "comment" if "the user
  has submitted less than 5 comments in
  the last hour"


• "job scheduler" may "schedule" a "task" if
  "no instances of the task are running"


                                             20
Assertions

• "user" can "view" a "group photo" if "user is
  a member of the group"


• "user" can "create" an "comment" if "the user
  hasDirect relationshipless than 5 and the resource.
       submitted between the role comments in
                 All dependencies are passed in.
  the last hour"
        “Visibility” is a good concept to keep in the ACL


• "job scheduler" may "schedule" a "task" if
  "no instances of the task are running"


                                                            21
Assertions

• "user" can "view" a "group photo" if "user is
  a member of the group"


• "user" can "create" an "comment" if "the user
  has submitted less than 5 comments in
  the last hour"

          Border-line – most dependencies contained
•   "job scheduler" may "schedule" a "task" if
          Does the time-based system state count as
                        “authorisation”?
    "no instances of the task are running"


                                                  22
Assertions

• "user" can "view" a "group photo" if "user is
  a member of the group"


• "user" can "create" an "comment" if "the user
  has submitted less thanoutside the scope in
    Advanced dependencies definitely
                                         5 comments
          This is a “pre-add” check for the model
  the last hour"


• "job scheduler" may "schedule" a "task" if
  "no instances of the task are running"


                                                 23
Let's see some code

 Zend_Acl


 Zend_Acl_Role_Interface


 Zend_Acl_Resource_Interface


 Zend_Acl_Assert_Interface


                               24
Simple, Static ACL

$acl = new Zend_Acl();
$eng = new Zend_Acl_Role('engineering');
$scotty = new Zend_Acl_Role('scotty');
$kirk = new Zend_Acl_Role('kirk');
$dilCrys = new Zend_Acl_Resource('dilithium crystals');


$acl->addRole($eng);
$acl->addRole($scotty, $eng);
$acl->addRole($kirk);
$acl->addResource($dilCrys);


$acl->allow($eng, $dilCrys);

                                                      25
Simple, Static ACL

echo "Can Scotty replace the dilithium crystals?n";
echo ($acl->isAllowed('scotty', 'dilithium crystals', 'replace')) ?
"Can don" : "Cannae don";
echo "Can Kirk seduce the dilithium crystals?n";
echo ($acl->isAllowed('kirk', 'dilithium crystals', 'seduce')) ?
"Really cann" : "Obviously notn";




rowan@swordbean:~$ php test01.php
Can Scotty replace the dilithium crystals?
Can do
Can Kirk seduce the dilithium crystals?
Obviously not



                                                                      26
Implementing Resource

    Any entity in your system:
•   Controllers
•   Models
•   Users
•   Files
•   Processes



                                 27
Implementing Resource
class Ship implements Zend_Acl_Resource_Interface
{
     public $captain;

     public $registry;

     public function getResourceId()
     {
          return $this->registry;
     }
}

$acl = new Zend_Acl();
$kirk = new Zend_Acl_Role('kirk');
$acl->addRole($kirk);

$ship = new Ship();
$ship->captain = 'kirk';
$ship->registry = 'ncc-1701';
$acl->addResource($ship);
                                                    28
Adding an Assertion
class IsCaptainOf implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null,
        Zend_Acl_Resource_Interface $resource = null, $privilege = null) {
        if ( !($resource instanceof Ship) ) {
            throw new   Zend_Acl_Exception(
               'IsCaptainOf assertion only valid on Ships' );
        }
        return ($role->getRoleId() == $resource->captain);
    }
}


$assert = new IsCaptainOf();
$acl->allow('kirk', 'ncc-1701', 'destruct', $assert);


echo "Can Kirk order self-destruct?n";
echo ($acl->isAllowed('kirk', 'ncc-1701', 'destruct')) ?
    "Star Trek III: The Search for Spockn" : "Non";

                                                                                  29
Adding an Assertion
class IsCaptainOf implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null,
        Zend_Acl_Resource_Interface $resource = null, $privilege = null) {
        if ( !($resource instanceof Ship) ) {
            throw new   Zend_Acl_Exception(
                'IsCaptainOf assertion only valid on Ships' );
        }
        return ($role->getRoleId() == $resource->captain);
    }
                                     Increasing complexity
}
                               Introducing extra points of failure
$assert = new IsCaptainOf();
$acl->allow('kirk', 'ncc-1701', 'destruct', $assert);


echo "Can Kirk order self-destruct?n";
echo ($acl->isAllowed('kirk', 'ncc-1701', 'destruct')) ?
    "Star Trek III: The Search for Spockn" : "Non";

                                                                                  30
Dynamic ACL

 Store config. in the DB

 Build on the fly

 One size does not fit all

                             31
Database structure




                     32
Database structure
                  Users not given
                permissions directly




                                       33
Database structure




                Role hierarchy restricted
                    to Group → User




                                            34
Database structure




                     Permissions assigned
                         to 1 Group




                                            35
Database structure



                 Resource is free text
                 Does not need DB link
                   e.g. Controllers




                                         36
Database structure




                     Same for privilege




                                          37
Database structure




                     Class name fragment




                                           38
DB Classes
class Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users';
    protected $_primary = 'user_id';
    protected $_dependentTables = array('UserGroups');
    protected $_rowClass = 'User';
}


class Groups extends Zend_Db_Table_Abstract
{
    protected $_name = 'groups';
    protected $_primary = 'group_id';
    protected $_dependentTables = array('UserGroups');
    protected $_rowClass = 'Group';
}

                                                         39
DB Classes
class UserGroups extends Zend_Db_Table_Abstract
{
    protected $_name = 'user_groups';
    protected $_primary = array('user_id', 'group_id');
    protected $_referenceMap = array(
         'User' => array(
              'columns'         => array('user_id'),
              'refTableClass'   => 'Users',
              'refColumns'      => array('user_id'),
         ),
         'Group' => array(
              'columns'         => array('group_id'),
              'refTableClass'   => 'Groups',
              'refColumns'      => array('group_id'),
         ),
    );
}

                                                          40
DB Classes

class Permissions extends Zend_Db_Table_Abstract
{
    protected $_name = 'permissions';
    protected $_primary = 'permission_id';
    protected $_referenceMap = array(
         'Group' => array(
              'columns'         => array('group_id'),
              'refTableClass'   => 'Groups',
              'refColumns'      => array('group_id'),
         ),
    );
}


                                                        41
Implementing Role
interface Role_Interface extends Zend_Acl_Role_Interface {
    public function getType();
}
class User extends Zend_Db_Table_Row_Abstract implements Role_Interface {
    public function getType() {
        return 'User';
    }
    public function getRoleId() {
        return $this->getType().':'.$this->user_id;
    }
}
class Group extends Zend_Db_Table_Row_Abstract implements Role_Interface {
    public function getType() {
        return 'Group';
    }
    public function getRoleId() {
        return $this->getType().':'.$this->group_id;
    }
}

                                                                             42
What do we
want to enforce?



Users in the “command” group
 may issue orders to users
    subordinate to them



                          43
Implementing Resource




                        44
Implementing Resource
interface Resource_Interface extends Zend_Acl_Role_Interface {
    public function getType();
}
class Order extends Zend_Db_Table_Row_Abstract implements Resource_Interface
{
    public function getType() {
        return 'Order';
    }
    public function getResourceId() {
        $id = $this->getType();
        if   ($this->order_id) {
             $id .= ':'.$this->order_id;
        }
        return $id;
    }
}


                                                                          45
Populate the DB
mysql> select * from groups;
+----------+-------------+
| group_id | name        |
+----------+-------------+
|       1 | command      |
|       2 | bridge crew |
+----------+-------------+
mysql> select * from permissions;
+---------------+-------+----------+----------+-----------+------------+
| permission_id | type   | group_id | resource | privilege | assert    |
+---------------+-------+----------+----------+-----------+------------+
|            1 | allow |         1 | Order    | read      | NULL       |
|            2 | allow |         1 | Order    | create    | IsSuperior |
|            3 | allow |       NULL | Order   | belay     | IsIssuer   |
|            4 | allow |         2 | Order    | read      | NULL       |
+---------------+-------+----------+----------+-----------+------------+

                                                                           46
Populate the DB


mysql> select u.name, g.name as `group`, r.name as `rank` from users u
      inner join user_groups ug on u.user_id = ug.user_id
      inner join groups g on ug.group_id = g.group_id
      inner join user_ranks ur on u.user_id = ur.user_id
      inner join ranks r on ur.rank_id = r.rank_id;
+------+-------------+---------+
| name | group      | rank      |
+------+-------------+---------+
| kirk | command    | captain |
| rand | bridge crew | yeoman   |
+------+-------------+---------+




                                                                         47
Issuing an order

$issuer = Zend_Auth::getInstance()->getIdentity();
$u = new Users();
$subord = $u->find(2)->current();


$order = new Order();
$order->superior_user_id = $issuer->user_id;
$order->subordinate_user_id = $subord->user_id;
$order->detail = "Get your red shirt, it's time for an away mission.";


$acl = new AclWrapper();
if (!$acl->isAllowed($issuer, $order, 'create')) {
    throw new Zend_Controller_Action_Exception(
       'Not allowed to create order!' , 403);
}
$order->save();

                                                                     48
Issuing an order

$issuer = Zend_Auth::getInstance()->getIdentity();
$u = new Users();
$subord = $u->find(2)->current();


$order = new Order();
$order->superior_user_id = $issuer->user_id;
                                 You could move
$order->subordinate_user_id = $subord->user_id;       this check
$order->detail = "Get your red shirt,    onto the model
                                        it's time for an away mission.";


$acl = new AclWrapper();
if (!$acl->isAllowed($issuer, $order, 'create')) {
    throw new Zend_Controller_Action_Exception(
       'Not allowed to create order!' , 403);
}
$order->save();

                                                                       49
Building the ACL
class AclWrapper
{
    public function isAllowed(User $role = null,
        Resource_Interface $resource = null, $privilege = null) {
        $acl = new Zend_Acl();
        $groups = $user->findGroups();
        foreach ($groups as $group) {
            $acl->addRole($group);
        }
        $acl->addRole($user, $groups);
        if (strpos($resource->getResourceId(), ':')) {
            $parent = new Zend_Acl_Resource($resource->getType());
            $acl->addResource($parent);
            $acl->addResource($resource, $parent);
        } else {
            $acl->addResource($resource);
        }
[...]
                                                                     50
Building the ACL
class AclWrapper
{
    public function isAllowed(User $role = null,
        Resource_Interface $resource = null, $privilege = null) {
        $acl = new Zend_Acl();
        $groups = $user->findGroups();
                                               Add Group roles
        foreach ($groups as $group) {
                                               Add the User role
            $acl->addRole($group);
        }
        $acl->addRole($user, $groups);
        if (strpos($resource->getResourceId(), ':')) {
            $parent = new Zend_Acl_Resource($resource->getType());
            $acl->addResource($parent);
            $acl->addResource($resource, $parent);
        } else {
            $acl->addResource($resource);
        }
[...]
                                                                     51
Building the ACL
class AclWrapper
{
    public function isAllowed(User $role = null,
        Resource_Interface $resource = null, $privilege = null) {
        $acl = new Zend_Acl();
        $groups = $user->findGroups();
        foreach ($groups as $group) {
            $acl->addRole($group);
        }
        $acl->addRole($user, $groups);
        if (strpos($resource->getResourceId(), ':')) {
            $parent = new Zend_Acl_Resource($resource->getType());
            $acl->addResource($parent);
            $acl->addResource($resource, $parent);
        } else {
            $acl->addResource($resource);   ':' means adding an instance
        }                                          and its parent
[...]
                                                                      52
Building the ACL
foreach ($groups as $group) {
            foreach ($groups->findPermissions as $permission) {
                $assert = null;
                $classname = $permission->assert;
                if (
                      $classname && class_exists($classname)
                      && is_subclass_of($classname, 'Zend_Acl_Assert_Interface')
                ) {
                      $assert = new $classname();
                }


                $op = ($permission->type == 'allow') ? 'allow' : 'deny';
                $acl->$op($group, $resource, $permission->privilege, $assert);
            }
        }


        return $acl->isAllowed($role, $resource, $privilege);
    }
}
                                                                                   53
Building the ACL
foreach ($groups as $group) {
            foreach ($groups->findPermissions as $permission) {
                $assert = null;
                $classname = $permission->assert;
                if (
                      $classname && class_exists($classname)
                      && is_subclass_of($classname, 'Zend_Acl_Assert_Interface')
                ) {
                      $assert = new $classname();
                }                                   Validate as much as possible!

                $op = ($permission->type == 'allow') ? 'allow' : 'deny';
                $acl->$op($group, $resource, $permission->privilege, $assert);
            }
        }


        return $acl->isAllowed($role, $resource, $privilege);
    }
}
                                                                                   54
Asserting Superiority
class IsSuperior implements Zend_Acl_Assert_Interface
{
    public function assert(
        Zend_Acl $acl, Zend_Acl_Role_Interface $role = null,
        Zend_Acl_Resource_Interface $resource = null, $privilege = null)
    {
        if (!$role instanceof User) {
            throw new Zend_Acl_Exception('Assertion only applies to Users');
        }
        if (!$resource instanceof Order) {
            throw new Zend_Acl_Exception('Assertion only applies to Orders');
        }
        $supRank = $role->findRanks()->current();
        $subRank = $resource->findUsersBySubordinate()->current();
        return ($supRank->rank_id > $subRank->rank_id);
    }
}

                                                                           55
Issuing an order

$issuer = Zend_Auth::getInstance()->getIdentity();
$u = new Users();
$subord = $u->find(2)->current();


$order = new Order();
$order->superior_user_id = $issuer->user_id;
$order->subordinate_user_id = $subord->user_id;
$order->detail = "Get your red shirt, it's time for an away mission.";


$acl = new AclWrapper();
if (!$acl->isAllowed($issuer, $order, 'create')) {
    throw new Zend_Controller_Action_Exception(
       'Not allowed to create order!' , 403);
}
$order->save();

                                                                     56
Conclusions




  Is this the right way?




                           57
Attaching the ACL

• Controller and Action?

• Model and Method?

• Business object and Action?

• All of the above?

                                58
Unit testing

• Pass the Zend_Acl into your wrapper

• Use a factory




                                        59
Caching the ACL

• Build everything for the User?

• Build everything for the Resource?

• Build everything for everything!




                                       60
Advice

• Think about what you want to protect

• Test your solution with realistic data

• Assume that you are wrong




                                           61
Questions?




             62
Feedback




  http://joind.in/2054

“...even a well presented talk by a charismatic speaker upset me.”




                                                                63
Credits

http://www.flickr.com/photos/innoxiuss/2824204305/
http://www.flickr.com/photos/carianoff/2849384997/




                                                     64

More Related Content

Similar to Practical Applications of Zend_Acl

Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignLightbend
 
Writing Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason LeeWriting Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason Leejaxconf
 
Let your DBAs get some REST(api)
Let your DBAs get some REST(api)Let your DBAs get some REST(api)
Let your DBAs get some REST(api)Ludovico Caldara
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpMichael Girouard
 
Collaborate instant cloning_kyle
Collaborate instant cloning_kyleCollaborate instant cloning_kyle
Collaborate instant cloning_kyleKyle Hailey
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationJonathan Wage
 
Security pitfalls in script-able infrastructure pipelines.
Security pitfalls in script-able infrastructure pipelines.Security pitfalls in script-able infrastructure pipelines.
Security pitfalls in script-able infrastructure pipelines.DefCamp
 
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Lucidworks
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
You're Off the Hook: Blinding Security Software
You're Off the Hook: Blinding Security SoftwareYou're Off the Hook: Blinding Security Software
You're Off the Hook: Blinding Security SoftwareCylance
 
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQDocker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQErica Windisch
 
Running your Java EE 6 Applications in the Cloud
Running your Java EE 6 Applications in the CloudRunning your Java EE 6 Applications in the Cloud
Running your Java EE 6 Applications in the CloudArun Gupta
 
Tectonic Summit 2016: The Origins of Kubernetes
Tectonic Summit 2016: The Origins of KubernetesTectonic Summit 2016: The Origins of Kubernetes
Tectonic Summit 2016: The Origins of KubernetesCoreOS
 
Running your Java EE 6 applications in the Cloud (FISL 12)
Running your Java EE 6 applications in the Cloud (FISL 12)Running your Java EE 6 applications in the Cloud (FISL 12)
Running your Java EE 6 applications in the Cloud (FISL 12)Arun Gupta
 

Similar to Practical Applications of Zend_Acl (20)

Akka and the Zen of Reactive System Design
Akka and the Zen of Reactive System DesignAkka and the Zen of Reactive System Design
Akka and the Zen of Reactive System Design
 
Writing Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason LeeWriting Plugged-in Java EE Apps: Jason Lee
Writing Plugged-in Java EE Apps: Jason Lee
 
Let your DBAs get some REST(api)
Let your DBAs get some REST(api)Let your DBAs get some REST(api)
Let your DBAs get some REST(api)
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented Php
 
Collaborate instant cloning_kyle
Collaborate instant cloning_kyleCollaborate instant cloning_kyle
Collaborate instant cloning_kyle
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
 
Play framework
Play frameworkPlay framework
Play framework
 
Security pitfalls in script-able infrastructure pipelines.
Security pitfalls in script-able infrastructure pipelines.Security pitfalls in script-able infrastructure pipelines.
Security pitfalls in script-able infrastructure pipelines.
 
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
Distributed Search in Riak - Integrating Search in a NoSQL Database: Presente...
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
You're Off the Hook: Blinding Security Software
You're Off the Hook: Blinding Security SoftwareYou're Off the Hook: Blinding Security Software
You're Off the Hook: Blinding Security Software
 
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQDocker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
Docker for Developers: Dev, Test, Deploy @ BucksCo Devops at MeetMe HQ
 
Running your Java EE 6 Applications in the Cloud
Running your Java EE 6 Applications in the CloudRunning your Java EE 6 Applications in the Cloud
Running your Java EE 6 Applications in the Cloud
 
Tectonic Summit 2016: The Origins of Kubernetes
Tectonic Summit 2016: The Origins of KubernetesTectonic Summit 2016: The Origins of Kubernetes
Tectonic Summit 2016: The Origins of Kubernetes
 
Boycott Docker
Boycott DockerBoycott Docker
Boycott Docker
 
Responsible JavaScript
Responsible JavaScriptResponsible JavaScript
Responsible JavaScript
 
Running your Java EE 6 applications in the Cloud (FISL 12)
Running your Java EE 6 applications in the Cloud (FISL 12)Running your Java EE 6 applications in the Cloud (FISL 12)
Running your Java EE 6 applications in the Cloud (FISL 12)
 
Containers 101
Containers 101Containers 101
Containers 101
 
Gradle
GradleGradle
Gradle
 
Elastc Search
Elastc SearchElastc Search
Elastc Search
 

More from Rowan Merewood

Estimation or, "How to Dig your Grave"
Estimation or, "How to Dig your Grave"Estimation or, "How to Dig your Grave"
Estimation or, "How to Dig your Grave"Rowan Merewood
 
A Dependency Injection Primer
A Dependency Injection PrimerA Dependency Injection Primer
A Dependency Injection PrimerRowan Merewood
 
Algorithm, Review, Sorting
Algorithm, Review, SortingAlgorithm, Review, Sorting
Algorithm, Review, SortingRowan Merewood
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy CodeRowan Merewood
 
State Machines to State of the Art
State Machines to State of the ArtState Machines to State of the Art
State Machines to State of the ArtRowan Merewood
 

More from Rowan Merewood (8)

Sensible scaling
Sensible scalingSensible scaling
Sensible scaling
 
Estimation or, "How to Dig your Grave"
Estimation or, "How to Dig your Grave"Estimation or, "How to Dig your Grave"
Estimation or, "How to Dig your Grave"
 
A Dependency Injection Primer
A Dependency Injection PrimerA Dependency Injection Primer
A Dependency Injection Primer
 
TDD and Getting Paid
TDD and Getting PaidTDD and Getting Paid
TDD and Getting Paid
 
Algorithm, Review, Sorting
Algorithm, Review, SortingAlgorithm, Review, Sorting
Algorithm, Review, Sorting
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
Tools and Talent
Tools and TalentTools and Talent
Tools and Talent
 
State Machines to State of the Art
State Machines to State of the ArtState Machines to State of the Art
State Machines to State of the Art
 

Recently uploaded

"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 

Recently uploaded (20)

"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 

Practical Applications of Zend_Acl

  • 1. Practical Applications of Zend_Acl Rowan Merewood
  • 2. Who is this? @rowan_m Software Engineer Team Lead http://merewood.org 2
  • 3. Why do this? So you don't have to. Problems encountered, solutions discovered, lessons learned. 3
  • 4. What do you want? More concept? - or - More code? 4
  • 5. What does this solve? The “Gold Standard” for security. 5
  • 6. Gold Standard Gold 79 Au thentication 196.97 Gold 79 Au thorisation 196.97 Gold 79 Au diting 196.97 B.W. Lampson. Computer Security in the Real World. Computer, 37(6):37–46, 2004 http://research.microsoft.com/en-us/um/people/blampson/69-SecurityRealIEEE/69-SecurityRealIEEE.htm 6
  • 7. Gold Standard Gold 79 Au thentication 196.97 Gold 79 Au thorisation 196.97 You are here. Gold 79 Au diting 196.97 B.W. Lampson. Computer Security in the Real World. Computer, 37(6):37–46, 2004 http://research.microsoft.com/en-us/um/people/blampson/69-SecurityRealIEEE/69-SecurityRealIEEE.htm 7
  • 9. Warning! There is no right answer 9
  • 10. Roles • A named group of privileges for a resource. • A role may inherit from many parent roles • Build the tree from leaf to root 10
  • 11. Roles • A user is a leaf node Client Contact Developer Lead Developer Employee Rowan 11
  • 12. Roles • A user is a leaf node Client Contact Developer Lead Developer Sales Employee Evil Rowan Rowan 12
  • 13. Roles • Use inheritance sparingly • Avoid circular dependencies • Over-complicated relationships • Difficult to configure 13
  • 14. Resources • Objects with which users can interact • A resource may have one parent • Build the tree from root to leaf 14
  • 15. Resources Ship Federation Klingon Galaxy class NCC-1701-D NCC-1701-E 15
  • 16. Resources Ship Federation Klingon Galaxy class Allow “bridge crew” role the “activate cloak” privilege NCC-1701-D NCC-1701-E 16
  • 17. Resources Allow “*” role the “self destruct” privilege asserting “is captain” Ship Federation Klingon Galaxy class NCC-1701-D NCC-1701-E 17
  • 18. Privileges • Simple – just strings • Qualifies the operation a role may perform against a resource • Shared vocabulary: CRUD 18
  • 19. Assertions • An arbitrary condition attached to the ACL returning true or false • Has access to the role, resource, privilege and ACL • Power and flexibility open to abuse 19
  • 20. Assertions • "user" can "view" a "group photo" if "user is a member of the group" • "user" can "create" an "comment" if "the user has submitted less than 5 comments in the last hour" • "job scheduler" may "schedule" a "task" if "no instances of the task are running" 20
  • 21. Assertions • "user" can "view" a "group photo" if "user is a member of the group" • "user" can "create" an "comment" if "the user hasDirect relationshipless than 5 and the resource. submitted between the role comments in All dependencies are passed in. the last hour" “Visibility” is a good concept to keep in the ACL • "job scheduler" may "schedule" a "task" if "no instances of the task are running" 21
  • 22. Assertions • "user" can "view" a "group photo" if "user is a member of the group" • "user" can "create" an "comment" if "the user has submitted less than 5 comments in the last hour" Border-line – most dependencies contained • "job scheduler" may "schedule" a "task" if Does the time-based system state count as “authorisation”? "no instances of the task are running" 22
  • 23. Assertions • "user" can "view" a "group photo" if "user is a member of the group" • "user" can "create" an "comment" if "the user has submitted less thanoutside the scope in Advanced dependencies definitely 5 comments This is a “pre-add” check for the model the last hour" • "job scheduler" may "schedule" a "task" if "no instances of the task are running" 23
  • 24. Let's see some code Zend_Acl Zend_Acl_Role_Interface Zend_Acl_Resource_Interface Zend_Acl_Assert_Interface 24
  • 25. Simple, Static ACL $acl = new Zend_Acl(); $eng = new Zend_Acl_Role('engineering'); $scotty = new Zend_Acl_Role('scotty'); $kirk = new Zend_Acl_Role('kirk'); $dilCrys = new Zend_Acl_Resource('dilithium crystals'); $acl->addRole($eng); $acl->addRole($scotty, $eng); $acl->addRole($kirk); $acl->addResource($dilCrys); $acl->allow($eng, $dilCrys); 25
  • 26. Simple, Static ACL echo "Can Scotty replace the dilithium crystals?n"; echo ($acl->isAllowed('scotty', 'dilithium crystals', 'replace')) ? "Can don" : "Cannae don"; echo "Can Kirk seduce the dilithium crystals?n"; echo ($acl->isAllowed('kirk', 'dilithium crystals', 'seduce')) ? "Really cann" : "Obviously notn"; rowan@swordbean:~$ php test01.php Can Scotty replace the dilithium crystals? Can do Can Kirk seduce the dilithium crystals? Obviously not 26
  • 27. Implementing Resource Any entity in your system: • Controllers • Models • Users • Files • Processes 27
  • 28. Implementing Resource class Ship implements Zend_Acl_Resource_Interface { public $captain; public $registry; public function getResourceId() { return $this->registry; } } $acl = new Zend_Acl(); $kirk = new Zend_Acl_Role('kirk'); $acl->addRole($kirk); $ship = new Ship(); $ship->captain = 'kirk'; $ship->registry = 'ncc-1701'; $acl->addResource($ship); 28
  • 29. Adding an Assertion class IsCaptainOf implements Zend_Acl_Assert_Interface { public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null) { if ( !($resource instanceof Ship) ) { throw new Zend_Acl_Exception( 'IsCaptainOf assertion only valid on Ships' ); } return ($role->getRoleId() == $resource->captain); } } $assert = new IsCaptainOf(); $acl->allow('kirk', 'ncc-1701', 'destruct', $assert); echo "Can Kirk order self-destruct?n"; echo ($acl->isAllowed('kirk', 'ncc-1701', 'destruct')) ? "Star Trek III: The Search for Spockn" : "Non"; 29
  • 30. Adding an Assertion class IsCaptainOf implements Zend_Acl_Assert_Interface { public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null) { if ( !($resource instanceof Ship) ) { throw new Zend_Acl_Exception( 'IsCaptainOf assertion only valid on Ships' ); } return ($role->getRoleId() == $resource->captain); } Increasing complexity } Introducing extra points of failure $assert = new IsCaptainOf(); $acl->allow('kirk', 'ncc-1701', 'destruct', $assert); echo "Can Kirk order self-destruct?n"; echo ($acl->isAllowed('kirk', 'ncc-1701', 'destruct')) ? "Star Trek III: The Search for Spockn" : "Non"; 30
  • 31. Dynamic ACL Store config. in the DB Build on the fly One size does not fit all 31
  • 33. Database structure Users not given permissions directly 33
  • 34. Database structure Role hierarchy restricted to Group → User 34
  • 35. Database structure Permissions assigned to 1 Group 35
  • 36. Database structure Resource is free text Does not need DB link e.g. Controllers 36
  • 37. Database structure Same for privilege 37
  • 38. Database structure Class name fragment 38
  • 39. DB Classes class Users extends Zend_Db_Table_Abstract { protected $_name = 'users'; protected $_primary = 'user_id'; protected $_dependentTables = array('UserGroups'); protected $_rowClass = 'User'; } class Groups extends Zend_Db_Table_Abstract { protected $_name = 'groups'; protected $_primary = 'group_id'; protected $_dependentTables = array('UserGroups'); protected $_rowClass = 'Group'; } 39
  • 40. DB Classes class UserGroups extends Zend_Db_Table_Abstract { protected $_name = 'user_groups'; protected $_primary = array('user_id', 'group_id'); protected $_referenceMap = array( 'User' => array( 'columns' => array('user_id'), 'refTableClass' => 'Users', 'refColumns' => array('user_id'), ), 'Group' => array( 'columns' => array('group_id'), 'refTableClass' => 'Groups', 'refColumns' => array('group_id'), ), ); } 40
  • 41. DB Classes class Permissions extends Zend_Db_Table_Abstract { protected $_name = 'permissions'; protected $_primary = 'permission_id'; protected $_referenceMap = array( 'Group' => array( 'columns' => array('group_id'), 'refTableClass' => 'Groups', 'refColumns' => array('group_id'), ), ); } 41
  • 42. Implementing Role interface Role_Interface extends Zend_Acl_Role_Interface { public function getType(); } class User extends Zend_Db_Table_Row_Abstract implements Role_Interface { public function getType() { return 'User'; } public function getRoleId() { return $this->getType().':'.$this->user_id; } } class Group extends Zend_Db_Table_Row_Abstract implements Role_Interface { public function getType() { return 'Group'; } public function getRoleId() { return $this->getType().':'.$this->group_id; } } 42
  • 43. What do we want to enforce? Users in the “command” group may issue orders to users subordinate to them 43
  • 45. Implementing Resource interface Resource_Interface extends Zend_Acl_Role_Interface { public function getType(); } class Order extends Zend_Db_Table_Row_Abstract implements Resource_Interface { public function getType() { return 'Order'; } public function getResourceId() { $id = $this->getType(); if ($this->order_id) { $id .= ':'.$this->order_id; } return $id; } } 45
  • 46. Populate the DB mysql> select * from groups; +----------+-------------+ | group_id | name | +----------+-------------+ | 1 | command | | 2 | bridge crew | +----------+-------------+ mysql> select * from permissions; +---------------+-------+----------+----------+-----------+------------+ | permission_id | type | group_id | resource | privilege | assert | +---------------+-------+----------+----------+-----------+------------+ | 1 | allow | 1 | Order | read | NULL | | 2 | allow | 1 | Order | create | IsSuperior | | 3 | allow | NULL | Order | belay | IsIssuer | | 4 | allow | 2 | Order | read | NULL | +---------------+-------+----------+----------+-----------+------------+ 46
  • 47. Populate the DB mysql> select u.name, g.name as `group`, r.name as `rank` from users u inner join user_groups ug on u.user_id = ug.user_id inner join groups g on ug.group_id = g.group_id inner join user_ranks ur on u.user_id = ur.user_id inner join ranks r on ur.rank_id = r.rank_id; +------+-------------+---------+ | name | group | rank | +------+-------------+---------+ | kirk | command | captain | | rand | bridge crew | yeoman | +------+-------------+---------+ 47
  • 48. Issuing an order $issuer = Zend_Auth::getInstance()->getIdentity(); $u = new Users(); $subord = $u->find(2)->current(); $order = new Order(); $order->superior_user_id = $issuer->user_id; $order->subordinate_user_id = $subord->user_id; $order->detail = "Get your red shirt, it's time for an away mission."; $acl = new AclWrapper(); if (!$acl->isAllowed($issuer, $order, 'create')) { throw new Zend_Controller_Action_Exception( 'Not allowed to create order!' , 403); } $order->save(); 48
  • 49. Issuing an order $issuer = Zend_Auth::getInstance()->getIdentity(); $u = new Users(); $subord = $u->find(2)->current(); $order = new Order(); $order->superior_user_id = $issuer->user_id; You could move $order->subordinate_user_id = $subord->user_id; this check $order->detail = "Get your red shirt, onto the model it's time for an away mission."; $acl = new AclWrapper(); if (!$acl->isAllowed($issuer, $order, 'create')) { throw new Zend_Controller_Action_Exception( 'Not allowed to create order!' , 403); } $order->save(); 49
  • 50. Building the ACL class AclWrapper { public function isAllowed(User $role = null, Resource_Interface $resource = null, $privilege = null) { $acl = new Zend_Acl(); $groups = $user->findGroups(); foreach ($groups as $group) { $acl->addRole($group); } $acl->addRole($user, $groups); if (strpos($resource->getResourceId(), ':')) { $parent = new Zend_Acl_Resource($resource->getType()); $acl->addResource($parent); $acl->addResource($resource, $parent); } else { $acl->addResource($resource); } [...] 50
  • 51. Building the ACL class AclWrapper { public function isAllowed(User $role = null, Resource_Interface $resource = null, $privilege = null) { $acl = new Zend_Acl(); $groups = $user->findGroups(); Add Group roles foreach ($groups as $group) { Add the User role $acl->addRole($group); } $acl->addRole($user, $groups); if (strpos($resource->getResourceId(), ':')) { $parent = new Zend_Acl_Resource($resource->getType()); $acl->addResource($parent); $acl->addResource($resource, $parent); } else { $acl->addResource($resource); } [...] 51
  • 52. Building the ACL class AclWrapper { public function isAllowed(User $role = null, Resource_Interface $resource = null, $privilege = null) { $acl = new Zend_Acl(); $groups = $user->findGroups(); foreach ($groups as $group) { $acl->addRole($group); } $acl->addRole($user, $groups); if (strpos($resource->getResourceId(), ':')) { $parent = new Zend_Acl_Resource($resource->getType()); $acl->addResource($parent); $acl->addResource($resource, $parent); } else { $acl->addResource($resource); ':' means adding an instance } and its parent [...] 52
  • 53. Building the ACL foreach ($groups as $group) { foreach ($groups->findPermissions as $permission) { $assert = null; $classname = $permission->assert; if ( $classname && class_exists($classname) && is_subclass_of($classname, 'Zend_Acl_Assert_Interface') ) { $assert = new $classname(); } $op = ($permission->type == 'allow') ? 'allow' : 'deny'; $acl->$op($group, $resource, $permission->privilege, $assert); } } return $acl->isAllowed($role, $resource, $privilege); } } 53
  • 54. Building the ACL foreach ($groups as $group) { foreach ($groups->findPermissions as $permission) { $assert = null; $classname = $permission->assert; if ( $classname && class_exists($classname) && is_subclass_of($classname, 'Zend_Acl_Assert_Interface') ) { $assert = new $classname(); } Validate as much as possible! $op = ($permission->type == 'allow') ? 'allow' : 'deny'; $acl->$op($group, $resource, $permission->privilege, $assert); } } return $acl->isAllowed($role, $resource, $privilege); } } 54
  • 55. Asserting Superiority class IsSuperior implements Zend_Acl_Assert_Interface { public function assert( Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null) { if (!$role instanceof User) { throw new Zend_Acl_Exception('Assertion only applies to Users'); } if (!$resource instanceof Order) { throw new Zend_Acl_Exception('Assertion only applies to Orders'); } $supRank = $role->findRanks()->current(); $subRank = $resource->findUsersBySubordinate()->current(); return ($supRank->rank_id > $subRank->rank_id); } } 55
  • 56. Issuing an order $issuer = Zend_Auth::getInstance()->getIdentity(); $u = new Users(); $subord = $u->find(2)->current(); $order = new Order(); $order->superior_user_id = $issuer->user_id; $order->subordinate_user_id = $subord->user_id; $order->detail = "Get your red shirt, it's time for an away mission."; $acl = new AclWrapper(); if (!$acl->isAllowed($issuer, $order, 'create')) { throw new Zend_Controller_Action_Exception( 'Not allowed to create order!' , 403); } $order->save(); 56
  • 57. Conclusions Is this the right way? 57
  • 58. Attaching the ACL • Controller and Action? • Model and Method? • Business object and Action? • All of the above? 58
  • 59. Unit testing • Pass the Zend_Acl into your wrapper • Use a factory 59
  • 60. Caching the ACL • Build everything for the User? • Build everything for the Resource? • Build everything for everything! 60
  • 61. Advice • Think about what you want to protect • Test your solution with realistic data • Assume that you are wrong 61
  • 63. Feedback http://joind.in/2054 “...even a well presented talk by a charismatic speaker upset me.” 63