001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.yarn.security.client; 020 021 022import java.io.IOException; 023import java.net.InetSocketAddress; 024 025import org.apache.hadoop.classification.InterfaceAudience.Private; 026import org.apache.hadoop.classification.InterfaceAudience.Public; 027import org.apache.hadoop.classification.InterfaceStability.Evolving; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.io.Text; 030import org.apache.hadoop.ipc.RPC; 031import org.apache.hadoop.net.NetUtils; 032import org.apache.hadoop.security.token.Token; 033import org.apache.hadoop.security.token.TokenRenewer; 034import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; 035import org.apache.hadoop.yarn.api.ApplicationClientProtocol; 036import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenRequest; 037import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest; 038import org.apache.hadoop.yarn.client.ClientRMProxy; 039import org.apache.hadoop.yarn.exceptions.YarnException; 040import org.apache.hadoop.yarn.util.Records; 041 042/** 043 * Delegation Token Identifier that identifies the delegation tokens from the 044 * Resource Manager. 045 */ 046@Public 047@Evolving 048public class RMDelegationTokenIdentifier extends YARNDelegationTokenIdentifier { 049 050 public static final Text KIND_NAME = new Text("RM_DELEGATION_TOKEN"); 051 052 public RMDelegationTokenIdentifier(){} 053 054 /** 055 * Create a new delegation token identifier 056 * @param owner the effective username of the token owner 057 * @param renewer the username of the renewer 058 * @param realUser the real username of the token owner 059 */ 060 public RMDelegationTokenIdentifier(Text owner, Text renewer, Text realUser) { 061 super(owner, renewer, realUser); 062 } 063 064 @Override 065 public Text getKind() { 066 return KIND_NAME; 067 } 068 069 public static class Renewer extends TokenRenewer { 070 071 @Override 072 public boolean handleKind(Text kind) { 073 return KIND_NAME.equals(kind); 074 } 075 076 @Override 077 public boolean isManaged(Token<?> token) throws IOException { 078 return true; 079 } 080 081 private static 082 AbstractDelegationTokenSecretManager<RMDelegationTokenIdentifier> localSecretManager; 083 private static InetSocketAddress localServiceAddress; 084 085 @Private 086 public static void setSecretManager( 087 AbstractDelegationTokenSecretManager<RMDelegationTokenIdentifier> secretManager, 088 InetSocketAddress serviceAddress) { 089 localSecretManager = secretManager; 090 localServiceAddress = serviceAddress; 091 } 092 093 @SuppressWarnings("unchecked") 094 @Override 095 public long renew(Token<?> token, Configuration conf) throws IOException, 096 InterruptedException { 097 final ApplicationClientProtocol rmClient = getRmClient(token, conf); 098 if (rmClient != null) { 099 try { 100 RenewDelegationTokenRequest request = 101 Records.newRecord(RenewDelegationTokenRequest.class); 102 request.setDelegationToken(convertToProtoToken(token)); 103 return rmClient.renewDelegationToken(request).getNextExpirationTime(); 104 } catch (YarnException e) { 105 throw new IOException(e); 106 } finally { 107 RPC.stopProxy(rmClient); 108 } 109 } else { 110 return localSecretManager.renewToken( 111 (Token<RMDelegationTokenIdentifier>)token, getRenewer(token)); 112 } 113 } 114 115 @SuppressWarnings("unchecked") 116 @Override 117 public void cancel(Token<?> token, Configuration conf) throws IOException, 118 InterruptedException { 119 final ApplicationClientProtocol rmClient = getRmClient(token, conf); 120 if (rmClient != null) { 121 try { 122 CancelDelegationTokenRequest request = 123 Records.newRecord(CancelDelegationTokenRequest.class); 124 request.setDelegationToken(convertToProtoToken(token)); 125 rmClient.cancelDelegationToken(request); 126 } catch (YarnException e) { 127 throw new IOException(e); 128 } finally { 129 RPC.stopProxy(rmClient); 130 } 131 } else { 132 localSecretManager.cancelToken( 133 (Token<RMDelegationTokenIdentifier>)token, getRenewer(token)); 134 } 135 } 136 137 private static ApplicationClientProtocol getRmClient(Token<?> token, 138 Configuration conf) throws IOException { 139 String[] services = token.getService().toString().split(","); 140 for (String service : services) { 141 InetSocketAddress addr = NetUtils.createSocketAddr(service); 142 if (localSecretManager != null) { 143 // return null if it's our token 144 if (localServiceAddress.getAddress().isAnyLocalAddress()) { 145 if (NetUtils.isLocalAddress(addr.getAddress()) && 146 addr.getPort() == localServiceAddress.getPort()) { 147 return null; 148 } 149 } else if (addr.equals(localServiceAddress)) { 150 return null; 151 } 152 } 153 } 154 return ClientRMProxy.createRMProxy(conf, ApplicationClientProtocol.class); 155 } 156 157 // get renewer so we can always renew our own tokens 158 @SuppressWarnings("unchecked") 159 private static String getRenewer(Token<?> token) throws IOException { 160 return ((Token<RMDelegationTokenIdentifier>)token).decodeIdentifier() 161 .getRenewer().toString(); 162 } 163 164 private static org.apache.hadoop.yarn.api.records.Token 165 convertToProtoToken(Token<?> token) { 166 return org.apache.hadoop.yarn.api.records.Token.newInstance( 167 token.getIdentifier(), token.getKind().toString(), token.getPassword(), 168 token.getService().toString()); 169 } 170 } 171}