View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.visibility;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Map.Entry;
25  
26  import com.google.protobuf.HBaseZeroCopyByteString;
27  
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.hadoop.classification.InterfaceAudience;
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.hbase.TagType;
32  import org.apache.hadoop.hbase.exceptions.DeserializationException;
33  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
34  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.MultiUserAuthorizations;
35  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.UserAuthorizations;
36  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabel;
37  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest;
38  import org.apache.hadoop.hbase.util.Bytes;
39  import org.apache.hadoop.util.ReflectionUtils;
40  
41  import com.google.protobuf.InvalidProtocolBufferException;
42  
43  /**
44   * Utility method to support visibility
45   */
46  @InterfaceAudience.Private
47  public class VisibilityUtils {
48  
49    public static final String VISIBILITY_LABEL_GENERATOR_CLASS = 
50        "hbase.regionserver.scan.visibility.label.generator.class";
51    public static final byte VISIBILITY_TAG_TYPE = TagType.VISIBILITY_TAG_TYPE;
52    public static final String SYSTEM_LABEL = "system";
53    private static final String COMMA = ",";
54  
55    /**
56     * Creates the labels data to be written to zookeeper.
57     * @param existingLabels
58     * @return Bytes form of labels and their ordinal details to be written to zookeeper.
59     */
60    public static byte[] getDataToWriteToZooKeeper(Map<String, Integer> existingLabels) {
61      VisibilityLabelsRequest.Builder visReqBuilder = VisibilityLabelsRequest.newBuilder();
62      for (Entry<String, Integer> entry : existingLabels.entrySet()) {
63        VisibilityLabel.Builder visLabBuilder = VisibilityLabel.newBuilder();
64        visLabBuilder.setLabel(HBaseZeroCopyByteString.wrap(Bytes.toBytes(entry.getKey())));
65        visLabBuilder.setOrdinal(entry.getValue());
66        visReqBuilder.addVisLabel(visLabBuilder.build());
67      }
68      return ProtobufUtil.prependPBMagic(visReqBuilder.build().toByteArray());
69    }
70  
71    /**
72     * Creates the user auth data to be written to zookeeper.
73     * @param userAuths
74     * @return Bytes form of user auths details to be written to zookeeper.
75     */
76    public static byte[] getUserAuthsDataToWriteToZooKeeper(Map<String, List<Integer>> userAuths) {
77      MultiUserAuthorizations.Builder builder = MultiUserAuthorizations.newBuilder();
78      for (Entry<String, List<Integer>> entry : userAuths.entrySet()) {
79        UserAuthorizations.Builder userAuthsBuilder = UserAuthorizations.newBuilder();
80        userAuthsBuilder.setUser(HBaseZeroCopyByteString.wrap(Bytes.toBytes(entry.getKey())));
81        for (Integer label : entry.getValue()) {
82          userAuthsBuilder.addAuth(label);
83        }
84        builder.addUserAuths(userAuthsBuilder.build());
85      }
86      return ProtobufUtil.prependPBMagic(builder.build().toByteArray());
87    }
88  
89    /**
90     * Reads back from the zookeeper. The data read here is of the form written by
91     * writeToZooKeeper(Map<byte[], Integer> entries).
92     * 
93     * @param data
94     * @return Labels and their ordinal details
95     * @throws DeserializationException
96     */
97    public static List<VisibilityLabel> readLabelsFromZKData(byte[] data)
98        throws DeserializationException {
99      if (ProtobufUtil.isPBMagicPrefix(data)) {
100       int pblen = ProtobufUtil.lengthOfPBMagic();
101       try {
102         VisibilityLabelsRequest request = VisibilityLabelsRequest.newBuilder()
103             .mergeFrom(data, pblen, data.length - pblen).build();
104         return request.getVisLabelList();
105       } catch (InvalidProtocolBufferException e) {
106         throw new DeserializationException(e);
107       }
108     }
109     return null;
110   }
111 
112   /**
113    * Reads back User auth data written to zookeeper.
114    * @param data
115    * @return User auth details
116    * @throws DeserializationException
117    */
118   public static MultiUserAuthorizations readUserAuthsFromZKData(byte[] data) 
119       throws DeserializationException {
120     if (ProtobufUtil.isPBMagicPrefix(data)) {
121       int pblen = ProtobufUtil.lengthOfPBMagic();
122       try {
123         MultiUserAuthorizations multiUserAuths = MultiUserAuthorizations.newBuilder()
124             .mergeFrom(data, pblen, data.length - pblen).build();
125         return multiUserAuths;
126       } catch (InvalidProtocolBufferException e) {
127         throw new DeserializationException(e);
128       }
129     }
130     return null;
131   }
132 
133   public static List<ScanLabelGenerator> getScanLabelGenerators(Configuration conf)
134       throws IOException {
135     // There can be n SLG specified as comma separated in conf
136     String slgClassesCommaSeparated = conf.get(VISIBILITY_LABEL_GENERATOR_CLASS);
137     // We have only System level SLGs now. The order of execution will be same as the order in the
138     // comma separated config value
139     List<ScanLabelGenerator> slgs = new ArrayList<ScanLabelGenerator>();
140     if (StringUtils.isNotEmpty(slgClassesCommaSeparated)) {
141       String[] slgClasses = slgClassesCommaSeparated.split(COMMA);
142       for (String slgClass : slgClasses) {
143         Class<? extends ScanLabelGenerator> slgKlass;
144         try {
145           slgKlass = (Class<? extends ScanLabelGenerator>) conf.getClassByName(slgClass.trim());
146           slgs.add(ReflectionUtils.newInstance(slgKlass, conf));
147         } catch (ClassNotFoundException e) {
148           throw new IOException(e);
149         }
150       }
151     }
152     // If the conf is not configured by default we need to have one SLG to be used
153     // ie. DefaultScanLabelGenerator
154     if (slgs.isEmpty()) {
155       slgs.add(ReflectionUtils.newInstance(DefaultScanLabelGenerator.class, conf));
156     }
157     return slgs;
158   }
159 }