1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 package org.apache.hadoop.hdfs.security;
20 
21 
22 
23 import java.io.ByteArrayInputStream;
24 import java.io.DataInputStream;
25 import java.io.IOException;
26 import java.net.InetAddress;
27 import java.net.NetworkInterface;
28 import java.security.PrivilegedExceptionAction;
29 import java.util.ArrayList;
30 import java.util.Enumeration;
31 
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.fs.FSDataOutputStream;
36 import org.apache.hadoop.fs.FileStatus;
37 import org.apache.hadoop.fs.FileSystem;
38 import org.apache.hadoop.fs.Path;
39 import org.apache.hadoop.fs.permission.FsPermission;
40 import org.apache.hadoop.hdfs.DFSConfigKeys;
41 import org.apache.hadoop.hdfs.HdfsConfiguration;
42 import org.apache.hadoop.hdfs.MiniDFSCluster;
43 import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
44 import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
45 import org.apache.hadoop.hdfs.web.WebHdfsTestUtil;
46 import org.apache.hadoop.security.TestDoAsEffectiveUser;
47 import org.apache.hadoop.security.UserGroupInformation;
48 import org.apache.hadoop.security.authorize.DefaultImpersonationProvider;
49 import org.apache.hadoop.security.authorize.ProxyUsers;
50 import org.apache.hadoop.security.token.Token;
51 import org.junit.AfterClass;
52 import org.junit.Assert;
53 import org.junit.BeforeClass;
54 import org.junit.Test;
55 import org.mockito.internal.util.reflection.Whitebox;
56 
57 public class TestDelegationTokenForProxyUser {
58   private static MiniDFSCluster cluster;
59   private static Configuration config;
60   final private static String GROUP1_NAME = "group1";
61   final private static String GROUP2_NAME = "group2";
62   final private static String[] GROUP_NAMES = new String[] { GROUP1_NAME,
63       GROUP2_NAME };
64   final private static String REAL_USER = "RealUser";
65   final private static String PROXY_USER = "ProxyUser";
66   private static UserGroupInformation ugi;
67   private static UserGroupInformation proxyUgi;
68 
69   private static final Log LOG = LogFactory.getLog(TestDoAsEffectiveUser.class);
70 
configureSuperUserIPAddresses(Configuration conf, String superUserShortName)71   private static void configureSuperUserIPAddresses(Configuration conf,
72       String superUserShortName) throws IOException {
73     ArrayList<String> ipList = new ArrayList<String>();
74     Enumeration<NetworkInterface> netInterfaceList = NetworkInterface
75         .getNetworkInterfaces();
76     while (netInterfaceList.hasMoreElements()) {
77       NetworkInterface inf = netInterfaceList.nextElement();
78       Enumeration<InetAddress> addrList = inf.getInetAddresses();
79       while (addrList.hasMoreElements()) {
80         InetAddress addr = addrList.nextElement();
81         ipList.add(addr.getHostAddress());
82       }
83     }
84     StringBuilder builder = new StringBuilder();
85     for (String ip : ipList) {
86       builder.append(ip);
87       builder.append(',');
88     }
89     builder.append("127.0.1.1,");
90     builder.append(InetAddress.getLocalHost().getCanonicalHostName());
91     LOG.info("Local Ip addresses: " + builder.toString());
92     conf.setStrings(DefaultImpersonationProvider.getTestProvider().
93             getProxySuperuserIpConfKey(superUserShortName),
94         builder.toString());
95   }
96 
97   @BeforeClass
setUp()98   public static void setUp() throws Exception {
99     config = new HdfsConfiguration();
100     config.setBoolean(DFSConfigKeys.DFS_WEBHDFS_ENABLED_KEY, true);
101     config.setLong(
102         DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_MAX_LIFETIME_KEY, 10000);
103     config.setLong(
104         DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_RENEW_INTERVAL_KEY, 5000);
105     config.setStrings(DefaultImpersonationProvider.getTestProvider().
106             getProxySuperuserGroupConfKey(REAL_USER),
107         "group1");
108     config.setBoolean(
109         DFSConfigKeys.DFS_NAMENODE_DELEGATION_TOKEN_ALWAYS_USE_KEY, true);
110     configureSuperUserIPAddresses(config, REAL_USER);
111     FileSystem.setDefaultUri(config, "hdfs://localhost:" + "0");
112     cluster = new MiniDFSCluster.Builder(config).build();
113     cluster.waitActive();
114     ProxyUsers.refreshSuperUserGroupsConfiguration(config);
115     ugi = UserGroupInformation.createRemoteUser(REAL_USER);
116     proxyUgi = UserGroupInformation.createProxyUserForTesting(PROXY_USER, ugi,
117         GROUP_NAMES);
118   }
119 
120   @AfterClass
tearDown()121   public static void tearDown() throws Exception {
122     if(cluster!=null) {
123       cluster.shutdown();
124     }
125   }
126 
127   @Test(timeout=20000)
testDelegationTokenWithRealUser()128   public void testDelegationTokenWithRealUser() throws IOException {
129     try {
130       Token<?>[] tokens = proxyUgi
131           .doAs(new PrivilegedExceptionAction<Token<?>[]>() {
132             @Override
133             public Token<?>[] run() throws IOException {
134               return cluster.getFileSystem().addDelegationTokens("RenewerUser", null);
135             }
136           });
137       DelegationTokenIdentifier identifier = new DelegationTokenIdentifier();
138       byte[] tokenId = tokens[0].getIdentifier();
139       identifier.readFields(new DataInputStream(new ByteArrayInputStream(
140           tokenId)));
141       Assert.assertEquals(identifier.getUser().getUserName(), PROXY_USER);
142       Assert.assertEquals(identifier.getUser().getRealUser().getUserName(),
143           REAL_USER);
144     } catch (InterruptedException e) {
145       //Do Nothing
146     }
147   }
148 
149   @Test(timeout=5000)
testWebHdfsDoAs()150   public void testWebHdfsDoAs() throws Exception {
151     WebHdfsTestUtil.LOG.info("START: testWebHdfsDoAs()");
152     WebHdfsTestUtil.LOG.info("ugi.getShortUserName()=" + ugi.getShortUserName());
153     final WebHdfsFileSystem webhdfs = WebHdfsTestUtil.getWebHdfsFileSystemAs(ugi, config, WebHdfsFileSystem.SCHEME);
154 
155     final Path root = new Path("/");
156     cluster.getFileSystem().setPermission(root, new FsPermission((short)0777));
157 
158     Whitebox.setInternalState(webhdfs, "ugi", proxyUgi);
159 
160     {
161       Path responsePath = webhdfs.getHomeDirectory();
162       WebHdfsTestUtil.LOG.info("responsePath=" + responsePath);
163       Assert.assertEquals(webhdfs.getUri() + "/user/" + PROXY_USER, responsePath.toString());
164     }
165 
166     final Path f = new Path("/testWebHdfsDoAs/a.txt");
167     {
168       FSDataOutputStream out = webhdfs.create(f);
169       out.write("Hello, webhdfs user!".getBytes());
170       out.close();
171 
172       final FileStatus status = webhdfs.getFileStatus(f);
173       WebHdfsTestUtil.LOG.info("status.getOwner()=" + status.getOwner());
174       Assert.assertEquals(PROXY_USER, status.getOwner());
175     }
176 
177     {
178       final FSDataOutputStream out = webhdfs.append(f);
179       out.write("\nHello again!".getBytes());
180       out.close();
181 
182       final FileStatus status = webhdfs.getFileStatus(f);
183       WebHdfsTestUtil.LOG.info("status.getOwner()=" + status.getOwner());
184       WebHdfsTestUtil.LOG.info("status.getLen()  =" + status.getLen());
185       Assert.assertEquals(PROXY_USER, status.getOwner());
186     }
187   }
188 }
189