Dynamic Code Evaluation in Java – Clever or Sloppy?

I am trying to create a flexible ACL framework in Java for my application.

Many ACL frameworks are built on a whitelist of rules, where a rule is in the form of owner:action:resource. For example,

  • “JOHN can VIEW resource FOOBAR-1”
  • “MARY can VIEW resource FOOBAR-1”
  • “MARY can EDIT resource FOOBAR-1”

This is attractive because the rules can easily be serialized/persisted to a database. But my application has complex business logic. For example,

  • “All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized”
  • “All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized”

Upon first thought, it would be a nightmare to devise a database schema that could handle infinitely complex rules such as these. Therefore, it seems as though I would need to “bake” them into the compiled application, evaluate them for each user, and then produce owner:action:resource rules as a result of the evaluation. I want to avoid baking the logic into the compiled application.

So, I was thinking of representing a rule in the form of predicate:action:resource, where the predicate is a boolean expression that determines whether a user is allowed. The predicate would be a string of a JavaScript expression that could be evaluated by Java’s Rhino engine. For example,

  • return user.getDept() == 1 && user.seniority > 5;

In doing so, the predicates could easily be persisted to the database.

Is this clever? Is this sloppy? Is this gimmicky? Is this over-engineered? Is this safe (apparently, Java can sandbox the Rhino engine).

10

Piping dynamic data into an interpreter of your implementation language is usually a bad idea, since it escalates the potential for data corruption into a potential for malicious application takeover. In other words, you are going out of your way to create a code injection vulnerability.

Your problem can be better solved by a rules engine or maybe a domain-specific language (DSL). Look those concepts up, there is no need to reinvent the wheel.

11

I did this, and I recommend that you don’t.

What I did was write all the business logic in Lua, and stored that Lua script in a database. When my application started up it would load and execute the script. That way I could update the business logic of my application without distributing a new binary.

I invariably found that I always needed to update the binary when making changes. Some changes were in the Lua script, but I’d invariably have a list of changes that needed to be made, and so I almost always ended up having to make some changes in the binary and some changes in the Lua script. My imagination that I could avoid distributing binaries all the time simply didn’t pan out.

What I found much more helpful was to ease the distribution of binaries. My application automatically checks for updates on startup, downloads, and installs any update. My users are thus always on the latest binaries that I’ve pushed. There is almost no difference between a change in the binary and a change in the scripts. If I did it again, I’d put even more effort to making the update seamless.

I would not have the database contain code. But you can do something similar by having the database contain function names and then using reflection to call them. When you add a new condition, you have to add it to your code and your database, but you can combine conditions and parameters that get passed to them to create quite complex evaluations.

In other words, if you have numbered departments, it would be easy to have a UserDepartmentIs check and a TodayIsAfter check and then combine them to have a Department=2 and Today>03/15/2016. If you then want to have a TodayIsBefore check so that you can end date the permission, you have to write the TodayIsBefore function.

I haven’t done this for user permissions, but have done it for data validation, but it should work.

XACML is the solution you are really looking for. It is a type of rules engine that is focused on access control only. XACML, a standard defined by OASIS, defines three parts:

  • an architecture
  • a policy language (which is really what you want)
  • a request / response scheme (how you ask for an authorization decision).

The architecture is as follows:

  • the Policy Decision Point (PDP) is the core part of the architecture. It is the component that evaluates incoming authorization requests against a known set of policies
  • the Policy Enforcement Point (PEP) is the piece of code that protects your application / API / service. The PEP intercepts the business request, creates a XACML authorization request, sends it off to the PDP, receives a response back, and enforces the decision inside the response.
  • the Policy Information Point (PIP) is the component that can connect the PDP to external sources of data e.g. an LDAP, a database or a web service. The PIP comes in handy when the PEP sends a request e.g. “Can Alice view doc #12?” and the PDP has a policy that requires the user’s age. The PDP will ask the PIP “give me Alice’s age” and will then be able to process the policies.
  • the Policy Administration Point (PAP) is the place where you manage the entire XACML solution (defining attributes, writing policies, and configuring the PDP).

eXtensible Access Control Markup Language - XACML Architecture

Here’s what your first use case looks like:

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

Your second use case would be:

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

You can combine both use cases into a single policy by using references:

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

And you’re done!

You can read more on XACML and ALFA from:

  • the XACML Developer’s Blog
  • the XACML Developer’s YouTube channel

What you really want here is XACML. It pretty much gives you exactly what you want. You don’t necessarily have to implement the full architecture with all the roles being completely separated… if you only have a single application, you can probably get away with integrating the PDP and PEP into your app with balana and the PIP is whatever your existing user database is.

Now, anywhere in your app you need to authorize something, you create a XACML request which has the user, the action, and the context, and the XACML engine will make the decision based on the XACML policy files you’ve written. These policy files could be kept in the database or on the filesystem, or wherever you want to keep the configuration. Axiomatics has a nice alternative to the XACML XML representation called ALFA that’s a little easier to read than the raw XML, and an Eclipse plugin to generate XACML XML from ALFA policies.

2

We did this at my current company, and we’re very happy with the results.

Our expressions are written in js, and we even use them to restrict the results the users can get from querying ElasticSearch.

The trick is making sure that enough info is available to make the decision, so that you can really write whatever perms you want without code changes, but at the same time keeping it fast.

We are not really worried with code injection attacks, as the permissions are written by those that have no need to attack the system. And the same applies to DOS attacks like the while(true) example. The admins of the system have no need to do that, they could just remove everybody’s permissions…

Update:

Something like XACML seems to be better as a central auth management point for an organization. Our use case is slightly different in that our clients tipically have not an IT department to run all that. We needed something self-contained but tried to preserve as much flexibility as possible.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật