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 static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
21  
22  import java.io.IOException;
23  import java.util.Map;
24  import java.util.regex.Pattern;
25  
26  import org.apache.hadoop.hbase.util.ByteStringer;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.hbase.classification.InterfaceStability;
29  import org.apache.hadoop.conf.Configuration;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.client.HTable;
32  import org.apache.hadoop.hbase.client.coprocessor.Batch;
33  import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
34  import org.apache.hadoop.hbase.ipc.ServerRpcController;
35  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsRequest;
36  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
37  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsRequest;
38  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.ListLabelsResponse;
39  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.SetAuthsRequest;
40  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabel;
41  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest;
42  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
43  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsService;
44  import org.apache.hadoop.hbase.util.Bytes;
45  
46  import com.google.protobuf.ServiceException;
47  
48  /**
49   * Utility client for doing visibility labels admin operations.
50   */
51  @InterfaceAudience.Public
52  @InterfaceStability.Unstable
53  public class VisibilityClient {
54  
55    /**
56     * Utility method for adding label to the system.
57     * 
58     * @param conf
59     * @param label
60     * @return VisibilityLabelsResponse
61     * @throws Throwable
62     */
63    public static VisibilityLabelsResponse addLabel(Configuration conf, final String label)
64        throws Throwable {
65      return addLabels(conf, new String[] { label });
66    }
67  
68    /**
69     * Utility method for adding labels to the system.
70     * 
71     * @param conf
72     * @param labels
73     * @return VisibilityLabelsResponse
74     * @throws Throwable
75     */
76    public static VisibilityLabelsResponse addLabels(Configuration conf, final String[] labels)
77        throws Throwable {
78      HTable ht = null;
79      try {
80        ht = new HTable(conf, LABELS_TABLE_NAME.getName());
81        Batch.Call<VisibilityLabelsService, VisibilityLabelsResponse> callable = 
82            new Batch.Call<VisibilityLabelsService, VisibilityLabelsResponse>() {
83          ServerRpcController controller = new ServerRpcController();
84          BlockingRpcCallback<VisibilityLabelsResponse> rpcCallback = 
85              new BlockingRpcCallback<VisibilityLabelsResponse>();
86  
87          public VisibilityLabelsResponse call(VisibilityLabelsService service) throws IOException {
88            VisibilityLabelsRequest.Builder builder = VisibilityLabelsRequest.newBuilder();
89            for (String label : labels) {
90              if (label.length() > 0) {
91                VisibilityLabel.Builder newBuilder = VisibilityLabel.newBuilder();
92                newBuilder.setLabel(ByteStringer.wrap(Bytes.toBytes(label)));
93                builder.addVisLabel(newBuilder.build());
94              }
95            }
96            service.addLabels(controller, builder.build(), rpcCallback);
97            VisibilityLabelsResponse response = rpcCallback.get();
98            if (controller.failedOnException()) {
99              throw controller.getFailedOn();
100           }
101           return response;
102         }
103       };
104       Map<byte[], VisibilityLabelsResponse> result = ht.coprocessorService(
105           VisibilityLabelsService.class, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
106           callable);
107       return result.values().iterator().next(); // There will be exactly one region for labels
108                                                 // table and so one entry in result Map.
109     } finally {
110       if (ht != null) {
111         ht.close();
112       }
113     }
114   }
115 
116   /**
117    * Sets given labels globally authorized for the user.
118    * @param conf
119    * @param auths
120    * @param user
121    * @return VisibilityLabelsResponse
122    * @throws Throwable
123    */
124   public static VisibilityLabelsResponse setAuths(Configuration conf, final String[] auths,
125       final String user) throws Throwable {
126     return setOrClearAuths(conf, auths, user, true);
127   }
128 
129   /**
130    * @param conf
131    * @param user
132    * @return labels, the given user is globally authorized for.
133    * @throws Throwable
134    */
135   public static GetAuthsResponse getAuths(Configuration conf, final String user) throws Throwable {
136     HTable ht = null;
137     try {
138       ht = new HTable(conf, LABELS_TABLE_NAME.getName());
139       Batch.Call<VisibilityLabelsService, GetAuthsResponse> callable = 
140           new Batch.Call<VisibilityLabelsService, GetAuthsResponse>() {
141         ServerRpcController controller = new ServerRpcController();
142         BlockingRpcCallback<GetAuthsResponse> rpcCallback = 
143             new BlockingRpcCallback<GetAuthsResponse>();
144 
145         public GetAuthsResponse call(VisibilityLabelsService service) throws IOException {
146           GetAuthsRequest.Builder getAuthReqBuilder = GetAuthsRequest.newBuilder();
147           getAuthReqBuilder.setUser(ByteStringer.wrap(Bytes.toBytes(user)));
148           service.getAuths(controller, getAuthReqBuilder.build(), rpcCallback);
149           GetAuthsResponse response = rpcCallback.get();
150           if (controller.failedOnException()) {
151             throw controller.getFailedOn();
152           }
153           return response;
154         }
155       };
156       Map<byte[], GetAuthsResponse> result = ht.coprocessorService(VisibilityLabelsService.class,
157           HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
158       return result.values().iterator().next(); // There will be exactly one region for labels
159                                                 // table and so one entry in result Map.
160     } finally {
161       if (ht != null) {
162         ht.close();
163       }
164     }
165   }
166 
167   /**
168    * Removes given labels from user's globally authorized list of labels.
169    * @param conf
170    * @param auths
171    * @param user
172    * @return VisibilityLabelsResponse
173    * @throws Throwable
174    */
175   public static VisibilityLabelsResponse clearAuths(Configuration conf, final String[] auths,
176       final String user) throws Throwable {
177     return setOrClearAuths(conf, auths, user, false);
178   }
179 
180   private static VisibilityLabelsResponse setOrClearAuths(Configuration conf, final String[] auths,
181       final String user, final boolean setOrClear) throws IOException, ServiceException, Throwable {
182     HTable ht = null;
183     try {
184       ht = new HTable(conf, LABELS_TABLE_NAME.getName());
185       Batch.Call<VisibilityLabelsService, VisibilityLabelsResponse> callable = 
186           new Batch.Call<VisibilityLabelsService, VisibilityLabelsResponse>() {
187         ServerRpcController controller = new ServerRpcController();
188         BlockingRpcCallback<VisibilityLabelsResponse> rpcCallback = 
189             new BlockingRpcCallback<VisibilityLabelsResponse>();
190 
191         public VisibilityLabelsResponse call(VisibilityLabelsService service) throws IOException {
192           SetAuthsRequest.Builder setAuthReqBuilder = SetAuthsRequest.newBuilder();
193           setAuthReqBuilder.setUser(ByteStringer.wrap(Bytes.toBytes(user)));
194           for (String auth : auths) {
195             if (auth.length() > 0) {
196               setAuthReqBuilder.addAuth(ByteStringer.wrap(Bytes.toBytes(auth)));
197             }
198           }
199           if (setOrClear) {
200             service.setAuths(controller, setAuthReqBuilder.build(), rpcCallback);
201           } else {
202             service.clearAuths(controller, setAuthReqBuilder.build(), rpcCallback);
203           }
204           VisibilityLabelsResponse response = rpcCallback.get();
205           if (controller.failedOnException()) {
206             throw controller.getFailedOn();
207           }
208           return response;
209         }
210       };
211       Map<byte[], VisibilityLabelsResponse> result = ht.coprocessorService(
212           VisibilityLabelsService.class, HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY,
213           callable);
214       return result.values().iterator().next(); // There will be exactly one region for labels
215                                                 // table and so one entry in result Map.
216     } finally {
217       if (ht != null) {
218         ht.close();
219       }
220     }
221   }
222 
223   /**
224    * Retrieve the list of visibility labels defined in the system.
225    * @param conf
226    * @param regex  The regular expression to filter which labels are returned.
227    * @return labels The list of visibility labels defined in the system.
228    * @throws Throwable
229    */
230   public static ListLabelsResponse listLabels(Configuration conf, final String regex)
231       throws Throwable {
232     HTable ht = null;
233     try {
234       ht = new HTable(conf, LABELS_TABLE_NAME.getName());
235       Batch.Call<VisibilityLabelsService, ListLabelsResponse> callable =
236           new Batch.Call<VisibilityLabelsService, ListLabelsResponse>() {
237         ServerRpcController controller = new ServerRpcController();
238         BlockingRpcCallback<ListLabelsResponse> rpcCallback =
239             new BlockingRpcCallback<ListLabelsResponse>();
240         public ListLabelsResponse call(VisibilityLabelsService service) throws IOException {
241          ListLabelsRequest.Builder listAuthLabelsReqBuilder = ListLabelsRequest.newBuilder();
242           if (regex != null) {
243             // Compile the regex here to catch any regex exception earlier.
244             Pattern pattern = Pattern.compile(regex);
245             listAuthLabelsReqBuilder.setRegex(pattern.toString());
246           }
247           service.listLabels(controller, listAuthLabelsReqBuilder.build(), rpcCallback);
248           ListLabelsResponse response = rpcCallback.get();
249           if (controller.failedOnException()) {
250             throw controller.getFailedOn();
251           }
252           return response;
253         }
254       };
255       Map<byte[], ListLabelsResponse> result =
256           ht.coprocessorService(VisibilityLabelsService.class, HConstants.EMPTY_BYTE_ARRAY,
257             HConstants.EMPTY_BYTE_ARRAY, callable);
258       return result.values().iterator().next(); // There will be exactly one region for labels
259       // table and so one entry in result Map.
260     }
261     finally {
262       if (ht != null) {
263         ht.close();
264       }
265     }
266   }
267 }