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.mapreduce;
019
020import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_FAMILY;
021import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
022import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABEL_QUALIFIER;
023
024import java.io.IOException;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.hbase.TableNotFoundException;
030import org.apache.hadoop.hbase.Tag;
031import org.apache.hadoop.hbase.client.Connection;
032import org.apache.hadoop.hbase.client.ConnectionFactory;
033import org.apache.hadoop.hbase.client.Result;
034import org.apache.hadoop.hbase.client.ResultScanner;
035import org.apache.hadoop.hbase.client.Scan;
036import org.apache.hadoop.hbase.client.Table;
037import org.apache.hadoop.hbase.security.visibility.Authorizations;
038import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
039import org.apache.hadoop.hbase.security.visibility.VisibilityLabelOrdinalProvider;
040import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
041import org.apache.hadoop.hbase.util.Bytes;
042import org.apache.yetus.audience.InterfaceAudience;
043import org.slf4j.Logger;
044import org.slf4j.LoggerFactory;
045
046/**
047 * This implementation creates tags by expanding expression using label ordinal. Labels will be
048 * serialized in sorted order of it's ordinal.
049 */
050@InterfaceAudience.Private
051public class DefaultVisibilityExpressionResolver implements VisibilityExpressionResolver {
052  private static final Logger LOG =
053    LoggerFactory.getLogger(DefaultVisibilityExpressionResolver.class);
054
055  private Configuration conf;
056  private final Map<String, Integer> labels = new HashMap<>();
057
058  @Override
059  public Configuration getConf() {
060    return this.conf;
061  }
062
063  @Override
064  public void setConf(Configuration conf) {
065    this.conf = conf;
066  }
067
068  @Override
069  public void init() {
070    // Reading all the labels and ordinal.
071    // This scan should be done by user with global_admin privileges.. Ensure that it works
072    Table labelsTable = null;
073    Connection connection = null;
074    try {
075      connection = ConnectionFactory.createConnection(conf);
076      try {
077        labelsTable = connection.getTable(LABELS_TABLE_NAME);
078      } catch (IOException e) {
079        LOG.error("Error opening 'labels' table", e);
080        return;
081      }
082      Scan scan = new Scan();
083      scan.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
084      scan.addColumn(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
085      ResultScanner scanner = null;
086      try {
087        scanner = labelsTable.getScanner(scan);
088        Result next = null;
089        while ((next = scanner.next()) != null) {
090          byte[] row = next.getRow();
091          byte[] value = next.getValue(LABELS_TABLE_FAMILY, LABEL_QUALIFIER);
092          labels.put(Bytes.toString(value), Bytes.toInt(row));
093        }
094      } catch (TableNotFoundException e) {
095        // Table not found. So just return
096        return;
097      } catch (IOException e) {
098        LOG.error("Error scanning 'labels' table", e);
099      } finally {
100        if (scanner != null) {
101          scanner.close();
102        }
103      }
104    } catch (IOException ioe) {
105      LOG.error("Failed reading 'labels' tags", ioe);
106      return;
107    } finally {
108      if (labelsTable != null) {
109        try {
110          labelsTable.close();
111        } catch (IOException ioe) {
112          LOG.warn("Error closing 'labels' table", ioe);
113        }
114      }
115      if (connection != null) {
116        try {
117          connection.close();
118        } catch (IOException ioe) {
119          LOG.warn("Failed close of temporary connection", ioe);
120        }
121      }
122    }
123  }
124
125  @Override
126  public List<Tag> createVisibilityExpTags(String visExpression) throws IOException {
127    VisibilityLabelOrdinalProvider provider = new VisibilityLabelOrdinalProvider() {
128      @Override
129      public int getLabelOrdinal(String label) {
130        Integer ordinal = null;
131        ordinal = labels.get(label);
132        if (ordinal != null) {
133          return ordinal.intValue();
134        }
135        return VisibilityConstants.NON_EXIST_LABEL_ORDINAL;
136      }
137
138      @Override
139      public String getLabel(int ordinal) {
140        // Unused
141        throw new UnsupportedOperationException(
142          "getLabel should not be used in VisibilityExpressionResolver");
143      }
144    };
145    return VisibilityUtils.createVisibilityExpTags(visExpression, true, false, null, provider);
146  }
147}