0

I have the following scenario:

  • I have an HTTP service where I have a logged in user with a keytab and a kerberos principal - let's name this user for the sake of the example service_user
  • Then I have a client which invokes this service and authenticates itself via kerberos (spnego) - let's name the user who invokes the service client_user
  • From my service I would like to launch a Yarn Java application (which works perfectly) and at the end from the Yarn container I need to invoke my service's callback endpoint which requires authentication
  • Inside the Yarn container I'm not in a kerberized environment, I only have delegation tokens
  • So ideally my service should accept spnego and delegation token authentications as well

I had a look at DelegationTokenAuthenticationFilter, but I wasn't able to figure out how I should be using it. I added it to my service and I see that DelegationTokenAuthenticationHandler#managementOperation can handle requests where I have op=GETDELEGATIONTOKEN in the query part. If I do something like curl --negotiate -u : http://host:port/callback?op= GETDELEGATIONTOKEN from command line I get back a delegation token which is fine.

But that's not what I want, right? What I would like to do is: client_user invoking my service, authenticating itself via spnego, the service creating a custom delegation token for client_user, passing that delegation token to the Yarn container (I set the HADOOP_TOKEN_FILE_LOCATION env variable), and then from the Yarn container calling back to my service using the delegation token I created.

I also tried creating a delegation token on my own way:

DelegationTokenManager tokenManager = new DelegationTokenManager(conf, new Text("..."));
tokenManager.init();
Token<? extends AbstractDelegationTokenIdentifier> token = tokenManager.createToken(ugi, renewer);
Credentials credentials = ...
credentials.addToken(new Text("..."), token);

Then this was available in my Yarn container where I did:

import static org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticator.DELEGATION_TOKEN_HEADER;

UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
Credentials credentials = currentUser.getCredentials();
Token<? extends TokenIdentifier> delegationToken = credentials.getToken(new Text("..."));
HttpURLConnection connection = ...
connection.setRequestProperty(DELEGATION_TOKEN_HEADER, delegationToken.encodeToUrlString());

And I see the DelegationTokenAuthenticationFilter picking up my token, but it's saying it's invalid. Something about it not being signed.

Am I even on the right path at all? Should I maybe forget about DelegationTokenAuthenticationFilter and simply extend AuthenticationFilter where I can accept a custom delegation token header in the HTTP request? Or should I use DelegationTokenAuthenticationFilter and try to override DelegationTokenManager#verifyToken somehow?

I see that for creating an HttpURLConnection in the Yarn container I could use DelegationTokenAuthenticatedURL.openConnection, but that requires a kerberized environment.

dfritsi
  • 1,224
  • 3
  • 14
  • 24
  • SPNego supports Kerberos and/or NTLM. Nothing else. You need to ship a keytab inside each "client" container and create a Kerberos TGT dynamically from Java code, before calling the "server", and let the HTTP client handle the challenge/response automatically. – Samson Scharfrichter Nov 09 '20 at 21:16
  • Hadoop delegation tokens are a just a custom trick to make it easier to work with Kerberos (designed for point-to-point auth) inside a distributed system. In short, the token relies on mutual trust between Hadoop nodes. and Hadoop services. External services have no reason to endorse that custom trust relationship. – Samson Scharfrichter Nov 09 '20 at 21:19

0 Answers0