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.hbase.security.token; 020 021import java.io.IOException; 022 023import org.apache.yetus.audience.InterfaceAudience; 024import org.apache.yetus.audience.InterfaceStability; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.hbase.security.UserProvider; 029import org.apache.hadoop.security.token.Token; 030 031/** 032 * Helper class to obtain a filesystem delegation token. 033 * Mainly used by Map-Reduce jobs that requires to read/write data to 034 * a remote file-system (e.g. BulkLoad, ExportSnapshot). 035 */ 036@InterfaceAudience.Private 037@InterfaceStability.Evolving 038public class FsDelegationToken { 039 private static final Logger LOG = LoggerFactory.getLogger(FsDelegationToken.class); 040 041 private final UserProvider userProvider; 042 private final String renewer; 043 044 private boolean hasForwardedToken = false; 045 private Token<?> userToken = null; 046 private FileSystem fs = null; 047 048 /* 049 * @param renewer the account name that is allowed to renew the token. 050 */ 051 public FsDelegationToken(final UserProvider userProvider, final String renewer) { 052 this.userProvider = userProvider; 053 this.renewer = renewer; 054 } 055 056 /** 057 * Acquire the delegation token for the specified filesytem. 058 * Before requesting a new delegation token, tries to find one already available. 059 * 060 * @param fs the filesystem that requires the delegation token 061 * @throws IOException on fs.getDelegationToken() failure 062 */ 063 public void acquireDelegationToken(final FileSystem fs) 064 throws IOException { 065 if (userProvider.isHadoopSecurityEnabled()) { 066 this.fs = fs; 067 userToken = userProvider.getCurrent().getToken("HDFS_DELEGATION_TOKEN", 068 fs.getCanonicalServiceName()); 069 if (userToken == null) { 070 hasForwardedToken = false; 071 try { 072 userToken = fs.getDelegationToken(renewer); 073 } catch (NullPointerException npe) { 074 // we need to handle NullPointerException in case HADOOP-10009 is missing 075 LOG.error("Failed to get token for " + renewer); 076 } 077 } else { 078 hasForwardedToken = true; 079 LOG.info("Use the existing token: " + userToken); 080 } 081 } 082 } 083 084 /** 085 * Releases a previously acquired delegation token. 086 */ 087 public void releaseDelegationToken() { 088 if (userProvider.isHadoopSecurityEnabled()) { 089 if (userToken != null && !hasForwardedToken) { 090 try { 091 userToken.cancel(this.fs.getConf()); 092 } catch (Exception e) { 093 LOG.warn("Failed to cancel HDFS delegation token: " + userToken, e); 094 } 095 } 096 this.userToken = null; 097 this.fs = null; 098 } 099 } 100 101 public UserProvider getUserProvider() { 102 return userProvider; 103 } 104 105 /** 106 * @return the account name that is allowed to renew the token. 107 */ 108 public String getRenewer() { 109 return renewer; 110 } 111 112 /** 113 * @return the delegation token acquired, or null in case it was not acquired 114 */ 115 public Token<?> getUserToken() { 116 return userToken; 117 } 118 119 public FileSystem getFileSystem() { 120 return fs; 121 } 122}