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