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