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 019 package org.apache.hadoop.yarn.security.client; 020 021 022 import java.io.IOException; 023 import java.net.InetSocketAddress; 024 025 import org.apache.hadoop.classification.InterfaceAudience.Private; 026 import org.apache.hadoop.classification.InterfaceAudience.Public; 027 import org.apache.hadoop.classification.InterfaceStability.Evolving; 028 import org.apache.hadoop.conf.Configuration; 029 import org.apache.hadoop.io.Text; 030 import org.apache.hadoop.ipc.RPC; 031 import org.apache.hadoop.net.NetUtils; 032 import org.apache.hadoop.security.SecurityUtil; 033 import org.apache.hadoop.security.token.Token; 034 import org.apache.hadoop.security.token.TokenRenewer; 035 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenIdentifier; 036 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; 037 import org.apache.hadoop.yarn.api.ApplicationClientProtocol; 038 import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenRequest; 039 import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest; 040 import org.apache.hadoop.yarn.client.ClientRMProxy; 041 import org.apache.hadoop.yarn.conf.YarnConfiguration; 042 import org.apache.hadoop.yarn.exceptions.YarnException; 043 import org.apache.hadoop.yarn.util.Records; 044 045 /** 046 * Delegation Token Identifier that identifies the delegation tokens from the 047 * Resource Manager. 048 */ 049 @Public 050 @Evolving 051 public class RMDelegationTokenIdentifier extends AbstractDelegationTokenIdentifier { 052 053 public static final Text KIND_NAME = new Text("RM_DELEGATION_TOKEN"); 054 055 public RMDelegationTokenIdentifier() { 056 } 057 058 /** 059 * Create a new delegation token identifier 060 * @param owner the effective username of the token owner 061 * @param renewer the username of the renewer 062 * @param realUser the real username of the token owner 063 */ 064 public RMDelegationTokenIdentifier(Text owner, Text renewer, Text realUser) { 065 super(owner, renewer, realUser); 066 } 067 068 @Override 069 public Text getKind() { 070 return KIND_NAME; 071 } 072 073 public static class Renewer extends TokenRenewer { 074 075 @Override 076 public boolean handleKind(Text kind) { 077 return KIND_NAME.equals(kind); 078 } 079 080 @Override 081 public boolean isManaged(Token<?> token) throws IOException { 082 return true; 083 } 084 085 private static 086 AbstractDelegationTokenSecretManager<RMDelegationTokenIdentifier> localSecretManager; 087 private static InetSocketAddress localServiceAddress; 088 089 @Private 090 public static void setSecretManager( 091 AbstractDelegationTokenSecretManager<RMDelegationTokenIdentifier> secretManager, 092 InetSocketAddress serviceAddress) { 093 localSecretManager = secretManager; 094 localServiceAddress = serviceAddress; 095 } 096 097 @SuppressWarnings("unchecked") 098 @Override 099 public long renew(Token<?> token, Configuration conf) throws IOException, 100 InterruptedException { 101 final ApplicationClientProtocol rmClient = getRmClient(token, conf); 102 if (rmClient != null) { 103 try { 104 RenewDelegationTokenRequest request = 105 Records.newRecord(RenewDelegationTokenRequest.class); 106 request.setDelegationToken(convertToProtoToken(token)); 107 return rmClient.renewDelegationToken(request).getNextExpirationTime(); 108 } catch (YarnException e) { 109 throw new IOException(e); 110 } finally { 111 RPC.stopProxy(rmClient); 112 } 113 } else { 114 return localSecretManager.renewToken( 115 (Token<RMDelegationTokenIdentifier>)token, getRenewer(token)); 116 } 117 } 118 119 @SuppressWarnings("unchecked") 120 @Override 121 public void cancel(Token<?> token, Configuration conf) throws IOException, 122 InterruptedException { 123 final ApplicationClientProtocol rmClient = getRmClient(token, conf); 124 if (rmClient != null) { 125 try { 126 CancelDelegationTokenRequest request = 127 Records.newRecord(CancelDelegationTokenRequest.class); 128 request.setDelegationToken(convertToProtoToken(token)); 129 rmClient.cancelDelegationToken(request); 130 } catch (YarnException e) { 131 throw new IOException(e); 132 } finally { 133 RPC.stopProxy(rmClient); 134 } 135 } else { 136 localSecretManager.cancelToken( 137 (Token<RMDelegationTokenIdentifier>)token, getRenewer(token)); 138 } 139 } 140 141 private static ApplicationClientProtocol getRmClient(Token<?> token, 142 Configuration conf) throws IOException { 143 String[] services = token.getService().toString().split(","); 144 for (String service : services) { 145 InetSocketAddress addr = NetUtils.createSocketAddr(service); 146 if (localSecretManager != null) { 147 // return null if it's our token 148 if (localServiceAddress.getAddress().isAnyLocalAddress()) { 149 if (NetUtils.isLocalAddress(addr.getAddress()) && 150 addr.getPort() == localServiceAddress.getPort()) { 151 return null; 152 } 153 } else if (addr.equals(localServiceAddress)) { 154 return null; 155 } 156 } 157 } 158 return ClientRMProxy.createRMProxy(conf, ApplicationClientProtocol.class); 159 } 160 161 // get renewer so we can always renew our own tokens 162 @SuppressWarnings("unchecked") 163 private static String getRenewer(Token<?> token) throws IOException { 164 return ((Token<RMDelegationTokenIdentifier>)token).decodeIdentifier() 165 .getRenewer().toString(); 166 } 167 168 private static org.apache.hadoop.yarn.api.records.Token 169 convertToProtoToken(Token<?> token) { 170 return org.apache.hadoop.yarn.api.records.Token.newInstance( 171 token.getIdentifier(), token.getKind().toString(), token.getPassword(), 172 token.getService().toString()); 173 } 174 } 175 }