RemoteSecurity
interface.
Many potential applications of Jini require network security. Although various third parties have made proprietary security extensions to Jini, until now the only security available to users of the standard Jini release is the security infrastructure of the Java platform. The Jini Community's Davis project is about to change that. Bob Scheifler is leading the development of the next release of Jini, in which security is the central concern, as part of the Davis project.
On Friday, April 12, 2002 Bill Venners visited the Sun Microsystems campus in Burlington, Massachusettes and interviewed Bob Scheifler, Sun Distinguished Engineer and architect in the Jini Group. In Part I of this interview, Scheifler discusses the need for security in Jini and the special security considerations of dynamically downloaded code. In Part II, Scheifler describes the mechanisms used to determine whether a proxy should be trusted. In Part III, Scheifler covers the mechanisms used to achieve object integrity. In this fourth installment of the interview, Scheifler discusses security constraints and the RemoteSecurity
interface.
Bill Venners: You designed a way to add network security to proxies without changing their interfaces. You defined a RemoteSecurity
interface that a proxy can implement to become a secure proxy. Could you talk about RemoteSecurity
?
Bob Scheifler: One of our goals was to add network security in a way that didn't require us to make API changes to all of the existing service interfaces. So we have an additional interface that proxies implement called RemoteSecurity
. It has only four methods, so it is not very complicated. And, in fact, three of the four methods are not very interesting. They are there for completeness. The main method is a way of setting security constraints on the proxy. I inject security constraints into the proxy. I tell the proxy what kind of network security I want for subsequent remote calls that I make through that proxy.
Bill Venners: What are security constraints?
Bob Scheifler: Security constraints are the object mechanism we use to describe what kind of network security we want. We talked before about mutual authentication, confidentially, and integrity. I need some way of describing which of those I want. I don't necessarily want confidentially on every call. Sometimes I do and sometimes I don't. To specify what kind of security you want, you provide objects that implement an interface called SecurityConstraint
. This interface has one method, which is, in fact, not very interesting. So most people can just ignore that method.
The basic security constraint classes we have are very simple. They are essentially the equivalent of Boolean constants. One of them is ClientAuthentication
. It has two public static final constant fields, YES
and NO
. YES
means I want client authentication. I want the client to authenticate to the server. And NO
means the client should not authenticate to the server.
There is another class called ServerAuthentication
. It also has YES
and NO
constants. YES
means the service should authenticate itself to the client. NO
means the server should not authenticate. There is a Confidentiality
class that has YES
and NO
constants. And an Integrity
class with YES
and NO
constants. So it is very simple. You do or you don't want those forms of security.
In the case of server authentication, just saying you want the server to authenticate itself isn't enough. You want to make sure the server authenticates as someone in particular, not just that it authenticates. So we have another security constraint class we call ServerMinPrincipal
(Min
as in minimum). We specify there the principal or principals the server should authenticate as. Principals are a naming mechanism. I specify the principals I expect the server to authenticate as. The ServerMinPrincipal
constraint means that the sever must authenticate at least as this identity. It might authenticate as more, I don't care, but it has to at least authenticate as this identity.
Those are the basic constraints. There are more. There are many other constraints that are used to refine how a client will authenticate itself to a service. ClientAuthentication.NO
, for example, is a way of refining how I want to authenticate. It means I want to remain anonymous. You are probably never going to use most of the NO
s. They are there for completeness of the model. If you don't care about something, the way to say you don't care is to say nothing, rather than to say NO
.
Bill Venners: I just don't inject any constraints into the proxy.
Bob Scheifler: If you don't care about integrity, you just won't inject any integrity constraints. You typically wouldn't say no. But a place where I would say no is if I want to be anonymous. I don't want you to know who I am. So client authentication no is a useful constraint if you want anonymity.
There are cases for client authentication where you don't want to be completely anonymous. You simply want to limit how much of your identity to expose to a server. When I talk to my bank, for example, I don't necessarily want the bank to know that I am a Sun employee. Even though I may have the ability to prove that I am a Sun employee, when I talk to my bank, I just want to prove that I am a customer of the bank. Or if I go to the Department of Motor Vehicles, I want to prove that this is my driver's license, but I don't want to give them my Visa card number. We have other constraints that control which subset of my collective client identity I will expose to the server.
Bill Venners: Both the server and the client provide what constraints they want.
Bob Scheifler: Right. We've got these individual constraints, and now we want to collect them together. We also have this class called SecurityConstraints
which is a way to collect constraints together. It collects constraints into two sets, one of which we call requirements and the other preferences. A requirement means this absolutely has to be done for the call. A preference means I'd like this to be done, but it doesn't have to be. An example of a preference might be anonymity. I would like to be anonymous, but if the server insists that I authenticate, that is OK.
Bill Venners: How would I express that with security constraints objects?
Bob Scheifler: If I prefer to be anonymous, I would put ClientAuthentication.NO
as a preference. If I want confidentiality, I would put Confidentiality.YES
as a preference.
Bill Venners: And if I don't say yes or no, I am saying I don't care.
Bob Scheifler: If you say nothing, you are saying you don't care. You get whatever you get. You get whatever the server decides is the right answer.
Bob Scheifler: Now that we have collected these security constraints, the next layer of aggregation is you might say that I want different security for different methods. If I do write operations for a database, I may want to authenticate myself because it is probably going to need access control in order to do the update. But maybe I would like to remain anonymous for reads. Assuming everybody can read, I really just want it to know what queries I'm making, not who I am. So you might want to have different strengths of security for different methods. We have an interface called MethodConstraints
, which is a map from method to constraints. You can express for each method that a proxy implements what constraints should be used for remote calls of that method.
The server and the client can express what constraints there should be for each method made through a proxy. On a server the constraints are specified essentially at the time the remote object is exported. The server puts a lower bound on the network security. The server defines the minimum constraints that should be on any given method of any proxy to the server. The client also sets constraints on the proxy. The client defines what constraints it wants for individual calls.
Bob Scheifler: There's a third category of client constraints called context constraints. Say I am about to call into a method that I know is going to make a bunch of remote calls on multiple proxies. I don't really want to mess around with the individual proxies. I just want confidentially for everything that is going to go on inside there. I can set up thread context constraints. I say, "For the duration of executing this whole body of code, any remote calls that it makes, please apply these context constraints."
At the time we make a call on a secure proxy for a server, what the proxy is obliged to do is to figure out what the server's constraints for that method are, figure out what the client's constraints for that method are, and figure out what the context constraints are. We must union all three sets of requirements together, and union all three sets of preferences together. We must then make sure the remote call obeys the union of the requirements and obeys the preferences as best it can. The proxy is obliged to do this. It is part of the contract of implementing the RemoteSecurity
interface that all the remote calls made through the proxy will do this process of unioning all the constraints and making sure that the remote call enforces all the requirements.
Bill Venners: What if some of the requirements conflict?
Bob Scheifler: There are various reasons why the requirements might not be met. The server might insist on client authentication, for example, and I might insist on anonymity. We can't make the call because we have a conflict. Or I might specify a constraint the server doesn't even understand. SecurityConstraint
is an interface. The constraint mechanism is extensible. We have defined a base set of constraints. If somebody wants to define new constraint classes, they are free to do so. A proxy might say, "I have no idea what this constraint means. I can't make the call because you said it is a requirement and I don't even know what it means." So that might happen.
A call might also fail because the proxy, even though it understands a constraint, is unable to implement it. You might insist on confidentiality, but maybe the proxy uses a protocol that doesn't support confidentiality. It will not be able to make the call. You might need certain constraints, but you don't actually have sufficient permissions. You might say, "I insist on authenticating to you," but the proxy might not have permission to get at your credentials to do authentication. So it might also fail for that reason. There are various reasons why a call might fail and throw an exception.
RemoteSecurity
and the Liskov Subsitution PrincipleBill Venners: The Liskov Substitution Principle says that if I pass you an object and you know one interface to it, say ServiceRegistrar
, you know how to use it as a ServiceRegistrar
no matter what its class is. But now if that object happens to also implement RemoteSecurity
, you are saying that the semantics of remote security apply to all the other methods of the object. Isn't that kind of unusual in object-oriented practice? Does it not violate the Liskov Substitution Principle?
Bob Scheifler: Yeah, in some ways it probably does. We go through a second interface to have an effect on the semantics of the first interface. I don't know if that is good or bad. It is certainly a true observation. There are some dimensions in which it could be argued that it is bad.
We want to be able set up context on the proxies that will survive all subsequent remote calls rather than having to express the constraints each time. If we try to express constraints on every call, then we would either have to step out of normal call semantics and somehow annotate the call with constraints, or add constraints as an extra parameter to every method. That is an option. But for our purposes there are overriding concerns because we have existing interfaces. We need a way to migrate compatibly forward without having to redefine all of the interfaces in the world.
The Jini Community, the central site for signers of the Jini Sun Community Source Licence to interact:
http://www.jini.org
To get involved in the Davis project, in which Jini security is being defined, go to:
http://davis.jini.org/
Have an opinion? Be the first to post a comment about this article.
Bill Venners is president of Artima Software, Inc. and editor-in-chief of Artima.com. He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Bill has been active in the Jini Community since its inception. He led the Jini Community's ServiceUI project that produced the ServiceUI API. The ServiceUI became the de facto standard way to associate user interfaces to Jini services, and was the first Jini community standard approved via the Jini Decision Process. Bill also serves as an elected member of the Jini Community's initial Technical Oversight Committee (TOC), and in this role helped to define the governance process for the community. He currently devotes most of his energy to building Artima.com into an ever more useful resource for developers.
Artima provides consulting and training services to help you make the most of Scala, reactive
and functional programming, enterprise systems, big data, and testing.