1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security;
19
20 import java.io.IOException;
21 import java.util.LinkedHashSet;
22 import java.util.Set;
23 import java.util.concurrent.Callable;
24 import java.util.concurrent.Executors;
25 import java.util.concurrent.TimeUnit;
26
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import com.google.common.cache.CacheBuilder;
29 import com.google.common.cache.CacheLoader;
30 import com.google.common.cache.LoadingCache;
31 import com.google.common.util.concurrent.ListenableFuture;
32 import com.google.common.util.concurrent.ListeningExecutorService;
33 import com.google.common.util.concurrent.MoreExecutors;
34 import com.google.common.util.concurrent.ThreadFactoryBuilder;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.fs.CommonConfigurationKeys;
37 import org.apache.hadoop.hbase.BaseConfigurable;
38 import org.apache.hadoop.security.Groups;
39 import org.apache.hadoop.security.UserGroupInformation;
40 import org.apache.hadoop.util.ReflectionUtils;
41
42
43
44
45 @InterfaceAudience.Private
46 public class UserProvider extends BaseConfigurable {
47
48 private static final String USER_PROVIDER_CONF_KEY = "hbase.client.userprovider.class";
49 private static final ListeningExecutorService executor = MoreExecutors.listeningDecorator(
50 Executors.newScheduledThreadPool(
51 1,
52 new ThreadFactoryBuilder().setDaemon(true).setNameFormat("group-cache-%d").build()));
53
54 private LoadingCache<String, String[]> groupCache = null;
55
56 static Groups groups = Groups.getUserToGroupsMappingService();
57
58 @Override
59 public void setConf(final Configuration conf) {
60 super.setConf(conf);
61
62 synchronized (UserProvider.class) {
63 if (!(groups instanceof User.TestingGroups)) {
64 groups = Groups.getUserToGroupsMappingService(conf);
65 }
66 }
67
68 long cacheTimeout =
69 getConf().getLong(CommonConfigurationKeys.HADOOP_SECURITY_GROUPS_CACHE_SECS,
70 CommonConfigurationKeys.HADOOP_SECURITY_GROUPS_CACHE_SECS_DEFAULT) * 1000;
71
72 this.groupCache = CacheBuilder.newBuilder()
73
74 .refreshAfterWrite(cacheTimeout, TimeUnit.MILLISECONDS)
75 .expireAfterWrite(10 * cacheTimeout, TimeUnit.MILLISECONDS)
76
77
78 .concurrencyLevel(20)
79
80
81 .build(new CacheLoader<String, String[]>() {
82
83
84
85
86 @Override
87 public String[] load(String ugi) throws Exception {
88 return getGroupStrings(ugi);
89 }
90
91 private String[] getGroupStrings(String ugi) {
92 try {
93 Set<String> result = new LinkedHashSet<String>(groups.getGroups(ugi));
94 return result.toArray(new String[result.size()]);
95 } catch (Exception e) {
96 return new String[0];
97 }
98 }
99
100
101 public ListenableFuture<String[]> reload(final String k,
102 String[] oldValue) throws Exception {
103
104 return executor.submit(new Callable<String[]>() {
105
106 @Override
107 public String[] call() throws Exception {
108 return getGroupStrings(k);
109 }
110 });
111 }
112 });
113 }
114
115
116
117
118
119
120
121 public static UserProvider instantiate(Configuration conf) {
122 Class<? extends UserProvider> clazz =
123 conf.getClass(USER_PROVIDER_CONF_KEY, UserProvider.class, UserProvider.class);
124 return ReflectionUtils.newInstance(clazz, conf);
125 }
126
127
128
129
130
131
132 public static void setUserProviderForTesting(Configuration conf,
133 Class<? extends UserProvider> provider) {
134 conf.set(USER_PROVIDER_CONF_KEY, provider.getName());
135 }
136
137
138
139
140
141 public String getCurrentUserName() throws IOException {
142 User user = getCurrent();
143 return user == null ? null : user.getName();
144 }
145
146
147
148
149 public boolean isHBaseSecurityEnabled() {
150 return User.isHBaseSecurityEnabled(this.getConf());
151 }
152
153
154
155
156
157
158 public boolean isHadoopSecurityEnabled() {
159 return User.isSecurityEnabled();
160 }
161
162
163
164
165
166 public User getCurrent() throws IOException {
167 return User.getCurrent();
168 }
169
170
171
172
173
174
175 public User create(UserGroupInformation ugi) {
176 if (ugi == null) {
177 return null;
178 }
179 return new User.SecureHadoopUser(ugi, groupCache);
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 public void login(String fileConfKey, String principalConfKey, String localhost)
196 throws IOException {
197 User.login(getConf(), fileConfKey, principalConfKey, localhost);
198 }
199 }