Search code examples
javakerberosthriftgssapi

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.


Solution

  • **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.