[New Zealand Digital Library] [Computer Science Technical Reports]
[Query Results]
----------------------------------------------------------------------------
1
The Spring Name Service
Sanjay Radia
Michael N. Nelson
Michael L. Powell
SMLI TR-93-16 November 1993
Abstract:
The Spring name service exploits and supports the uniformity of objects in
the Spring object-oriented distributed system. The name service can be used
to associate any name with any object independent of the type of object, and
arbitrary name spaces can be created and used as first-class objects. The
same client interface is used not only for all conventional operating system
and network naming, but also for other services that support naming-style
interaction. The architecture of the name service is open, supporting
combinations of trusted and untrusted name servers and object
implementations.
The name service integrates access control and persistence for objects in a
way that allows object implementations to delegate responsibility to the
name service, or to implement their own policies. The interfaces between
different name servers and between name servers and object implementations
allow a variety of implementation strategies for objects and name servers,
providing different levels performance, persistence, robustness, security,
and convenience.
email addresses:
sanjay.radia@eng.sun.com
michael.nelson@eng.sun.com
michael.powell@eng.sun.com
A Sun Microsystems, Inc. Businessfl
M/S 29-01
2550 Garcia Avenue
Mountain View, CA 94043
----------------------------------------------------------------------------
2
The Spring Name Service
Sanjay Radia, Michael N. Nelson, and Michael L. Powell
Sun Microsystems Laboratories, Inc.
2550 Garcia Avenue
Mountain View, CA 94043
1 Introduction
An operating system has various kinds of objects, such as files, printers,
services, etc., that need to be given names. Most operating systems have
several name services, each tailored for a specific kind of object. Such
type specific name services are usually built into the subsystem
implementing those objects. For example, a file system typically includes
its own mechanism for binding names to files, accessing files by name, etc.,
and manages the database of those bindings. In the UNIX??1 operating system,
the name space for printers is stored in /etc/printcap, and is used by the
various printing commands. Lightweight name services such as environment
variables in UNIX[8] have their own name space with library implementations.
Type specific name services have interfaces that are designed for objects of
the specific type, and are unsuitable for general naming. Distributed
systems usually have one or more higher level name services called directory
services, such as Grapevine[3], Lampson?s global name service[2], or
X.500[6], which are used for resource location, mail addressing, and
authentication. Directory services bind names to data values that have to be
resolved at another level.
In systems with such diverse name services, the client has to deal with
different names and name services, depending on the objects being accessed.
Often, separate parts of the name space must be used for different types of
objects since, for example, it is not possible to bind a file as an
environment variable. Another problem is that the non?uniform name spaces
cannot generally be composed together. For example, the name spaces for
files cannot be attached to the name spaces for environment variables.
Defining new objects or services that are accessed by name can be
complicated and cumbersome, since the new objects must be made to ?fit in?
somewhere, or a new name space must be defined and implemented.
Difficulties in Providing a Uniform Name Service
Providing a uniform name service has been difficult because the entities
being named have different representations. Type specific name services
provide tokens that must be used for a particular purpose, since the type is
assumed; for example, in UNIX, looking up a file returns an integer, which
is used for file operations. On the other hand, directory services provide
values that must be resolved at another level to be useful; for example,
looking up a host returns a byte string that can be interpreted as a network
address.
One solution is to pick a particular object type, map all objects to provide
that type?s interface, and make all the object implementations (called
object managers in Spring2) implement the type specific name service. This
approach is popular in UNIX, where various objects are made to look like
files, since the file and the file name service are the most versatile parts
of the system. There are several problems. Unfortunately, it is difficult to
make every object behave like a file, since the file interface is limited in
capturing the semantics of many objects. For example, Plan 9[5, 4], which
uses this approach extensively, still has a separate name service to find
file servers. Another problem with this approach is that each object manager
1. UNIX is a registered trademark of UNIX System Laboratories.
2. Spring is an internal code name only.
----------------------------------------------------------------------------
3
must still implement its own (file) name service, which makes it difficult
to introduce new object types into the system. A more detailed comparison
with Plan 9 is provided in Section 8.
The uniformity of objects in object oriented systems offers an opportunity
for a uniform name service. However, existing object oriented systems either
have not provided a uniform name service or have provided one with serious
restrictions. Programming language based object oriented systems such as
Smalltalk rely on the name space of variables provided by the programming
language. Systems like Choices[10,10] have the serious restriction that the
object managers?the servers that implement the objects?must be integrated
and reside with the name service. This makes it difficult to add new object
types.
One of the main difficulties in building a uniform name service has been
that the service often needs to interact with the object managers for the
purpose of persistence and security. Type?specific name services such as the
file system can address these problems easily, since the implementations of
the name service and the objects reside together. Thus, for example, the
name service implementation knows how to turn live files into those stored
on persistent storage. Furthermore, there is complete trust between the two
components to provide the user with a uniform view of access control?the
name service can check the access control list on a file just like it checks
the access control list on a directory. Directory services avoid the problem
by simply binding names to data values, leaving the client to interpret the
values. If, for example, a data value represents a way to get to a service,
then it is up to the client to ensure that a persistent form (such as an
address instead of a connection identifier) is bound, and that the value
returned from a name resolution is turned into a live form when needed.
Similarly, if the data value represents a way to get to a secure service,
then the client has to perform additional authentication steps.
The Spring Name Service
Spring provides a uniform name service: in principle, any object can be
bound to any name. This applies whether the object is local to a process,
local to a machine, or resident elsewhere on the network; whether it is
transient or persistent; whether it is a standard system object, a process
environment object, or a user specific object. Name services and name spaces
do not need to be segregated by object type. Different name spaces can be
composed to create new name spaces.
By using a common name service, we do not burden clients with the
requirement to use different names or different name services depending on
what objects are being accessed. Similarly, we do not burden all object
implementations with constructing name spaces?the name service provides
critical support to integrate new kinds of objects and new implementations
of existing objects into Spring. Object implementations maintain control
over the representation and storage of their objects, who is allowed access
to them, and other crucial details. Although Spring has a common name
service and naming interface, the architecture allows different name servers
with different implementation properties to be used as part of the name
service.
Spring differs from existing name services in that its contexts and name
spaces are first class objects: they can be accessed and manipulated
directly. For example, two applications can exchange and share a private
name space. Traditionally, such applications would have had to build their
own naming facility, or incorporate the private name space into a larger
system?wide name space, and access it indirectly via the root or working
context.
The naming interface can be used even in subsystems whose primary purpose is
not naming. For example, a spreadsheet application may support the naming
interface to allow access to its cells by name. Like other name spaces, the
spreadsheet name space could be attached to another name space. Transient
name services, such as process environment variables, can also implement the
same interface. Although different
----------------------------------------------------------------------------
4
implementations may be used to meet the different performance and
distribution needs of these various name spaces, the interface is the same.
Spring object references are generally not persistent, and instead, naming
is used to support the persistence of objects (we explain our reasons and
approach in more detail later in the paper). It is expected that
applications generally (re)acquire objects from the name service, which
deals with the persistence aspect of objects if the name space happens to be
persistent.3 A Spring name server managing a persistent part of a name space
converts the object references and objects to and from their persistent form
(much like the UNIX file system, which converts open files to and from their
persistent form). One difficulty in integrating persistence is that naming
is a generic service for an open?ended collection of object types, and hence
cannot be expected to know how to make each object type persistent. Spring
objects are abstractions, so the object manager has ultimate control of the
(hidden) state of the object. We provide a general interface between object
managers and the name service that allows persistence to be integrated into
the name service while allowing the implementation to control its storage.
Because the name service is the most common mechanism for acquiring objects,
it is a natural place for access control and authentication. Since the name
service must provide these functions to protect the name space, it is
reasonable to use the same mechanism to protect named objects. The naming
architecture allows object managers to determine how much to trust a
particular name server, and an object manager is permitted to forego the
convenience and implement its own access control and authentication if it
wishes. Similarly, name servers can choose to trust or not to trust other
name servers.
The distinguishing features of the Spring name service are a uniform and
extensible name service, a general naming model with first class name
spaces, and integrated support for access control and persistence. While
different name services have provided some of these features in the past,
the challenge in Spring has been to integrate all into a single name
service.
This Paper
This paper describes the architecture of the Spring name service, focusing
on its distinguishing features mentioned above. After the overview of the
Spring system in Section 2, Section 3 presents the naming model on which the
name service is built. Sections 4 and 5 present our general approach to
persistence and security, and describe the framework for them, and this
leads to a discussion in Section 6 of the interface and protocols used for
interactions among clients, name servers, and object managers. Various
examples from our system, including our naming policies, are described in
Section 7. In Section 8, we make comparisons with other related work.
Finally, Section 9 provides some concluding remarks.
2 An Overview of the Spring System
Spring is a distributed, object oriented operating system. A Spring object
is an abstraction that is defined by an interface, expressed in the IDL
interface definition language [18], which specifies the set of operations
that may be performed on the object. IDL supports multiple inheritance of
interfaces, and Spring encourages this, allowing objects to export their
functionality via multiple interfaces. An interface is a strongly typed
contract between the implementation (the object manager) and the client of
the object. The granularity of Spring objects spans a wide range, from small
data?like objects to larger objects, such as files and print services. The
implementations vary from data accessors and libraries, to separate
protected servers, to distributed services implemented by multiple servers.
3. In fact, we would implement persistent object references by registering
objects in the name service, using a name server designed for that purpose.
----------------------------------------------------------------------------
5
Clients manipulate objects by performing operations on them, or passing them
as parameters in operations on other objects. Generally, clients are unaware
of the location or implementation of the objects they are using. The client
of an object is a domain, which includes an address space, threads, and
other resources. To invoke operations on the object, a client must have the
representation of the object, which is simply the information needed to
direct operations to the implementation of the object (see Figure 1).
Ordinarily, clients are unaware of the details of the representation. An
object implemented in another domain will usually have a representation
containing one or more doors. A door is a capability?like handle[15] that is
used for making protected and remote procedure calls to external object
managers (usually called servers). We also allow lightweight objects, where
both the state and the implementation of the object reside in the client
domain.
A door is implemented by the Spring microkernel, is valid for a particular
domain, and is not forgeable. Doors form the basis for security in Spring;
most Spring objects are capability?like unforgeable objects that use doors
in their representation (such objects are as secure as doors are).
Doors are not persistent?a client cannot store a door in persistent memory
for later use. When a client dies, all its doors become invalid. When an
object manager dies, all its exported doors also become invalid. Although
more complicated representations with more persistence have been implemented
[14], the most common way of accomplishing persistence is to bind objects
into the name service, and later reacquire them by name.
3 The Basic Spring Naming Model
If we are to succeed with a single uniform name service, the naming model
needs to be general enough to capture all our naming needs. We use the model
described in [1][19], which has been shown to describe a wide range of
naming schemes
Names have meaning only in the context in which they are used. The name
service allows an object to be associated with a name in some context. A
name is said to denote an object. A context is an object that contains a set
of name?to?object associations, or name bindings. In Spring, a context is
any object that supports the context interface. An object may be bound to
several different names in possibly several different contexts at the same
time. In general, an object is unaware of the names that are bound to it.
Indeed, an object may not have any names bound to it.
Resolving a name is an operation on a context to obtain the object denoted
by the name. Binding a name is an operation on a context to associate a name
with a particular object. These operations return or take as a parameter the
object itself, not a lower?level identifier for the object, as some systems
do[10][12].
A context is like any other object, and therefore can be bound to a name in
some context. By binding contexts in other contexts we can create a naming
graph, a directed graph with nodes and labeled edges, where the nodes with
outgoing edges are contexts. Given a context in some naming graph, a
sequence of names can be used to refer to an object relative to that
context. Such a sequence of names is called a compound
Figure 1. Client and Server of an Object
State of O
Client of Object Manager/
Representation of O Server of O
Object O
----------------------------------------------------------------------------
6
name. A name with a single component is called a simple name. Informally, we
refer to the naming graph spanned by a context as a name space, which
includes all bindings of names and objects that are accessible directly or
indirectly through that context.
A client of the name service performs naming operations via operations on
context objects. The name service is implemented by one or more object
managers, called name servers, which implement context objects. As shown in
Figure 2, a client can use a context object implemented by a name server to
acquire an object implemented by some object manager. Figure 3 shows a
naming graph partitioned into three parts implemented by two name servers.
In general, a client is unaware of which name server contains which parts of
the name space, just as clients of any object in Spring are unaware of the
exact implementation of the objects they use.
In many systems, a program has two contexts: the root of some global name
space, and the local context for the program. In Spring, a domain can have
as many context objects as desired. A domain may be started with contexts
given by its parent domain as implicit or explicit arguments, or can get
contexts as a result of invoking or being invoked. In particular, resolving
a name that denotes a context returns another context. A process can manage
its contexts in various ways. They can be assigned to different variables in
the programming language or bound to names in contexts. User interface
programs may manage multiple contexts for the user; for example, a shell may
allow multiple working contexts, or a desktop environment may associate them
with folders on the desk. The meaning and usage of a context is determined
by convention. If everyone believes that a particular context is ?global,?
then it will have that characteristic. However, it is always possible to
implement a context that is not connected into any other name space.
Client has a context (implemented by name server) containing a binding from
name foo to object O
implemented by object manager.
Context object
Client
Name Server State of context
foo
Object Manager
implementing object O
C
object O
Figure 2. Separation of Client, Name Server, and Object Manager
Resolve operation returns
copy of object O
State of O
Name Service
Context object
Client
Name Server 1
Name Server 2
A client has a context implemented by name server 1. Part of the naming
graph spanned by this context is implemented in name server 2 and name
server 1
Figure 3. A Name Space Partitioned into 3 Parts Implemented by 2 Name
Servers
----------------------------------------------------------------------------
7
A context and the name space it spans can be manipulated directly. A context
can be passed around like any other object. Name spaces can be composed by
binding a context to a name in some name space. Given a set of contexts, one
can construct a new context using that set, such as an ordered merge context
(like union mounts in Plan 9), where a name space is created by merging the
bindings from several contexts. The resulting new context can be used like
any other context: it can be passed around, bound to a name, etc. Context
constructions add flexibility without resorting to special name resolution
rules or mechanisms. If we were not able to manipulate contexts directly, we
might have been forced to limit the use of ordered merges to ?mount? time
(as in Plan 9), and to make the notion of merges a part of the naming
interface.
3.1 Names
Names are conventionally represented as strings, are usually printable, and
usually have some syntax for encoding different information by convention.
To deal with issues of internationalization, and to be impartial with
respect to accessing other existing name spaces, the Spring name service
defines a structural representation for names, rather than encoding values
such as version numbers and file extensions in the syntax. The presentation
and parsing of names is relegated to user interface software.
A compound name is a sequence of components. Each component is an unordered
set of elements. The identifier element of a component is an arbitrary
UNICODE [7] string4 that is never parsed (only compared for equality) by the
name service. Other elements of a component encode version numbers (allowing
references to the latest version), an object ?kind? (analogous to file name
extensions), etc.
Attributes add descriptive power to name components in a syntax independent
way. In the absence of such a feature, users normally resort to syntactic
convention. For example, in UNIX, suffixes such as ?.c?, ?.o?, etc., are
used. Applications like the C compiler depend on such syntactic conventions
to make name transformations such as from foo.c to foo.o. Unfortunately,
such syntactic conventions are natural?language dependent. In Spring, we
would like applications to make such name transformations for names in any
character set. The kind attribute is used to address the needs of such
applications. The version allows us to describe a specific version, without
resorting to syntax like foo!5.
3.2 Naming Operations
The primary interface between a client and the name service is the context
interface. There are issues of type safety that are beyond the scope of this
paper, which are resolved using parameterized type interfaces [17]. The
following are the common operations on contexts:
? named_object = context.resolve (name, mode)
Returns the object denoted by the name. The mode argument indicates intended
use of the object, and is described in more detail in Section 5.3.
? context.bind (name, binding_type, named_object, acl)
Binds the name to the object in the context (or in a context reachable from
it, if the name is a compound name). The binding type is used to distinguish
bindings that the name service has to process during resolution: symbolic
links specify symbolic_binding, name spaces are grafted by specifying
context_binding, and normal objects specify normal_binding. The acl is the
binding?s access control list.
? new_context = context.bind_new_context (name, acl)
Creates a new context with a particular name. It is also possible to create
contexts that are (as yet) unnamed, although this is an operation on the
name server interface, not the context interface.
4. Our current implementation simply uses ASCII strings.
----------------------------------------------------------------------------
8
? iterator = context.get_all_bindings (name)
Returns the binding information in the context.
? context.unbind (name)
Deletes a binding.
3.3 Naming Policies
The Spring name service does not prescribe particular naming polices. Our
current policy is to provide a combination of system?based shared name
spaces, per?user name spaces, and per?domain name spaces, as described in
Section 8.2. Each domain is passed by default at least one context by its
parent.
3.4 The Name Resolution Process
The process of name resolution (and, in part, any naming operation) starts
with presentation of the name to the name service through a context object.
If the name is a simple name, then that context performs the requested
operation. However, if the name is a compound name, the first context
obtains the object named by the first name component (which must be another
context in order for the operation to proceed), then forwards the operation
to that context, with the remaining part of the name as a parameter. It will
often be the case that the second context object is implemented by the same
name server as the first, in which case the forwarding may be implicit.
Nonetheless, at any point it is possible for the next context to be in a
different name server, requiring the request to actually be forwarded. The
Spring name service defines an interface for name servers to use for this
purpose.
In most cases, the request ultimately ends with an operation on the object
manager?for example, to obtain the requested object on a resolve operation.
This operation is through the name?sever to object?manager interface. The
three interfaces?the client interface, the name?server to name?server
interface, and the name?server to object?manager interface?define the
architecture of the Spring name service. The rest of this paper will mostly
focus on the latter two interfaces and how they are used to provide
persistence and security for objects in Spring.
4 Persistence of Objects and Name Bindings
Figure 4 shows three different kinds of persistence that must be considered:
(A) the persistence of the object state, (B) the persistence of access by a
client to the object, and (C) the persistence of the binding between a name
and an object.
The first kind, the persistence of the object state, is an issue for the
object manager. It can use whatever facilities it chooses to store the state
of the object for subsequent use. This information can be stored and
retrieved at any time, although it is typically stored when no client has an
object that refers to it, and is retrieved when a client is given access to
the object. Another consideration is that one may want to trigger the object
manager to make the object state persistent only if some client is
interested in the object being persistent, so that if clients are interested
in only transient forms of the object, then no state needs to be saved.
The second kind, persistence of access to the object (or a persistent
reference to the object), is common in many object oriented systems, such as
Clouds [12]. Values (called object ids) are typically used to designate
objects. An object id is effectively a low?level persistent identifier that
logically identifies the object, and is translated during object invocation
into the object?s physical location (since the object may move) by what is
often called a location service. Although a client can store such object
ids, it usually has several, and has to distinguish them by names; thus,
such systems usually provide higher?level name services to map meaningful
names to object ids.
----------------------------------------------------------------------------
9
Such systems use the object id for both persistence of access and for normal
access during invocation. We decided to avoid this, and instead, separate
these for two reasons. Firstly, there are many objects that will never be
persistent, and therefore should not have to pay any cost to support general
persistence. For example, domains are by default not persistent. Secondly,
the representation of a Spring object?the part held by a client?is generally
designed so as to quickly forward a method invocation to the server
implementing the object. If the representation were some form of a
persistent identifier, we would have to perform the translation step
mentioned above. We believe this cost (or that of caching the translation)
should not be necessary during object invocation. Clients generally deal
with objects in their active form, and require the fast normal access to
objects, and only occasionally deal with the persistent form of objects
requiring persistence of access. If the two are separated, the translation
step can be performed when some persistent reference to an object is turned
to an active form.
In Spring, instead of using low?level persistent object ids for persistence
of access, we use the name service and normal names. To support this, we
provide the third kind of persistence, persistence of name binding. A Spring
client that wishes to have persistence of access will bind the object to a
name in a persistent name server, and later resolve the name when it needs
to access the object. The object returned by the name server will contain a
representation suitable for fast invocations and for passing the object
efficiently as an argument.
Persistent name bindings may not be required of all name spaces, nor for all
parts of a given name space. Some name servers simply hold name?to?object
bindings in primary memory, implementing a transient name space that
disappears when the server dies. Such policies are essential to avoid
burdening transient objects with the overhead associated with persistence
when accessed via the name service.
How does the name service make an object persistent? In the UNIX operating
system, the file management and the name space management are implemented
together, and it is easy for the name service to turn a file to and from its
persistent form. Choices takes a similar approach by requiring that all
object managers reside with the persistent name server. We find this
approach impractical, since naming is a generic service for an open?ended
collection of object types, and the name service is separate and autonomous
from the servers implementing the various objects in the system.
When an object is bound in a persistent name server, the name server must
contact the object manager, notifying it that one of its objects needs to be
persistent, and must obtain appropriate information that will be needed
later when the object is (re)created5 at name resolution time. For this we
have designed the freezing/melting interface. Freezing is the transformation
of the representation of an object into a form
Context object
Client
Name Server
Three notions of persistence: (A) the persistence of the object state, (B)
the persistence of the access by a client to the object, and (C) the
persistence of the binding between a name and an object.
State of context
foo
Object Manager
implementing object O
C
object O
Figure 4. Notions of Persistence
Resolve operation returns
copy of object O
State of O
Copy of O
Saved State
A
B
C
----------------------------------------------------------------------------
10
called a freeze token, which is a data value, not an object. That value can
later be melted to generate an object. Thus, the name server stores
name?to?object bindings as name?to?freeze?token bindings.
Since freeze tokens are forgeable, the connection to the object manager for
freezing and melting requires authentication. The freezing service ensures
that the same principal is performing the freeze and melt operations.
The freezing/melting interface can be used for all types of objects, can be
used by any client (including the name service itself), and insulates the
name service from the details of making the state of a particular kind of
object persistent. It provides a uniform way of dealing with persistence,
and defines the requirements for adding to the system new objects that wish
to use the name service.
5 Security and Access Control
There are four issues that have influenced our security design: trust,
protection, convenience, and performance. The first two relate to the
integrity of the name service itself, and how that impacts the objects that
use it; the last two are less fundamental from a security perspective, but
are essential for the general usefulness of naming.
5.1 The Four Issues
The first issue is trust between the parties involved in naming. We do not
assume that all naming components are trustworthy, but rather assume that
trust is established when needed by means of authentication. Resolving a
name can involve multiple name servers and an object manager, possibly
crossing boundaries of trust. Figure 5 shows the parties involved in one
example: the client, two name servers, and the object manager implementing
the object bound to the name being resolved.
The client interacts with name server A when performing an operation on
context C?say, resolving the name .6 Name server A does not trust the
client, and will require authentication. Server A resolves the first two
components to a context implemented in server B. Server B may or may
not trust server A when it says that it is performing the operation on
behalf of the client. Similarly, the object manager may or may not trust
name server B when B requests the bound object on behalf of the client.
Because we allow untrusted components to participate in naming, we must be
able to establish trust where appropriate by means of authentication.
5. We don?t consider the state of an object stored on a disk to be an
object, and hence refer to creating an object from a stored state rather
than activating an object.
6. We use the notation in this paper; however, this is not the
syntax for naming in Spring.
Context C
Client
Name Server A
Name Server B
A client has a context implemented by name server A. Part of the name space
spanned by this context is implemented in name server B. The name space in
server B has a binding to an object implemented by an object manger.
Figure 5. The Parties Involved in a Name Resolution
Object Manager OM
a
d
b
e c
----------------------------------------------------------------------------
11
The second issue is protection of the name service information from
unauthorized operations. A name server must protect itself by ensuring that
clients (which may be other name servers) performing naming operations are
permitted to do so. The name service must supply the means for clients to
specify who may bind objects into, unbind objects from or otherwise alter
its name space. Similarly, object managers also want control over which
clients can access its objects and in which modes.
The third issue is to make it convenient for clients to get, and for object
managers to provide, access to objects through the name service. If it is
inconvenient, we would expect other services to arise that provide objects
instead of the name service. In the typical case, a client resolving a name
wishes to get an authenticated, ready?to?use version of the object. The
object manager would like to receive a single operation with enough
information to validate the request and produce the appropriate object. We
would like to keep the protocols simple and the number of steps to a minimum
while providing sufficient security. While some object managers may wish to
implement their own access control lists, many others would prefer to leave
this to a trusted name server through which their objects are made available
to clients. Since almost every entity of interest in Spring is implemented
as an object, relegating access control lists to name servers makes the
general task of implementing objects simpler.
The last issue is performance. By developing and reusing trusted
relationships for multiple operations, it is possible to reduce the cost of
obtaining secure objects. In particular, the normal cases, where trust is
well? known, can be efficient, and the expense of establishing trust can be
borne by those who use different levels of trust. In addition, by returning
an authenticated object to the client when possible, authentication overhead
is reduced.
In Spring, the name service is the place where a client turns forgeable
names into authenticated, capability? like objects. It is crucial that the
name service perform name resolution in a secure fashion. During a name
resolution, the name service must:
1. Check all context nodes in the resolution path to see if the resolution
is permitted.
2. Check to see if the client is allowed to access the object in the mode he
has requested.
3. Arrange to return an authenticated object in the requested mode.
5.2 Authentication
A Spring object is like a capability: a client with an object is ordinarily
assumed to be able to perform the operations defined by the object.7 A
client usually uses an authenticated context where the principal on whose
behalf naming operations are performed is encoded in the state of the
context. The principal is most often established by an authentication
process that is performed to get the initial contexts for a domain. From
such authenticated contexts, a client resolves names to obtain additional
objects without authentication steps unless and until it encounters an
indirect name server or object manager that does not trust the name server
that implements the context object on which the client performed the resolve
operation.
In Figure 6, consider the client, who holds context C authenticated for
principal P (the state of the context in name server A will encode the
principal P), and resolves the name to obtain the denoted object
also authenticated for principal P. If server B trusts server A8 when A says
that it is performing the request on behalf of authenticated principal P,
and if the object manager similarly trusts server B, then the resolve
request can be performed without any authentication; the denoted object,
authenticated for P, will be returned to the client. If B does not trust A,
then the request will be interrupted (an exception will be
7. An object may be encoded with ?any principal? or ?untrusted principal?,
and may support only the authentication?related operations necessary to
produce a new object with greater capabilities after authentication.
8. If server A and B are in the same address space, then they trust each
other implicitly.
----------------------------------------------------------------------------
12
raised), which will cause the client to authenticate with B before
continuing. Similarly, the client will have to authenticate with the object
manager if the object manager does not trust B.
The trust between two name servers may be complete, nil, or partial. This
trust is established and encoded in the authenticated context object that
connects the name spaces implemented by the two name servers. If name server
B trusts name server A completely, the connection object (link b in Figure
6) is a special, authenticated, name?server to name?server context which
allows A to perform operations on behalf of all principals. The name?server
to name?server context interface has the following operation:
named_object = resolve_on_behalf (name, mode, principal_name)
On the other hand, if a normal context object, authenticated for a
particular principal P, connects name servers A and B, then A can perform
operations on behalf of P only.
For example, the local file server (which implements the file name space)9
completely trusts the local machine name server, and therefore a name
resolution along a path from the machine name space to the file name space
does not require additional authentication, since the two name spaces are
connected via a name?server to name?server context. (Our naming environment
is described in Section 7.6.) On the other hand, context objects bound in a
domain?s private name space are authenticated using the domain?s principal,
to avoid additional authentication.
The authenticated connections between two name servers and between a name
server and an object manager are established once, and are reused to avoid
authentication overhead. Similarly, the relationship between name servers
and object managers is established using authenticated objects, as discussed
in the next section.
Passing Contexts as Capabilities
An interesting case arises when a client passes a context to another client
who is a different principal. As is the case with other objects, possession
of the object ordinarily permits the second client to perform operations as
if it were the first client. However, when a multi?component name is
resolved in a context, the resolution path may cross into servers other than
the one that implements the context. Thus, for contexts, the delegation of
authority when a context is passed is valid only so long as trust boundaries
are not crossed. At that point, the second client must either proceed under
its own identity, or must negotiate through the first client for access to
further contexts, just as the first client would do if it were issuing the
request. Thus, an
9. Note that while name servers are generally separate from object managers,
for access to our UNIX world and UNIX compatible disks, we have file servers
that manage both the files and the file name space, and are accessed through
the standard naming interface.
Context C
Client
Name Server A
Name Server B
A client has a context implemented by name server A and B. The name space in
server B has a binding to an object implemented by an object manger. The
resolves name to get the object.
Figure 6. Authentication and Name Resolution
Object Manager OM
a
d
b
e c
Object O
authenticated for
principal P
Resolve returns O
authenticated for principal P
----------------------------------------------------------------------------
13
authenticated context is a capability that allows access to a portion of the
name spaces spanned by that context without further authentication. This
portion includes the name space managed by the name server implementing the
authenticated context (e.g. the portion implemented by name server A in the
case of context C) and recursively the portions implemented by name servers
that trust this name server (e.g., the portion implemented by name server B
if B trusts A).
5.3 Access Control on Naming Operations and Objects
The name service defines and implements an access control model based on
Access Control Lists (ACLs). Each context has an ACL; a principal is granted
a set of rights encoded in a bit mask, for example, to permit searching,
binding into, or deleting from contexts. Since this facility was required to
control operations on context objects, we decided to provide an ACL on each
binding for access control of objects. An object manager may implement ACLs
for its object if it desires, although many object managers export their
objects through name servers they trust, and rely on the per?binding ACLs
provided by these name servers.
This raises an interesting issue: the access control depends on the path
used to resolve names. Note that even in traditional name services that
allow DAGs (as hard or symbolic links), the access control depends on the
path used to resolve a name, with the final access control being on the
object itself. The same is true for our scheme when object managers
implement their ACLs. However, some object managers do not implement any
ACLs, and simply rely on the per?binding ACL. Such object managers usually
publish their objects through only one name server (the one they trust), and
the per?binding ACL where the object manager bound the object can be viewed
as ?the object?s ACL.? Of course, a client who obtains such an object can
always rebind it in a different part of the name space to share with others,
but this object will retain the limited access with which it was originally
issued.
Because the access rights for contexts cannot anticipate all the possible
semantics of objects, we introduce the notion of mode, which is a value that
defines the set of rights with which the object is intended to be used. The
name service checks that the principal (as encoded in the context object)
making the resolve request has the rights specified in the mode parameter.
It passes the mode parameter to the object manager, in order to permit it to
create an object with no more access rights than specified in the mode?for
example, to allow a client with read and write access to obtain an object
that permits only read access. The resolve operation fails if the client is
not entitled to access the object in that mode.
The meanings of the access rights are determined by the semantics of the
objects. Generally, they are considered part of the interface for that
object. There is one mode, called the default mode, that is understood by
name servers and all object managers. When this mode bit is specified to the
resolve operation, the object will be returned with the maximum possible
rights for the given client.
5.4 Summary
The Spring name service allows untrusted components to participate in
providing naming and publishing objects. Authentication is done at
appropriate times to establish trust. These trust relationships are encoded
in capability?like authenticated context objects, which are reused to avoid
authentication complexity and overhead after trust is established.
Since the name service needs to implement authentication and access control
to protect itself, it is natural to have the name service provide those same
services in an integrated way for the convenience of clients and object
managers. When trust cannot be established, or when object managers have
stronger security requirements, they resort to direct authentication between
the client and name server or object manager.
----------------------------------------------------------------------------
14
6 Interactions between the Client, Name Servers, and Object Manager
The preceding sections have discussed the requirements and general approach
for persistence and security. This section shows how the three participants
in naming?the client, the name server, and the object manager?interact. The
interfaces and protocols provide flexible support for persistence and
security, and allow a variety of policies, implementations, and
optimizations.
6.1 Client and Name Server Interaction
During a resolve operation (and, in fact, any operation with a compound
name, since a resolution occurs to navigate the naming graph), if the name
server gets to a point where it cannot continue the resolution, but where
the client may be able to, it will raise the cannot_proceed exception. The
exception returns information needed to continue the operation, such as the
name processed so far, the rest of the name to process, a context in which
to continue the naming operation, and other data required to complete the
naming operation. The exception is raised in various situations, including
inadequate implementation, handling of symbolic links, and when boundaries
of trust are crossed during the naming operation.
A client?side name service library catches the exception and continues the
operation. A resolve operation is processed in the client side library as:
while {
try {
result = context.resolve(name, mode)
exit_loop
} except ex {
cannot_proceed {
if (ex.reason == cannot_continue_resolution) {
context = authenticate_if_necessary(ex.context_in_which_to_continue,
credentials);
name = ex.reminding_name
} else if (ex.reason == cannot_authenticate_object) {
result = authenticate_and_get_object(ex.zero_rights_object, credentials,
mode);
exit_loop
} else ...
}
}
}
When a trust boundary has been crossed and an exception is raised, it is
necessary for the client to authenticate itself with the returned context or
object in order to continue the operation. Note that this is also the
opportunity for the client to authenticate the new name server, since the
client is trusting the name service to provide the proper objects (in order
to avoid Trojan horses).
6.2 Name Server and Object Manager Interaction
After the name has been resolved to the point of a particular binding, and
after access rights have been checked to ensure that the operation is
permitted, the name server needs to interact with an object manager. A
persistent name server interacts with an object manager to freeze and melt
objects. This is done through the object manager?s freezing_service. A
transient name service, or a persistent name service that has melted once
and cached the resulting object, interacts with the object manager during a
resolve operation to generate a copy of the denoted object in a specific
mode authenticated for a particular client. This is done through the object
manager?s duplication_service.
Both the duplication and the freezing service objects may be implemented
directly by the object manager or delegated to some other service. Generic
forms of these services are available for simple object manag-
----------------------------------------------------------------------------
15
ers. Name servers typically cache authenticated connections to the
duplication and freezing services, but of course, they may be revoked by the
object manager or deleted and reacquired by the name server at any time.
Also, as we show below, duplication, freezing, and melting may in some cases
take place locally at the name server.
The name service obtains these services using the object manager identifier,
which is simply a name that each object provides via the
get_object_manager_id operation. The name service resolves the object
manager identifier in a well?known context, resulting in an appropriately
authenticated freezing or duplication service object. Obtaining the services
indirectly via a name instead of directly via the object is an important
factor in freezing and melting securely (as explained below).
6.2.1 Duplicating an object
The object returned as the result of a name resolution usually encodes the
appropriate principal and the requested mode. The dup operation on the
duplication_service takes the object to be duplicated, the desired
principal, and the desired mode, and returns an object authenticated as that
principal and enabled for that mode. If the client requested the default
mode, then the maximum allowed mode is specified to the dup operation.
Most object managers make their objects available to their clients by
binding these objects in some name space. If the object manager does not
trust the name server managing the name space through which it publishes its
objects, then it must implement its own ACLs. When a client resolves the
name of such a published object, a duplication request arrives at the object
manager. If the object manager implements its own ACLs, it will check it and
raise an access_denied exception if access is not permitted. If the object
manager trusts the name server, then it accepts its word on the principal,
and returns an authenticated object in the requested mode. If it does not
trust the name server, then it will return an unauthenticated object, and
the name server will propagate the result to the client via a cannot_proceed
exception, allowing the client to perform an authentication step.
A client will often bind an object that was obtained in a specific mode for
a particular principal into a name space for sharing with another client.
When a duplication request arrives for such an object, the object manager
will compare the principal requested with that encoded in the object; if
they are the same, then it will return a duplicate object with a mode that
is the same as or less than the original mode (note that since the
principals are the same, it not necessary for the object manager to trust
the name server). If the principals are different, the object manager
implements its own ACLs, and the ACL permits the requested mode for the
requested principal, then an appropriate authenticated or unauthenticated
object is returned, depending on whether the object manager trusts the name
server. In all other cases, it will raise the access denied exception. What
is interesting here is that when an object is passed as a capability via the
name service, it will succeed only if the principals are the same or if the
object manager implements its own ACLs.10
If there is no duplication service, then the object manager does not support
modes or encode principals, and the object representation can be copied
locally by the name server. There are also some degenerate duplication
services implemented by name servers?for example, to copy the state of an
object that is only data. Exotic duplication services are also possible?for
example, a duplication service might limit the number of copies of an object
that could be allowed at once.
6.2.2 Freezing and melting an object
The freeze and melt operations are performed as part of binding and
resolving names in a persistent name server. In both cases, it is necessary
for the name server to interact with the freezing service without using the
object. When melting, the object is not available, only its freeze token is,
and the name server must
10. We are currently investigating alternative ways of dealing with such
capabilities bound in a name space.
----------------------------------------------------------------------------
16
convince the freezing service that it is the same name server that froze the
object previously. This is one reason why during freezing, although the
object is available, freezing is not an operation on the object, since the
object manager needs to establish who is asking for the object to be frozen.
A second reason is that it is important that the name server ensure that it
freezes and melts objects at the same freezing service (or rather, obtains
the freezing service in the same way). Otherwise, it is quite easy to
compromise the security of the name service. For example, one may consider
it natural to combine the steps to get the object manager identifier (omid)
and the freeze operation as part of a single (freeze) operation on the
object. Then one could implement bind and resolve as:
This approach has a serious security problem. A malicious client in concert
with a malicious object manager can trick a name server to give, for
example, the password object in write mode as follows: the malicious client
binds a name to an object implemented by the malicious object manager.
During the freeze operation, the malicious object manager returns to the
name server the object manager identifier of the password object (which can
be obtained from the password object) and the freeze token of the password
object (which is forgeable and it has been able to guess). The malicious
client resolves the object for write? mode (it has permission, since it did
the bind). The name server is tricked into performing the melt operation at
the freezing service of the password object and returning the object in
write?mode.
Our design ensures that freezing and melting are performed at the same
place:
Since freeze tokens are forgeable, connection to a freezing service must be
authenticated in order to ensure that the name service is trusted to melt
the particular object. For practical purposes, freeze tokens are not
globally unique but are scoped relative to the freezing service that issued
the token.
During the life of a system, object managers and their freezing services
will occasionally crash. One could require system administration to arrange
for the object managers to be restarted after every crash. A better approach
would be for the melt operation to trigger the start of the corresponding
object manager. This would allow object mangers to be up only when active
instances of their objects are around, and die otherwise. This can be made
to occur easily using the freezing scheme recursively. Before melting an
object, the name service first tries to access the freezing service by
resolving its object manager identifier. This requires melting the freezing
service object, and can trigger the object manager to be restarted if it is
not running. For bootstrapping, we require freezing services to be frozen
and melted at special services; the system only has to ensure that such
services are kept alive.
As with duplication services, freezing and melting are usually done by the
object manager, but may be done elsewhere. One special case freezing service
is used for objects that are only data. In this case, the
bind(n, bt, o):
= o?>freeze();
store_binding(n, bt, omid, ftoken)
resolve(n, mode):
= get_binding_for_name(n)
fs = get_authenticated_freeze_service(omid);
o = fs?>melt(ftoken, mode);
return o
bind(n, bt, o):
omid = o?>object_manager_id()
fs = freezing_ctx?>resolve(omid)
ftoken = fs?>freeze(o)
store_binding(n, bt, omid, ftoken)
resolve(n, mode):
= get_binding_for_name(n)
fs = freezing_ctx?>resolve(omid)
o = fs?>melt(ftoken, mode)
return o
----------------------------------------------------------------------------
17
freezing service simply returns the representation of the object as the
freeze token; the melt operation regenerates the object from the token which
contains the representation. This generic freezing service is available in
libraries that are linked into name servers.
Another interesting case is the ?transient object freezing service,? which
can be used for objects that cannot be made persistent (such as the object
that represents a domain). This service simply keeps the objects passed for
freezing in primary memory and issues freeze tokens, subsequently returning
the objects when asked to melt them. This service may conveniently be linked
into various object managers, or can be implemented separately. It relieves
all persistent name servers from handling unfreezable objects, and provides
the uniformity where all objects, even those that cannot be made persistent,
can be bound in persistent name spaces.
6.3 Name?Server to Name?Server Interaction
A multi?component name resolution (on a resolve or other operation) can
cross name server boundaries. Consider a name resolution crossing from name
server A to name server B in Figure 6. Server A performs part of the
resolution, and forwards the remaining name to server B, giving the name of
the principal on whose behalf the resolution is being performed. Server B
returns a properly authenticated object or raises an exception, such as
cannot_proceed. Server A returns the results to the client.
Name server B raises the cannot_proceed exception in two situations. One is
when this exception is raised by an object manager or another name server
with whom name server B interacts during the resolution; in this case, name
server B simply re?raises this same exception. The second situation arises
when server B does not trust A, in which case server B will raise the
cannot_proceed exception, requiring the client to authenticate itself with
server B and continue the operation.
As we mentioned in Section 5.2, two name spaces implemented by two name
servers are connected by an authenticated normal context object or by an
authenticated name?server to name?server context object.
7 Use of Name Services in Spring
This section illustrates how the name service is used in Spring for a wide
variety of purposes. It demonstrates the general usefulness of the context
interface, and the range of implementations that are possible.
7.1 Uniform Name Services
Although Spring does not have the concept of a global name space, the name
service is universal, in that any object to be named can be named using the
same name service: this applies whether the object is local to a process,
local to a machine, or resident elsewhere on the network; whether it is
transient or persistent; whether it is a standard system object, a process
environment object, or a user specific object. (Note that in Spring, not all
objects are named. However, any object that is to be named can indeed be
named using our name service.)
As a result, tools to browse and manipulate name spaces can be used on any
name space, whether for debugging a transient collection of objects, or for
searching for file objects. Although not all name spaces are linked
together, over time we have composed different name spaces in different
ways. For example, the name space given to a domain when it is created is
composed of transient and persistent, and of local and networked name
spaces.
7.2 Ordered Merges
Ordered merges in other systems are usually restricted to special
situations, such as command search paths or unions at mount time. In Spring,
since context objects can be manipulated directly, we did not clutter the
----------------------------------------------------------------------------
18
context interface with a notion of merges. Instead, we provided merges as a
separate contexts implemented in a library. We give several examples below
of our use of ordered merges in constructing name spaces.
7.3 Generic Implementations
Generic implementations of contexts are available in dynamically linked
libraries. They provide persistent and transient name spaces, and implement
the full security model. We also have a client side name service library
that handles the cannot_proceed exception and other client side
responsibilities. The name space of a domain, the name space of a machine,
and the name space shared by a set of machines all use these generic
implementations. Applications and services whose primary purpose is not
naming use a much simpler and more specific implementation.
Currently, we have several freezing services. For example, we have a file
server that manages unnamed files; its freezing service returns an extended
inode number as a freeze token. Data?like objects use the generic freezing
service. By default, objects that do not have their own freezing service
(because they are not persistent) use the transient object freezing service
mentioned in Section 6.2; as a result, all Spring objects can be bound in a
persistent name space.
7.4 Interoperation with Foreign Name Spaces
Sun?s NIS? directory provides information about various resources in our
UNIX network. We have implemented a gateway that allows access to the NIS
name space from Spring. The gateway supports the context interface, and
translates between NIS names and Spring names, handling issues of syntax.
Thus, Spring clients can set or retrieve NIS data using the Spring naming
interface.
7.5 Accessing Foreign Named Objects
We access files in the UNIX file system via a service that encapsulates the
UNIX file system. We map the UNIX name space into a Spring name space,
exporting UNIX files as Spring files and UNIX directories as Spring
contexts. A client wishing to open a file performs a resolve operation on a
context, specifying the access mode desired. The server forwards the request
to the UNIX file system, and encapsulates the resulting UNIX file as a
Spring object. In the encapsulation, we have extended the original UNIX file
system semantics to allow arbitrary objects to be bound into contexts. For
example, non?local files and non?file objects are simply frozen, and the
resulting freeze token is stored in a file.
7.6 Policies: The Spring Naming Environment
The Spring name service does not prescribe particular naming polices. Our
current policy is to provide a combination of system?based shared name
spaces, per?user name spaces, and per?domain name spaces that can be
customized by attaching name spaces from different parts of the distributed
environment. We use ordered merge constructions for further flexibility in
tailoring name spaces.
In Spring, machines are grouped into villages, based on geographic location,
security considerations, administrative convenience, etc. There is a high
degree of sharing within a village, but limited and controlled sharing
across villages. A machine has a local name space for its local entities,
and a village has a name space for the entities shared among machines. The
village name spaces are connected via an enterprise level name space. These
system based name spaces are used to make system resources available to
clients.
Each user has a private name space that persists across login sessions, much
like the home directory in UNIX. The main difference in Spring is that a
user is allowed to attach various name spaces to configure a private naming
view.
----------------------------------------------------------------------------
19
Each domain also has its own private name space that can be customized to
access arbitrary name spaces? in particular, parts of the machine and
village name spaces, and typically, the per?user name space of the user on
whose behalf the domain is executing. The per?domain name space also
incorporates private name spaces such as the environment variables name
space. The per?domain view captures the dynamic and run?time environment of
a computation. In particular, it has bindings for system objects such as
binaries and libraries based on the current site of execution; as remote
execution is performed or as a process migrates, the per?domain view may
change. In general, it is not necessary for a domain?s naming view to
persist when the corresponding domain dies. A domain?s private name space
typically contains the following (see also Figure 8):
? Private name bindings
The domain?s name space has bindings for environment variables and program
input/output objects. (A special mechanism to pass standard I/O objects as
implicit parameters is not needed.)
? Shared name spaces
Several shared name spaces are attached to the domain?s name space using
well?known names: ~ (the per?user name space of the user owning the domain),
user (the name spaces of different users), and dev (devices). If there were,
for example, a worldwide global name space, we would attach it to the name
space of a domain using a well?known name. The use of well?known names
provides coherence (transparency) in naming in the distributed environment.
? Generic name spaces containing standard system objects
A domain?s name space has generic name spaces that contain system objects:
sys (executables under sys/bin and libraries under sys/lib) and services
(such as services/authentication). The name spaces of sys and services have
parallel structures in both the machine and village. These name spaces
contain copies of such system objects for local use.11
The sys and services name spaces in a domain?s private name space are
typically an ordered merge of the corresponding name spaces of the machine
and village. The merge arranges for the local instance to be visible first.
A user can also keep similar structures in his home contexts, which can be
used for further tailoring of these name spaces. During remote execution,
the merges are automatically re?evaluated to take advantage of the name
spaces of the remote site.
Each parent domain passes to its child a context defining the child?s
private name spaces. This is usually a copy of the parent?s context. Since
most domains make few changes to their name spaces, we make the child?s
context a copy?on?write copy of the parent?s. Note that a domain can be
given and can acquire other contexts. The init domain initializes a domain
name space that it passes to its children; they, in particular the domains
that are created as a user logs in, further customize their inherited naming
view.
Implementation of the Naming Environment
The naming environment is implemented by several name servers. The
machine/domain name server (one per machine) implements the machine name
space and also the name spaces of each of the domains on that machine. The
village name server (one per village, though it may be replicated)
implements the village name space shared by all machines in the village. The
domain name space has parts of the machine and village name spaces attached
to it. (Figure 8 shows a typical configuration of name spaces and name
servers.) The machine name space also has parts of the village name space
attached to it. In addition, for access to our UNIX world and UNIX
compatible file system disks, we have several file servers that implement
the
11. The local copies are in addition to what is kept automatically by our
caching scheme. Local copies allow a machine to maintain local autonomy,
especially during disconnected operations.
----------------------------------------------------------------------------
20
files and the file name space accessed via our standard name service
interface. These file name spaces are attached to the machine and village
name spaces.
The trust between name servers is established and encoded in the
authenticated context object that connects the corresponding name spaces
implemented by the name servers. For example, in Figure 8, consider the name
space of files on the local disk which is attached to the local machine?s
name space; the file server completely trusts the local machine name server,
and therefore a name resolution along a path from the machine name space to
the file name space does not require additional authentication. Similarly,
the file servers in the village trust the village name server. The
name?server to name?server context is used to attach the file name spaces to
both cases.
On the other hand, context objects bound in a domain?s private name space
(see Figure 8) are normal context objects authenticated using the domain?s
principal, so that names resolved through these contexts do not require
additional authentication as name server boundaries are crossed. This
optimization significantly
users
sys
bin lib
joe
jim ~ services
dev
sun
Figure 7. A Typical Per?Domain Name Space
the root of the domain name space
----------------------------------------------------------------------------
21
reduces the authentication overhead when a domain resolves names. The
village name server does not trust most machine name servers, and hence
requires clients to authenticate on naming operations.
7.7 Contexts Implemented by other Services
Many services and applications allow access to various pieces of information
distinguished by identifiers. The context interface is useful to such
subsystems, even though their primary business is not the name service. One
example is that of the generic monitoring objects used by many different
services to give statistics about the server. The various values,
represented as data?only objects, are accessed by names through the context
interface. The implementation needs to support only two operations, resolve
and get_all_bindings, much as any read?only context would.
A second example is in the dynamic object invocation service, which allows
an invocation to be performed without first having been compiled. Using
interface specifications from a database, arguments to the operation are
bound in a context object, using IDL formal parameter identifiers as the
names. The context is passed with other information to the invocation
service, which marshals the arguments, performs the call, and returns the
results in a similar context.
7.8 Virtual Worlds and Name Spaces
One often needs to build virtual worlds, in which clients are insulated from
aspects of the real world. This is difficult to support with traditional
name services that have rigid notions of name spaces and root contexts. In
Spring, it is easy to create a parallel set of name spaces for particular
purposes. In our development environment, several releases of the system are
tested and used simultaneously. Each new release of Spring publishes
executables, libraries, and services, which are accessed through the release
versions of the sys and services name spaces. In most cases, developers do
not break binary compatibility, and need to override only some objects.They
use an ordered merge to overlay their name spaces on the standard release
Figure 8. A Typical Configuration of Name Spaces and Name Servers
NS
domain
per
NS
machine
Machine/domain name server
NS
Village Village name server
NS
file
NS
file
File server File server
name space
one or more attachments
between name spaces
NS
----------------------------------------------------------------------------
22
name spaces, resulting in a parallel world with partly shared name spaces.
When binary compatibility is broken, they create a private, separate world
with its name spaces.
8 Related Work
8.1 Uniformity
As mentioned in the introduction, the lack of uniformity in conventional
systems causes three problems. Firstly, clients have to use a different name
service depending on the kind of object being named. Secondly, defining new
objects or services that are accessed by name can be complicated and
cumbersome, since the new objects must be made to ?fit in? somewhere, or a
new name space must be defined and implemented. Thirdly, the non?uniform
name spaces generally cannot be composed together.
DCE[12] has made an attempt to improve uniformity by composing name spaces
such as file system name spaces onto the higher level directory name space.
This is done through special entities called junctions. For example, a
junction point in the directory level name space called fs signals that one
is entering the file system name space (it is like a specialized mount
point). This provides network?wide access to files: a client can name files
and file systems in other parts of the network. However, the client is still
faced with multiple name spaces and their corresponding naming interfaces.
(Furthermore, it not clear how easy it is to create new junctions when
introducing new object types and their corresponding name spaces.) While DCE
does not provide a uniform name service, it provides a uniform way of
accessing the various name spaces in the network.
Plan 9
Given the lack of some unifying concept like an object, the Plan 9 approach
is probably the best way of providing uniformity of naming in UNIX or other
non?object oriented systems. However, in an object oriented system, our
approach has several advantages over Plan 9?s approach of attempting to make
all objects look like files.
The first advantage is that in Spring, nameable objects have strong
well?defined interfaces that are appropriate for the particular type of
object. We do not attempt to make all objects obey the file interface and
hide the object?s true interface inside the read, write, and ioctl
operations.
The second advantage is that the effort required to make new object types
nameable is low. Nameable objects in Spring do not have to be made to obey
the file interface, and object managers do not have to implement the name
service. For example, objects implemented by the Spring kernel, such as
domains (processes), VM objects, and kernel monitoring objects, are
routinely bound into the machine?s name spaces; the kernel did not have to
change the nature of these objects or implement a name service to make this
possible. This means that new nameable objects and new implementations of
nameable objects can be added to the system at any time without modifying
the implementation of the name service. Spring developers routinely create
new objects and make them available via the name service.
In contrast, Plan 9 requires that nameable non?file objects be made to look
like files, and that implementations of the non?file objects implement the
(file) name service. Although Plan 9 has been able to make many objects look
like files, it does require a certain amount of effort which is not required
in our system. Furthermore, we believe that the Plan 9 approach cannot
succeed for all kinds of objects. Indeed, the network name space in Plan 9
(the name space that binds file servers) does not map very easily to a file
system, and hence is a separate non?file name service[5].
The third advantage is that Spring name spaces need not be segregated by the
type of objects being bound in them. For example, we can store a file in our
equivalent of the /proc file system, and we can store a domain object in the
file system. This functionality is not possible in Plan 9, since the /proc
implementa-
----------------------------------------------------------------------------
23
tion deals exclusively with processes being made to look like files, and the
regular file system deals only with real files.12 Thus, in spite of making
most objects look like files, a lack of uniformity is evident, since each
?file server? can only bind objects of the same true type.
Other Object Oriented Systems
Although, the uniformity of objects in object oriented systems offers an
opportunity for a uniform name service, existing object oriented systems
either have not provided a uniform name service or have provided one with
serious restrictions. Programming language based object oriented systems
such as Smalltalk rely on the name space of variables with nested scopes
provided by the programming language. In Emerald, objects were generally
obtained using the language based variable naming scheme, and did not use a
general name service[20,21]. Others like Choices[10,11] have the serious
restriction that the object managers must be integrated and reside with the
name service; this makes it difficult to add new object types. Furthermore,
Choices provides two name services: one for persistent objects and one for
transient objects.
One of the main difficulties has been that the name service often needs to
interact with the object managers for the purpose of persistence and
security. For example, Choices avoided the problem by providing two name
services, one for persistent objects and the other for transient objects. It
also requires that the persistent name server and all the object managers of
objects being named reside together, which makes adding new objects or
implementations difficult.
8.2 The Naming Model and Environment
We chose a general naming model and made contexts and name spaces first
class entities that can be manipulated directly and passed around like any
other object. This first class nature is not merely a consequence of being
object oriented?we could have simply required that names be resolved
relatively through the root or working context. In UNIX, for example,
opening a directory returns a file that can be used for listing the
directory entries, but cannot be used for other directory operations, such
as creating new directories. Also, UNIX applications that need to exchange
and share a private name space would have had to build their own naming
facility or incorporate the private name space into a larger system?wide
name space and access it indirectly via the root or working context. Spring
applications can share and exchange private contexts and name spaces. The
first class nature of contexts has also made it very simple for us to
support context constructs like ordered merges without limiting the use of
ordered merges to ?mount? time (as in Plan 9) and without making the notion
of merges a part of the naming interface.
Our name service leaves policies to a higher level. Our current policy is
based on per?domain (like Plan 9), per?user, and system based name spaces.
We rely on attaching name spaces and ordered merges to tailor a per?domain
name space. We have avoided Plan 9?s per?process mount tables, which are
clearly more flexible, for two reasons. Firstly, we found that ordered
merges allow a process sufficient flexibility in configuring its name space,
and have not found the need to add the notion of per?process mount tables.
Secondly, when a private name space overlays a shared name space, resolving
names in the shared name space becomes more complex in a distributed
environment: one cannot blindly resolve path names in a remote shared name
space, as private local mounts may overlay parts of it.
8.3 Persistence
In Clouds, all object references are persistent and the name server does not
have to deal with the issue of making objects persistent. Spring object
references, on the other hand, are not persistent. The freezing architecture
is used to convert object references to and from their persistent form and
also to communicate
12. The best one can do in Plan 9 is to use the union mount to attach
special file systems behind the regular directory, so as to allow regular
files to be created ?ahead? of the mounted special file system.
----------------------------------------------------------------------------
24
to the object manager that one of its objects needs to be made persistent.
The Spring name service plays a crucial role in persistence?a client that
needs an object to be persistent simply binds the object in a persistent
name space and later retrieves it using its name.
Choices provides two different name services, these being for persistent and
transient objects, respectively. Spring provides a single name service
interface for persistent and transient name spaces, and allows persistent or
transient objects to be bound in either kind of name space.
In type specific name services such as the UNIX file system, the object
manager and the name service reside together, and can easily turn objects to
and from their live form; they do not need a general freezing architecture.
Directory services avoid the issue by simply mapping names to data values,
leaving the client to turn a data value into a live usable object.
8.4 Security
The trust between Spring name servers may be complete, nil, or partial, and
is encoded in the authenticated context object that connects name spaces.
Previous name services have used a more static structure for the trust
relationships between name servers.
In the UNIX file system, trust between different parts of the file name
space connected via the mount operation is not an issue, since all the name
spaces are managed with the kernel. With NFS? (Sun?s distributed computing
file system), when a name resolution is forwarded to an NFS server, the
server trusts the client machine as long as the principal (user id in UNIX)
is other than the root.
In X500[6] , the directory service agents authenticate with each other, and
when a name resolution along with the client?s principal name is forwarded
from one directory service agent to another, the second one trusts the first
one to have authenticated the client.
In DCE, within a cell, name servers trust other name servers. Across cells
there is no trust, and the client must have an account on the foreign cell
and perform authentication. In Spring, even within a village (similar to a
cell), there are different degrees of trust. For example (see Figure 8), the
machine name servers trust the village name servers, but the reverse is
generally not true. Within a machine, all name servers, including file
servers, trust the machine name server. Furthermore, partial trust is
established for name spaces bound in the per?domain namespace by using
contexts authenticated for the domain?s principal. In DCE, the equivalent of
the cannot_proceed exception is handled in the client agent process, while
in Spring, it is handled in a library in the client itself.
Spring architecture allows object managers to determine how much to trust a
particular name server, and an object manager is permitted to forego the
convenience of per?binding ACLs and implement its own access control and
authentication, if it wishes. The issue of trust between object managers and
name servers is fairly unique to our name service. It does not arise in
conventional type specific name services such as the file system, because
the name service and the object manager are implemented in the same server.
Directory services avoid the issue by simply mapping names to data values,
leaving the client to turn a data value into a connection to an object
manager after authentication.
9 Concluding Remarks
The Spring system, including its name service, is in daily use for its own
development and further experimentation. The name service provides
acceptable performance in its various uses, although optimization work is
ongoing. The system also supports UNIX compatibility mode binaries (the
emulation package is a thin veneer on Spring services[16]).
The distinguishing features of the Spring name service are as follows:
----------------------------------------------------------------------------
25
? Uniform and extensible name service. Name services and name spaces do not
need to be segregated by the type of the object?in principle, any object
could be bound to any name.The name service provides critical support to
integrate new kinds of objects and new implementations of existing objects
into Spring. It also provides this same capability for name servers,
including the ability to extend the name space and compose new name spaces.
? General naming model with first class name spaces. We use a general naming
model, based on names and contexts, that is powerful enough to meet the
various naming needs of the operating system, applications, and users.
Contexts are ?first class? objects that can be directly used to create and
manipulate name spaces and to pass them around like other objects. A name
space need not be part of some larger global name space; policies such as
notions of root or working context are not part of the name service, but can
be built on top of it. The naming interface is generic, and is applicable to
non?traditional use, such as in spreadsheets.
? Integrated support for access control and persistence. The name service
architecture provides access control and persistence for those object
managers who wish to delegate those functions to it, while allowing them to
retain control when needed. Clients see the name service and object managers
well integrated, as in type specific name services.
While our object oriented environment made uniformity possible, there were a
number of challenges, especially with regards to integrating persistence and
security.
The Spring name service plays an important role in accomplishing the goals
of Spring. We have successfully integrated all name?to?object mechanisms in
one service. By masking the differences between objects of different types
or of different implementations, we can add new facilities to the system, or
can replace existing facilities in a first class way. Programmers and users
do not need to learn new models and new methods of access, and are insulated
from many changes and extensions.
In making Spring secure and robust, the overhead in complexity and
development can be a substantial impediment. Having the name service provide
access control and a framework for persistence has made it easier to have
these capabilities pervasively in Spring services.
Other object oriented systems have made use of the uniformity of objects.
Spring carries those objectives further, truly separating naming into a
service in its own right, rather than making it an adjunct to one or more
objects. Moreover, that name service is not just a generic addition to a
collection of type specific name services, but is the only name service used
in Spring.
The context interface has proven useful in a growing variety of situations
in Spring. As we expand the application base and usages of the system, we
find more ways to use the name interface, and discover more advantages of
having access to functionality through a naming?style interface.
A result that remains to be proven, but toward which work is ongoing, is
that the uniformity and extensibility provided by objects and naming at the
system level will accrue benefits to users of the system.
10 References
[1] J. H. Saltzer. Naming and Binding Objects. In Operating Systems: An
Advanced Course, volume 60, pages 99?? 208. Springer?Verlag, New York, 1978.
[2] Lampson, B., ?Designing a Global Name Service?, Proceedings of the 5th
ACM Symposium on Principles of Distributed Computing, 1?10, Calgary Canada,
Aug. 1986.
[3] Birrell et. al. ?Grapevine: An Exercise in Distributed Computing?, Comm.
of ACM, April, 982, pages 260?273
[4] Pike R., Presotto D., Thompson, K., and Trickey H., ?Plan 9 from Bell
Labs? Proceedings of 1990 UKUUG Conference, July, 1990
----------------------------------------------------------------------------
26
[5] Pike R., Presotto D., Thompson, K., and Trickey H., ?Use of Name Spaces
in Plan 9?, Unpublished report, 1992
[6] CCITT, X500, 1988
[7] UNICODE
[8] Thompson K., and Ritchie D.M, ?The UNIX Timesharing System?, Comm. of
ACM, July, 1974, pages 365?375
[9] Cheriton D. and Mann T.P, ?Decentralizing a Global Naming Service for
Improved Performance and Fault Tolerance? ACM Trans. on Computer Systems, 7,
2 (May, 1989), pages 147?183
[10] Campbell R.H., Islam N., and Madany P., ?Choices, Frameworks, and
Refinement,? USENIX Computing Systems. 5, 3 (summer 1992), Pages 217?257
[11] Madany P., ?Personal Communication,?, 1992
[12] J. M. Berabeu?Auban et al, ?The Architecture of Ra: A Kernel for
Clouds?, 22th Hawaii International Conference on System Sciences, Jan 1989,
pages 936?945.
[13] Radia S. Madany. P., Powell M. P, ?Persistence in an Extensible System
with General Naming?, internal Spring document
[14] Hamilton G., Powell M. P., Mitchell J. G, Subcontract: ?A Flexible Base
for Distributed Programming?, SMLI technical report 93?13
[15] Hamilton G., Kougiouris P., ?The Spring Nucleus: A Microkernel for
Objects?, USENIX Summer Conference, July 1993
[16] Khalidi, Y. A. and Nelson, M. N., ?An Implementation of UNIX on an
Object?oriented Operating System?, USENIX Winter Conference, January 1993.
[17] Radia S., Powell M. P., ?Generic Services and Type Parameterization?,
internal Spring document
[18] OMG, CORBA 1.1
[19] Radia, S. Names, Contexts, and Closure Mechanisms in Distributed
Computing Environments, Ph.D. thesis, Univ. of Waterloo, Dept. of Comp.
Sci., Waterloo, Ontario, Canada, 1989. Also report UW/ICR 90?01.
[20] Jul E., Levy H., Hutchinson N., Black A., ?Fine?Grained Mobility in the
Emerald System,? 11th ACM Symposium on Operating Systems Principals.
November 1987
[21] Hutchinson N., ?Personal Communication,?, 1993
----------------------------------------------------------------------------
27
? Copyright 1993 Sun Microsystems, Inc. The SMLI Technical Report Series is
published by Sun Microsystems Laboratories, Inc. Printed in U.S.A.
Unlimited copying without fee is permitted provided that the copies are not
made nor distributed for direct commercial advantage, and credit to the
source is given. Otherwise, no part of this work covered by copyright hereon
may be reproduced in any form or by any means graphic, electronic, or
mechanical, including photocopying, recording, taping, or storage in an
information retrieval system, without the prior written permission of the
copyright owner.
TRADEMARKS
Sun, Sun Microsystems, and the Sun logo are trademarks or registered
trademarks of Sun Microsystems, Inc. UNIX and OPEN LOOK are registered
trademarks of UNIX System Laboratories, Inc. NIS MicroStation is a
registered trademark of SPARC International, Inc. All SPARC trademarks,
including the SCD Compliant Logo, are trademarks or registered trademarks of
SPARC International, Inc. SPARCstation, SPARCserver, SPARCengine,
SPARCworks, and SPARCompiler are licensed exclusively to Sun Microsystems,
Inc. DCE is a registered trademark of DCE Group Limited. NFS is a registered
trademark of Sun Microsystems, Inc. All other product names mentioned herein
are the trademarks of their respective owners.
----------------------------------------------------------------------------