Package org.apache.hadoop.hbase.security.visibility

Source Code of org.apache.hadoop.hbase.security.visibility.VisibilityUtils

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.security.visibility;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.Tag;
import org.apache.hadoop.hbase.TagType;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.io.util.StreamUtils;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.MultiUserAuthorizations;
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.UserAuthorizations;
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabel;
import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest;
import org.apache.hadoop.hbase.util.ByteStringer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.util.ReflectionUtils;

import com.google.protobuf.InvalidProtocolBufferException;

/**
* Utility method to support visibility
*/
@InterfaceAudience.Private
public class VisibilityUtils {

  public static final String VISIBILITY_LABEL_GENERATOR_CLASS =
      "hbase.regionserver.scan.visibility.label.generator.class";
  public static final byte VISIBILITY_TAG_TYPE = TagType.VISIBILITY_TAG_TYPE;
  public static final byte VISIBILITY_EXP_SERIALIZATION_TAG_TYPE =
      TagType.VISIBILITY_EXP_SERIALIZATION_TAG_TYPE;
  public static final String SYSTEM_LABEL = "system";
  public static final Tag VIS_SERIALIZATION_TAG = new Tag(VISIBILITY_EXP_SERIALIZATION_TAG_TYPE,
      VisibilityConstants.SORTED_ORDINAL_SERIALIZATION_FORMAT);
  private static final String COMMA = ",";

  /**
   * Creates the labels data to be written to zookeeper.
   * @param existingLabels
   * @return Bytes form of labels and their ordinal details to be written to zookeeper.
   */
  public static byte[] getDataToWriteToZooKeeper(Map<String, Integer> existingLabels) {
    VisibilityLabelsRequest.Builder visReqBuilder = VisibilityLabelsRequest.newBuilder();
    for (Entry<String, Integer> entry : existingLabels.entrySet()) {
      VisibilityLabel.Builder visLabBuilder = VisibilityLabel.newBuilder();
      visLabBuilder.setLabel(ByteStringer.wrap(Bytes.toBytes(entry.getKey())));
      visLabBuilder.setOrdinal(entry.getValue());
      visReqBuilder.addVisLabel(visLabBuilder.build());
    }
    return ProtobufUtil.prependPBMagic(visReqBuilder.build().toByteArray());
  }

  /**
   * Creates the user auth data to be written to zookeeper.
   * @param userAuths
   * @return Bytes form of user auths details to be written to zookeeper.
   */
  public static byte[] getUserAuthsDataToWriteToZooKeeper(Map<String, List<Integer>> userAuths) {
    MultiUserAuthorizations.Builder builder = MultiUserAuthorizations.newBuilder();
    for (Entry<String, List<Integer>> entry : userAuths.entrySet()) {
      UserAuthorizations.Builder userAuthsBuilder = UserAuthorizations.newBuilder();
      userAuthsBuilder.setUser(ByteStringer.wrap(Bytes.toBytes(entry.getKey())));
      for (Integer label : entry.getValue()) {
        userAuthsBuilder.addAuth(label);
      }
      builder.addUserAuths(userAuthsBuilder.build());
    }
    return ProtobufUtil.prependPBMagic(builder.build().toByteArray());
  }

  /**
   * Reads back from the zookeeper. The data read here is of the form written by
   * writeToZooKeeper(Map<byte[], Integer> entries).
   *
   * @param data
   * @return Labels and their ordinal details
   * @throws DeserializationException
   */
  public static List<VisibilityLabel> readLabelsFromZKData(byte[] data)
      throws DeserializationException {
    if (ProtobufUtil.isPBMagicPrefix(data)) {
      int pblen = ProtobufUtil.lengthOfPBMagic();
      try {
        VisibilityLabelsRequest request = VisibilityLabelsRequest.newBuilder()
            .mergeFrom(data, pblen, data.length - pblen).build();
        return request.getVisLabelList();
      } catch (InvalidProtocolBufferException e) {
        throw new DeserializationException(e);
      }
    }
    return null;
  }

  /**
   * Reads back User auth data written to zookeeper.
   * @param data
   * @return User auth details
   * @throws DeserializationException
   */
  public static MultiUserAuthorizations readUserAuthsFromZKData(byte[] data)
      throws DeserializationException {
    if (ProtobufUtil.isPBMagicPrefix(data)) {
      int pblen = ProtobufUtil.lengthOfPBMagic();
      try {
        MultiUserAuthorizations multiUserAuths = MultiUserAuthorizations.newBuilder()
            .mergeFrom(data, pblen, data.length - pblen).build();
        return multiUserAuths;
      } catch (InvalidProtocolBufferException e) {
        throw new DeserializationException(e);
      }
    }
    return null;
  }

  public static List<ScanLabelGenerator> getScanLabelGenerators(Configuration conf)
      throws IOException {
    // There can be n SLG specified as comma separated in conf
    String slgClassesCommaSeparated = conf.get(VISIBILITY_LABEL_GENERATOR_CLASS);
    // We have only System level SLGs now. The order of execution will be same as the order in the
    // comma separated config value
    List<ScanLabelGenerator> slgs = new ArrayList<ScanLabelGenerator>();
    if (StringUtils.isNotEmpty(slgClassesCommaSeparated)) {
      String[] slgClasses = slgClassesCommaSeparated.split(COMMA);
      for (String slgClass : slgClasses) {
        Class<? extends ScanLabelGenerator> slgKlass;
        try {
          slgKlass = (Class<? extends ScanLabelGenerator>) conf.getClassByName(slgClass.trim());
          slgs.add(ReflectionUtils.newInstance(slgKlass, conf));
        } catch (ClassNotFoundException e) {
          throw new IOException(e);
        }
      }
    }
    // If the conf is not configured by default we need to have one SLG to be used
    // ie. DefaultScanLabelGenerator
    if (slgs.isEmpty()) {
      slgs.add(ReflectionUtils.newInstance(DefaultScanLabelGenerator.class, conf));
    }
    return slgs;
  }

  /**
   * Get the list of visibility tags in the given cell
   * @param cell - the cell
   * @param tags - the tags array that will be populated if
   * visibility tags are present
   * @return true if the tags are in sorted order.
   */
  public static boolean getVisibilityTags(Cell cell, List<Tag> tags) {
    boolean sortedOrder = false;
    Iterator<Tag> tagsIterator = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(),
        cell.getTagsLengthUnsigned());
    while (tagsIterator.hasNext()) {
      Tag tag = tagsIterator.next();
      if (tag.getType() == VisibilityUtils.VISIBILITY_EXP_SERIALIZATION_TAG_TYPE) {
        int serializationVersion = tag.getBuffer()[tag.getTagOffset()];
        if (serializationVersion == VisibilityConstants.VISIBILITY_SERIALIZATION_VERSION) {
          sortedOrder = true;
          continue;
        }
      }
      if (tag.getType() == VisibilityUtils.VISIBILITY_TAG_TYPE) {
        tags.add(tag);
      }
    }
    return sortedOrder;
  }

  /**
   * Checks if the cell has a visibility tag
   * @param cell
   * @return true if found, false if not found
   */
  public static boolean isVisibilityTagsPresent(Cell cell) {
    Iterator<Tag> tagsIterator = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(),
        cell.getTagsLengthUnsigned());
    while (tagsIterator.hasNext()) {
      Tag tag = tagsIterator.next();
      if (tag.getType() == VisibilityUtils.VISIBILITY_TAG_TYPE) {
        return true;
      }
    }
    return false;
  }

  /**
   * Checks for the matching visibility labels in the delete mutation and
   * the cell in consideration
   * @param cell - the cell
   * @param visibilityTagsInDeleteCell - that list of tags in the delete mutation
   * (the specified Cell Visibility)
   * @return true if matching tags are found
   */
  public static boolean checkForMatchingVisibilityTags(Cell cell,
      List<Tag> visibilityTagsInDeleteCell) {
    List<Tag> tags = new ArrayList<Tag>();
    boolean sortedTags = getVisibilityTags(cell, tags);
    if (tags.size() == 0) {
      // Early out if there are no tags in the cell
      return false;
    }
    if (sortedTags) {
      return checkForMatchingVisibilityTagsWithSortedOrder(visibilityTagsInDeleteCell, tags);
    } else {
      try {
        return checkForMatchingVisibilityTagsWithOutSortedOrder(cell, visibilityTagsInDeleteCell);
      } catch (IOException e) {
        // Should not happen
        throw new RuntimeException("Exception while sorting the tags from the cell", e);
      }
    }
  }

  private static boolean checkForMatchingVisibilityTagsWithOutSortedOrder(Cell cell,
      List<Tag> visibilityTagsInDeleteCell) throws IOException {
    List<List<Integer>> sortedDeleteTags = sortTagsBasedOnOrdinal(
        visibilityTagsInDeleteCell);
    List<List<Integer>> sortedTags = sortTagsBasedOnOrdinal(cell);
    return compareTagsOrdinals(sortedDeleteTags, sortedTags);
  }

  private static boolean checkForMatchingVisibilityTagsWithSortedOrder(
      List<Tag> visibilityTagsInDeleteCell, List<Tag> tags) {
    boolean matchFound = false;
    if ((visibilityTagsInDeleteCell.size()) != tags.size()) {
      // If the size does not match. Definitely we are not comparing the
      // equal tags.
      // Return false in that case.
      return matchFound;
    }
    for (Tag tag : visibilityTagsInDeleteCell) {
      matchFound = false;
      for (Tag givenTag : tags) {
        if (Bytes.equals(tag.getBuffer(), tag.getTagOffset(), tag.getTagLength(),
            givenTag.getBuffer(), givenTag.getTagOffset(), givenTag.getTagLength())) {
          matchFound = true;
          break;
        }
      }
    }
    return matchFound;
  }

  private static List<List<Integer>> sortTagsBasedOnOrdinal(Cell cell) throws IOException {
    Iterator<Tag> tagsItr = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(),
        cell.getTagsLengthUnsigned());
    List<List<Integer>> fullTagsList = new ArrayList<List<Integer>>();
    while (tagsItr.hasNext()) {
      Tag tag = tagsItr.next();
      if (tag.getType() == VisibilityUtils.VISIBILITY_TAG_TYPE) {
        getSortedTagOrdinals(fullTagsList, tag);
      }
    }
    return fullTagsList;
  }

  private static List<List<Integer>> sortTagsBasedOnOrdinal(List<Tag> tags) throws IOException {
    List<List<Integer>> fullTagsList = new ArrayList<List<Integer>>();
    for (Tag tag : tags) {
      if (tag.getType() == VisibilityUtils.VISIBILITY_TAG_TYPE) {
        getSortedTagOrdinals(fullTagsList, tag);
      }
    }
    return fullTagsList;
  }

  private static void getSortedTagOrdinals(List<List<Integer>> fullTagsList, Tag tag)
      throws IOException {
    List<Integer> tagsOrdinalInSortedOrder = new ArrayList<Integer>();
    int offset = tag.getTagOffset();
    int endOffset = offset + tag.getTagLength();
    while (offset < endOffset) {
      Pair<Integer, Integer> result = StreamUtils.readRawVarint32(tag.getBuffer(), offset);
      tagsOrdinalInSortedOrder.add(result.getFirst());
      offset += result.getSecond();
    }
    Collections.sort(tagsOrdinalInSortedOrder);
    fullTagsList.add(tagsOrdinalInSortedOrder);
  }

  private static boolean compareTagsOrdinals(List<List<Integer>> tagsInDeletes,
      List<List<Integer>> tags) {
    boolean matchFound = false;
    if (tagsInDeletes.size() != tags.size()) {
      return matchFound;
    } else {
      for (List<Integer> deleteTagOrdinals : tagsInDeletes) {
        matchFound = false;
        for (List<Integer> tagOrdinals : tags) {
          if (deleteTagOrdinals.equals(tagOrdinals)) {
            matchFound = true;
            break;
          }
        }
      }
      return matchFound;
    }
  }
}
TOP

Related Classes of org.apache.hadoop.hbase.security.visibility.VisibilityUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.