In this section, we examine the fundamental elements of the Legion
architecture and provide examples of security mechanisms that we have
designed for it.
Legion is composed of independent, active objects. All
entities of interest within the system---processing resources,
storage, users, etc.---are represented by objects .
These objects communicate via asynchronous method invocations, supported by
an underlying message passing system. Each method invocation contains a
set of explicit (i.e., actual) parameters, and an optional set of arbitrary
implicit parameter attributes--value pairs that are available to
called objects. Method calls can produce an arbitrary set of results.
Using data-flow information encoded in Legion method invocations, results
are forwarded directly to where they are needed, rather than necessarily
back to the caller. Objects are instances of
classes that define their interface, which must be a
superset of a minimal object-mandatory
interface. Object-mandatory methods include functions, such as an interface
query, and methods to implement object persistence.
Legion objects are persistent and are defined as in one of two states:
active or inert. An active object is hosted
within its own running process and can service method invocations.
An inert object's state (called its Object Persistent Representation, or OPR) is stored on a persistent storage device managed within the system.
Objects implement internal methods to store and recover their dynamic state.
Every object in a Legion system is identified by a unique,
location-independent Legion Object Identifier, or LOID. LOIDs
consist of a variable number of variable length binary fields. As a
default security practice, one of the LOID fields stores an X.509
certificate including (at minimum) an RSA public key.
Including an object's public key in its
LOID makes it easy for other objects to encrypt communications to that
object or to verify messages as signed by that particular object.
Objects can just extract the key from the LOID rather than looking
it up in a separate database: making the key an integral part of an
object's name eliminates some kinds of public key tampering.
Example 1: User Identity
Legion users also have LOIDs. A user creates his own LOID, which is
registered with the system and entered in appropriate system
groups and access control lists by resource providers. When an object
makes a call on behalf of a user, the user's LOID and associated
credentials provide the basis for authentication and authorization.
The ownership of a user's LOID resides in the user's unique knowledge
of the private key that is paired with it. The private key is kept
encrypted on disk, on a smart card, or in some other safe place.
For a resource the essential step in an access request is determining
the caller's identity. If a user communicates directly with the target
object, he can establish his identity with an
authentication protocol. In a distributed object system,
however, the user typically accesses resources indirectly, and objects
need to be able to perform actions on his behalf.
To transfer the user's identity in Legion, we issue
credentials to objects. A credential is a list of rights granted
by the credential's maker, normally the user or his proxy.
A credential is passed through call chains, and is presented to
a resource to gain access.
The resource checks the rights in the
credential and who the maker is, and uses that information in deciding
to grant access.
There are two main types of credentials in Legion:
delegated credentials and bearer credentials. A
delegated credential specifies exactly who is granted the listed rights,
whereas simple possession of a bearer credential grants the rights
listed within it. A credential specifies
the period for which it is valid,
who is allowed to use the credential, and which method calls it can
be used for.
The credential also includes the identity and digital signature of its maker.
Tools or commands directly executed by the user create the credentials
they need to carry out their actions. The credentials are made as specific
as possible to avoid unnecessary dispersion of authority.
Short timeouts in credentials, coupled with user-specific Refresh Objects
that can revalidate expired credentials, permit a variety of recovery tactics
if a credential or user key is stolen.
Additional details concerning credentials and credential refresh can be found
Legion Runtime Library
The implementation of Legion objects is supported by a Legion
Runtime Library (LRTL) interface. The LRTL provides services analogous to
a traditional Object Request Broker (ORB), defining the interfaces to
services such as message passing, object control (e.g., creation, location,
deletion), and other basic required mechanisms.
A critical element of the LRTL is its flexible, configurable protocol
stack . All of the processing performed during the
construction and execution of invocations on the object-caller side, and
in the receipt, assembly, and service of invocations on the
object-implementation side, is configured using a flexible event-based model.
This feature of the Legion software allows tool builders to provide
drop-in protocol layers for Legion object implementations in a convenient
fashion. For example, adding message privacy through a cryptographic
protocol is simply a matter of registering the appropriate message
processing event handlers into the Legion protocol stack---the added service
is transparent to the application developer.
Example 2: Access Control
In Legion, access is the ability to call a method on an object. The
object may represent a file, a Legion service, a device, or any other
resource. Access control is not centralized in any one part of the
Legion system. Each object is responsible for enforcing its own access
control policy. It may collaborate with other objects in making
an access decision, and indeed, this allows an administrator to control
policy for multiple objects from a single point. The Legion architecture
does not require this, however.
The general model for access control is that each method call received
at an object passes through a MayI layer before being serviced.
MayI is specified as an event in the configurable LRTL protocol
stack . MayI decides whether to grant access according
to whatever policy it implements. If access is denied, the object
will respond with an appropriate security exception.
MayI can be implemented in multiple ways.
The default LRTL MayI implementation is based on access control lists
and credential checking. In this MayI, allow and deny
access control lists containing user and group LOIDs can be specified
for each method in an object.
When a method call is received, the credentials it carries are checked
by MayI and compared against the access control lists.
Multiple credentials can be carried in a call;
checking continues until one provides access.
The form of access control provided by the default MayI is sufficient
for some kinds of objects, such as file objects, but not for others.
The LRTL configurable,
event-based protocol stack makes it easy to replace or supplement the
default MayI with extra functionality.
Furthermore, the default MayI itself is relatively simple to modify if,
for example, new forms of credentials or different kinds of access control
lists must be supported. With the Legion security architecture, these types
of changes can be made on a local basis without affecting other parts of a
Example 3: Communication Privacy and Integrity
integrity services are provided at the level of Legion messages. When
a Legion message is prepared for sending,
an event handler that implements a default message security layer is triggered.
This layer inspects the implicit parameters accompanying a
message to determine which security functions to apply.
In the the current LRTL, a message may be sent with no security,
in private mode, or in protected mode. In both private
and protected modes, certain key elements of a message (e.g., any contained
credentials) are encrypted. The functional difference between the two modes
is in how the rest of the message (body plus other implicit parameters)
is treated. In private mode it is encrypted, whereas in protected mode
only a digest is generated to provide an integrity guarantee.
Unless private mode is already on, protected mode is selected automatically
if a message contains credentials. This is a failsafe measure to
prevent credentials from being transmitted in the clear.
Details of the encryption mechanisms can be found in .
Because the mode in use is stored in implicit parameters, it propagates
through call chains. For example, a user can select private mode when
calling an object. The calls that the object makes on behalf of the
user will also use private mode, and so on down the line.
The security layer does not provide mutual authentication. The sender
can be assured of the identity of the recipient, because only the
desired recipient can read the encrypted parts of the message. The
recipient usually doesn't care who the actual sender is; its decisions
are based solely on the credentials that arrived in the message.
Within the general Legion object model, we define the interfaces to a
set of basic classes that are fundamental to the operation of the
system, and that support the implementation of the object model itself.
Host Objects in Legion represent processing resources. When a Legion
object is activated, it is a Host Object that actually creates a
process to contain the newly activated
object. The Host Object thus controls access to its processing resource and
can enforce local policies, e.g., ensuring that a user does not consume
more processing time than allotted.
Vault Objects in Legion represent stable storage available within the
system for containing OPRs. Just as Host Objects are the managers of active
Legion objects, Vault Objects are the managers of inert Legion objects.
For example, Vaults are the point of access control to storage resources,
and can enforce policies such as file system allocations.
Hosts and Vaults provide the system with interfaces to processing and
storage resources. The use of these interfaces is encapsulated by Class
Manager Objects. [In many of the cited Legion references,
Class Manager Objects are referred to simply as "Class Objects."]
Class Managers are responsible for managing the
placement, activation, and deactivation of a set of objects of a given
class. They provide a central mechanism for specifying policy for
a set of like objects. Policies set by the Class Manager include
defining which implementations are valid for instances, which hosts are
suitable for execution of instances, which users may create new instances,
and so on. In addition to setting policy for instances, Class Managers
serve as location authorities for instances, supporting the binding
of LOIDs to low-level object addresses (typically an IP address
plus port number).
A critical aspect of the Legion core object classes is that they define
interfaces, not implementations. The Legion software distribution
provides a number of default reference implementations of each
core object type, but the model explicitly enables and encourages the
configuration, extension, and even replacement of local core object
implementations to suit site- and user-specific functionality and
performance requirements. For example, by replacing the implementation
of the Host Object, a site can define arbitrary mechanisms and policies
for the usage of their computational resources.
Object Management and Isolation
The management of active and inert objects by Legion core objects is
an important point of local security mechanism and policy in Legion.
Fundamentally, Legion software runs on existing operating systems with
their own security policies. It is therefore critical that the implementation
of the Legion object model ensure that extra-Legion mechanisms cannot be
used to subvert higher-level security mechanisms. Similarly, it is
important to ensure that Legion does not break local security policies at
a sites. A local system administrator is generally concerned with who can
create processes on his system via Legion, what those processes can do,
and who pays for their resource use. On Legion's side, there is
a need to prevent user objects from interfering with one another or with
core system objects (e.g., Hosts and Vaults), and to maintain the privacy
of persistent state (OPRs). The latter is particularly significant because
objects store their private keys in their OPRs.
The needs of Legion are common to any multi-user operating system, and
our approach to providing them is to leverage off of existing
operating system services. Our general strategy for isolating
objects from one another in the default Legion implementation is to
use separate accounts to execute different user objects. Similarly, we
use local accounts and storage system protections to protect OPRs.
Accounts that can be used for these purposes fall into two categories.
For those Legion users who happen to have accounts on the local system,
processes and storage that represent the user's objects can be owned by
the user's local account. For other users, we support the use
of a pool of generic accounts that are designated for Legion use.
The generic accounts usually have minimal permissions (e.g., no home
directory, no group memberships, etc.). The local Host and Vault Objects use
their own dedicated local accounts to ensure isolation from other user
We encapsulate the privileged operations necessary for this policy in a
Process Control Daemon (PCD) that executes
on the host, providing services to the Host and Vault in a controlled
fashion. The PCD is a small, easily vetted program that runs with
root permissions. It is configured only to allow access by the Host/Vault
account. Two of its key functions are recursive change ownership of a
directory, process creation under a designated account, and process
termination. The PCD limits the user-ids to which these operations can
be applied to a set configured by the local system administrator.
The set includes the generic Legion accounts and potentially the accounts
of local Legion users.