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.assertEquals; 021 022import java.io.IOException; 023import java.security.PrivilegedExceptionAction; 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.List; 027import org.apache.hadoop.conf.Configuration; 028import org.apache.hadoop.fs.Path; 029import org.apache.hadoop.hbase.HBaseTestingUtil; 030import org.apache.hadoop.hbase.NamespaceDescriptor; 031import org.apache.hadoop.hbase.TableName; 032import org.apache.hadoop.hbase.client.*; 033import org.apache.hadoop.hbase.security.User; 034import org.apache.hadoop.hbase.util.Bytes; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038final class TestHDFSAclHelper { 039 private static final Logger LOG = LoggerFactory.getLogger(TestHDFSAclHelper.class); 040 041 private static final String USER_OWNER = "owner"; 042 043 private TestHDFSAclHelper() { 044 } 045 046 static void grantOnTable(HBaseTestingUtil util, String user, TableName tableName, 047 Permission.Action... actions) throws Exception { 048 SecureTestUtil.grantOnTable(util, user, tableName, null, null, actions); 049 } 050 051 static void createNamespace(HBaseTestingUtil util, String namespace) throws IOException { 052 if ( 053 Arrays.stream(util.getAdmin().listNamespaceDescriptors()) 054 .noneMatch(ns -> ns.getName().equals(namespace)) 055 ) { 056 NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(namespace).build(); 057 util.getAdmin().createNamespace(namespaceDescriptor); 058 } 059 } 060 061 static Table createTable(HBaseTestingUtil util, TableName tableName) throws Exception { 062 createNamespace(util, tableName.getNamespaceAsString()); 063 TableDescriptor td = getTableDescriptorBuilder(util, tableName) 064 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "true").build(); 065 byte[][] splits = new byte[][] { Bytes.toBytes("2"), Bytes.toBytes("4") }; 066 User user = User.createUserForTesting(util.getConfiguration(), USER_OWNER, new String[] {}); 067 SecureTestUtil.grantGlobal(util, user.getShortName(), Permission.Action.CREATE); 068 SecureTestUtil.createTable(util, user, td, splits); 069 return util.getConnection().getTable(tableName); 070 } 071 072 static Table createMobTable(HBaseTestingUtil util, TableName tableName) throws Exception { 073 createNamespace(util, tableName.getNamespaceAsString()); 074 TableDescriptor td = TableDescriptorBuilder.newBuilder(tableName) 075 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(COLUMN1).setMobEnabled(true) 076 .setMobThreshold(0).build()) 077 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(COLUMN2).setMobEnabled(true) 078 .setMobThreshold(0).build()) 079 .setValue(SnapshotScannerHDFSAclHelper.ACL_SYNC_TO_HDFS_ENABLE, "true").build(); 080 byte[][] splits = new byte[][] { Bytes.toBytes("2"), Bytes.toBytes("4") }; 081 User user = User.createUserForTesting(util.getConfiguration(), USER_OWNER, new String[] {}); 082 SecureTestUtil.grantGlobal(util, user.getShortName(), Permission.Action.CREATE); 083 SecureTestUtil.createTable(util, user, td, splits); 084 return util.getConnection().getTable(tableName); 085 } 086 087 static TableDescriptor createUserScanSnapshotDisabledTable(HBaseTestingUtil util, 088 TableName tableName) throws Exception { 089 createNamespace(util, tableName.getNamespaceAsString()); 090 TableDescriptor td = getTableDescriptorBuilder(util, tableName).build(); 091 byte[][] splits = new byte[][] { Bytes.toBytes("2"), Bytes.toBytes("4") }; 092 User user = User.createUserForTesting(util.getConfiguration(), USER_OWNER, new String[] {}); 093 SecureTestUtil.grantGlobal(util, user.getShortName(), Permission.Action.CREATE); 094 SecureTestUtil.createTable(util, user, td, splits); 095 try (Table t = util.getConnection().getTable(tableName)) { 096 put(t); 097 } 098 return td; 099 } 100 101 static TableDescriptorBuilder getTableDescriptorBuilder(HBaseTestingUtil util, 102 TableName tableName) { 103 return TableDescriptorBuilder.newBuilder(tableName) 104 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(COLUMN1).build()) 105 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(COLUMN2).build()); 106 } 107 108 static void createTableAndPut(HBaseTestingUtil util, TableName tableNam) throws Exception { 109 try (Table t = createTable(util, tableNam)) { 110 put(t); 111 } 112 } 113 114 static final byte[] COLUMN1 = Bytes.toBytes("A"); 115 static final byte[] COLUMN2 = Bytes.toBytes("B"); 116 117 static void put(Table hTable) throws IOException { 118 List<Put> puts = new ArrayList<>(); 119 for (int i = 0; i < 6; i++) { 120 Put put = new Put(Bytes.toBytes(i)); 121 put.addColumn(COLUMN1, null, Bytes.toBytes(i)); 122 put.addColumn(COLUMN2, null, Bytes.toBytes(i + 1)); 123 puts.add(put); 124 } 125 hTable.put(puts); 126 } 127 128 static void put2(Table hTable) throws IOException { 129 List<Put> puts = new ArrayList<>(); 130 for (int i = 0; i < 10; i++) { 131 if (i == 5) { 132 continue; 133 } 134 Put put = new Put(Bytes.toBytes(i)); 135 put.addColumn(COLUMN1, null, Bytes.toBytes(i + 2)); 136 put.addColumn(COLUMN2, null, Bytes.toBytes(i + 3)); 137 puts.add(put); 138 } 139 hTable.put(puts); 140 } 141 142 /** 143 * Check if user is able to read expected rows from the specific snapshot 144 * @param user the specific user 145 * @param snapshot the snapshot to be scanned 146 * @param expectedRowCount expected row count read from snapshot, -1 if expects 147 * AccessControlException 148 * @throws IOException user scan snapshot error 149 * @throws InterruptedException user scan snapshot error 150 */ 151 static void canUserScanSnapshot(HBaseTestingUtil util, User user, String snapshot, 152 int expectedRowCount) throws IOException, InterruptedException { 153 PrivilegedExceptionAction<Void> action = 154 getScanSnapshotAction(util.getConfiguration(), snapshot, expectedRowCount); 155 user.runAs(action); 156 } 157 158 static PrivilegedExceptionAction<Void> getScanSnapshotAction(Configuration conf, 159 String snapshotName, long expectedRowCount) { 160 return () -> { 161 try { 162 Path restoreDir = new Path(SnapshotScannerHDFSAclHelper.SNAPSHOT_RESTORE_TMP_DIR_DEFAULT); 163 Scan scan = new Scan(); 164 TableSnapshotScanner scanner = 165 new TableSnapshotScanner(conf, restoreDir, snapshotName, scan); 166 int rowCount = 0; 167 while (true) { 168 Result result = scanner.next(); 169 if (result == null) { 170 break; 171 } 172 rowCount++; 173 } 174 scanner.close(); 175 assertEquals(expectedRowCount, rowCount); 176 } catch (Exception e) { 177 LOG.debug("Scan snapshot error, snapshot {}", snapshotName, e); 178 assertEquals(expectedRowCount, -1); 179 } 180 return null; 181 }; 182 } 183}