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}