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.hbase.security.access;
20 
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23 
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.Abortable;
32 import org.apache.hadoop.hbase.TableName;
33 import org.apache.hadoop.hbase.HBaseTestingUtility;
34 import org.apache.hadoop.hbase.testclassification.LargeTests;
35 import org.apache.hadoop.hbase.Waiter.Predicate;
36 import org.apache.hadoop.hbase.security.User;
37 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
38 import org.junit.AfterClass;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.junit.experimental.categories.Category;
42 
43 /**
44  * Test the reading and writing of access permissions to and from zookeeper.
45  */
46 @Category(LargeTests.class)
47 public class TestZKPermissionsWatcher {
48   private static final Log LOG = LogFactory.getLog(TestZKPermissionsWatcher.class);
49   private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
50   private static TableAuthManager AUTH_A;
51   private static TableAuthManager AUTH_B;
52   private final static Abortable ABORTABLE = new Abortable() {
53     private final AtomicBoolean abort = new AtomicBoolean(false);
54 
55     @Override
56     public void abort(String why, Throwable e) {
57       LOG.info(why, e);
58       abort.set(true);
59     }
60 
61     @Override
62     public boolean isAborted() {
63       return abort.get();
64     }
65   };
66 
67   private static TableName TEST_TABLE =
68       TableName.valueOf("perms_test");
69 
70   @BeforeClass
beforeClass()71   public static void beforeClass() throws Exception {
72     // setup configuration
73     Configuration conf = UTIL.getConfiguration();
74     SecureTestUtil.enableSecurity(conf);
75 
76     // start minicluster
77     UTIL.startMiniCluster();
78     AUTH_A = TableAuthManager.get(new ZooKeeperWatcher(conf,
79       "TestZKPermissionsWatcher_1", ABORTABLE), conf);
80     AUTH_B = TableAuthManager.get(new ZooKeeperWatcher(conf,
81       "TestZKPermissionsWatcher_2", ABORTABLE), conf);
82   }
83 
84   @AfterClass
afterClass()85   public static void afterClass() throws Exception {
86     UTIL.shutdownMiniCluster();
87   }
88 
89   @Test
testPermissionsWatcher()90   public void testPermissionsWatcher() throws Exception {
91     Configuration conf = UTIL.getConfiguration();
92     User george = User.createUserForTesting(conf, "george", new String[] { });
93     User hubert = User.createUserForTesting(conf, "hubert", new String[] { });
94 
95     assertFalse(AUTH_A.authorizeUser(george, TEST_TABLE, null,
96       TablePermission.Action.READ));
97     assertFalse(AUTH_A.authorizeUser(george, TEST_TABLE, null,
98       TablePermission.Action.WRITE));
99     assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
100       TablePermission.Action.READ));
101     assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
102       TablePermission.Action.WRITE));
103 
104     assertFalse(AUTH_B.authorizeUser(george, TEST_TABLE, null,
105       TablePermission.Action.READ));
106     assertFalse(AUTH_B.authorizeUser(george, TEST_TABLE, null,
107       TablePermission.Action.WRITE));
108     assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
109       TablePermission.Action.READ));
110     assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
111       TablePermission.Action.WRITE));
112 
113     // update ACL: george RW
114     List<TablePermission> acl = new ArrayList<TablePermission>();
115     acl.add(new TablePermission(TEST_TABLE, null, TablePermission.Action.READ,
116       TablePermission.Action.WRITE));
117     final long mtimeB = AUTH_B.getMTime();
118     AUTH_A.setTableUserPermissions(george.getShortName(), TEST_TABLE, acl);
119     // Wait for the update to propagate
120     UTIL.waitFor(10000, 100, new Predicate<Exception>() {
121       @Override
122       public boolean evaluate() throws Exception {
123         return AUTH_B.getMTime() > mtimeB;
124       }
125     });
126     Thread.sleep(1000);
127 
128     // check it
129     assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
130       TablePermission.Action.READ));
131     assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
132       TablePermission.Action.WRITE));
133     assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
134       TablePermission.Action.READ));
135     assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
136       TablePermission.Action.WRITE));
137     assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
138       TablePermission.Action.READ));
139     assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
140       TablePermission.Action.WRITE));
141     assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
142       TablePermission.Action.READ));
143     assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
144       TablePermission.Action.WRITE));
145 
146     // update ACL: hubert R
147     acl = new ArrayList<TablePermission>();
148     acl.add(new TablePermission(TEST_TABLE, null, TablePermission.Action.READ));
149     final long mtimeA = AUTH_A.getMTime();
150     AUTH_B.setTableUserPermissions("hubert", TEST_TABLE, acl);
151     // Wait for the update to propagate
152     UTIL.waitFor(10000, 100, new Predicate<Exception>() {
153       @Override
154       public boolean evaluate() throws Exception {
155         return AUTH_A.getMTime() > mtimeA;
156       }
157     });
158     Thread.sleep(1000);
159 
160     // check it
161     assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
162       TablePermission.Action.READ));
163     assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
164       TablePermission.Action.WRITE));
165     assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
166       TablePermission.Action.READ));
167     assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
168       TablePermission.Action.WRITE));
169     assertTrue(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
170       TablePermission.Action.READ));
171     assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
172       TablePermission.Action.WRITE));
173     assertTrue(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
174       TablePermission.Action.READ));
175     assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
176       TablePermission.Action.WRITE));
177   }
178 }
179