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.
Note: <ed>,<david>,<chin>, <andy> are
indices
in the users table.
<OSCARS-eng><OSCARS-op>,<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 suggest that
a user should get all his authorizations based on group attributes.
attributes Table
id (int) | attribute name (string) |
attribute type (int) |
1 |
OSCARS-engineer |
group |
2 |
OSCARS-operator | group |
3 |
OSCARS-user | group |
4 |
OSCARS-administrator | group |
5 |
OSCARS-service | group |
6 |
HOPI-developer | group |
7 |
user-bob | user |
8 |
user-alice | user |
9 |
user-david |
user |
id (int) | loginId (int) | attribute id (int) |
1 |
<ed> | <OSCARS-eng> |
11 |
<david> | <user-david> |
2 |
<david> |
<OSCARS-user> |
8 |
<david> | <OSCARS-admin> |
3 |
<chin> | <OSCARS-eng> |
6 |
<andy> | <HOPI-dev> |
7 |
<andy> | <OSCARS-user> |
13 |
<alice> |
<user-alice> |
14 |
<bob> |
<user-bob> |
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 |
0 |
|
<user-alice> | reservations | query |
all-users |
0 |
|
<user-alice> | reservations | modify |
all-users |
0 |
|
<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 |
|
<OSCARS-eng> | users | query |
null
[2] |
null | |
<OSCARS-eng> | users | modify |
null
[2] |
null | |
<OSCARS-eng> | reservations |
list |
all-users |
1 |
|
<OSCARS-eng> | reservations | query |
all-users |
1 |
|
<OSCARS-eng> | reservations | create |
specify-path-elements |
1 |
|
<OSCARS-eng> | reservations | modify |
all-users |
1 |
|
<OSCARS-eng> | reservations |
signal |
all-users |
1 |
|
<OSCARS-eng> |
domains |
query |
|||
<OSCARS-eng> |
domains |
modify |
|||
<OSCARS-op> |
users |
query |
null [2] |
||
<OSCARS-op> | users | modify |
null [2] |
||
<OSCARS-op> | reservations |
list |
all-users | 1 |
|
<OSCARS-op> | reservations | query |
all-users | 1 |
|
<OSCARS-user> |
users | query |
null [2] | ||
<OSCARS-user> |
users | modify |
null [2] | ||
<OSCARS-user> |
reservations |
list |
null
[3] |
||
<OSCARS-user> | reservations | query |
null [3] | ||
<OSCARS-user> | reservations | create |
null [3] | ||
<OSCARS-user> | reservations | modify |
null [3] | ||
<OSCARS-user> |
reservations |
signal |
null
[3] |
||
<OSCARS-admin> |
users |
list |
all-users |
1 |
|
<OSCARS-admin> | users | query |
all-users | 1 |
|
<OSCARS-admin> | users | modify |
all-users | 1 |
|
<OSCARS-admin> | users |
create |
|||
<user-david> |
reservations |
create |
specify-path-elements |
1 |
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