OSCARS Authorization Policy



Introduction

An authorization decision consists of deciding if an authenticated entity should be allowed to perform some action on a controlled resource. In OSCARS an authenticated entity may be a bandwidth user or a bandwidth reservation service from another domain; the fundamental resource is bandwidth though the domain, and the fundamental permission is right to reserve some fraction of the available bandwidth. Since available bandwidth is a limited resource, some finer control is needed such as the maximum allowed bandwidth and duration. In addition, some users of the system needed to request or suggest possible internal routing for the data path.

OSCARS chose to do attribute-based authorization primarily as a way of consolidating authorization policy to make it more understandable to users and OSCARS administrators and partly in anticipation of integrating with an external attribute provider such as Shibboleth or VOMS. An attribute is some characteristic of a user, such as being a member of some project, a holder of some role, or just his identity as expressed as a registered user name or x.509 identity certificate. A user gets the maximum of all the privileges granted to all of the attributes that he has.

OSCARS is currently a self-contained system that defines who its registered users are and what attributes each one has. As a result, it needs to control who may manage users and their permissions, so users become a controlled resource in addition to bandwidth. A final resource is the internal topology, since we want control who may view the actual topology and who may see and abstracted version of it.

The underlying guideline of our design and implementation is to keep authorization policy and implementation as simple as possible. We have tried to make the granularity of access decisions no finer than is actually required, and have defined roles to consolidate sets of permissions into sets that an actual user would need. Some of our underlying assumptions are: Most users will get their permissions by being members of a group/role, rather than by individual grants. The number of group/roles will be small. The number of resources and permissions will be small. While the implementation may scale to larger numbers, the ability of the users and administrators to understand it will not.

We are currently intending to authorize a reservation that has been forwarded to ESnet from an adjacent domain based on the attributes assigned to that domain rather than the end user who is requesting the reservation. Thus the number of users that must be registered with the system can remain manageable. The name of the user is included in the forwarded request, so it can be used for auditing purposes or can later be used for authorization.

Authorization policy requirements

The following paragraphs list the various actions that we want to control with respect to the resources that OSCARS controls.

Permissions with respect to users

Permissions with respect to bandwidth and reservations

(signaling instantiates a reservation by causing the appropriate commands to be sent to the routers involved)

Permissions with respect to topology (not implemented yet)

Policy Implementation

All access decisions are made by one of two methods which are called from each place in the code that is about to grant some access. Access policy is stored in a database, and an access decision is made by doing table lookups based on the requestor, the action requested and the resource. Authorizations may have constraints attached, in which case the parameters of the request must meet the constraints.

The following tables define the components for authorization:

Users may have 1 or more attributes. Attributes are arbitrary strings, defined in the attributes table, e.g. ESnet-Engineer, Atlas-PI, CMS-member.

The advantage of attributes is that it allows a set of authorizations to be crafted which can then be applied to a class of users. Otherwise, each time a new user registers, he must be given the correct and complete set of permissions for whatever he wants to do. In our example below, if a new network engineer, Ned, arrives, we would need to duplicate all the authorization entries that Ed has for him. If we had just entered those authorizations for "ESnet-Engineer" then we would just need to assign Ned that attribute. It also makes the tables smaller and thus may make it easier to understand the global picture of who has what permissions.

With attribute-based authorization, the access check will need to look up user attributes, then look up authorizations for each attribute the user has and merge them (take the maximum of the permissions).

Default behaviors

Example Tables

We have users alice, bob, ed, david chin and andy. Alice and bob have all their permissions individually assigned. Ed, chin and andy get all their permissions from group attributes. David gets most permissions from groups but has one more added individually.

Note: <ed>,<david>,<chin>, <andy> are indices in the users table.
<ESnet-eng><ESnet-dev>,<user-chin>,<user-david> are indices in the attributes table.
A user would only need an "id-entry" in the attribute table if some authorization was to be granted explicitly to him. It is probable that a user will get all his authorizations based on group attributes.

attributes Table

id (int) attribute name (string)
attribute type (int)
1
ESnet-engineer
group
2
ESnet-developer group
3
ESnet-user group
4
ESnet-administrator group
5
ESnet-service group
6
HOPI-developer group
7
user-bob user
8
user-alice user
9
user-david
user

userAttributes table

id (int)  loginId (int) attribute id (int)
1
<ed> <ESnet-eng>
11
<david> <user-david>
8
<david> <ESnet-admin>
9
<david> <ESnet-dev>
3
<chin> <ESnet-eng>
4
<chin> <ESnet-user>
5
<chin> <ESnet-dev>
6
<andy>  <HOPI-dev>
7
<andy> <ESnet-user>
13
<alice>
<user-alice>
14
<bob>
<user-bob>

Authorization Table


id
(int)
attributeId
(int)

resource
permission
constraint name
(string)
value (int)
1=true, 0=false


<user-alice>
users
list
null [1]


<user-alice> users query
null [1]


<user-alice> users modify
null [1]


<user-alice> reservations
create
max-bandwidth
10M

<user-alice> reservations create
max-duration
600min

<user-alice> reservations list
all-users


<user-alice> reservations query
all-users


<user-alice> reservations modify
all-users


<user-alice> reservations modify max-bandwidth 10M

<user-alice> reservations modify max-duration 600min

<user-bob>
users
list
all-users
1

<user-bob> users query
all-users
1

<user-bob> users modify
all-users
1

<user-bob> reservations
create
specify-path-elements
0

<user-bob> reservations list
all-users
1

<user-bob> reservations query
all-users
1

<user-bob> reservations modify
all-users
1

<user-bob> reservations modify
specify-path-elements 0

<ESnet-eng>
users
list
null  [2] null

<ESnet-eng> users query
null  [2]
null

<ESnet-eng> users modify
null  [2]
null

<ESnet-eng> reservations
list
all-users
1

<ESnet-eng> reservations query
all-users
1

<ESnet-eng> reservations create
specify-path-elements
1

<ESnet-eng> reservations modify
all-users
0

<ESnet-dev>
users
list
all-users
1

<ESnet-dev>
users query
all-users 1

<ESnet-dev> users modify
all-users 0

<ESnet-dev> reservations
list
all-users 1

<ESnet-dev> reservations query
all-users 1

<ESnet-dev> reservations create
max-bandwidth
10M

<ESnet-dev> reservations create
max-duration
10min

<ESnet-dev> reservations modify
all-users
0

<ESnet-dev> reservations modify max-bandwidth 10M

<ESnet-dev> reservations modify max-duration 10min

<ESnet-user>
users
list
null [2]


<ESnet-user>
users query
null [2]

<ESnet-user>
users modify
null [2]

<ESnet-user>
reservations
list
null  [3]


<ESnet-user> reservations query
null  [3]

<ESnet-user> reservations create
null  [3]

<ESnet-user> eservations modify
null  [3]

<ESnet-admin>
users
list
all-users
1

<ESnet-admin> users query
all-users 1

<ESnet-admin> users modify
all-users 1

<ESnet-admin> users
create



<user-david>
reservations
create
specify-path-elements
1

Defaults
[1] same as all-users=0, selfOnly
[2] manage and view only his own user info
[3] unlimited bandwidth and duration, only modify, list and query own reservations, not input path components.

Alice is the least privileged. She is allowed to make reservations of a limited bandwidth and duration, and only see and modify her own information. Bob is the leader of a group making reservations. He is allowed to make reservations of unlimited bandwidth, unlimited duration, specify ingress, egress and hops and see and manage other users and their reservations. Ed is a network engineer. As an ESnet-engineer he can make reservations for the purpose of testing, can see but not modify other's reservations, can only see user information, and has free rein over the topology.  An ESnet developer can make reservations of limited bandwidth and durations, view everybody's reservations but only modify his own, and can see and modify all user information. An ESnet user can make reservations of unlimited bandwidth and duration, but only view his own reservations and user information. An ESnet admin can manage all user information, but not see or modify reservations. <user-david> has all the permissions of an ESnet developer and ESnet admin and can also specify path elements when creating a reservation.

CheckAccess Implementation

The preferred way to implement access control is to isolate the access checking in one place, called the PolicyDecisionPoint that returns a permit or deny  response and is called by all access control points (aka Policy Enforcement Points/ PEP) to see if an action is authorized. The AAA/UserManager class provides two  methods for access checking. The first would be called anyplace where a reservation is not being modified and the second by createReservation and modifyReservation.

Standard checkAccess method:

AuthValue UserManager.checkAccess(String user, String resource, String permission);

Initialize the return value to DENIED
Lookup user in userAttribute table to get list of all attributes
For each attribute lookup ((attrId,resource,permission) in authorization table.
    If deny is returned, continue
    If there is no constraint, set returnValue to SELFONLY and continue
    If all-users=true is returned, return ALLUSERS
    If all-users=false is returned, set returnValue to SELFONLY and continue
At end of loop return SELFONLY or DENIED

checkAccess method called by createReservation and modifyReservation:

AuthValue UserManager.checkModResAccess(String user,String resource, String permission, int ReqBandWidth, int ReqDuration, Boolean specify-path-elements);

Start out with
    ReturnValue = DENIED
    bandwidthOK = false
    maxdurationOK = false
    specPathElemOK = false.
Lookup user in userAttributes table and get a list of attributes for this user.
For each attribute lookup and Authrorization(AttrId,resource,permission)
   for the authorization returned
         if the constraint is null
mark bandwidthOK=true and durationOK=true,
and returnValue=SELFONLY
       if the constraint is max-bandwidth
mark bandwidthOK= true if  reqBandwidth < constraintValue
      if constraint is max-duration
    mark durationOK if reqDuration < constraintValue
     if constraint is spec-path-element
     mark specPathElemOK = true
     if constraint is all-users
     if value = 1 set returnValue = ALLUSERS
    if value = 0 set returnValue = SELFONLY
At the end of the attribute list
   if bandwidthOK = false or maxdurationOK = false
    return DENIED
if specify-path-element= true and specPathElemsOK = false
    return DENIED
otherwise return ReturnValue