Skip navigation.

Policy Managers Guide

  Previous Next vertical dots separating previous/next from contents/index/pdf Contents Index View as PDF   Get Adobe Reader

Defining Rules

This topic describes the basic steps to defining rules. Before you begin designing rules, however, you should know which resources you want to protect with your rules. The following sections describe key concepts and tasks for securing resources, and discusses how to write rules to protect those resources:

 


Overview of Securing Resources

A resource represents an underlying entity that can be protected from unauthorized access using security roles and security policies. Examples of resources include Enterprise Applications and Web Applications. Figure 3-1 illustrates the overall process for securing resources.

Figure 3-1 Securing Resources

Securing Resources


 
  1. Administrators typically assign users to groups based on an organizational hierarchy, however this is not necessary. You can use the Administration Application to configure an external user repository or you can add directories, users, and groups using the console. A user can be a member of multiple groups; and, a group may be a member one or more other groups. Figure 3-1 shows three groups with two users each. User 1 and User 3 are members of multiple groups. BEA recommends assigning users to groups to increase efficiency for administrators who work with many users, since groups change less frequently than users.
  2. Administrators create roles based on established business procedures. The security role consists of one or more role rules, each of which may include one or more constraints. A constraint specifies the circumstances under which a particular group is granted or denied the role on the resource.
  3. At runtime, the security service compares the user profile against the role rule to determine whether users in the group are dynamically granted a role. This process is referred to as role mapping. In Figure 3-1, Group 2 is the only group that is granted a security role. Individual users can also be granted a role, but this is a less typical practice. BEA recommends assigning privileges to roles (rather than users or groups) to secure resources, because doing so promotes separation of duty and increases efficiency for administrators who work with many users.
  4. Administrators create a security policy based on established business procedures. The security policy consists of one or more policy rules, each of which may include one or more constraints. The policy statement specifies the circumstances under which a particular role is granted access to a user or group for a protected resource.
  5. The security service uses the security policy, user profile and resource to determine whether or not to grant access to the protected resource. Only users who are granted the security role (either directly or through group membership) can access the resource. In Figure 3-1, User 3 and User 6 can access the protected resource because they are members of Group 2 and Group 2 is granted the necessary security role.

 


Designing and Writing Rules

A rule is a statement of what action a user or group can perform on a resource. To design and write rules, follow the instructions and guidelines presented in the following topics:

Rule Structure

Security policies use rules to grant or deny users permission or roles on resources. A rule is a structured statement of what action a user or group can perform on a resource. The general rule (policy or role) structure is:

effect(right, resource, subject[user]) IF constraint [AND/OR/NOT] constraint;

Where:

effect is GRANT, DENY, or DELEGATE

right is a privilege or role

resource is the entity being protected by the rule

subject is a user, group, or role

constraint is one or more conditions (for example., AND, OR, NOT) under which the rule applies.

A right, resource, or subject can also be a list.

These rules follow a grammar that is similar to English grammar. The structure of a rule is like a sentence and the policy elements can be thought of as parts of that sentence, for example:

GRANT (action, resource, subject, delegator) IF constraint;

The GRANT portion of the rule represents the effect and designates permission for the user, group or role (subject) to access the specified resource. For instance, the rule:

GRANT(any, //app/policy/acme/payroll, //user/acme/agarcia/);

grants any privileges related to the acme payroll application to the user agarcia in the acme directory.

All access to resources is considered denied until explicitly granted with a rule. Once an entitlement is granted, you must explicitly deny it with a DENY rule to revoke that right (or you can simply remove the GRANT rule). Explicit denies are very powerful and cannot be overruled. Sometimes you may want to explicitly deny an entitlement to ensure that user or group can never gain access to a specific resource. Similarly:

DENY (//priv/view, //app/policy/acme/payroll, //sgrp/acme/receptionist/);

denies the view privilege related to the acme payroll application to everyone belonging to the group called receptionist in the acme directory.

A delegation rule allows you to share the role or privileges of one user with another. In addition, you might add a constraint that restricts this sharing to a certain time of day or date range, for example:

DELEGATE (//priv/any, //app/policy/acme, //user/acme/joe/, //user/acme/larry/);

delegates any privileges related to the acme application from larry to joe.

Group Inheritance

Users or groups inherit the right (privilege or role) of any group to which they belong, either directly or through their parents. Group inheritance allows each user in the group to assume all the group rights to which they are members, either directly or indirectly through their parent groups (or the groups of their parents). Both users and groups can have parent groups but only groups can have children. Group inheritance is very powerful as it allows you to define entitlements once and have the rules apply to all members.

Note: BEA recommends that you define your role granting policy using groups, rather than individual users. Rules written directly on users should be used for exceptions or short-lived rules to handle unusual or infrequent situations.

It is important to note that parent groups usually have fewer rights than their children. As you move from the bottom of the resource tree to the top, the groups inherit the rights of their ancestors and are directly granted.

Direct and Indirect Group Membership

The immediate members of a group are called direct members. Direct members appear immediately below their parent on the inheritance tree. A member that has an inherited membership is called indirect member. An indirect member appears to either side of the parent group, rather than directly below. The collection of all groups available, either directly or through inheritance, is referred to as group closure.

Closed-world Assumption

The policy evaluation strategy imposes a closed-world assumption. This means that before you specifically create a rule granting rights, users and groups have no rights. You must grant rights with a rule before a user can do anything. Because of this closed-world assumption, all rights to are implicitly denied until rules grant specific rights as needed.

With the closed-world assumption, a group initially has no rights granted. The closed-world assumption has the powerful advantage of having your application error on the side of caution. That is, if you forget to apply a rule, someone may be denied access rather than be granted access to something to which they should not have access. Thus, a denied user usually will let you know there is a problem (and, if they do not, that is probably okay).

Without the closed-world assumption (or if you grant all rights to every user), a user with unintended rights may never tell you they have access, which may have disastrous consequences. Once you grant a right, you must explicitly deny it to revoke that right. Explicit DENY rules cannot be overruled. Figure 3-2 shows an example of a typical group hierarchy.

Figure 3-2 Typical Group Hierarchy

Typical Group Hierarchy


 

Group Hierarchy Examples

The following two examples demonstrate the application of rules to a group hierarchy. They are both based on the same group hierarchy as Figure 3-2. Explicit DENY rules always take precedence over GRANT rules. However, the implied DENY of the closed-world assumption does not. For example, in Figure 3-3, Reginald receives the grant through the Traders role even though there is an implied deny on the Managers role.

Figure 3-3 Application of a Grant Rule to a Group Structure


 

Application of a Grant Rule to a Group Structure


 

In Figure 3-4, all the groups are granted the right through their Employees parent and then the Managers group is specifically denied the right with a DENY rule. Notice that Reginald is denied the right despite being a descendent of the Employees group.

Figure 3-4 Application of a Deny Rule to a Group Structure

Application of a Deny Rule to a Group Structure


 

After seeing how groups work, you might wonder why you can clone a user in the Administration Console, when you can create a user with the same qualities by creating a group for both users, and then assign that group to any parent groups, rather than assigning individual users. This method does create two users with the same permissions, but there are two potential drawbacks to this approach:

Restricting Rule Inheritance

Rules are inherited in a number of ways:

You can restrict rule inheritance by limiting its applicability. For instance, if you limit the applicability of the original GRANT, then you do not need to create a DENY rule. This can prevent you from getting into scenarios where DENY is too restrictive. However, you can use these same techniques to prevent DENY rules from restricting more than you would like them to. For example, this rule is applicable to any resources under the "protected" resource:

GRANT(//role/admin, //app/policy/www.myserver.com/protected, //sgrp/acme/manager/) IF sys_obj_q = //app/policy/www.myserver.com/protected;

where: sys_obj_q is a system attribute on which the query is performed. For more information on the system attributes (which begin with the prefix sys_), see Request Attributes. The constraint in this rule keeps it from being applicable to the descendants of the protected resource, thus blocking rule inheritance. In this case, you need to add this rule to grant managers the admin role to financial, assuming financial is virtual. If it is defined, you can just write the second rule:

GRANT(//priv/read, //app/policy/www.myserver.com/protected, //sgrp/acme/manager/) if sys_obj_q = www.myserver.com/protected/financial;

or

GRANT(//role/admin, //app/policy/www.myserver.com/protected/financial, //sgrp/acme/manager/); 

The next rule restricts the rule to apply only to users who are members of both the manager and controller groups.

GRANT(//role/admin, //app/policy/www.myserver.com/protected, //sgrp/acme/manager/) if sys_obj_q //sgrp/acme/controller/ IN sys_subjectgroups;

If you have lots of resources with the same leaf name, you can also write the policy like this:

GRANT(//role/admin, //app/policywww.myserver.com, //sgrp/acme/manager/) if sys_obj = protected;
GRANT(//role/admin, //app/policywww.myserver.com, //sgrp/acme/manager/) if sys_obj = financial;

or using pattern matching:

GRANT(//role/admin, //app/policywww.myserver.com, //sgrp/acme/manager/) if sys_obj like "*/protected"
GRANT(//role/admin, //app/policywww.myserver.com, //sgrp/acme/manager/) if sys_obj like "*/financial"

Resource Attribute Inheritance

Like users and groups, descendant resources also inherit the attributes of any parent resource. Resource inheritance allows each child resource in the tree to assume all of the attributes of the parent resource. Resource attribute inheritance is also very powerful as it allows you to define attributes on the parent resource, and have the attributes be inherited to all child resources automatically.

It is recommended that you define your attributes on parents, rather than individual child resources. When an attribute is explicitly defined for a child, the attribute overrides any inherited value. Rules written directly for child resources should be used for exceptions or short-lived rules to handle unusual circumstances.

Constraints

Constraints limit when or under what circumstances the rule applies. All constraints start with the keyword IF and end with a semicolon (;). Simple constraints usually contain two values separated by an operator. The following example shows a rule with a constraint:

GRANT(//priv/any, //app/policy/MyApp, //sgrp/ORG/allusers/) IF purchaseAmount < 2000;

In this rule, any user of the resource MyApp who is in the ORG directory is allowed to spend any amount less than $2000.

Constraints are very useful because they allow your application to have different responses based on your dynamic application, data, or business environment. For example, you might use a constraint to grant a user access to a resource only during certain hours of the day.

To limit the user in the previous example to having privileges only in December and January, you would add the constraint:

IF month IN [december, january];

To limit the user to accessing the application from a computer with a particular static IP address, you would add the constraint:

IF clientip = 207.168.100.1

Several types of attributes are provided that are automatically computed for you (see Declarations).

Note: Once a grant result is determined, the rest of the applicable GRANT rules are ignored. If your business logic requires the evaluation of multiple constraints, you must combine them into a complex constraint using an AND operator.

Declarations

Declarations allow administrators to add new keywords to the policy language. These keywords can represent new data types, constants, attributes, or evaluation functions. Declaration names must start with a letter or an underscore. There are four types of declarations:

For programmers, type declarations are enumerated types. Type declarations declare the composition of the enumerated type and define an ordered list of acceptable values. Attributes and evaluation functions declare an instance (variable) of a built-in or enumerated type. Attributes are based on predefined or user-defined types, and evaluation functions are based on Boolean types.

Type Declarations

A type declaration defines a class or group of values from which you can create constants and attributes. A type declaration is a template for constants and attributes. For example, an attribute of the built-in type integer may only have integer values. Many attributes can use the same type declaration, but each attribute is limited to one type, and this type cannot change without deleting and recreating the attribute. For example, you could have dozens of integer attribute variables, but each one is based on the same integer type declaration. You could think of a type declaration as the cookie cutter and attributes as the cookies.

Several types are provided for you to use:

Note: Different types of declarations cannot have the same names as they share the same namespace. For example, you cannot have a constant and an attribute both called account_number. In addition, the values of enumerated types share this namespace. So, continuing with our example, you could not create constants or attributes with the values Crows, Ducks, or Geese (or Birds).

User-Defined Types

You can also create your own types. For example, you might create a type called Insurance that contains the values Truck, Car and Motorcycle. You would declare it like this:

enum Insurance = (Truck, Car, Motorcycle);

Once you declare a type, you must declare an attribute to use the type in your rules. You can declare an attribute based on your new type like this:

cred Transportation : Insurance;

Once declared, you must give the attribute a value, like this:

Transportation = Motorcycle;

As mentioned earlier, you can compare the value based on your type by testing if the value is greater to or less than a value in the list. For example, to make your list order represent the relative level of insurance of a vehicle, you might use this constraint to see if your Transportation attribute is greater than a Car enumeration:

IF Transportation > Car

If Transportation is a Motorcycle, given the order of the list defined earlier, this would return TRUE and your constraint allows implementation of the rule.

Constant Declarations

A constant is a named value or set of values that does not change at runtime. For instance, if you set a constant named Rate to 12, rules can then refer to the constant Rate rather than using its literal value, 12. Constants are used to:

Constants are especially useful if the value changes periodically and you use the constant in more than one location. For example, if you enter a rate value 12 into multiple rules, you need to individually change each one. Instead, if you use the constant Rate, you can edit the value once and have it take effect in every rule that refers to it.

Simple Constant

Here are some examples of simple constant declarations:

CONST Insurance = "home";
CONST InterestRate= 12;

Constants can contain other constants in their value:

CONST ClosurePoints = 2;
Or even enumerated types:
CONST FavoriteVehicle = Motorcycle;

If you enclose Motorcycle in quotation marks, this constant would contain a string without any special meaning. Using our earlier example, without the marks, it is recognized as the special value Motorcycle of type Vehicles.

Constants List

A constant can also contain a list of more than one value. For example, you could define a constant called MyColors with the values red, green, blue, white and black.

Constant lists differ from enumerated type lists. Types are used to restrict the values an attribute may contain. For example, an integer may only contain numerals and a constant list is simply a declared list or range of values with no implied order. A constant list always has an underlying type. In the previous example, the underlying type is a string. You can also create lists of any other type.

There are a few rules for defining constant lists:

Here are some examples of constant lists:

CONST MyPets = ["Dogs", "Cats", "Birds"];
CONST CurrentAge = [1..120];
CONST WorkWeek = [monday..friday];
CONST Transportation = [Motorcycle];

You can even place another constant list within a constant list, like this:

CONST FamilyPets = ["Ferrets", "Birds", MyPets];

One benefit of a constant list is that it saves you from having to write multiple rules or string-together constraints to test if a value belongs in a group. Without constant lists, you would need to compare your value to each independent constant, rather than perform one quick test to see if the value belongs in the list. For example, given the constant list:

CONST Manager = ["Bert", "Marty", "Sandy"];

If you want to find out if your string attribute called Active contains a value that is in the Manager list, you could write constraints to test for these three possibilities:

IF Active = "Bert"
OR Active = "Marty"
OR Active = "Sandy";

or you could simply write:

IF Active IN Managers

As mentioned before, there is no implied order to the Manager list. So, even if Bert is clearly a more privileged Manager than Sandy, this test is invalid.

If "Bert" > "Sandy" 

For the test to work, you need to create an enumerated type containing the three managers names.

Evaluation Function Declarations

An evaluation function is a declaration that returns one of two values: true or false. These values come from a pre-defined function and are included by using a plug-in extension that a programmer creates specifically for your application. Additionally, you can use any of the built-in evaluation functions available in all applications.

For instance, your programmer might create a plug-in for your accounting application that includes an evaluation function called Overdrawn that contains the results of a calculation of whether the account was overdrawn for that month. A constraint for a deny rule might use that function like this:

[Deny user access to something] IF Overdrawn();

Like functions and procedures in programming, evaluation functions can take zero or more parameter values, which are passed to the plug-in. For example, if you wanted to provide the overdrawn amount, you might use it like this:

[Deny user access to something] IF Overdrawn(500);

Evaluation functions can dynamically take different numbers or types of parameter values each time they are referenced in a rule. It is up to the programmer writing the evaluation function code to correctly handle the parameters.

Authorization Caching Expiration Functions

Authorization caching allows the system to cache the result of an authorization call and use that result if future identical calls are made. The cache is smart and automatically invalidates itself if there is a policy change or other client side change that would affect the authorization results. The cache is not smart enough to know when authorizations depend on dynamic data. Dynamic data includes date and time values, as well as evaluation plug-ins that reference external sources. If you are using authorization caching you need to set expiration times on rules that reference dynamic data. For additional information on caching, see the Performance and Caching, in the BEA WebLogic Enterprise Security Administration Guide.

Note: By default, authorization caching is turned off.

Table 3-1 lists the expiration functions for the authorization cache that let you set an expiration time for the decision. This way you can instruct the cache to only hold the value for a given period of time, based on Greenwich Mean Time (GMT), or not to hold it at all.

Table 3-1 Expiration Functions for Authorization Cache 

Function

Argument Type

Description

valid_for_mseconds
integer

Valid for a given number of milliseconds.

valid_for_seconds
integer

Valid for a given number of seconds.

valid_for_minutes
integer

Valid for a given number of minutes.

valid_for_hours
integer

Valid for a given number of hours.

valid_until_timeofday
time

Valid until the specified time on the date the evaluation is performed.

valid_until_time24
integer

Valid until the specified time on the date the evaluation is performed.

valid_until_hour
integer

Valid until the specified hour on the date the evaluation is performed.

valid_until_minute
integer

Valid until the specified minute of the hour the evaluation is performed.

valid_until_date
Date

Valid until the specified date.

valid_until_year
integer

Valid until the specified year.

valid_until_month
month_type

Valid until the specified month of the year the evaluation is performed.

valid_until_dayofyear
integer

Valid until the specified day of the year the evaluation is performed

valid_until_dayofmonth
integer

Valid until the specified day of the month the evaluation is performed.

valid_until_dayofweek
Dayofweek_type

Valid until the specified day of the week the evaluation is performed.

valid_until_timeofday_gmt
time

Valid until the specified time on the date the evaluation is performed in GMT time.

valid_until_time24_gmt
integer

Valid until the specified time on the date the evaluation is performed in GMT time.

valid_until_hour_gmt
integer

Valid until the specified minute of the hour the evaluation is performed in GMT time.

valid_until_minute_gmt
integer

Valid until the specified minute of the hour the evaluation is performed in GMT time.

valid_until_date_gmt
Date

Valid until the specified date in GMT time.

valid_until_year_gmt
integer

Valid until the specified year in GMT time.

valid_until_month_gmt
month_type

Valid until the specified month of the year the evaluation is performed in GMT time.

valid_until_dayofyear_gmt
integer

Valid until the specified day of the year the evaluation is performed in GMT time.

valid_until_dayofmonth_gmt
integer

Valid until the specified day of the month the evaluation is performed in GMT time.

valid_until_dayofweek_gmt
Dayofweek_type

Valid until the specified day of the week the evaluation is performed in GMT time.


 

For example, if you had the following rule:

GRANT(//priv/order,//app/restaurant/breakfast,//group/customers/
allusers) if hour < 11;

And if authorization caching is enabled, you could write the following rule:

GRANT(//priv/order,//app/restaurant/breakfast,//group/customers/allusers) if hour < 11 and valid_until_hour(11);

With authorization caching, the result of this rule is cached until 11:00 AM, at which time it expires.

Not calling valid_until_hour results in caching the grant decision until the next policy distribution. So you can see that if you are using authorization caching it is important to update your time dependent rules appropriately.

Attribute Declarations

An attribute is a variable that you can use in your rules. Attributes store values that are predefined or dynamically defined at runtime.

Declaring an attribute allows you to associate an instance of that attribute with an identity or a resource. For example, you can declare a identity attribute named "email" of type "string", and then associate email addresses to users.

Attributes make rules more legible by replacing certain constraint values with logical names. You can use attributes to put values in constraints that depend on conditions unknown when you write the rule, such as timeofday. Attributes contain values for your input data that your rules can manipulate. That is, they can serve as variables, for example, in our earlier example, account_balance could be used as an attribute.

There are four ways to use attributes:

Attributes are specific instances of a declared type. For example, an attribute of the type integer can only contain an integer value. Attributes can represent any type whether provided as part of the product or defined by the you. Here are some examples of attribute declarations:

cred month : month_type;
cred timeofday : time;
cred pencils_swiped : integer;

Static Attributes

Many attributes are specific instances of a declaration type. These attributes are often user (identity) attributes. For example, if you had a type called ColorType, you might have the static credentials HairColor and EyeColor, which are both of type ColorType. You can attach these static attributes to a user. Table 3-2 lists some examples of user attributes.

Table 3-2 User Attributes

Instance

Type

MonthBorn

month_type

ArrivalTime

time

Pencils_needed

integer


 

As previously discussed, there are several attribute types. Attributes differ from constants in that their value may change, but not the name and value type. Depending on the user making the request, a different value can be calculated for the attribute. In contrast, constants have a static value, as well as a static name and type. The declaration for a user attribute is attached to one or more directories. Because of this, all users in the same directory have the same user attribute names but not necessarily the same values for those attributes. Attributes can be applied to users, groups, and resources; however, each one behaves a bit differently.

Identity Attributes

User attributes store information about an individual user. For instance, you could have an attribute called AgeRange that stores a range of dates. Attributes are associated with a directory through a directory schema. The schema states that all users of a given directory have a given set of available attributes. Additionally the schema determines if the attribute value is a list.

You can also assign attributes to groups (although groups may only contain list attributes). Thus, users can inherit the attributes of all groups to which they belong. However, a user can still have a unique value for an inherited attribute. If you do not assign the user attribute a value, then the user inherits the value of the attribute from the group. This is how group attributes provide default attribute values for users who are members of those groups. If a user has the same attribute as a group, but a different value is assigned to the user attribute, the value of the user attribute always takes precedence of the value of the group attribute.

Even an empty string, " ", is considered a value for purposes of this rule. Therefore, if you do not assign a value, the user attribute does not take precedence over a group attribute of the same name. However, if you placed an empty string in the user attribute, it does take precedence.

Group attributes behave very differently from user attributes. Group attribute values are cumulative — if the same attribute exists in more than one place in the inheritance path of a user, the values of the attributes are merged and passed on to the user. For example, assume you have a user called Bob, and Bob is a member of the Manager group, which in turn is a member of the Employee group. If both Manager and Employee both have an attribute called WorkPlace with the values primary and secondary respectively, Bob would inherit a WorkPlace attribute with the value primary and secondary (a list attribute). In fact, to support this merging of attribute values, all group attributes must be list attributes. If the attribute merging finds the same value more than once, it eliminates the redundancy from the final list value.

Resource Attributes

Like the other attributes, resource attributes store information about the entity to which they belong. For example, the Banking application might have an attribute called Version that contains the current version number for the application, denoted as a string.

Resource attributes behave differently from user or group attributes. While they do inherit attributes and their values, they do not merge any values of redundant attributes. If the same attribute exists in more than one place in an tree, the resource first attempts to take the attribute from itself. Failing that, the resource takes the value of the attribute from the first resource above it on the tree that contains the attribute. The attributes of the same name on still higher nodes are ignored; once an instance of the attribute is found, the search ends.

For example, assume that you have an application resource called Banking that contains a variety of banking features. Deposit is a resource of the ATMCard application, which in turn is an application node below the Banking organization node. If both the ATMCard resource and the Banking application have the Version attribute defined with a value (and Deposit does not), Deposit inherits the value of the Version attribute from ATMCard. The Banking Version attribute is ignored.

Dynamic Attributes

A dynamic attribute is an attribute with a value that may change at policy evaluation time. Dynamic attributes have their value set by the provider, your application, or through a plug-in function. These attributes can have any type of value.

Additionally, plug-ins can be registered to compute the value of dynamic attributes.These plug-ins can retrieve the values of other attributes and use them to compute the attribute value needed.

Time and Date Attributes

Numerous time and date system attributes are pre-defined. Most system attributes allow you to use comparison and range operators. Table 3-3 lists the built-in time and date attributes provided for you to use.

Table 3-3 Built-In Time and Date System Attributes 

Attribute

Value

Range or Format

time24 
integer 

0-2359

time24gmt1 
integer 

0-2359

dayofweek 
Dayofweek_type

Sunday-Saturday

dayofweekgmt 
Dayofweek_type

Sunday-Saturday

dayofmonth 
integer 

1-31

dayofmonthgmt 
integer 

1-31

dayofyear 
integer 

1-366

dayofyeargmt 
integer 

1-366

daysinmonth 
integer 

28-31

daysinyear 
integer 

365-366

minute 
integer 

0-59

minutegmt 
integer 

0-59

month 
month_type

January-December

monthgmt 
month_type

January-December

year 
integer 

0-9999

yeargmt 
integer 

0-9999

timeofday 
time 

HH:MM:SS

timeofdaygmt 
time 

HH:MM:SS

hour 
integer 

0-23

hourgmt 
integer 

0-23

currentdate 
Date

MM/DD/YYYY

currentdategmt 
Date

MM/DD/YYYY


1. gmt is an abbreviation for Greenwich Mean Time


 

Request Attributes

There is a set of system attributes that contain details of the request. Table 3-4 describes these attributes and provides and example of each one.

Table 3-4 Built-In Request System Attributes 

Attribute

Value

Range or Format

sys_defined

Evaluation function

Returns true if all arguments passed to it are defined attributes (either single valued or list). Using an undefined attribute in a rule causes a runtime error. This can occur when the value of the attribute is determined from the application code, either through the context handler or the resource object. If there is a chance that the attribute does not have a value, then use the sys_defined evaluation function to ensure that a value exists before it is used. For example

grant() if sys_defined(foo) and foo = "bar";

sys_external_attributes

list of strings

A resource attribute set through the Administration Console on an application resource to indicate what attributes are needed for dynamic evaluation. This contains a list of attribute names.

sys_rule_subj_q

string

Qualified subject user or group name in the currently evaluated rule: //user/wles/system/

sys_rule_subj

string

Unqualified subject user or group name in the currently evaluated rule: system

Servername

string

Name of the server, where an ARME process is running.

sys_rule_obj_q

string

Qualified resource name for the currently evaluated rule: //app/policy/foo

sys_rule_obj

string

Unqualified resource name for the currently evaluated rule: foo

sys_rule_priv_q

string

Qualified current rule privilege: //priv/write

sys_rule_priv

string

Unqualified current rule privilege: write

sys_subjectgroups_q

list of string

List of groups to which the current user belongs: ["//sgrp/wles/admin/," "//sgrp/wles/managers/"]

sys_subjectgroups

list of strings

List of unqualified group names to which user belongs: ["admin", "managers"]

sys_dir_q

string

Directory of the user: //dir/wles

sys_dir

string

Directory of the user, unqualified form: wles

sys_user_q

string

Current user: //user/wles/system/

sys_user

string

Current user: unqualified form: system

sys_obj_type

enumeration

Set through the Administration Console on the resource. Valid values include:

  • Organizational node (orgnode)

  • Application node (appnode)

  • Binding node (bndnode)

  • Application Binding node (bndappnode)

  • Resource node (resnode)

sys_obj_distribution_point

Boolean enumeration {yes, no}

Distribution point set through the Administration Console on the resource. Setting this to yes, displays the resource on the distribution page as a potential point of distribution.

sys_suppress_rule_exceptions

Boolean enumeration {yes, no}

Set through the Administration Console to indicate whether to continue evaluation if a rule with missing data is encountered.

sys_app_q

string

Name of the binding resource for the resource on which query is performed: //app/policy/WLES/admin

sys_app

string

Unqualified name of the binding resource for the resource on which the query is performed: admin

sys_obj_q

string

Resource on which the query is performed: //app/policy/foo/bar

sys_obj

string

Resource on which the query is performed: bar

sys_priv_q

string

Effect of the current rule: //priv/foo

sys_priv

string

Unqualified form of the effect of the current rule: foo

sys_privilege

string

The action referenced in the context of a role mapping request.

sys_direction

enumeration

Defines the direction of authorization: once, post or prior.


 

Writing Policy for Web Server Web Applications

This section discusses writing security policy for web applications that are protected using either of the Web Server Security Service Modules (SSMs): the IIS Web Server SSM or the Apache Web Server SSM.

In the context of a web application, a policy defines the rules that enforce security to protect your web application from unauthorized access. A security policy defines who can do what, where, and when.

The resource that the web application policy protects is a URL. The resource is expressed as a BEA WebLogic Enterprise Security representation, which separates the resource and the action. The action is the method: GET, HEAD, POST, PUT.

When writing security policies for web applications hosted on web servers you must take the resource format, the action format, and the application context (information relevant to the request environment) into consideration.

For more information, see the following topics:

Resource Format

The resource format passed to the provider is a portion of the full URL. The fully qualified URL is available in the context as "url". The resource format is as follows:

/path/to/directory/page.html

Using this resource format allows the Web Server Security Service Module to handle many virtual servers, each server with their own separate policy.

Action Format

The action passed through to the provider is the method name from the HTTP protocol. GET, POST, HEAD, PUT, or some other custom action (if the web server supports it).

Application Context

The application context provides a mechanism to write authorization policy based on request attributes such as query parameters, cookies, or header information.

An application context is passed through to the Authorization and Role Mapping providers and is associated with any audit records logged. This context contains values relevant to the request environment at the time the provider processes the call. The values in the context are not prefixed with key names that segment the context into related values. If a query string name and HTTP header name collide, only one will be represented in the application context. The order in which names are added from the HTTP request is undefined.

The Web Server Security Service Module (SSM) supports the following context keys:

Note: All context keys are returned as strings, including date, which is normally a type.

When you write security rules for web applications that are protected by a Web Server SSM, you add the context key value pair (name/value) to the constraint. For example the rule:

grant ( //priv/any, //app/policy, //sgrp/allusers/ ) if accept-language like "*us_en*";

where accept-language is the name and "*us_en*" is the value.

grants any privilege on any resource to all users whose browser is configured to accept United States English.

The rule:

grant ( //priv/any, //app/policy, //sgrp/allusers/ ) if session.accesscount < 100;

grants any privilege on any resource to all users 100 times within the session. On the 101st evaluation of this rule within the session access will be denied.

Header Context Key (HEADERNAME)

Header context keys return values in the HTTP request header. This key is returned as a string. Any value in the header can be retrieved and so there is no hard-coded set of keys in this context. The HEADERNAME component of this context key is case sensitive, and specifically linked to the HTTP protocol. Examples of keys often available are: "date", "if-modified-since", "referrer", or "user-agent".

Note: The date key, which is usually a type, is returned as a string.

Query Context Key (VARNAME)

The Query context key returns values that are on the URL query-string. This key is returned as a string. The VARNAME portion of this key is case sensitive and refers to the query string variable encoded within the request. For example, if the URL includes a query such as ?test=endcoded%20char, the security policy rule query is:

 "if query.test= "encoded char"

Cookie Context Key (COOKIENAME)

The cookie context key returns values passed to the web server as cookies. This key is returned as a string. The COOKIENAME portion is this key is case sensitive and refers to the name of the cookie passed to this request from the browser. The value of the cookie returned is application specific and may need further decoding

Using Named Keys in the Web Application Policy

In addition to using elements of the resource to map the resource to the web application resource hierarchy in the administration server, the named values themselves can be referenced directly in policy constraints. For example, to write a policy on policy2.asp so that a policy only applies to the file if there is a mode=view argument, you would write the following constraint:

grant( //priv/any, //app/policy/mywebapp/policy2.asp, //sgrp/allusers/ ) if if mode="view";

This rule applies the constraint to access to the policy2.asp file if mode is either an HTTP header or a query string argument.

Web Application Context Handler

The Web Server SSM implement a context handler that provides contextual information from the HTTP request to the security framework. This information includes HTTP header, query arguments, and cookies. All information is in a single namespace. Therefore, there is the possibility of name collisions between the name/value pairs.

Retrieval of Response Attributes

The Web Server SSM retrieves response attributes during the authorization process and provides them in a form that a layered web application could use. For more information on response attributes, see Using Response Attributes

 


Designing More Advanced Rules

There are two ways to can create and implement rules:

All rules follow a standard structure:

GRANT|DENY|DELEGATE (privilege|role, resource, subject|delegator]) IF constraint;

You can extend the basic rule syntax to encompass very complex situations by grouping rules and adding constraints.

You use each rule component to specify a particular aspect of the rule. The functions of the rule components are as follows:

Syntax requirements for basic rules include:

Multiple Components

You are not limited to one role, privilege, resource or subject per rule. You may specify sets by enclosing them in brackets [ ] and separating the individual items with commas. For example:

GRANT(any, //app/policy/MyApp, [//user/ORG/USER21/, //user/ORG/USER22/]);

Rule Constraints

A constraint is a statement that limits when or under what circumstances permission is granted, denied or delegated. All constraints start with the keyword IF. The following is an example of a rule with a constraint:

GRANT(any, //app/MyApp, //user/ORG/USER21)
IF UserBudget < 2000;

Comparison Operators

Constraints support the comparison operators listed in Table 3-5.

Table 3-5 Comparison Operators 

Symbol

Operation

Applicable Types

=

Equal to

All

!=

Not equal to

All

>

Greater than

All except String

<

Less than

All except String

=>

Greater than or equal to

All except String

=<

Less than or equal to

All except String

LIKE

Matches regular expression

String

NOTLIKE

Does not match regular expression

String

IN

Included in a list

List of any type

NOTIN

Not included in a list

List of any type


 

Regular Expressions

This section summarizes basic rules for writing regular expressions along with some simple examples for use with constraints.

There are two operators, LIKE and NOTLIKE, that are used to perform regular expression matching on attribute values or string literals. This is typically used for pattern matching on resource names. For example, the following rule provides access (GET) to all JPGs in the a web application (//app/policy/MyWebApp).

GRANT(//priv/GET, //app/policy/MyWebApp, //role/webusers)
IF sys_resource LIKE ".*\\.JPG"; 

Regular Expression Syntax

The regular expression syntax follows certain rules.

Any character that is not a special character matches itself. Special characters are:

   +     *     ?     .     [     ]     ^     $

A backslash (\) followed by any special character matches the literal character. For example:

"\*u"

matches "u".

A period (.) matches any character. For example:

".ush"

matches any string containing the set of characters, such as "Lush" or "Mush".

A set of brackets ([]) indicates a one-character regular expression matching any of the characters in the set. For example:

"[abc]"

matches either "a", "b", or "c".

A dash (-) indicates a range of characters. For example:

"[0-9]" 

matches any single digit.

A caret (^) at the beginning of a set indicates that any character outside of the set matches. For example:

"[^abc]"

matches any character other than "a", "b", or "c" not including an empty string.

The following rules are used to build a multi-character regular expressions.

Parentheses (( )) indicate that two regular expressions are combined into one. For example:

(ma)+ 

matches one or more instances of "mad's".

The OR character ( | ) indicates a choice of two regular expressions. For example:

bell(b|ies) 

matches either "belly" or "bellies".

A single-character regular expression followed by an asterisk (*) matches zero or more occurrences of the regular expression. For example:

"[0-9]*" 

matches any sequence of digits or an empty string.

A single-character regular expression followed by an plus sign (+) matches one or more occurrences of the regular expression. For example:

"[0-9]+" 

matches any sequence of digits but not an empty string.

A single-character regular expression followed by a question mark (?) matches either zero or one occurrence of the regular expression. For example:

"[0-9]?"

matches any single digit or an empty string.

A concatenation of regular expression matches the corresponding concatenation of strings. For example:

[A-Z][a-z]* 

matches any word starting with a capital letter.

When you use a regular expression that contains backslashes, the constraint evaluator and the regular expression operation both assume that any backslashes are used to escape the character that follows. To specify a regular expression that exactly matches "a\a", create the regular expression using four backslashes as follows:

LIKE "a\\\\a"

Likewise, with the period character "." you need to include two backslashes in the expression:

LIKE "\\."

Constraint Sets

There are two operators, IN and NOTIN, used to test the memberships of sets in your constraint. A constraint set is a definition of a set of items, notated by one or more values separated by commas, enclosed in square brackets, and prefaced with either the keyword IN or NOTIN. For example, rather than writing:

. . . IF NextMonth = january or
. . . NextMonth = february or
. . . NextMonth = march;

You can write:

. . . IF NextMonth IN [january, february, march] ;

The keyword IN means in this set of values, and NOTIN means not in this set of values. Neither keyword is case sensitive.

You can also specify a range of values in a set of constraints. For example, the statement:

IF age NOTIN[1..100]

says if the age value is not between 1 and 100 (inclusive), then the statement is true. The keywords IN and NOTIN work well with attributes based on enumerated types and constant sets.

String Comparisons

You can test for specific text strings in your constraints by using the keywords LIKE and NOTLIKE. For example, assume you have a user attribute called GroupID. This attribute contains a string of data indicating information about the group the user belongs to:

UserQualities = "59NY20BREQ";

To check for and exclude users in the New York office, you can test the GroupID attribute for NY as follows:

(Grant Rule) IF GroupID NOTLIKE "*NY*";

where * represents any number of characters. Similarly, if you want to ensure that the user was in New York, you can add this constraint:

(Grant Rule) IF GroupID LIKE "*NY*";

Similar to IN and NOTIN, LIKE and NOTLIKE are not case sensitive.

To compare a string to a policy element in the constraint, replace the first characters of the element with a wildcard. Normally, the system does not evaluate a policy element as a string. For example, to compare a user, enter the constraint using the following format:

IF user like "??user/acme/Joe/";

Complex Rule Constraints

You can use additional constraints to create more complicated conditions for your rules; however, these are not always required.

Boolean Operators

You can build complex rule constraints by using logical operators. Boolean operators allow you to string multiple constraints together and to have the whole constraint return true only if certain patterns of the component constraints are true. For instance, if the whole constraint is only true if both component constraints are true.

If one of them is not true, then the whole constraint is not true, as the following example:

(whole constraint) is true IF (first constraint is true) AND (second constraint is true)

Or in another example, where it is true if either component is true:

(whole constraint) is true IF (first constraint is true) OR (second constraint is true)

Boolean operators are nothing more than a way to make these kinds of statements. You can write a complex Boolean constraint like this:

IF userBudget < 2000 AND ThisMonth = December

This constraint is only true if userBudget is less than $2000 and the current month is December. Table 3-6 lists the three Boolean operators allowed.

Table 3-6 Boolean Operators 

Operator

Description

AND

Each component must be true.

OR

At least one component must be true.

NOT

The component cannot be true.


 

The third Boolean operator is NOT, which simply reverses the truth of a constraint. So, if the constraint is true, it becomes false, or vice versa. For example, if you want to make sure it is not December, you can write:

IF NOT ThisMonth = December

Your use of these Boolean operators can get as complex as you want. For example, you can have the following constraint:

IF A AND B OR NOT C

In English, this means, If both A and B are true or if C is not true, then the constraint is true. With a little thought, that is easy enough, but what about a complex constraint, such as:

IF A AND B OR C AND NOT D

Does it mean, if A and B are true or C is true and D is not true, grant the privilege, or does it mean, if A and B or C is true and D is not true, grant the privilege, or does it mean something else?

Associativity and Precedence

One way to decipher Boolean expressions is to understand keyword precedence, the order in which keywords are evaluated; and, associativity, the direction in which terms are grouped. The order of precedence is:

  1. NOT
  2. AND
  3. OR

AND and OR are left associative and NOT is right associative. That is, with AND and OR the system always looks to the immediate left of the keyword for the first value and to the immediate right for the second value. With NOT, the system only looks to the immediate right because NOT does not compare two or more values; it affects only one value. If our earlier example is evaluated using associativity and precedence, it means, If either both A and B are true or if C is true and D is not, the constraint is true.

Grouping with Parentheses

Rather than remembering the rules about associativity and precedence, the easiest thing to do is to use parentheses to logically group your AND, OR, and NOT statements.

In the previous example:

IF A AND B OR C AND NOT D

you can evaluate the statement by applying the rules of associativity and precedence or you can logically group the statements in parentheses as follows:

IF (A AND B) OR (C AND NOT D)

This eliminates ambiguity from the statement. It becomes clear that there are two constraints: (A AND B) and (C AND NOT D), and that one of those constraints must be true for the statement to be true because the two statements have an OR between them.

Changing the location of the parentheses can change the meaning of the statement. For example:

IF (A AND B OR C) AND (NOT D)

changes the statement completely. Now there are two constraints: (A AND B OR C) and (NOT D), in which both must be true for the statement to be true.

You may nest parentheses within parentheses to clarify or change the logic of the statement. For example:

IF ((A AND B) OR C) AND (NOT D)

is the same statement as the previous example, but it is now even clearer. However, if the parentheses are changed slightly, as in:

IF (A AND (B OR C)) AND (NOT D)

the meaning completely changes.

To understand complex grouped statements with parentheses, follow these rules:

Boolean Operators and Constraint Sets

Rather than building long OR or AND statements, you can define sets of constraints for your rules. A constraint set defines a set of items. For example, rather than writing:

If ThisMonth = january OR ThisMonth = february
OR ThisMonth = march

you can write:

IF ThisMonth IN [january, february, march]

The keyword IN means in this set of values, and NOTIN means not in this set of values.

You can also specify a range of values in a set of constraints. For example, the following statement:

IF age NOTIN[1..100]

says if the age value is not between 1 and 100 (inclusive), then the statement is true.

The keywords IN and NOTIN work well with credentials based on enumerated types and with constant sets.

You may be wondering about the value of constraint sets when the constraint statement is nearly as long as the chain of ORs that you would instead have to write. Besides the ability to specify ranges of values, the real benefit to constraint sets is that you can predefine them, as a constant (Constant Declarations). Using the previous example:

IF ThisMonth in [january, february, march]

using a predefined a constant list called FirstQuarter, you can write:

IF ThisMonth in FirstQuarter

rather than the longer bracketed statement.

 


Using Response Attributes

Response attributes are defined as a list of the attributes you want to return from the authorization system when a request is made by an application. Response attributes provide a mechanism for allowing the authorization system to pass arbitrary information back through the Security Framework to the caller. The use of this information is typically application specific. Some examples of how you can use response attributes include:

Response attributes are typically specified using built-in evaluation functions that report name/value pairs. There are two functions for returning attributes: report() and report_as(). These functions always return TRUE (if there are no errors), and their information is passed to your application as response attributes, embedded within the ResponseContextCollector.

You use report() and report_as() in the rule after an IF statement used in a constraint. It is best to use them in a logical if this rule is evaluated, then manner, even though "then" does not exist in the language.

For example:

if (constraint) and report_as (name,value);

While the functions are run when the rule is evaluated, they are not really constraints of the rule. Data reported by the functions are returned only if the adjudicated authorization decision agrees with the rule. This means the attributes returned from GRANT rules are not passed to the caller unless the overall access decision is PERMIT.

report() Function

The report function takes one or more attributes as input parameters and sets a corresponding response attribute with the name/value pair of the supplied attributes. For example, suppose you have the attribute called department, containing the value Accounting. If the following constraint was evaluated:

IF report(department);

the response attribute (department = accounting) is set in the response context results. Your client application can then use this information in many ways, for example:

report_as() Function

The report_as function loads a named response attribute with a specified value. The value may be an attribute, a constant or a string literal. You can specify multiple values, in which case the response attribute is returned as a list.

IF report_as("error","Your account balance is too low");
IF report_as("query", "Select * from record_table where dept_type = ", department); 
IF report_as("userlogin", trading_login,trading_password);
IF report_as("url","http://www.xyz.com/userinfo/xyz100383.htm");

Report Function Rules Language

The report function returns the name/value pair of the specified attribute. The value may be a one or more strings and is determined using the attribute retrieval mechanism of the authorization system. This means that the attribute can come from the following sources: system, user, resource or context.

The report_as function allows you to write the rule to specify both the attribute name and value:

report_as("company", "BEA Systems")

Additionally, you can specify a list of values, as follows:

report_as("accounts", "123", "456", "789")

The value portion of the report function supports de-referencing. Assume the user attribute favorite_color is part of a user profile. You can put the following statement into a rule:

report_as("window_background", favorite_color)

This allows you to set the response attribute window_background with the value of the favorite color that is stored in another attribute. You can use any of the supported language data types as values, but they are all returned to the provider using their string representation and no additional type data is transmitted.

Note: Reporting the same attribute multiple times from the same rule, results in only the last report clause date being used. For example:

grant (p,o,s) if report as ("car", "porche") and report_as ("car", "ford");

where: (p,o,s) is shorthand for privilege, object, and subject,

results in response attribute car = ford.

Using Evaluation Plug-ins to Specify Response Attributes

The ASI Authorization and ASI Role Mapping providers support the use of custom evaluation plug-ins to generate response attributes. The report and report_as functions are just special implementations of ASI Authorization and ASI Role Mapping provider plug-ins. Using custom evaluation functions, you can write even more complex statements. For example, the following rule retrieves the current stock price from an authoritative source.

grant(//priv/lookup, //app/policy/stockprice, //role/everyone)
if report_stock_price("BEAS");

A plug-in that implements this function must handle all of the logic required to obtain the actual stock price and then return it in a response attribute. Listing 3-1 shows an example of how to use a plug-in to implement this function.

Listing 3-1 Stock Price Function Implementation

TruthValue report_stock_price(Session &sess, const char *fname,
char **argv) {
const char* stock_symbol=argv[0];
//lookup stock price using custom logic
double price;
bool found = lookup_stock_price(stock_symbol, &price);
if(!found) {
return TV_FALSE;//price not found
}
//change numeric value into a string
char pricestr[1024];
snprintf(pricestr,1023,"%f",price);
//setup the return data
sess.appendReturnData("stock_price",
new AttributeValue((const char*)pricestr));
return TV_TRUE;
}

For additional information on using ASI Authorization and ASI Role Mapping provider plug-ins, see Provider Extensions in the BEA WebLogic Enterprise Security Administration Guide.

 


Using queryResources and grantedResources

This feature allows a caller to query the authorization system to determine access on a set of resources rather then a single resource. The ASI Authorization provider determines access to all child nodes of the node specified in the access query, and returns lists indicating which nodes are granted and which nodes are denied.

The client performs an isAccessAllowed query on the parentResource. This resource must be a binding node or a resource of a binding node.

The queryResources functionality evaluation is triggered by the presence of some qrvalue value in the com.bea.security.authorization.queryResources attribute of the ContextHandler. The access decision for the parentResource is returned, as normal. One of the return attributes for this decision is a com.bea.security.Authorization.grantedResources return attribute. One of the return attributes for this decision is a com.bea.security.Authorization.deniedResources return attribute.

For grantedResources, the value of this attribute is a list of values for the qrvalue resource attribute; or, if the qrvalue is an empty string, the value is the internal ARME name for the resource. This list is an intersection of all child nodes of parentResource and all resources for which the ASI Authorization provider and ASI Role Mapping provider and role policy evaluates to GRANT. If the qrvalue attribute is not defined on a particular child node, it is omitted to allow an application to deal with identification of the resource other than the internal ARME representation of it, which is not trivial to convert back to the framework resource.

This list can contain duplicate values. If the empty value for the qrvalue is used, the returned resource name is unique and defined for each child node.

The same applies for the deniedResources, except for the resources that the policy evaluates to DENY. For example, assume that an application makes an isAccessAllowed call on the //app/policy/Foo resource and sets the value of the queryResources attribute to object_id. The authorization policy has no rules set on the Foo resource, thus an ABSTAIN result is returned.

Now let's assume that Foo has child nodes Foo/A, Foo/B, Foo/C. The authorization policy allows access to Foo/A and Foo/C, given the role policy on Foo by all providers, and the role policy for A and C for a security provider. Assume that A and C have an object_id resource attribute equal to "rA" and "rC". Then, the above query returns an attribute grantedResources with the value ["rA", "rC"].

For role providers other than the ASI Role Mapper provider, roles granted on the parentResource are assumed to apply to all child nodes of the parentResource. For the role policy, it is evaluated as usual for all child nodes.

To receive the results, you must supply a ResponseContextCollector in the ContextHandler request.

When the application needs to call into the Security Framework to query resources it passes in:

AppContextElement qrElement = new SimpleContextElement( "com.bea.security.authorization.", "queryResources", "name"); appContext.addElement(qrElement); 

When it retrieves the list of resources from the response, for granted resources, it must call:

AppContextElement granted = responseContext.getElement( "com.bea.security.Authorization.grantedResources");

or, for denied resources:

AppContextElement denied = responseContext.getElement( "com.bea.security.Authorization.deniedResources");

Note: The case for authorization on the request and the response is not the same.

 

Skip navigation bar  Back to Top Previous Next