Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kerberos for Thrift?

I have a simple Thrift based java application I have written. It is really very simple, not much more than a "Hello World" message transport using Thrift in java. I have been told that I need to add Kerberos support to my message. I have done some googling and am surprised that Thrift does not already have Kerberos support in some form (or if it does, I cannot find it). I thought about writing my own wrapper using GSSAPI, but I cannot wrap/unwrap my Thrift message as that screws up the Thrift message format.

Has anyone ever Kerberized Thrift?.. or know how it would be done?

Thanks, in advance.

like image 264
Wanderer Avatar asked Dec 10 '12 14:12

Wanderer


1 Answers

**So, I guess there is a way to do this via the SASL/GSS APIs. It confuses me as to why I don't see any great examples of this on the internet anywhere. However, I post an example of what I have created in the hopes that it will be a help to others... or that someone can correct my delusion of doing something useful here.

Sample Server code:

TServerSocket serverTransport = new TServerSocket(7911);  // new server on port 7911
HelloWorldService.Processor<Iface> processor = new HelloWorldService.Processer<Iface>(new ThriftServerImpl());  // This is my thrift implementation for my server
Map<String, String> saslProperties = new HashMap<String, String>();  // need a map for properties
saslProperties.put(Sasl.QOP, "true");
saslProperties.put(Sasl.QOP, "auth-conf");  // authorization and confidentiality

TSaslServerTransport.Factory saslTransportFactory = new TSaslServerTransport.Factory();     // Creating the server definition
saslTransportFactory.addServerDefinition(
            "GSSAPI",       //  tell SASL to use GSSAPI, which supports Kerberos
            "myserviceprincipal",   //  base kerberos principal name - myprincipal/[email protected] 
            "my.server.com",    //  kerberos principal server - myprincipal/[email protected]
            saslProps,      //  Properties set, above
            new SaslRpcServer.SaslGssCallbackHandler()));  //  I don't know what this really does... but I stole it from Hadoop and it works.. so there.

Tserver server = new TThreadPoolServer(newTThreadPoolSErver.Args(serverTransport).transportFactory(saslTrasnportFactory).processor(processor));

server.serve();   // Thrift server start

Sample Client Code

TTransport transport = new TSocket("my.server.com", 7911);   // client to connect to server and port
saslProperties.put(Sasl.QOP, "true");
saslProperties.put(Sasl.QOP, "auth-conf");  // authorization and confidentiality

TTransport saslTransport = new TSaslTransport(
            "GSSAPI",       //  tell SASL to use GSSAPI, which supports Kerberos
            null,           //  authorizationid - null
            "myserviceprincipal",   //  base kerberos principal name - myprincipal/[email protected] 
            "my.server.com",    //  kerberos principal server - myprincipal/[email protected]
            saslProps,      //  Properties set, above
            null,           //  callback handler - null
            transport);     //  underlying transport

TProtocol protocol = new TBinaryProtocol(saslTransport);    // set up our new Thrift protocol

HelloWorldService.Client client = new HelloWorldService.Client(protocol);   // Setup our thrift client
saslTransport.open();

String response = client.hello("Hi There");   // send message

System.out.println("response = " + response);

transport.close();

Other condsiderations:

* I set several java properties on both the client and the server.
- java.security.krb5.realm = MY.REALM // realm name
- java.security.krb5.kdc = my.kdc.com // kdc server
- javax.security.auth.useSubjectCredsOnly = false // Allow JAAS to get the TGT.
- java.security.auth.login.config = /etc/myapp/conf/jaas.conf - required jaas file
- sun.security.krb5.debug = true // helped with diagnosing problems.
* The jaas.conf file specified, above, needs to have two entries (maybe only one per server...). I cannot remember where I gleaned this information from.. but here is my file:

com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/etc/myapp/conf/myapp.keytab"
    useTicketCache=true
    principal="myuserprincipal"
    debug=true;
};

com.sun.security.jgss.accept {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    keyTab="/etc/myapp/conf/myapp.keytab"
    useTicketCache=false
    principal="myserviceprincipal/my.server.com"
    debug=true;
};

(back to considerations....)
* Despite having a Sasl.QOP of "auth-conf".. the first(?) message that gets transmitted is not encrypted. Maybe this is just a handshake, or something. The remaining messages appear to be encrypted, but this first one prints an ugly message to the console of "No encryption was performed by peer". It would be nice to not get that message, as it will cause grief down the road (warranted or not).

Anyway, I hope this helps someone... or alternatively can provoke some improvements that will help me. :) Hard to believe I spend 2-3 days doing this, and only a small amount of code came out of it , but I knew neither Kerberos or Thrift very well when I started.

Thanks for reading.

like image 131
Wanderer Avatar answered Oct 29 '22 21:10

Wanderer