19

I'm developing a system which uses thrift. I'd like clients identity to be checked and operations to be ACLed. Does Thrift provide any support for those?

Igor Gatis
  • 4,648
  • 10
  • 43
  • 66

3 Answers3

13

Not directly. The only way to do this is to have an authentication method which creates a (temporary) key on the server, and then change all your methods so that the first argument is this key and they all additionally raise an not-authenticated error. For instance:

exception NotAuthorisedException {
    1: string errorMessage,
}

exception AuthTimeoutException {
    1: string errorMessage,
}

service MyAuthService {
    string authenticate( 1:string user, 2:string pass )
        throws ( 1:NotAuthorisedException e ),

    string mymethod( 1:string authstring, 2:string otherargs, ... )
        throws ( 1:AuthTimeoutException e, ... ),
}

We use this method and save our keys to a secured memcached instance with a 30min timeout for keys to keep everything "snappy". Clients who receive an AuthTimeoutException are expected to reauthorise and retry and we have some firewall rules to stop brute-force attacks.

Phillip B Oldham
  • 18,807
  • 20
  • 94
  • 134
  • 2
    @JensG No, you'd want to send the password in an encrypted format and check that encoded string server-side. Bcrypt is good for this, since the string sent over the wire may not match exactly the string stored, but when checked using the bcrypt algorithm may still validate. – Phillip B Oldham Aug 27 '13 at 07:45
  • If this is the case you would not be sending clear text passwords but if an attacker is able to read the hashed password he could replay the authentication call and gain access to your services. – cjungel Sep 11 '14 at 19:19
  • 2
    It's possible to secure the communication using SSL. http://www.doublecloud.org/2014/01/securing-thrift-traffic-uncommon-but-important-use-case/ describes how to create a server key pair and use the certificate in the client to encrypt the traffic. This mechanism should provide a secure channel and you could implement a custom authentication / authorization as described in the answer. – cjungel Sep 11 '14 at 19:48
3

Tasks like autorisation and permissions are not considered as a part of Thrift, mostly because these things are (usually) more related to the application logic than to a general RPC/serialization concept. The only Thing that Thrift supports out of the box right now is the TSASLTransport. I can't say much about that one myself, simply because I never felt the need to use it.

The other option could be to make use of THeaderTransport which unfortunately at the time of writing is only implemented with C++. Hence, if you plan to use it with some other language you may have to invest some additional work. Needless to say that we accept contributions ...

JensG
  • 13,148
  • 4
  • 45
  • 55
0

A bit late (I guess very late) but I had modified the Thrift Source code for this a couple of years ago.

Just submitted a ticket with the Patch to https://issues.apache.org/jira/browse/THRIFT-4221 for just this.

Have a look at that. Basically the proposal is to add a "BeforeAction" hook that does exactly that.

Example Golang generated diff

+       // Called before any other action is called
+       BeforeAction(serviceName string, actionName string, args map[string]interface{}) (err error)
+       // Called if an action returned an error
+       ProcessError(err error) error
 }

 type MyServiceClient struct {
@@ -391,7 +395,12 @@ func (p *myServiceProcessorMyMethod) Process(seqId int32, iprot, oprot thrift.TP
        result := MyServiceMyMethodResult{}
        var retval string
        var err2 error
-       if retval, err2 = p.handler.MyMethod(args.AuthString, args.OtherArgs_); err2 != nil {
+       err2 = p.handler.BeforeAction("MyService", "MyMethod", map[string]interface{}{"AuthString": args.AuthString, "OtherArgs_": args.OtherArgs_})
+       if err2 == nil {
+               retval, err2 = p.handler.MyMethod(args.AuthString, args.OtherArgs_)
+       }
+       if err2 != nil {
+               err2 = p.handler.ProcessError(err2)
dg428
  • 413
  • 6
  • 14