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 java.io.IOException; 021import java.util.List; 022import java.util.Optional; 023import org.apache.hadoop.fs.Path; 024import org.apache.hadoop.hbase.CompareOperator; 025import org.apache.hadoop.hbase.HBaseInterfaceAudience; 026import org.apache.hadoop.hbase.client.Append; 027import org.apache.hadoop.hbase.client.CheckAndMutate; 028import org.apache.hadoop.hbase.client.CheckAndMutateResult; 029import org.apache.hadoop.hbase.client.Delete; 030import org.apache.hadoop.hbase.client.Durability; 031import org.apache.hadoop.hbase.client.Increment; 032import org.apache.hadoop.hbase.client.Mutation; 033import org.apache.hadoop.hbase.client.Put; 034import org.apache.hadoop.hbase.client.RegionInfo; 035import org.apache.hadoop.hbase.client.Result; 036import org.apache.hadoop.hbase.coprocessor.CoreCoprocessor; 037import org.apache.hadoop.hbase.coprocessor.ObserverContext; 038import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 039import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 040import org.apache.hadoop.hbase.coprocessor.RegionObserver; 041import org.apache.hadoop.hbase.filter.ByteArrayComparable; 042import org.apache.hadoop.hbase.filter.Filter; 043import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker; 044import org.apache.hadoop.hbase.regionserver.InternalScanner; 045import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress; 046import org.apache.hadoop.hbase.regionserver.ScanOptions; 047import org.apache.hadoop.hbase.regionserver.ScanType; 048import org.apache.hadoop.hbase.regionserver.Store; 049import org.apache.hadoop.hbase.regionserver.StoreFile; 050import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker; 051import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest; 052import org.apache.hadoop.hbase.util.Pair; 053import org.apache.hadoop.hbase.wal.WALEdit; 054import org.apache.hadoop.hbase.wal.WALKey; 055import org.apache.yetus.audience.InterfaceAudience; 056 057@CoreCoprocessor 058@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) 059public class RegionReadOnlyController extends AbstractReadOnlyController 060 implements RegionCoprocessor, RegionObserver { 061 062 @Override 063 public Optional<RegionObserver> getRegionObserver() { 064 return Optional.of(this); 065 } 066 067 @Override 068 public void preFlushScannerOpen(ObserverContext<? extends RegionCoprocessorEnvironment> c, 069 Store store, ScanOptions options, FlushLifeCycleTracker tracker) throws IOException { 070 if (!isWritableInReadOnlyMode(c)) { 071 internalReadOnlyGuard(); 072 } 073 RegionObserver.super.preFlushScannerOpen(c, store, options, tracker); 074 } 075 076 @Override 077 public void preFlush(final ObserverContext<? extends RegionCoprocessorEnvironment> c, 078 FlushLifeCycleTracker tracker) throws IOException { 079 if (!isWritableInReadOnlyMode(c)) { 080 internalReadOnlyGuard(); 081 } 082 RegionObserver.super.preFlush(c, tracker); 083 } 084 085 @Override 086 public InternalScanner preFlush(ObserverContext<? extends RegionCoprocessorEnvironment> c, 087 Store store, InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException { 088 if (!isWritableInReadOnlyMode(c)) { 089 internalReadOnlyGuard(); 090 } 091 return RegionObserver.super.preFlush(c, store, scanner, tracker); 092 } 093 094 @Override 095 public void preMemStoreCompaction(ObserverContext<? extends RegionCoprocessorEnvironment> c, 096 Store store) throws IOException { 097 internalReadOnlyGuard(); 098 RegionObserver.super.preMemStoreCompaction(c, store); 099 } 100 101 @Override 102 public void preMemStoreCompactionCompactScannerOpen( 103 ObserverContext<? extends RegionCoprocessorEnvironment> c, Store store, ScanOptions options) 104 throws IOException { 105 internalReadOnlyGuard(); 106 RegionObserver.super.preMemStoreCompactionCompactScannerOpen(c, store, options); 107 } 108 109 @Override 110 public InternalScanner preMemStoreCompactionCompact( 111 ObserverContext<? extends RegionCoprocessorEnvironment> c, Store store, InternalScanner scanner) 112 throws IOException { 113 internalReadOnlyGuard(); 114 return RegionObserver.super.preMemStoreCompactionCompact(c, store, scanner); 115 } 116 117 @Override 118 public void preCompactSelection(ObserverContext<? extends RegionCoprocessorEnvironment> c, 119 Store store, List<? extends StoreFile> candidates, CompactionLifeCycleTracker tracker) 120 throws IOException { 121 if (!isWritableInReadOnlyMode(c)) { 122 internalReadOnlyGuard(); 123 } 124 RegionObserver.super.preCompactSelection(c, store, candidates, tracker); 125 } 126 127 @Override 128 public void preCompactScannerOpen(ObserverContext<? extends RegionCoprocessorEnvironment> c, 129 Store store, ScanType scanType, ScanOptions options, CompactionLifeCycleTracker tracker, 130 CompactionRequest request) throws IOException { 131 if (!isWritableInReadOnlyMode(c)) { 132 internalReadOnlyGuard(); 133 } 134 RegionObserver.super.preCompactScannerOpen(c, store, scanType, options, tracker, request); 135 } 136 137 @Override 138 public InternalScanner preCompact(ObserverContext<? extends RegionCoprocessorEnvironment> c, 139 Store store, InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker, 140 CompactionRequest request) throws IOException { 141 if (!isWritableInReadOnlyMode(c)) { 142 internalReadOnlyGuard(); 143 } 144 return RegionObserver.super.preCompact(c, store, scanner, scanType, tracker, request); 145 } 146 147 @Override 148 public void prePut(ObserverContext<? extends RegionCoprocessorEnvironment> c, Put put, 149 WALEdit edit, Durability durability) throws IOException { 150 if (!isWritableInReadOnlyMode(c)) { 151 internalReadOnlyGuard(); 152 } 153 RegionObserver.super.prePut(c, put, edit, durability); 154 } 155 156 @Override 157 public void prePut(ObserverContext<? extends RegionCoprocessorEnvironment> c, Put put, 158 WALEdit edit) throws IOException { 159 if (!isWritableInReadOnlyMode(c)) { 160 internalReadOnlyGuard(); 161 } 162 RegionObserver.super.prePut(c, put, edit); 163 } 164 165 @Override 166 public void preDelete(ObserverContext<? extends RegionCoprocessorEnvironment> c, Delete delete, 167 WALEdit edit, Durability durability) throws IOException { 168 if (!isWritableInReadOnlyMode(c)) { 169 internalReadOnlyGuard(); 170 } 171 RegionObserver.super.preDelete(c, delete, edit, durability); 172 } 173 174 @Override 175 public void preDelete(ObserverContext<? extends RegionCoprocessorEnvironment> c, Delete delete, 176 WALEdit edit) throws IOException { 177 if (!isWritableInReadOnlyMode(c)) { 178 internalReadOnlyGuard(); 179 } 180 RegionObserver.super.preDelete(c, delete, edit); 181 } 182 183 @Override 184 public void preBatchMutate(ObserverContext<? extends RegionCoprocessorEnvironment> c, 185 MiniBatchOperationInProgress<Mutation> miniBatchOp) throws IOException { 186 if (!isWritableInReadOnlyMode(c)) { 187 internalReadOnlyGuard(); 188 } 189 RegionObserver.super.preBatchMutate(c, miniBatchOp); 190 } 191 192 @Override 193 public boolean preCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> c, 194 byte[] row, byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, 195 Put put, boolean result) throws IOException { 196 if (!isWritableInReadOnlyMode(c)) { 197 internalReadOnlyGuard(); 198 } 199 return RegionObserver.super.preCheckAndPut(c, row, family, qualifier, op, comparator, put, 200 result); 201 } 202 203 @Override 204 public boolean preCheckAndPut(ObserverContext<? extends RegionCoprocessorEnvironment> c, 205 byte[] row, Filter filter, Put put, boolean result) throws IOException { 206 if (!isWritableInReadOnlyMode(c)) { 207 internalReadOnlyGuard(); 208 } 209 return RegionObserver.super.preCheckAndPut(c, row, filter, put, result); 210 } 211 212 @Override 213 public boolean preCheckAndPutAfterRowLock( 214 ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, byte[] family, 215 byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, Put put, boolean result) 216 throws IOException { 217 if (!isWritableInReadOnlyMode(c)) { 218 internalReadOnlyGuard(); 219 } 220 return RegionObserver.super.preCheckAndPutAfterRowLock(c, row, family, qualifier, op, 221 comparator, put, result); 222 } 223 224 @Override 225 public boolean preCheckAndPutAfterRowLock( 226 ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, Filter filter, Put put, 227 boolean result) throws IOException { 228 if (!isWritableInReadOnlyMode(c)) { 229 internalReadOnlyGuard(); 230 } 231 return RegionObserver.super.preCheckAndPutAfterRowLock(c, row, filter, put, result); 232 } 233 234 @Override 235 public boolean preCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> c, 236 byte[] row, byte[] family, byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, 237 Delete delete, boolean result) throws IOException { 238 if (!isWritableInReadOnlyMode(c)) { 239 internalReadOnlyGuard(); 240 } 241 return RegionObserver.super.preCheckAndDelete(c, row, family, qualifier, op, comparator, delete, 242 result); 243 } 244 245 @Override 246 public boolean preCheckAndDelete(ObserverContext<? extends RegionCoprocessorEnvironment> c, 247 byte[] row, Filter filter, Delete delete, boolean result) throws IOException { 248 if (!isWritableInReadOnlyMode(c)) { 249 internalReadOnlyGuard(); 250 } 251 return RegionObserver.super.preCheckAndDelete(c, row, filter, delete, result); 252 } 253 254 @Override 255 public boolean preCheckAndDeleteAfterRowLock( 256 ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, byte[] family, 257 byte[] qualifier, CompareOperator op, ByteArrayComparable comparator, Delete delete, 258 boolean result) throws IOException { 259 if (!isWritableInReadOnlyMode(c)) { 260 internalReadOnlyGuard(); 261 } 262 return RegionObserver.super.preCheckAndDeleteAfterRowLock(c, row, family, qualifier, op, 263 comparator, delete, result); 264 } 265 266 @Override 267 public boolean preCheckAndDeleteAfterRowLock( 268 ObserverContext<? extends RegionCoprocessorEnvironment> c, byte[] row, Filter filter, 269 Delete delete, boolean result) throws IOException { 270 if (!isWritableInReadOnlyMode(c)) { 271 internalReadOnlyGuard(); 272 } 273 return RegionObserver.super.preCheckAndDeleteAfterRowLock(c, row, filter, delete, result); 274 } 275 276 @Override 277 public CheckAndMutateResult preCheckAndMutate( 278 ObserverContext<? extends RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate, 279 CheckAndMutateResult result) throws IOException { 280 internalReadOnlyGuard(); 281 return RegionObserver.super.preCheckAndMutate(c, checkAndMutate, result); 282 } 283 284 @Override 285 public CheckAndMutateResult preCheckAndMutateAfterRowLock( 286 ObserverContext<? extends RegionCoprocessorEnvironment> c, CheckAndMutate checkAndMutate, 287 CheckAndMutateResult result) throws IOException { 288 internalReadOnlyGuard(); 289 return RegionObserver.super.preCheckAndMutateAfterRowLock(c, checkAndMutate, result); 290 } 291 292 @Override 293 public Result preAppend(ObserverContext<? extends RegionCoprocessorEnvironment> c, Append append) 294 throws IOException { 295 internalReadOnlyGuard(); 296 return RegionObserver.super.preAppend(c, append); 297 } 298 299 @Override 300 public Result preAppend(ObserverContext<? extends RegionCoprocessorEnvironment> c, Append append, 301 WALEdit edit) throws IOException { 302 internalReadOnlyGuard(); 303 return RegionObserver.super.preAppend(c, append, edit); 304 } 305 306 @Override 307 public Result preAppendAfterRowLock(ObserverContext<? extends RegionCoprocessorEnvironment> c, 308 Append append) throws IOException { 309 internalReadOnlyGuard(); 310 return RegionObserver.super.preAppendAfterRowLock(c, append); 311 } 312 313 @Override 314 public Result preIncrement(ObserverContext<? extends RegionCoprocessorEnvironment> c, 315 Increment increment) throws IOException { 316 internalReadOnlyGuard(); 317 return RegionObserver.super.preIncrement(c, increment); 318 } 319 320 @Override 321 public Result preIncrement(ObserverContext<? extends RegionCoprocessorEnvironment> c, 322 Increment increment, WALEdit edit) throws IOException { 323 internalReadOnlyGuard(); 324 return RegionObserver.super.preIncrement(c, increment, edit); 325 } 326 327 @Override 328 public Result preIncrementAfterRowLock(ObserverContext<? extends RegionCoprocessorEnvironment> c, 329 Increment increment) throws IOException { 330 internalReadOnlyGuard(); 331 return RegionObserver.super.preIncrementAfterRowLock(c, increment); 332 } 333 334 @Override 335 public void preReplayWALs(ObserverContext<? extends RegionCoprocessorEnvironment> ctx, 336 RegionInfo info, Path edits) throws IOException { 337 if (!isWritableInReadOnlyMode(ctx)) { 338 internalReadOnlyGuard(); 339 } 340 RegionObserver.super.preReplayWALs(ctx, info, edits); 341 } 342 343 @Override 344 public void preBulkLoadHFile(ObserverContext<? extends RegionCoprocessorEnvironment> ctx, 345 List<Pair<byte[], String>> familyPaths) throws IOException { 346 internalReadOnlyGuard(); 347 RegionObserver.super.preBulkLoadHFile(ctx, familyPaths); 348 } 349 350 @Override 351 public void preCommitStoreFile(ObserverContext<? extends RegionCoprocessorEnvironment> ctx, 352 byte[] family, List<Pair<Path, Path>> pairs) throws IOException { 353 internalReadOnlyGuard(); 354 RegionObserver.super.preCommitStoreFile(ctx, family, pairs); 355 } 356 357 @Override 358 public void preWALAppend(ObserverContext<? extends RegionCoprocessorEnvironment> ctx, WALKey key, 359 WALEdit edit) throws IOException { 360 // Only allow this operation for whitelisted table. 361 // See {@link writableTables set} for details. 362 if (!isWritableInReadOnlyMode(key.getTableName())) { 363 internalReadOnlyGuard(); 364 } 365 RegionObserver.super.preWALAppend(ctx, key, edit); 366 } 367}