Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A new design is being proposed, but it is not finalized. Anyone who is interested is welcome to comment, critique, and add suggestions.

Security-Aware Artifacts

Introduction

The current OFBiz security implementation uses indirect security control - where permission services are used to control access to OFBiz artifacts. Permission services are small scripts that evaluate user permissions, determine if a user is related to a piece in data in some way, and other tasks. In the end, the script returns an access-granted or access-denied result (hasPermission) that is used to control access to the artifact(s) managed by the script.

...

A permission service can be extended by assigning a Service Event Condition Action (SECA) to it. If the primary permission service returns hasPermission=false, the SECA is triggered and an additional permission service is run. The result of the second permission service controls access to the artifact(s).

Disadvantages

Since the current OFBiz security implementation uses indirect security control, there is no direct connection of permission logic to the artifact that the logic is trying to control access to. Access to a particular artifact could be (and often is) controlled by a handful of different scripts. While this may appear to be an advantage (because it's flexible), it becomes a problem when something about the artifact changes that requires a change in access control. Permission scripts that control the artifact must be tracked down and updated.

...

Any time a new artifact is created that needs access control, a new script needs to be written to control it.

A Different Approach

What if we took the job of artifact access control away from the permission services and gave it to the artifacts themselves? What if every artifact was security-aware?

Instead of an artifact's access being controlled in a handful of places, it is controlled in one place - within the artifact itself. There is no complicated intermediary code that must consider all possible interactions a user might have with a set of artifacts. Since all artifacts are security-aware, fine grained control is possible. There is no need for cumbersome conditional logic to control an artifact - the artifact controls itself.

Design Overview

There are three key players in the Security-Aware Artifact design:

...

Default behaviors for types of artifacts will be well documented, so the developer and OFBiz administrator will know exactly how permissions will affect each artifact.

Design Details

If each artifact has its own set of permissions, there could be potentially thousands of permissions - an administration nightmare! It would be helpful to have artifact permissions organized in a hierarchy - so that permissions defined higher up in the hierarchy are inherited by artifacts lower in the hierarchy. The hierarchy will reduce the number of permissions needed.

...

  1. The entity engine passes an unfiltered list of entities to the service, the service picks matching records from the list and returns them. The advantage to this approach is we can use existing code to implement it. The disadvantage is it is inefficient.
  2. The service returns an EntityCondition that represents the constraint, and the entity engine merges that EntityCondition with any condition it already has. The advantage to this approach is the list of entities is filtered by the database. The disadvantage is there is no way to return an EntityCondition in mini-language. Mini-language would have to be extended, or the EntityCondition would have to be constructed in a Beanshell or Groovy script, or the filters would have to be written in Java.

The Authorization Manager

The Authorization Manager (AM) is a piece of software responsible for managing users and and their permissions.

...

Although design implementation is beyond the scope of this document, for the sake of illustration let's say the AM builds an internal tree structure from all of the user's permissions. The tree structure would look just like the artifact hierarchy - but it only includes artifact identifiers the user has permissions for. Using the requesting artifact's identifier (and working from left to right), the AM "walks the tree" - looking for permission flags and permission services. While the AM walks the tree, it keeps a copy of the last permissions found. Every time new permissions are found, they replace the previous copy (that is how permission inheritance is achieved). Eventually, the AM will encounter the end of the tree or the end of the artifact identifier. When that happens, the AM returns the last permissions found.

The OFBiz User Group

Sometimes it is desirable to assign some basic permissions to ALL OFBiz users. Mailing list comments indicate that some installations meet that need by using a custom CreateUser service, or a SECA that adds the permissions to new users, or some other solution.

...

In this design, that need is fulfilled by having a default (or "out-of-the-box") User Group called OFBiz Users. The Authorization Manager will make all new users a member of that group, and consequently that group will be included in all permission checks. The Authorization Manager will throw an exception any time an attempt is made to delete the "OFBiz Users" user group.

The Not-Logged-In User

The Security-Aware Artifact design introduces a fundamental problem: How do you get a user logged in? The various artifacts needed to log in a user won't operate without a UserLogin GenericValue present (and necessary permissions assigned to that user).

In this design, the problem is solved with a Not-Logged-In user account. That user's account is disabled, and it is assigned only the permissions needed to get a user logged in. Front-end processors (event/request handlers, etc) create the Not-Logged-In UserLogin GenericValue so that artifacts needed for login can be used.

The Super User

It is common to have a way to identify an administrator user, or super user. There are two ways that can be accomplished in this design:

...

Artifacts must treat the admin permission as expected - it is the same as having all permissions. If the admin permission appears in a list of permission flags, it takes precedence - all other permission flags and permission services are ignored.

Artifact Reuse

Handling permissions with reused artifacts is greatly simplified with the Security-Aware Artifacts design. The problems associated with the existing intermediary design plus coarse-grained permissions are eliminated.

...

Not all artifact reuse will be this simple. But the more complicated scenarios can be accommodated by finding ways to "graft" the reused artifact into the new component's artifact hierarchy - which will provide a means to assign permissions to the reused artifact.

Proposed Implementation Details

Note

DEJ20090528: After thinking about this data model more and discussing it with a couple of others I don't think we should use what I have outlined below and instead we should create a more normalized data model. The main difference would be a few different entities in place of the bloated and denormalized SecurityArtifactAuth entity.

Existing Entities to Use:

UserLogin
UserLoginSecurityGroup
SecurityGroup

New Entities to Add:

SecurityArtifactAuth
-securityArtifactAuthId*
-securityGroupId
-securityArtifactGroupId
-authTypeEnumId (NotSpecified, Allow, Deny, AlwaysAllow (overrides Deny))
-authorizedActionEnumId (View, Create, Updated, Delete, All)
-recordViewEntityName
-recordFilterByDateEnumId (True, False, ByName)
-userMatchFieldName - for record level matching will lookup in recordViewEntityName view-entity for the currently logged in userLoginId or partyId, and if this field is set it will use this field name to match against, otherwise it will look for the userLoginId field or the partyId field in the view-entity
-authServiceName - this service will be called according to the pattern of current auth services and must return true/approved in addition to anything else passing that is populated in this entity

...

NOTE: we may want to move some fields between SecurityArtifactAuth and SecurityArtifactGroupMember as some things could go in either place, but should only go into one and which one they make sense in is a good question (and I've taken a pass here, but we may want to change it)

Possible Entities to Add:

-Could use these to make view-entity configurations on the fly (this may be WAY too technical for most users, so considering this a pretty low priority)

...

DynamicViewEntityJoin
entityAlias
relEntityAlias
keyName
relKeyName
relOptional

Order of Artifact Checking - For WebApp Request

An ExecutionContext object is maintained that has an artifactAccessStack. In the artifactAccessStack as each artifact calls/users another artifact it is pushed onto the stack, and when it finished it pops itself off the stack. With this at any point we can see which artifacts were used to get to where we are. For the higher-level webapp-specific artifacts this will be kept in the request, for the widgets this will be kept in their context, for services it will be in the context, and for entities it will be in a thread-local variable. This is called an ExecutionContext because it may be used for more than just security/authorization purposes, and in fact we should refactor the current code that keeps track of the user and other things in ThreadLocal variables (mostly for the entity engine) so that they are in this ExecutionContext object.

...

Note

The following hierarchy has been called a "dynamic hierarchy" and it is not finalized. There is an alternative to it called "static hierarchy" - mentioned above.

Example Chain:

  • Component
    • WebApp
      • ControllerRequest
        • ControllerRequestEvent
          • Service
            • Entity
              • EntityField
      • ControllerView
        • WidgetScreen
          • Service
            • Entity
              • EntityField
          • FtlFile
            • WidgetScreen
          • WidgetForm
            • WidgetFormField

Authorization Manager Implementation

Wiki Markup
The existing security classes will be refactored so the Security abstract class is converted to an interface, and the OFBizSecurity class will implement the interface. The Authorization Manager methods will be added to the Security interface, and the existing methods will be deprecated. This will make the conversion backward-compatible with existing installations. \[I refactored the security classes on my local copy, and it works fine. I can commit those changes if there are no objections. \-Adrian\]

Access Control Scenarios

1. User X can use Artifact Y for anything that artifact supports and on any data (where "artifact" is a screen, web page, part of a screen or page, service, general logic, etc). Details

...