View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.thrift2;
20  
21  import java.nio.ByteBuffer;
22  import java.security.PrivilegedExceptionAction;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import javax.security.auth.Subject;
29  import javax.security.auth.login.AppConfigurationEntry;
30  import javax.security.auth.login.Configuration;
31  import javax.security.auth.login.LoginContext;
32  import javax.security.sasl.Sasl;
33  
34  import org.apache.hadoop.hbase.thrift2.generated.TColumnValue;
35  import org.apache.hadoop.hbase.thrift2.generated.TGet;
36  import org.apache.hadoop.hbase.thrift2.generated.THBaseService;
37  import org.apache.hadoop.hbase.thrift2.generated.TPut;
38  import org.apache.hadoop.hbase.thrift2.generated.TResult;
39  import org.apache.thrift.protocol.TBinaryProtocol;
40  import org.apache.thrift.protocol.TProtocol;
41  import org.apache.thrift.transport.TFramedTransport;
42  import org.apache.thrift.transport.TSaslClientTransport;
43  import org.apache.thrift.transport.TSocket;
44  import org.apache.thrift.transport.TTransport;
45  
46  public class DemoClient {
47  
48    private static String host = "localhost";
49    private static int port = 9090;
50    private static boolean secure = false;
51  
52    public static void main(String[] args) throws Exception {
53      System.out.println("Thrift2 Demo");
54      System.out.println("Usage: DemoClient [host=localhost] [port=9090] [secure=false]");
55      System.out.println("This demo assumes you have a table called \"example\" with a column family called \"family1\"");
56  
57      // use passed in arguments instead of defaults
58      if (args.length >= 1) {
59        host = args[0];
60      }
61      if (args.length >= 2) {
62        port = Integer.parseInt(args[1]);
63      }
64      if (args.length >= 3) {
65        secure = Boolean.parseBoolean(args[2]);
66      }
67  
68      final DemoClient client = new DemoClient();
69      Subject.doAs(getSubject(),
70        new PrivilegedExceptionAction<Void>() {
71          @Override
72          public Void run() throws Exception {
73            client.run();
74            return null;
75          }
76        });
77    }
78  
79    public void run() throws Exception {
80      int timeout = 10000;
81      boolean framed = false;
82  
83      TTransport transport = new TSocket(host, port, timeout);
84      if (framed) {
85        transport = new TFramedTransport(transport);
86      } else if (secure) {
87        /**
88         * The Thrift server the DemoClient is trying to connect to
89         * must have a matching principal, and support authentication.
90         *
91         * The HBase cluster must be secure, allow proxy user.
92         */
93        Map<String, String> saslProperties = new HashMap<String, String>();
94        saslProperties.put(Sasl.QOP, "auth-conf,auth-int,auth");
95        transport = new TSaslClientTransport("GSSAPI", null,
96          "hbase", // Thrift server user name, should be an authorized proxy user.
97          host, // Thrift server domain
98          saslProperties, null, transport);
99      }
100 
101     TProtocol protocol = new TBinaryProtocol(transport);
102     // This is our thrift client.
103     THBaseService.Iface client = new THBaseService.Client(protocol);
104 
105     // open the transport
106     transport.open();
107 
108     ByteBuffer table = ByteBuffer.wrap("example".getBytes());
109 
110     TPut put = new TPut();
111     put.setRow("row1".getBytes());
112 
113     TColumnValue columnValue = new TColumnValue();
114     columnValue.setFamily("family1".getBytes());
115     columnValue.setQualifier("qualifier1".getBytes());
116     columnValue.setValue("value1".getBytes());
117     List<TColumnValue> columnValues = new ArrayList<TColumnValue>();
118     columnValues.add(columnValue);
119     put.setColumnValues(columnValues);
120 
121     client.put(table, put);
122 
123     TGet get = new TGet();
124     get.setRow("row1".getBytes());
125 
126     TResult result = client.get(table, get);
127 
128     System.out.print("row = " + new String(result.getRow()));
129     for (TColumnValue resultColumnValue : result.getColumnValues()) {
130       System.out.print("family = " + new String(resultColumnValue.getFamily()));
131       System.out.print("qualifier = " + new String(resultColumnValue.getFamily()));
132       System.out.print("value = " + new String(resultColumnValue.getValue()));
133       System.out.print("timestamp = " + resultColumnValue.getTimestamp());
134     }
135 
136     transport.close();
137   }
138 
139   static Subject getSubject() throws Exception {
140     if (!secure) return new Subject();
141 
142     /*
143      * To authenticate the DemoClient, kinit should be invoked ahead.
144      * Here we try to get the Kerberos credential from the ticket cache.
145      */
146     LoginContext context = new LoginContext("", new Subject(), null,
147       new Configuration() {
148         @Override
149         public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
150           Map<String, String> options = new HashMap<String, String>();
151           options.put("useKeyTab", "false");
152           options.put("storeKey", "false");
153           options.put("doNotPrompt", "true");
154           options.put("useTicketCache", "true");
155           options.put("renewTGT", "true");
156           options.put("refreshKrb5Config", "true");
157           options.put("isInitiator", "true");
158           String ticketCache = System.getenv("KRB5CCNAME");
159           if (ticketCache != null) {
160             options.put("ticketCache", ticketCache);
161           }
162           options.put("debug", "true");
163 
164           return new AppConfigurationEntry[]{
165               new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
166                   AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
167                   options)};
168         }
169       });
170     context.login();
171     return context.getSubject();
172   }
173 }