1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.test;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24
25 import java.io.IOException;
26 import java.util.List;
27
28 import org.apache.commons.cli.CommandLine;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.fs.FileSystem;
33 import org.apache.hadoop.fs.Path;
34 import org.apache.hadoop.fs.permission.FsPermission;
35 import org.apache.hadoop.hbase.HBaseConfiguration;
36 import org.apache.hadoop.hbase.IntegrationTestingUtility;
37 import org.apache.hadoop.hbase.testclassification.IntegrationTests;
38 import org.apache.hadoop.hbase.util.AbstractHBaseTool;
39 import org.apache.hadoop.hbase.util.FSUtils;
40 import org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper;
41 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
42 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
43 import org.apache.hadoop.util.ToolRunner;
44 import org.apache.zookeeper.KeeperException;
45 import org.apache.zookeeper.KeeperException.Code;
46 import org.apache.zookeeper.ZooDefs.Ids;
47 import org.apache.zookeeper.ZooDefs.Perms;
48 import org.apache.zookeeper.data.ACL;
49 import org.apache.zookeeper.data.Id;
50 import org.apache.zookeeper.data.Stat;
51 import org.junit.experimental.categories.Category;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 @Category(IntegrationTests.class)
68 public class IntegrationTestZKAndFSPermissions extends AbstractHBaseTool {
69
70 private static final Log LOG = LogFactory.getLog(IntegrationTestZKAndFSPermissions.class);
71 private String superUser;
72 private String masterPrincipal;
73 private boolean isForce;
74 private String fsPerms;
75 private boolean skipFSCheck;
76 private boolean skipZKCheck;
77
78 public static final String FORCE_CHECK_ARG = "f";
79 public static final String PRINCIPAL_ARG = "p";
80 public static final String SUPERUSER_ARG = "s";
81 public static final String FS_PERMS = "fs_perms";
82 public static final String SKIP_CHECK_FS = "skip_fs_check";
83 public static final String SKIP_CHECK_ZK = "skip_zk_check";
84
85 @Override
86 public void setConf(Configuration conf) {
87 super.setConf(conf);
88 }
89
90 @Override
91 protected void addOptions() {
92 addOptNoArg(FORCE_CHECK_ARG, "Whether to skip configuration lookup and assume a secure setup");
93 addOptWithArg(PRINCIPAL_ARG, "The principal for zk authorization");
94 addOptWithArg(SUPERUSER_ARG, "The principal for super user");
95 addOptWithArg(FS_PERMS, "FS permissions, ex. 700, 750, etc. Defaults to 700");
96 addOptNoArg(SKIP_CHECK_FS, "Whether to skip checking FS permissions");
97 addOptNoArg(SKIP_CHECK_ZK, "Whether to skip checking ZK permissions");
98 }
99
100 @Override
101 protected void processOptions(CommandLine cmd) {
102 isForce = cmd.hasOption(FORCE_CHECK_ARG);
103 masterPrincipal = getShortUserName(conf.get("hbase.master.kerberos.principal"));
104 superUser = cmd.getOptionValue(SUPERUSER_ARG, conf.get("hbase.superuser"));
105 masterPrincipal = cmd.getOptionValue(PRINCIPAL_ARG, masterPrincipal);
106 fsPerms = cmd.getOptionValue(FS_PERMS, "700");
107 skipFSCheck = cmd.hasOption(SKIP_CHECK_FS);
108 skipZKCheck = cmd.hasOption(SKIP_CHECK_ZK);
109 }
110
111 private String getShortUserName(String principal) {
112 for (int i = 0; i < principal.length(); i++) {
113 if (principal.charAt(i) == '/' || principal.charAt(i) == '@') {
114 return principal.substring(0, i);
115 }
116 }
117 return principal;
118 }
119
120 @Override
121 protected int doWork() throws Exception {
122 if (!isForce) {
123 if (!"kerberos".equalsIgnoreCase(conf.get("hbase.security.authentication"))) {
124 LOG.warn("hbase.security.authentication is not kerberos, and -f is not supplied. Skip "
125 + "running the test");
126 return 0;
127 }
128 }
129
130 if (!skipZKCheck) {
131 testZNodeACLs();
132 } if (!skipFSCheck) {
133 testFSPerms();
134 }
135 return 0;
136 }
137
138 private void testZNodeACLs() throws IOException, KeeperException, InterruptedException {
139
140 ZooKeeperWatcher watcher = new ZooKeeperWatcher(conf, "IntegrationTestZnodeACLs", null);
141 RecoverableZooKeeper zk = ZKUtil.connect(this.conf, watcher);
142
143 String baseZNode = watcher.baseZNode;
144
145 LOG.info("");
146 LOG.info("***********************************************************************************");
147 LOG.info("Checking ZK permissions, root znode: " + baseZNode);
148 LOG.info("***********************************************************************************");
149 LOG.info("");
150
151 checkZnodePermsRecursive(watcher, zk, baseZNode);
152
153 LOG.info("Checking ZK permissions: SUCCESS");
154 }
155
156 private void checkZnodePermsRecursive(ZooKeeperWatcher watcher,
157 RecoverableZooKeeper zk, String znode) throws KeeperException, InterruptedException {
158
159 boolean expectedWorldReadable = watcher.isClientReadable(znode);
160
161 assertZnodePerms(zk, znode, expectedWorldReadable);
162
163 try {
164 List<String> children = zk.getChildren(znode, false);
165
166 for (String child : children) {
167 checkZnodePermsRecursive(watcher, zk, ZKUtil.joinZNode(znode, child));
168 }
169 } catch (KeeperException ke) {
170
171 if (ke.code() != Code.NOAUTH) {
172 throw ke;
173 }
174 }
175 }
176
177 private void assertZnodePerms(RecoverableZooKeeper zk, String znode,
178 boolean expectedWorldReadable) throws KeeperException, InterruptedException {
179 Stat stat = new Stat();
180 List<ACL> acls = zk.getZooKeeper().getACL(znode, stat);
181 String[] superUsers = superUser == null ? null : superUser.split(",");
182
183 LOG.info("Checking ACLs for znode znode:" + znode + " acls:" + acls);
184
185 for (ACL acl : acls) {
186 int perms = acl.getPerms();
187 Id id = acl.getId();
188
189
190 if (Ids.ANYONE_ID_UNSAFE.equals(id)) {
191
192 assertTrue(expectedWorldReadable);
193
194 assertEquals(perms, Perms.READ);
195 } else if (superUsers != null && ZooKeeperWatcher.isSuperUserId(superUsers, id)) {
196
197 assertEquals(perms, Perms.ALL);
198 } else if (new Id("sasl", masterPrincipal).equals(id)) {
199
200 assertEquals(perms, Perms.ALL);
201 } else {
202 fail("An ACL is found which is not expected for the znode:" + znode + " , ACL:" + acl);
203 }
204 }
205 }
206
207 private void testFSPerms() throws IOException {
208 Path rootDir = FSUtils.getRootDir(conf);
209
210 LOG.info("");
211 LOG.info("***********************************************************************************");
212 LOG.info("Checking FS permissions for root dir:" + rootDir);
213 LOG.info("***********************************************************************************");
214 LOG.info("");
215 FileSystem fs = rootDir.getFileSystem(conf);
216
217 short expectedPerms = Short.valueOf(fsPerms, 8);
218
219 assertEquals(
220 FsPermission.createImmutable(expectedPerms),
221 fs.getFileStatus(rootDir).getPermission());
222
223 LOG.info("Checking FS permissions: SUCCESS");
224 }
225
226 public static void main(String[] args) throws Exception {
227 Configuration configuration = HBaseConfiguration.create();
228 IntegrationTestingUtility.setUseDistributedCluster(configuration);
229 IntegrationTestZKAndFSPermissions tool = new IntegrationTestZKAndFSPermissions();
230 int ret = ToolRunner.run(configuration, tool, args);
231 System.exit(ret);
232 }
233 }