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