Apache Fortress SAML Demo

The aim of this tutorial is to connect Apache Directory Fortress with Spring Security SAML and a common Identity Provider – SSO Circle.com. It’s not intended to highlight all of the possible locations in code where security checks may be applied.  For that take a look at The Apache Fortress End-to-End Security Tutorial.


Fortress SAML Demo

Go to https://github.com/shawnmckinney/fortress-saml-demo, complete the steps under the README.

More info here: Fortress-Saml-Demo

Saml-Demo-Block-Diagram-Master

What Are Temporal Constraints?

Defined

Ability to control when an entity activation occurs based on time and date criteria.  Temporal constraints are typically applied during User and Role activation as part of an authentication or authorization check.

What Are They For?

Can be used to limit when a User may log onto or activate a particular Role within a security domain.  Follows the principle of least privilege as it ensures access rights are only granted when appropriate.

How Do They Work?

There may be policies to control what dates, times, and days of week a User may access a particular area of the system and in what Role.  Can also be used to enforce a lockout period when the User is inactive or otherwise away for an extended period of time.

Apache Fortress Temporal Constraints

Fortress allows constraints to be applied onto both User and Role entities.  There are rules that fire during an activation event (any policy enforcement API call):

  1. Can the entity be active on this Date?
  2. Is the entity within a lockout period?
  3. Has the entity exceeded a particular inactive period?
  4. Can the entity be used at this time?
  5. Can the entity be used on this day?
  6. Are there mutual exclusion constraints that prevent activating this entity?  (Roles Only)

These temporal constraint rules are pluggable and may be added, overridden or removed.

What is Delegated Administration?

Defined

The ability to control access on the security system itself.  This control is exercised inside the policy administration programs.

In addition to what functions may be executed, we must control which entities to operate on.  A common use case is to allow User X the ability to reset and unlock passwords only for Users within Organization Y.  Another is the administrator may only assign a specific subset of Roles to Users who reside inside their Organization.  Additionally we must also be able to limit an Administrator to a specific subset of Roles in which to Grant to a subset of Permissions.  Indeed every API that changes state inside the back-end security repository must be governed via a well understood delegated administration policy.


Administrative Role-Based Access Control (ARBAC)

Apache Fortress has implemented ARBAC02. [link to paper].  This is a formal model for Delegated Administration and builds on the ANSI RBAC specification.  The control is marshaled into three interfaces:

  1. Delegated Admin Manager – Provides CRUD for related entities like Administrative Roles and Permissions.
  2. Delegated Review Manager – Interrogation of Delegated Admin policy objects.
  3. Delegated Access Manager – Enforcement of Delegated Administration Policies.

1 & 2 are for management of the Delegated Admin policies themselves.  3 is for enforcement of Delegated Admin policies at runtime.


Delegated Admin Policy Enforcement

There are two types of controls:

  1. Ensure that the caller has the permission to call the security administrative method (e.g. addUser, addRole, addPermission,…)
  2. Ensure the caller is entitled to perform the function for a given organization (e.g. which Users and Permissions to grant access rights).

With Fortress, the Delegated Administration control is baked into its APIs.  The enforcement occurs during API invocation which means it can’t be circumvented by poorly implemented administrative programs.

In addition to control, every API invocation leaves an audit trail so you may determine what policies changed, by whom, when and where.

Enabling Java EE and Fortress Security inside an Apache Wicket Web App

JavaDukeJammingfortress100    Wicket-Image

Introduction

The aim of this tutorial is to demonstrate how a simple wicket web app can be converted to use java EE and fortress security.  It’s not intended to highlight all of the possible locations in code where security checks may be applied.  For that take a look at The Apache Fortress End-to-End Security Tutorial.


Course Prerequisites

Before starting, you need a working fortress environment up and running.  Complete one of the following:


 Steps to Enable Security in Wicket Sample

1. Download the fortress wicket-sample project

a. extract the zip

b. follow the instructions in README.md

You may now hit the sample web app:

http://localhost:8080/wicket-sample

no security

no security

This is the view you will see when clicking on link for Page1.  Despite what it says about rbac perms, it’s an example of an app that’s not secured.  Users are not required to logon and may navigate freely.

To enable security for this app, continue on…

The following instructions are duplicated by: README-ENABLE-FORTRESS.md


2. Add the Java EE security required artifacts

If you are using the wicket-sample source, this is already done.  It includes wicket components LoginPage.java, LogoutPage.java (plus associated markup files LoginPage.html, LogoutPage.html), and the static html files under the /login folder.  These files control the flow between the container and wicket with java EE security enabled.

java EE login page

java EE login page

more on java EE security

Declarative style of security, one with no api calls made by programmer (during logon).  This makes java EE security both error resistant and hardened to attack, though it tends to get in the way of the page flows.  We’ll cover this topic, in more detail, on a future post.


3. Edit the pom.xml

Prepare maven for fortress.

a. Uncomment the fortress web dependency at the top of the file.

 <!-- TODO STEP 3: uncomment for fortress security dependency: -->
 <dependency>
   <groupId>org.apache.directory</groupId>
   <artifactId>fortress-web</artifactId>
   <version>${project.version}</version>
   <classifier>classes</classifier>
 </dependency>

b. Uncomment the maven ant task near the bottom of the file.

This plugin calls the fortress load procedure during normal maven tasks like install or deploy.  The fortress load inserts the app’s security policy into ldap.  It can be overridden by passing param -Dnoload which tells the plugin not to execute.

 <plugin>
   <artifactId>maven-antrun-plugin</artifactId>
   <version>1.7</version>
   <executions>
   <execution>
     <phase>test</phase>
     <configuration>
     <target name="fortress-load"
       if="load.file"
       description="Loads wicket sample security policy into ldap">
...

At the completion of this step, the necessary binaries will be available to the app and the app’s security policy file will be ready to load.


4. Edit the web.xml

Prepare the app for fortress.

a. Uncomment the spring settings.

 <!-- TODO STEP 4a: uncomment to enable fortress spring bean injection: -->
 <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
 </context-param>

 <listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

Notice that we’re including a link to a spring context file: applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
...
  <bean id="accessMgr" 
    class="org.apache.directory.fortress.core.AccessMgrFactory"   
    scope="prototype"
    factory-method="createInstance">
    <constructor-arg value="HOME"/>
  </bean>

  <bean id="j2eePolicyMgr" 
     class="org.apache.directory.fortress.realm.J2eePolicyMgrFactory" 
     scope="prototype"
     factory-method="createInstance">
  </bean>
...

The context file holds the metadata necessary to wire the fortress objects in with their constructors and subsequently get injected into the web app as spring beans.

b. Uncomment the java ee security constraints from web.xml:

 <!-- TODO STEP 4b: uncomment to enable Java EE Security: -->
 <security-constraint>
    ...

Now container security has been enabled for this web app.  It authenticates, checks roles and maintains the session.

The wicket logout page is excluded from java EE security constraints.  Otherwise, a problem occurs preventing unauthorized users from logging out.

 <security-constraint>
   <web-resource-collection>
   <web-resource-name>app</web-resource-name>
     <url-pattern>/wicket/bookmarkable/org.wicketsample.LogoutPage</url-pattern>
   </web-resource-collection>
   <!-- OMIT auth-constraint -->
 </security-constraint>

5. Rename context.xml.example to context.xml

Prepare the app for the fortress realm.

<Context reloadable="true">
 <Realm className="org.apache.directory.fortress.realm.tomcat.Tc7AccessMgrProxy"
   debug="0"
   resourceName="UserDatabase"
   defaultRoles=""
   containerType="TomcatContext"
   realmClasspath=""
 />
</Context>

This file hooks a web app into the tomcat fortress realm which performs security functions like authenticate and isUserInRole. It’s also where the security session gets created by fortress.

more on the realm

The fortress realm’s proxy jar must be present under tomcat’s lib folder (as discussed in the quickstarts).

The proxy jar is a shim that uses a URLClassLoader to reach its implementation libs.  The proxy prevents the realm impl libs, pulled in as dependency to web app, from interfering with the container’s system classpath thus providing an error free deployment process free from classloader issues.  The proxy offers the flexibility for each web app to determine its own version/type of security realm to use, satisfying a variety of requirements related to web hosting and multitenancy.


6. Rename fortress.properties.example to fortress.properties.

Prepare fortress for either apacheds or openldap server usage.

Pick One:

a. ApacheDS

# This param tells fortress what type of ldap server in use:
ldap.server.type=apacheds

# ldap host:
host=localhost

# ldap port:
port=10389

# These credentials are used for read/write access to all nodes under suffix:
admin.user=uid=admin,ou=system
admin.pw=secret

# This is min/max settings for LDAP administrator pool connections that have read/write access to all nodes under suffix:
min.admin.conn=1
max.admin.conn=10

# This node contains fortress properties stored on behalf of connecting LDAP clients:
config.realm=DEFAULT
config.root=ou=Config,dc=example,dc=com

# Used by application security components:
perms.cached=true

# Fortress uses a cache:
ehcache.config.file=ehcache.xml

b. OpenLDAP

# This param tells fortress what type of ldap server in use:
ldap.server.type=openldap

# ldap host:
host=localhost

# openldap default port:
port=389

# These credentials are used for read/write access to all nodes under suffix:
admin.user=cn=Manager,dc=example,dc=com
admin.pw=secret

# This is min/max settings for LDAP administrator pool connections that have read/write access to all nodes under suffix:
min.admin.conn=1
max.admin.conn=10

# This node contains fortress properties stored on behalf of connecting LDAP clients:
config.realm=DEFAULT
config.root=ou=Config,dc=example,dc=com

# Used by application security components:
perms.cached=true

# Fortress uses a cache:
ehcache.config.file=ehcache.xml

7. Edit WicketApplication.java

Tell wicket about fortress sessions and objects.

a. Uncomment fortress session override.

Here we override app’s wicket session with a new one that can hold onto fortress session and perms:

 // TODO STEP 7a: uncomment save fortress session to wicket session:
 @Override
 public Session newSession(Request request, Response response)
 {
   return new WicketSession(request);
 }

b. Uncomment fortress spring bean injector.

Next we tell the app to use spring to inject references to fortress security objects:

 // TODO STEP 7b: uncomment to enable injection of fortress spring beans:
 getComponentInstantiationListeners().add(new SpringComponentInjector(this));

These steps are necessary to get fortress runtime wired into the sample app.


8. Edit WicketSampleBasePage.java

Get fortress objects injected to the wicket base page, enable fortress secured page links.

a. Uncomment fortress spring bean injection.

This step automatically instantiates the fortress objects needed for security processing.

 // TODO STEP 8a: enable spring injection of fortress bean here:
 @SpringBean
 private AccessMgr accessMgr;

 @SpringBean
 private J2eePolicyMgr j2eePolicyMgr;

These objects are used by the app to make AccessMgr calls to functions like checkAccess and sessionPermissions.

b. Uncomment call to enableFortress.

This performs the boilerplate security functions required by fortress during app session startup:

 // TODO STEP 8b: uncomment call to enableFortress:
 try
 {
   SecUtils.enableFortress( 
      this, ( HttpServletRequest ) getRequest().getContainerRequest(), 
      j2eePolicyMgr, accessMgr );
 }
 catch (org.apache.directory.fortress.core.SecurityException se)
 {
    ...
 }

c. Change to FtBookmarkablePageLink

The advantage here is other than a name change, everything else stays the same, and now the links are secured.

 // TODO STEP 8c: change to FtBookmarkablePageLink:
 add( new FtBookmarkablePageLink( "page1.link", Page1.class ) );
 add( new FtBookmarkablePageLink( "page2.link", Page2.class ) );
 add( new FtBookmarkablePageLink( "page3.link", Page3.class ) );

This component maps a page link to a fortress permission.  The wicket id passed in, e.g. page1.link, is converted to a fortress permission, objName: page1, opName: link.


9. Edit Page1.java, Page2.java, Page3.java

Enable fortress secured buttons.  Each page has three buttons.  Same as before, only the name changes.

a – i. change the button class name to FtIndicatingAjaxButton:

 // TODO STEP 9a: change to FtIndicatingAjaxButton:
 add( new FtIndicatingAjaxButton( "page1.button1" )

This component maps the buttons to fortress permissions.  The wicket id, e.g. page1.button1, is converted to a fortress permission, objName: page1, opName: button1.


10. Build & Deploy Web App

Deploy to tomcat server:

mvn clean tomcat:deploy -Dload.file

Or if already deployed:

mvn clean tomcat:redeploy -Dload.file

The -Dload.file system parameter tells maven to load the wicket sample security policy into ldap in addition to deploying the app.  Since the load needs to happen just once, you may drop it from future invocations:

mvn tomcat:redeploy

We’re done with setup.  Now onto testing…


Testing the Sample App Security Policy

The wicket-sample security policy is loaded automatically during maven deployment step.  The file:  wicket-sample-security-policy.xml

How to create an rbac policy was covered recently:

The Seven Steps of Role Engineering

The diagram below depicts the wicket sample role hierarchy and its user to role assignments:

sample security policy

sample security policy

  • wsBaseRole is inherited by all other roles
  • wsSuperUsers inherits wsUsers1Role, wsUsers2Role and wsUsers3Role
  • wsUser1 is assigned wsUsers1Role and has access to buttons on Page1
  • wsUser2 is assigned wsUsers2Role and can hit buttons on Page2
  • wsUser3 is assigned wsUsers3Role and has buttons on Page3
  • wsSuperUser is assigned wsSuperUser role has all pages and all buttons

Use Cases for Testing

a. wssuperuser/password

Receives links for Page1, Page2 and Page3.

wsSuperUser launch page

wsSuperUser launch page

b. wsuser1/password

Receives a page link for Page1.  May only view and click on Page1’s buttons.

wsUser1 launch page

wsUser1 launch page

c. wsuser2/password

Receives link for Page2.  May only view and click on Page2’s buttons.

wsUser2 launch page

wsUser2 launch page

d. wsuser3/password

Receives link for Page3.  May only view and click on Page3’s buttons.

wsUser3 launch page

wsUser3 launch page


More on sample security policy

As stated in the beginning, the sample wicket security controls are not comprehensive.  For example, a user may navigate by manually entering page urls thus sidestepping the secured page link component.  In this scenario the user will be prevented from clicking on buttons unless otherwise authorized.  Still, allowing users to navigate to unauthorized pages is a bad practice.  The Apache Fortress End-to-End Security Tutorial uses spring security controls to lock down pages.  There are many other ways – how would you do it?

The Seven Steps of Role Engineering

Defined

Role Engineering is the process by which an organization develops, defines, enforces, and maintains role-based access control. RBAC is often seen as a way to improve security controls for access and authorization, as well as to enforce access policies such as segregation of duties (SoD) to meet regulatory compliance.  Nov 5, 2014
— Oracle Corporation (Blogs)

Presentation

Link to slides for a related presentation, A Practical Guide To Role Engineering, JavaOne conference, October 27, 2015.


Project

Link to GitHub project corresponding to this topic: role-engineering-sample


Introduction

The Role engineering process takes us from a human readable policy syntax to what is loaded into an rbac engine and used by a given application or system.

Here we follow the ANSI RBAC (INCITS 359) spec which prescribes methods like:

This tutorial demonstrates role engineering techniques using standard rbac as applied to a sample set of security use cases.

There is a corresponding github project, written in Java that uses Apache Fortress to show how:

Role-Engineering-Block-Diagram-Masterhttps://github.com/shawnmckinney/role-engineering-sample


1. Define Security Use Cases for the Application

sample use case:

Role-Engineering-Sample-Use-Case

First we’ll describe the policies in a way humans can understand by writing them down as use cases translated from the diagram.

Use case definitions:

[ legend: red – roles | blue – objects | green – operations ]

use case #1 : User must authenticate before landing on the home page.

Every set of security use cases necessarily contains a logon step.  With rbac, it implies a call to the createSession api, where credentials are checked and roles activated.

use case #2 : User must be a Buyer before placing bid on auction or buying an item.

A role named ‘Buyers’ is granted rights to place bids and purchase auction items.  This use case requires a call to the checkAccess api which we’ll discuss later.

use case #3 : User must be a Seller to create an auction or ship an item purchased.

We add role ‘Sellers’, and grant the authority to create an auction and ship an item that has just been sold.

use case #4 : All Users may create an account and search items.

Another role, named ‘Users’, is granted the rights to create a new account and search a list of items up for auction.  It will be a base role that Buyers and Sellers both extend.

use case #5 : A particular user may be a Buyer, or a Seller, but never both simultaneously.

An interesting scenario to consider.  Perhaps a conflict of interest due to how they collide.  Not to worry, document and move on.


 2. Define the Roles in the App

The use cases must now be converted into entity lists.  Though still human readable, the new data formats are aligned with RBAC.

Create a list of Role names.  Use names pulled from use cases 2, 3, and 4.

Add Roles:

  • role name: “Users” description: “Basic rights for all buyers and sellers”
  • role name: “Buyers” description: “May bid on and purchase items”
  • role name: “Sellers” description: “May setup auctions and ship items”

Buyers and Sellers inherit from Users as described in use case #4.

Add Role Inheritance Relationships

  • child name: “Buyers” parent name: “Users
  • child name: “Sellers” parent name: “Users

Don’t forget the role combination rule in use case #5:

Role Activation Constraint

  • role name: “Buyers
  • role name: “Sellers
  • type: “DYNAMIC
  • cardinality: “2

 3. Define the Resources and Operations

RBAC Permissions are mappings between objects and operations.  Here we list the perms described in use cases 2, 3 and 4.

Add Permissions:

  • object name: “Item” description: “This is a product that is available for purchase”
    • operation name: “search” description: “Search through list of items”
    • operation name: “bid” description: “Place a bid on a given product”
    • operation name: “buy” description: “Purchase a given product”
    • operation name: “ship” description: “Ships a given product after sale”
  • object name: “Auction” description: “Controls a particular online auction”
    • operation name: “create” description: “May start a new auction”
  • object name: “Account” description: “Each user must have one of these”
    • operation name: “create” description: “Ability to setup a new account”

 4. Map the Roles to the Resources and Operations

Get the list of grants.  Again, these mappings naturally derive from the use cases.

Grant Permissions to Roles:

  • role: “Buyers” object name: “Item” oper: “bid
  • role: “Buyers” object name: “Item” oper: “buy
  • role: “Sellers” object name: “Item” oper: “ship
  • role: “Sellers” object name: “Auction” oper: “create
  • role: “Users” object name: “Item” oper: “search
  • role: “Users” object name: “Account” oper: “create

 5. Create the RBAC policy load file

Hand to the analyst, trained in the particulars of the RBAC engine, the entity lists created in steps 2, 3 and 4.  That info will be hand keyed into graphical interface screen, or (better yet) translated to machine readable syntax and loaded automatically by recurrent batch job.

role-engineering-sample-security-policy.xml – download from github.
...
<addrole>
  <role name="Role_Users" description=“Base Role for Buyers and Sellers"/>
  <role name="Role_Buyers" description="May bid on and purchase products"/>
  <role name="Role_Sellers" description="May start auctions and ship items"/>
</addrole>

<addroleinheritance>
  <relationship child="Role_Buyers" parent="Role_Users"/>
  <relationship child="Role_Sellers" parent="Role_Users"/>
</addroleinheritance>

<addpermgrant>
  <permgrant objName="SellersPage" opName="link" roleNm="Role_Sellers"/>
  <permgrant objName="BuyersPage" opName="link" roleNm="Role_Buyers"/>
  <permgrant objName="Item" opName="bid" roleNm="Role_Buyers"/>
  <permgrant objName="Item" opName="buy" roleNm="Role_Buyers"/>
  <permgrant objName="Item" opName="ship" roleNm="Role_Sellers"/>
  <permgrant objName="Auction" opName="create" roleNm="Role_Sellers"/>
  <permgrant objName="Item" opName="search" roleNm="Role_Users"/>
  <permgrant objName="Account" opName="create" roleNm="Role_Users"/>
</addpermgrant>

<addsdset>
  <sdset name="BuySel" 
         setmembers="Role_Buyers,Role_Sellers" 
         cardinality="2“
         setType="DYNAMIC" 
         description="Cannot activate both at once."/>
</addsdset>

<addpermobj>
  <permobj objName="Item" description=“..." ou="p1" />
  <permobj objName="Auction" description=“..." ou="p1" />
  <permobj objName="Account" description=“..." ou="p1" />
</addpermobj>

<addpermop>
  <permop objName="Item" opName="bid" description="Bid on a given product"/>
  <permop objName="Item" opName="buy" description="Purchase a given product"/>
  <permop objName="Item" opName="ship" description="Place a product up for sale"/>
  <permop objName="Item" opName="search" description="Search through item list"/>
  <permop objName="Auction" opName="create" description="May start a new auction"/>
  <permop objName="Account" opName="create" description="Ability to add a new account"/>
</addpermop>
...

At the completion of this step, the RBAC policy is loaded into the engine and ready for use.


 6. Add Permission Checks to Application

It’s time to get the developers involved because there will be code that looks (something) like this:

RbacSession session = getSession();
Permission permission = new Permission( "Item", "bid" );
return accessMgr.checkAccess( session, permission );

How to instrument the checks is up to you.  Obviously you won’t hard code the perms.  Observe proper isolation to decouple your app from the details of the underlying security system.  Favor declarative checks over programmatic.  The usual concerns.

A previous post offers ideas, if willing to get dirty hands 🙂

Apache Fortress End-to-End Security Tutorial


 7. Assign Roles to the Users

Before users may access the app, they must be assigned one or more of the corresponding roles.  These relationships may be recorded into the RBAC datastore with a batch script (as below), but often times performed by GUI, e.g. during application enrollment.

Sample user to role assignment policy file
...
<adduserrole>
  <userrole userId="johndoe" name="Role_Buyers"/>
  <userrole userId="johndoe" name="Role_Sellers"/>
  <userrole userId="johndoe" name="Super_Users"/>
  <userrole userId="ssmith" name="Role_Buyers"/>
  <userrole userId="rtaylor" name="Role_Sellers"/>
</adduserrole>
...

The following diagram depicts the role to role and user to role relationships defined by this policy.

role-role and user-role relationships

role-role and user-role relationships


RBAC Extra Credit

A. What happens when johndoe signs on?

(Will both roles be activated into the RBAC session?)

No, one of the roles must be discarded due to SoD constraint.

begin johndoe logon trace using fortress console
Enter userId:
johndoe 
 name :Sellers
 msg :validate userId [johndoe] failed activation of assignedRole [Sellers] 
 validates DSD Set Name:BuySel Cardinality:2

RBAC allows the caller to select one or more roles during createSession.  So we may call with johndoe passing either of their assigned roles in the argument list.  This process is called selective role activation.  Thus John Doe may be a Buyer during one session and Seller the next, never both at once.

more on createSession:

Session createSession(User user,
                    boolean isTrusted)
                      throws SecurityException

The following attributes may be set when calling this method


B. What if we want to prevent someone from being assigned both roles?

 Use Static Separation of Duties instead

...
<addsdset> 
  <sdset name="BuySel" 
         setmembers="Role_Buyers,Role_Sellers" 
         cardinality="2“ 
         setType="STATIC" 
         description="Cannot assign both to one user."
  /> 
</addsdset>
...

What happens now when we try to assign a user both roles?

begin assignUser trace in fortress console
Enter userId:
janedoe
Enter role name:
sellers
ERROR: assignUser failed SSD check, rc=5088
Role [sellers], SSD Set Name [buysel2], Cardinality:2

Remember, constraints applied at role…

  • assignment time: are Static Separation of Duties (SSD)
  • activation time: are Dynamic Separation of Duties (DSD)

C. What perms will a Buyer get?

When a user activates the Buyers role what perms will they have?

begin ssmith perm trace using fortress console
**perm:1***
object name [Account]
operation name [create]

**perm:2***
object name [Item] 
operation name [search]

**perm:3***
object name [Item]
operation name [buy]

**perm:4***
object name [Item] 
operation name [bid]

 D. What about a Seller?

When a user activates the Sellers role what perms will they have?

begin rtaylor perm trace using fortress console
**perm:1***
object name [Account]
operation name [create]

**perm:2***
object name [Item] 
operation name [search] 

**perm:3***
object name [Auction] 
operation name [create]
 
**perm:4***
object name [Item]
operation name [ship]

 E. Why do Buyers and Sellers have common perms?

Notice that Buyers and Sellers both have access rights to Account.create and Item.search.  The reason is both extend a common base role: Users.


F. The above use case is overly simplistic.  Can we do something more realistic?

The Apache Fortress End-to-End Security Tutorial delves into fine-grained access control of data tied to customers.  It demonstrates how to implement a complicated set of requirements, verified with automated selenium test cases.

User to Role Relations in Tutorial

user to role relations in security tutorial

user to role relations in security tutorial

Role to Permission Relations in Tutorial

role to permission relations in security tutorial

role to permission relations in security tutorial


Apache Fortress End-to-End Security Tutorial

The tutorial provides a how-to guide for applying end-to-end security enforcement across a sample Java Web environment using Java EE, Spring and Apache Fortress security.

Requirements covered include authentication, authorization and confidentiality. Both declarative and programmatic enforcement controls will be used.  Authorization granularity ranges from coarse (java EE, spring) to fine (fortress).

To get started, follow the instructions in the README located on github:

https://github.com/shawnmckinney/apache-fortress-demo

More info here:  anatomy-secure-web-app-lrtf-2017.pdf

How Much is One Millisecond Worth To You?

For those who don’t keep these kinds of details in their heads a millisecond is 1/1000th of a second.

With respect to security processing what can be done in that time increment – can you perform a fine-grained permission check over the network?  How about logging results into a remote database?

Would you believe me if I told you we can perform both operations within that allotment of time on a modest hardware configuration?  What if I also tried to tell you that over eleven thousand of these requests may be performed a second with the same response time?

Such were the results as documented in this series of benchmarks:

fortress-rbac-accelerator-pdp-benchmark-report

Read more about the accelerator rationale here:

the-case-for-a-policy-decision-point-inside-the-ldap-server

Fortress RBAC Accelerator PDP Benchmark Report

Benchmark Overview

This post provides a summary of a recent benchmark effort for the Fortress RBAC Accelerator.  The RBAC accelerator uses LDAPv3 extended operations to perform the following access control functions:

  1. Create Session – attempts to authenticate client; if successful, initiates an RBAC session by activating one or more user roles
  2. Check Access – determines if user has access rights for a given resource
  3. Add Active Role – attempts activation for a given role into user’s RBAC session
  4. Drop Active Role – deactivates a given role from user’s RBAC session
  5. Delete Session – deletes the given RBAC session from the server
  6. Session Roles – Returns the active roles associated with current session

The result of each of the above functions are persisted to LMDB for audit trail.

Benchmarks performed using a Jmeter test client to drive load for CheckAccess (#2).  The server hosts the OpenLDAP daemon which has the RBAC accelerator overlay.

Client Machine

  • operating system: ubuntu 13.04
  • kernel: 3.8.0-32-generic
  • processor: Intel® Core™ i7-4702MQ CPU @ 2.20GHz × 8
  • memory: 16GB (doesn’t use anywhere close to that)
  • Java version 7

Server Machine

  • operating system: ubuntu 14.04
  • kernel: 3.13.0-32-generic
  • processor: Intel® Core™ i7-4980HQ CPU @ 2.80GHz × 4
  • memory: 8GB
  • OpenLDAP version: 2.4.39

Test Details

  • 25 threads running on client
  • each thread runs checkAccess 50,000 times
  • 1,250,000 total
  • Client CPU load: approximately 50%

Test Results

  • Response time: 1 millisecond
  • Throughput: 11,533 transactions per second
  • Server CPU load: approximately 85%

The Case for a Policy Decision Point inside the LDAP Server

Feature image from: http://kb.linuxvirtualserver.org/wiki/Building_Scalable_Network_Services

Why on earth would you do that?

We all understand that runtime characteristics change as processes get moved around the network.  Having problems with network io?  Move the database daemon to the same tier as the client process.  Worried about file io?  Store the data in memory as opposed to disk.  etc…

These same notions apply for system architecture with respect to security.  Location of policy enforcement, decision, and database processes hugely impact the overall welfare of your organization’s computational systems.

With these kinds of thoughts, let’s move the security processes around and see what happens.

But first, we’ll define them:

1. Policy Enforcement Point (PEP)

Invoked by client programs for security policy enforcement.  These gatekeepers are embedded directly into their host thus require platform specific bindings.  The less impact to their host, the better.

2. Database (DB)

Invoked by PDPs to store security credentials, attributes and activity logs.  An important concern is speed; to be used correctly, it’s used often.  Another important concern is reliability; the integrity of its data is mission critical.

3. Policy Decision Point (PDP)

Invoked by PEPs and dependent on a DB.  Responsible for computing:

  • authentication – with passwords or keys
  • authorization – with attributes or permissions
  • audit trail – identify subjects, decisions, time/date/locations, and resources

Three types of PDPs

  • Type 1 – runs in-process to PEP, with out-of-process DB
  • Type 2 – runs out-of-process to PEP, with out-of-process DB
  • Type 3 – runs out-of-process to PEP, with in-process DB

PDP Type 1 (runs in-process to PEP)

The Tomcat JDBC Realm is a Type 1 PDP.  It functions both as PEP and PDP.  Other Type 1’s include Apache Fortress, Shiro and Spring Security.  Most of the open-source security frameworks are this type.  The policy decisions happen synchronously inside the client process.

Type 1 PDP interaction between processes

The PEP and PDP process reside on one tier; the DB process on another.

The PEP and PDP process reside on one tier; the DB process on another.

Benefits of Type 1 PDP

Type 1 PDP advantages
  • simple – only security framework and DB required
  • widely available
  • works well for single deployments of stand-alone apps
Type 1 PDP disadvantages
  • more code exposed to the client (making deployment harder)
  • more load on the client
  • more memory consumed on the client
  • more network io traffic on the client
  • fewer platforms supported (can it run on Java, NET, PHP, Python, and all the others?)

PDP Type 2 (runs out-of-process to PEP and DB)

Here the PDP and DB both run out-of-process to the PEP.  These types of PDPs are more complicated and usually obtained as separate COTS or OSS products.  For example, CA Siteminder, Tivoli Access Manager, Oracle Access Manager, Shibboleth, CAS and many others.

Type 2 PDP interaction between processes

The PEP, PDP and DB processes reside on separate tiers from one another.

The PEP, PDP and DB processes reside on separate tiers from one another.

Benefits of Type 2 PDP

Type 2 PDP advantages
  • less network traffic on client
  • less cpu consumed on client
  • less memory consumed on client
  • less code exposed to client (making deployment simpler)
  • more platforms supported (simple to code PEP ‘shims’ to communicate with centralized PDPs)
Type 2 PDP disadvantages
  • more security processes to maintain due to PEP, PDP and DB all running separately (increasing management burden)
  • poor response time due to extra network hops
  • poor throughput due to PDP reliance on heavyweight communication protocols (xml/json/http)

PDP Type 3 (runs out-of-process to PEP and in-process to DB)

The PDP and DB run in-process and the PEP is out-of-process.  The advantage here is offloading computations from the PEP reducing load and traffic from the client.  It gains speed over the Type 2 because of the embedded database.

Type 3 PDP interaction between processes

The PEP process resides on one tier; the PDP and DB process on another.

The PEP process resides on one tier; the PDP and DB process on another.

Benefits of Type 3 PDP

Type 3 PDP advantages
  • all of Type 2
  • embedded database speed gain
  • embedded database reliability gain
Type 3 PDP disadvantages
  • poor throughput due to reliance on heavyweight communication protocols (xml/json/http)

The Case for a PDP in OpenLDAP

The OpenLDAP RBAC Accelerator is a Type 3 PDP.  It has all the advantages of its type without the disadvantage because using extended LDAP protocols is very efficient.  It runs inside of the OpenLDAP slapd daemon and uses LMDB, which is the fastest embedded, key-value database available, giving a nice turbo boost to read/write speeds.

Now let’s return to the original question:  Why on earth would you do that?

To enable authentication, fine-grained authorization, and audit trail on every platform.  To ease concerns for high cpu, memory, network, and file io consumption.  And to use well understood technologies that can be widely distributed.

Why another open source iam product?

A question that has been lingering.  It’s fair game, but before I get around to actually answering, let’s remember how we got here.

Late 90’s

Before the first open source iam product existed we had standard policy enforcement protocols in use.  Examples include Java’s ee security & jaas. Unix had PAM, sudo and kerberos.  Windows, NTLM and SPNEGO.  There were web-based protocols like HTTP basic auth and ISAPI.

IAM Complete Solution Defined

Those policy enforcement mechanisms didn’t meet the wider requirements of a complete solution:

  • extensible and pluggable policy enforcement services
  • centralized policy decision point services
  • common policy administration services
  • common policy information services
  • audit and review capabilities

The gaps made us scramble to meet the need.

Early to Mid 2000’s

Commercial vendors ruled.  Several more policy enforcement protocols appeared including liberty, saml, ws-*, xmlsecurity and xacml.  Those in need either built or bought because open source iam solutions were barely in existence.

There were many open source projects that provided the legos to build with.

2008

The era of opportunity for open source innovation.  Most of the technical problems were solved.  All one had to do was assemble a solution using the building blocks available in the public domain.

But not another access control framework.  Needed a complete solution.

2009

As code construction commenced on fortress, many open source policy enforcement frameworks became widely used, such as spring security and opensso, but still no complete solution.

2011

Around the the time of the first fortress release the situation changed.  Sun’s merger with Oracle foretold the end of the commercial vendor stranglehold creating a void in which companies like Symas, Linagora, Evolveum, and Tirasa sprung complete solutions.

Today

Now that we have several complete open source iam solutions on the market, the industry continues to focus on policy enforcement standards, the latest being oauth, uma and open id connect.

But we continue to struggle because uniform policy enforcement is the tip of iceberg.  More benefit comes through shared policy decision and admin services.  This promotes reuse of infrastructure and data across organizational, vendor and platform boundaries.

Tomorrow

Policy enforcement protocols will continue to be volatile and ill-equipped.

Standards-based policy decision and admin services will continue to be needed.

So that Vendor A’s PEP can plug into Vendor B’s PDP, and Vendor C’s PAP can plug in Vendor D’s PIP.

Why Fortress

Based on ansi incits 359, our best hope for standardizing the complete iam solution.