001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.security.access;
019
020import static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertTrue;
022
023import java.util.ArrayList;
024import java.util.List;
025import java.util.concurrent.atomic.AtomicBoolean;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.hbase.Abortable;
028import org.apache.hadoop.hbase.HBaseClassTestRule;
029import org.apache.hadoop.hbase.HBaseTestingUtility;
030import org.apache.hadoop.hbase.TableName;
031import org.apache.hadoop.hbase.Waiter.Predicate;
032import org.apache.hadoop.hbase.security.User;
033import org.apache.hadoop.hbase.testclassification.LargeTests;
034import org.apache.hadoop.hbase.testclassification.SecurityTests;
035import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
036import org.junit.AfterClass;
037import org.junit.BeforeClass;
038import org.junit.ClassRule;
039import org.junit.Test;
040import org.junit.experimental.categories.Category;
041import org.slf4j.Logger;
042import org.slf4j.LoggerFactory;
043
044/**
045 * Test the reading and writing of access permissions to and from zookeeper.
046 */
047@Category({SecurityTests.class, LargeTests.class})
048public class TestZKPermissionWatcher {
049
050  @ClassRule
051  public static final HBaseClassTestRule CLASS_RULE =
052      HBaseClassTestRule.forClass(TestZKPermissionWatcher.class);
053
054  private static final Logger LOG = LoggerFactory.getLogger(TestZKPermissionWatcher.class);
055  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
056  private static TableAuthManager AUTH_A;
057  private static TableAuthManager AUTH_B;
058  private final static Abortable ABORTABLE = new Abortable() {
059    private final AtomicBoolean abort = new AtomicBoolean(false);
060
061    @Override
062    public void abort(String why, Throwable e) {
063      LOG.info(why, e);
064      abort.set(true);
065    }
066
067    @Override
068    public boolean isAborted() {
069      return abort.get();
070    }
071  };
072
073  private static TableName TEST_TABLE =
074      TableName.valueOf("perms_test");
075
076  @BeforeClass
077  public static void beforeClass() throws Exception {
078    // setup configuration
079    Configuration conf = UTIL.getConfiguration();
080    SecureTestUtil.enableSecurity(conf);
081
082    // start minicluster
083    UTIL.startMiniCluster();
084    AUTH_A = TableAuthManager.getOrCreate(new ZKWatcher(conf,
085      "TestZKPermissionsWatcher_1", ABORTABLE), conf);
086    AUTH_B = TableAuthManager.getOrCreate(new ZKWatcher(conf,
087      "TestZKPermissionsWatcher_2", ABORTABLE), conf);
088  }
089
090  @AfterClass
091  public static void afterClass() throws Exception {
092    UTIL.shutdownMiniCluster();
093  }
094
095  @Test
096  public void testPermissionsWatcher() throws Exception {
097    Configuration conf = UTIL.getConfiguration();
098    User george = User.createUserForTesting(conf, "george", new String[] { });
099    User hubert = User.createUserForTesting(conf, "hubert", new String[] { });
100
101    assertFalse(AUTH_A.authorizeUser(george, TEST_TABLE, null,
102      TablePermission.Action.READ));
103    assertFalse(AUTH_A.authorizeUser(george, TEST_TABLE, null,
104      TablePermission.Action.WRITE));
105    assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
106      TablePermission.Action.READ));
107    assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
108      TablePermission.Action.WRITE));
109
110    assertFalse(AUTH_B.authorizeUser(george, TEST_TABLE, null,
111      TablePermission.Action.READ));
112    assertFalse(AUTH_B.authorizeUser(george, TEST_TABLE, null,
113      TablePermission.Action.WRITE));
114    assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
115      TablePermission.Action.READ));
116    assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
117      TablePermission.Action.WRITE));
118
119    // update ACL: george RW
120    List<TablePermission> acl = new ArrayList<>(1);
121    acl.add(new TablePermission(TEST_TABLE, null, TablePermission.Action.READ,
122      TablePermission.Action.WRITE));
123    final long mtimeB = AUTH_B.getMTime();
124    AUTH_A.setTableUserPermissions(george.getShortName(), TEST_TABLE, acl);
125    // Wait for the update to propagate
126    UTIL.waitFor(10000, 100, new Predicate<Exception>() {
127      @Override
128      public boolean evaluate() throws Exception {
129        return AUTH_B.getMTime() > mtimeB;
130      }
131    });
132    Thread.sleep(1000);
133
134    // check it
135    assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
136      TablePermission.Action.READ));
137    assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
138      TablePermission.Action.WRITE));
139    assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
140      TablePermission.Action.READ));
141    assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
142      TablePermission.Action.WRITE));
143    assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
144      TablePermission.Action.READ));
145    assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
146      TablePermission.Action.WRITE));
147    assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
148      TablePermission.Action.READ));
149    assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
150      TablePermission.Action.WRITE));
151
152    // update ACL: hubert R
153    acl = new ArrayList<>(1);
154    acl.add(new TablePermission(TEST_TABLE, null, TablePermission.Action.READ));
155    final long mtimeA = AUTH_A.getMTime();
156    AUTH_B.setTableUserPermissions("hubert", TEST_TABLE, acl);
157    // Wait for the update to propagate
158    UTIL.waitFor(10000, 100, new Predicate<Exception>() {
159      @Override
160      public boolean evaluate() throws Exception {
161        return AUTH_A.getMTime() > mtimeA;
162      }
163    });
164    Thread.sleep(1000);
165
166    // check it
167    assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
168      TablePermission.Action.READ));
169    assertTrue(AUTH_A.authorizeUser(george, TEST_TABLE, null,
170      TablePermission.Action.WRITE));
171    assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
172      TablePermission.Action.READ));
173    assertTrue(AUTH_B.authorizeUser(george, TEST_TABLE, null,
174      TablePermission.Action.WRITE));
175    assertTrue(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
176      TablePermission.Action.READ));
177    assertFalse(AUTH_A.authorizeUser(hubert, TEST_TABLE, null,
178      TablePermission.Action.WRITE));
179    assertTrue(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
180      TablePermission.Action.READ));
181    assertFalse(AUTH_B.authorizeUser(hubert, TEST_TABLE, null,
182      TablePermission.Action.WRITE));
183  }
184}