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.visibility; 019 020import java.io.IOException; 021import java.util.Map; 022import java.util.Objects; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.PrivateCellUtil; 025import org.apache.hadoop.hbase.filter.FilterBase; 026import org.apache.hadoop.hbase.util.ByteRange; 027import org.apache.hadoop.hbase.util.SimpleMutableByteRange; 028import org.apache.yetus.audience.InterfaceAudience; 029 030/** 031 * This Filter checks the visibility expression with each KV against visibility labels associated 032 * with the scan. Based on the check the KV is included in the scan result or gets filtered out. 033 */ 034@InterfaceAudience.Private 035class VisibilityLabelFilter extends FilterBase { 036 037 private final VisibilityExpEvaluator expEvaluator; 038 private final Map<ByteRange, Integer> cfVsMaxVersions; 039 private final ByteRange curFamily; 040 private final ByteRange curQualifier; 041 private int curFamilyMaxVersions; 042 private int curQualMetVersions; 043 044 public VisibilityLabelFilter(VisibilityExpEvaluator expEvaluator, 045 Map<ByteRange, Integer> cfVsMaxVersions) { 046 this.expEvaluator = expEvaluator; 047 this.cfVsMaxVersions = cfVsMaxVersions; 048 this.curFamily = new SimpleMutableByteRange(); 049 this.curQualifier = new SimpleMutableByteRange(); 050 } 051 052 @Override 053 public boolean filterRowKey(Cell cell) throws IOException { 054 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 055 return false; 056 } 057 058 @Override 059 public ReturnCode filterCell(final Cell cell) throws IOException { 060 if ( 061 curFamily.getBytes() == null || !(PrivateCellUtil.matchingFamily(cell, curFamily.getBytes(), 062 curFamily.getOffset(), curFamily.getLength())) 063 ) { 064 curFamily.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); 065 // For this family, all the columns can have max of curFamilyMaxVersions versions. No need to 066 // consider the older versions for visibility label check. 067 // Ideally this should have been done at a lower layer by HBase (?) 068 curFamilyMaxVersions = cfVsMaxVersions.get(curFamily); 069 // Family is changed. Just unset curQualifier. 070 curQualifier.unset(); 071 } 072 if ( 073 curQualifier.getBytes() == null || !(PrivateCellUtil.matchingQualifier(cell, 074 curQualifier.getBytes(), curQualifier.getOffset(), curQualifier.getLength())) 075 ) { 076 curQualifier.set(cell.getQualifierArray(), cell.getQualifierOffset(), 077 cell.getQualifierLength()); 078 curQualMetVersions = 0; 079 } 080 curQualMetVersions++; 081 if (curQualMetVersions > curFamilyMaxVersions) { 082 return ReturnCode.SKIP; 083 } 084 085 return this.expEvaluator.evaluate(cell) ? ReturnCode.INCLUDE : ReturnCode.SKIP; 086 } 087 088 @Override 089 public void reset() throws IOException { 090 this.curFamily.unset(); 091 this.curQualifier.unset(); 092 this.curFamilyMaxVersions = 0; 093 this.curQualMetVersions = 0; 094 } 095 096 @Override 097 public boolean equals(Object obj) { 098 if (!(obj instanceof VisibilityLabelFilter)) { 099 return false; 100 } 101 if (this == obj) { 102 return true; 103 } 104 VisibilityLabelFilter f = (VisibilityLabelFilter) obj; 105 return this.expEvaluator.equals(f.expEvaluator) 106 && this.cfVsMaxVersions.equals(f.cfVsMaxVersions); 107 } 108 109 @Override 110 public int hashCode() { 111 return Objects.hash(this.expEvaluator, this.cfVsMaxVersions); 112 } 113}