| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hcatalog.templeton; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.security.PrivilegedExceptionAction; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.FileSystem; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.hive.conf.HiveConf; |
| import org.apache.hadoop.hive.metastore.HiveMetaStoreClient; |
| import org.apache.hadoop.hive.metastore.api.MetaException; |
| import org.apache.hadoop.io.Text; |
| import org.apache.thrift.TException; |
| import org.apache.hadoop.security.Credentials; |
| import org.apache.hadoop.security.UserGroupInformation; |
| import org.apache.hadoop.security.token.Token; |
| |
| /** |
| * Helper class to run jobs using Kerberos security. Always safe to |
| * use these methods, it's a noop if security is not enabled. |
| */ |
| public class SecureProxySupport { |
| private Path tokenPath; |
| private final String HCAT_SERVICE = "hcat"; |
| private boolean isEnabled; |
| private String user; |
| |
| public SecureProxySupport() { |
| isEnabled = UserGroupInformation.isSecurityEnabled(); |
| } |
| |
| private static final Log LOG = LogFactory.getLog(SecureProxySupport.class); |
| |
| /** |
| * The file where we store the auth token |
| */ |
| public Path getTokenPath() { |
| return (tokenPath); |
| } |
| |
| /** |
| * The token to pass to hcat. |
| */ |
| public String getHcatServiceStr() { |
| return (HCAT_SERVICE); |
| } |
| |
| /** |
| * Create the delegation token. |
| */ |
| public Path open(String user, Configuration conf) |
| throws IOException, InterruptedException { |
| close(); |
| if (isEnabled) { |
| this.user = user; |
| File t = File.createTempFile("templeton", null); |
| tokenPath = new Path(t.toURI()); |
| Token fsToken = getFSDelegationToken(user, conf); |
| String hcatTokenStr; |
| try { |
| hcatTokenStr = buildHcatDelegationToken(user); |
| } catch (Exception e) { |
| throw new IOException(e); |
| } |
| Token<?> msToken = new Token(); |
| msToken.decodeFromUrlString(hcatTokenStr); |
| msToken.setService(new Text(HCAT_SERVICE)); |
| writeProxyDelegationTokens(fsToken, msToken, conf, user, tokenPath); |
| |
| } |
| return tokenPath; |
| } |
| |
| /** |
| * Cleanup |
| */ |
| public void close() { |
| if (tokenPath != null) { |
| new File(tokenPath.toUri()).delete(); |
| tokenPath = null; |
| } |
| } |
| |
| /** |
| * Add Hadoop env variables. |
| */ |
| public void addEnv(Map<String, String> env) { |
| if (isEnabled) { |
| env.put(UserGroupInformation.HADOOP_TOKEN_FILE_LOCATION, |
| getTokenPath().toUri().getPath()); |
| } |
| } |
| |
| /** |
| * Add hcat args. |
| */ |
| public void addArgs(List<String> args) { |
| if (isEnabled) { |
| args.add("-D"); |
| args.add("hive.metastore.token.signature=" + getHcatServiceStr()); |
| args.add("-D"); |
| args.add("proxy.user.name=" + user); |
| } |
| } |
| |
| class TokenWrapper { |
| Token<?> token; |
| } |
| |
| private Token<?> getFSDelegationToken(String user, |
| final Configuration conf) |
| throws IOException, InterruptedException { |
| LOG.info("user: " + user + " loginUser: " + UserGroupInformation.getLoginUser().getUserName()); |
| final UserGroupInformation ugi = UgiFactory.getUgi(user); |
| |
| final TokenWrapper twrapper = new TokenWrapper(); |
| ugi.doAs(new PrivilegedExceptionAction<Object>() { |
| public Object run() throws IOException { |
| FileSystem fs = FileSystem.get(conf); |
| twrapper.token = fs.getDelegationToken(ugi.getShortUserName()); |
| return null; |
| } |
| }); |
| return twrapper.token; |
| |
| } |
| |
| private void writeProxyDelegationTokens(final Token<?> fsToken, |
| final Token<?> msToken, |
| final Configuration conf, |
| String user, |
| final Path tokenPath) |
| throws IOException, InterruptedException { |
| |
| |
| LOG.info("user: " + user + " loginUser: " + UserGroupInformation.getLoginUser().getUserName()); |
| final UserGroupInformation ugi = UgiFactory.getUgi(user); |
| |
| |
| ugi.doAs(new PrivilegedExceptionAction<Object>() { |
| public Object run() throws IOException { |
| Credentials cred = new Credentials(); |
| cred.addToken(fsToken.getService(), fsToken); |
| cred.addToken(msToken.getService(), msToken); |
| cred.writeTokenStorageFile(tokenPath, conf); |
| return null; |
| } |
| }); |
| |
| } |
| |
| private String buildHcatDelegationToken(String user) |
| throws IOException, InterruptedException, MetaException, TException { |
| HiveConf c = new HiveConf(); |
| final HiveMetaStoreClient client = new HiveMetaStoreClient(c); |
| LOG.info("user: " + user + " loginUser: " + UserGroupInformation.getLoginUser().getUserName()); |
| final TokenWrapper twrapper = new TokenWrapper(); |
| final UserGroupInformation ugi = UgiFactory.getUgi(user); |
| String s = ugi.doAs(new PrivilegedExceptionAction<String>() { |
| public String run() |
| throws IOException, MetaException, TException { |
| String u = ugi.getUserName(); |
| return client.getDelegationToken(u); |
| } |
| }); |
| return s; |
| } |
| } |