RE: RE: [Mx4j-user] RE: mx4j-Bugs-969175: Security and delegation
"Ron Vered" <[email protected]>
| Newsgroups | gmane.comp.java.mx4j.devel |
|---|---|
| Message-ID | <8FEAA1F16948B54D81DEC98AFAC9F39B07042D19@SDCEXMB01.corp.siebel.com> |
Eamonn, Thank you for detailed response. We implemented something very similar to what you propose. It would be nice, however, if you could do it in a straight forward manner, maybe in a way similar to what I suggested. This way, connection reuse will happen explicitly for ALL TRANSPORTS without hacks and tricks. BTW, your comment about why not to have delegation can be asked on existing API. JSR already decided to have delegation. So the only question remaining is whether to support only one security model or allow for other possibilities. Note that Server side already has PasswordAuthenticator (or similar) class, so it already knows how to convert credentials to Subject. Regards, Ron. -----Original Message----- From: Eamonn McManus [mailto:[email protected]] Sent: Tuesday, September 28, 2004 9:01 AM To: Ron Vered Cc: MX4J-Dev (E-mail); Bordet, Simone; Luis Miguel Alventosa Subject: Re: [Mx4j-devel] RE: [Mx4j-user] RE: mx4j-Bugs-969175: Security and delegation Ron, I am not sure that your point about reusing the same SSL connection is really that important. If two different connections specify equal RMIClientSocketFactory objects and connect to the same server, then they are eligible to share the same RMI connection. The RMI infrastructure arranges this. Two SslRMIClientSocketFactory objects are always equal, so this should be true for you. Therefore you should find that you are only establishing an SSL connection once to a given server, even if you have several different JMXConnector connections. The JNDI lookup cost is not great and with a little more effort you can explicitly do it just once and reuse the retrieved object for every connection. Concerning the proposed API changes, we would of course need corresponding API changes on the server side to specify how to validate the client's credentials. Without excluding the possibility of adding this functionality, I'd just note that it should be possible to do it with today's API. Here's how. The connector server allows you to specify an MBeanServerForwarder via the method JMXConnectorServer.setMBeanServerForwarder. The idea is that this object is a kind of interceptor between the real MBean Server and the Connector Server: JMXConnectorServer --> MBeanServer becomes JMXConnectorServer --> MBeanServerForwarder --> MBeanServer MBeanServerForwarder extends MBeanServer, so in a configuration like this each method of the MBeanServerForwarder could check the client credentials before forwarding the request to the real MBeanServer. Something like this: public class CheckingForwarder implements MBeanServerForwarder { public CheckingForwarder(MBeanServer mbs) { this.mbs = mbs; } public Object getAttribute(ObjectName on, String attrName) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException { checkCallerCredentials(); return mbs.getAttribute(on, attrName); } ...likewise for all the other methods of MBeanServer... } The question is obviously how the checkCallerCredentials() method can get the caller's credentials to check them. You can do this by using subject delegation. The client uses getMBeanServer(Subject) to specify the Subject to use, including its credentials. The server can access this Subject using Subject.getSubject(AccessController.getContext()). Then it can examine the credentials and throw a SecurityException if they are not correct. (The details of verifying credentials are up to you but for example it could involve consulting a password file or doing a check with LDAP.) One obvious problem here is that the serialized form of a Subject does not include its credentials as returned by Subject.getPrivateCredentials() and Subject.getPublicCredentials(). So you cannot communicate your credentials in that way. Instead you need a little hack, which is to encode the credentials inside a Principal in the Subject. For example, you could define PasswordPrincipal and put PasswordPrincipal("elderberries") in the Subject to communicate a password of "elderberries". The checkCallerCredentials() method would check this, and probably destroy the credentials afterwards so that they would not be visible to the MBeans being invoked. (Each request will deserialize a new copy of the Subject with its Principals, so destroying the PasswordPrincipal for one request doesn't affect subsequent ones.) Implementing every single method of MBeanServer in the CheckingForwarder is very tedious, especially because of the "throws" clauses, so a nicer approach is to use java.lang.reflect.Proxy. I am imagining something like this: public class CheckingHandler implements InvocationHandler { public CheckingHandler(MBeanServer mbs) { this.mbs = mbs; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("getMBeanServer")) return mbs; else if (method.getName().equals("setMBeanServer")) throw new IllegalArgumentException("MBeanServer already set"); else { checkCallerCredentials(); return method.invoke(mbs, args); } } private final MBeanServer mbs; } MBeanServerForwarder forwarder = (MBeanServerForwarder) Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), new Class[] {MBeanServerForwarder.class}, new CheckingHandler(mbs)); connectorServer.setMBeanServerForwarder(forwarder); Regards, -- Éamonn McManus, JSR 255 Spec Lead Ron Vered wrote: > Eamonn, > > I agree with you that RMI is incomplete with respect to security. > > Reading your response I see you are coming from deep understanding of > the internals. I am mainly looking at the API and what I can do with > it compared with what I am required to do. > > The security model (which I think is valid) where a Subject is sent to > the other side and this Subject is the delegate does not work for us, > for a specific application and we find it too constricting. What we > want is to be able to send credentials too. > > API wise, consider the following: > > JMXConnector cntor = JMXConnectorFactory.connect(url, env); > MBeanServerConnection connection = > cntor.getMBeanServerConnection(); > > /* bunch of operations with 'connection' > * could be implemented per request, or per 'connection' object > * caller does not know > * authentication done once regardless > */ > > MBeanServerConnection conn2 = cntor.getMBeanServerConnection(env2); // env2 has delegate credentials > > /* bunch of operations with 'conn2' > * potentially implemented per 'conn2' instance > * so authentication is done once (with some reasonable exclusions) > * caller still unaware of how this works > */ > > MBeanServerConnection conn2 = > cntor.getMBeanServerConnection(delegateSubject); > > /* same thing */ > > Or you could do this: > > JMXConnector cntor = JMXConnectorFactory.connect(url); > MBeanServerConnection connection = > cntor.getMBeanServerConnection(env); > > /* bunch of operations with 'connection' > * could be implemented per request, or per 'connection' object > * caller does not know > * authentication done once regardless > */ > > MBeanServerConnection conn2 = cntor.getMBeanServerConnection(env2); // env2 has delegate credentials > > /* bunch of operations with 'conn2' > * potentially implemented per 'conn2' instance > * so authentication is done once (with some reasonable exclusions) > * caller still unaware of how this works > */ > > MBeanServerConnection conn2 = > cntor.getMBeanServerConnection(delegateSubject); > > /* same thing */ > > In both cases, there is only one addition to the API, being able to > pass in credentials to getMBeanServerConnection(). > > So, if JMX authentication protocol requires few messages to be > exchanged, this authentication is done once for several JMX operations > to follow. > > Please also consider that a new connection potentially requires TCP + > SSL + <transport> + JNDI and TCP + SSL + <transport> + JMX messages to > be exchanged before you can do productive work. Where as reusing a > connection, requires either no additional messages, or just JMX > messages. In addition, in a server to server environment (what we > have) could potentially relieve resource utilization and unnecessary > network traffic. > > Regards, > Ron. > > -----Original Message----- > From: Eamonn McManus [mailto:[email protected]] > Sent: Monday, September 06, 2004 5:50 AM > To: Ron Vered > Cc: MX4J-Dev (E-mail); Bordet, Simone; Luis Miguel Alventosa > Subject: Re: [Mx4j-devel] RE: [Mx4j-user] RE: mx4j-Bugs-969175: Security and delegation > > > Ron, > > Ron Vered wrote: > >>>Here's how we could consider changing the API. Suppose a security >>>context (subject and/or codebase and/or signers), say "creator", >>>makes a >>> >>>JMXConnectorServer and supplies a JMXAuthenticator. Later, a >>>connection >>> >>>arrives, and the JMXAuthenticator returns a Subject for it containing >>>the Principal "remote". Today, basically both "remote" and "creator" >>>must have all needed permissions for the reason I detailed. However, >>>suppose we say that an MBean operation that needs FilePermission is >>>allowed if EITHER: >>>(1) both "remote" and "creator" have FilePermission (the current >>>requirement); OR >>>(2) "remote" has FilePermission and "creator" has >>>SubjectDelegationPermission("remote"). >> >>[Ron] This is OK provided the "remote" is some specified principal >>class and name, both of the policy writer's choosing and where it can >>potentially be "*" for all. > > > Right. Check out the spec for SubjectDelegationPermission: > <http://java.sun.com/j2se/1.5.0/docs/api/javax/management/remote/SubjectDelegationPermission.html> > which already allows exactly this. > > >>>Concerning your second request, to be able to have several >>>authenticated >>> >>>Subjects use the same RMI connection without using delegation, I am >>>not >>>convinced that this gets you enough, compared with simply opening a >>>connection per authenticated Subject, to justify the additional >>>complexity. RMI can share the actual network connections between a pair >>> >>>of JVMs anyway -- it doesn't have to open a different TCP/IP >>>connection >>>for each RMI connection, except in circumstances (involving socket >>>factories) where it would be impossible to share the JMX Remote >>>connection anyway. > > > > >>[Ron] I don't understand what complexity you are referring to, in >>addition to passing in Subject argument, have an overload accepting >>credentials, similar to a connect. Basically, make delegation and >>connection symmetric. Note that RMI may be able to do this >>multiplexing in some scenarios, but please also consider load-balanced >>applications and other transports. You already (wisely) decided to >>have delegation, so please support it in a symmetric manner, which >>allows different security models to be implemented. > > > If I understand, you are saying that it's all very well for RMI to > share > connections, but say we are using something like JMXMP which doesn't, > how do we allow multiple identities to share the same connection then? > I am not sure what the answer is. JMXMP, like the RMI connector, has an > authentication step when the connection is established, only. Adding > the ability to authenticate on every request still doesn't seem very > different from just establishing a connection per request. Indeed, it > is likely to be substantially more costly than establishing one > connection per Subject, as you can do today. > > If we want to be able to support challenge/response authentication, > then > we would need a design something like this: The client can contact the > server at any time, authenticate, and receive a cookie representing the > authenticated identity. Then, in any subsequent request, it can supply > the cookie, and the request will automatically be performed using the > previously-authenticated identity. > > The server must be allowed to invalidate the cookie at any time, both > because a client that authenticated last month isn't necessarily still > valid, and because we don't want the server to be required to maintain > client state for an unbounded period of time. This means that when the > client does a request containing an authentication cookie, it must be > prepared to get back an error, re-authenticate, and re-issue the request. > > In essence, this duplicates what the RMI connector already does. Each > authenticated connection is represented by a separate RMI object. The > RMI object-id (a 64-bit securely-random integer) is the cookie. The > server can unexport the RMI object for a connection at any time, > whereupon the client must make a new authenticated connection. For the > RMI connector, I still don't think there is anything to be gained by > adding support for sharing different authenticated identities over the > same RMI connection. > > Adding such support for other connectors could be interesting. But I > don't think there is a need for this to be reflected in the generic > client API. I still think this would lead to the API being > substantially more complicated than it currently is. I could be wrong, > though -- do you have an idea of what you would like the changed client > API to look like? > > Regards, ------------------------------------------------------------------------------ This e-mail message is for the sole use of the intended recipient(s) and contains confidential and/or privileged information belonging to Siebel Systems, Inc. or its customers or partners. Any unauthorized review, use, copying, disclosure or distribution of this message is strictly prohibited. If you are not an intended recipient of this message, please contact the sender by reply e-mail and destroy all soft and hard copies of the message and any attachments. Thank you for your cooperation. ==================================================== ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl