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.ipc;
019
020import static org.apache.hadoop.hbase.ipc.TestProtobufRpcServiceImpl.SERVICE;
021import static org.apache.hadoop.hbase.ipc.TestProtobufRpcServiceImpl.newBlockingStub;
022import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getKeytabFileForTesting;
023import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.getPrincipalForTesting;
024import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.loginKerberosPrincipal;
025import static org.apache.hadoop.hbase.security.HBaseKerberosUtils.setSecuredConfiguration;
026import static org.junit.jupiter.api.Assertions.assertTrue;
027
028import java.io.File;
029import java.net.InetSocketAddress;
030import java.util.Collections;
031import org.apache.hadoop.conf.Configuration;
032import org.apache.hadoop.hbase.HBaseTestingUtil;
033import org.apache.hadoop.hbase.HConstants;
034import org.apache.hadoop.hbase.security.HBaseKerberosUtils;
035import org.apache.hadoop.hbase.security.SecurityInfo;
036import org.apache.hadoop.hbase.security.User;
037import org.apache.hadoop.hbase.testclassification.MediumTests;
038import org.apache.hadoop.hbase.testclassification.SecurityTests;
039import org.apache.hadoop.minikdc.MiniKdc;
040import org.apache.hadoop.security.UserGroupInformation;
041import org.junit.jupiter.api.AfterAll;
042import org.junit.jupiter.api.BeforeAll;
043import org.junit.jupiter.api.BeforeEach;
044import org.junit.jupiter.api.Tag;
045import org.junit.jupiter.api.Test;
046import org.mockito.Mockito;
047
048import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
049
050import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProtos;
051import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface;
052
053@Tag(SecurityTests.TAG)
054@Tag(MediumTests.TAG)
055public class TestSecurityRpcSentBytesMetrics {
056
057  protected static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
058
059  protected static final File KEYTAB_FILE =
060    new File(TEST_UTIL.getDataTestDir("keytab").toUri().getPath());
061
062  protected static MiniKdc KDC;
063  protected static String HOST = "localhost";
064  protected static String PRINCIPAL;
065
066  protected String krbKeytab;
067  protected String krbPrincipal;
068  protected UserGroupInformation ugi;
069  protected Configuration clientConf;
070  protected Configuration serverConf;
071
072  protected static void initKDCAndConf() throws Exception {
073    KDC = TEST_UTIL.setupMiniKdc(KEYTAB_FILE);
074    PRINCIPAL = "hbase/" + HOST;
075    KDC.createPrincipal(KEYTAB_FILE, PRINCIPAL);
076    HBaseKerberosUtils.setPrincipalForTesting(PRINCIPAL + "@" + KDC.getRealm());
077    // set a smaller timeout and retry to speed up tests
078    TEST_UTIL.getConfiguration().setInt(RpcClient.SOCKET_TIMEOUT_READ, 2000000000);
079    TEST_UTIL.getConfiguration().setInt("hbase.security.relogin.maxretries", 1);
080  }
081
082  protected static void stopKDC() throws InterruptedException {
083    if (KDC != null) {
084      KDC.stop();
085    }
086  }
087
088  protected final void setUpPrincipalAndConf() throws Exception {
089    krbKeytab = getKeytabFileForTesting();
090    krbPrincipal = getPrincipalForTesting();
091    ugi = loginKerberosPrincipal(krbKeytab, krbPrincipal);
092    clientConf = new Configuration(TEST_UTIL.getConfiguration());
093    setSecuredConfiguration(clientConf);
094    serverConf = new Configuration(TEST_UTIL.getConfiguration());
095    setSecuredConfiguration(serverConf);
096  }
097
098  @BeforeAll
099  public static void setUp() throws Exception {
100    initKDCAndConf();
101  }
102
103  @AfterAll
104  public static void tearDown() throws Exception {
105    stopKDC();
106    TEST_UTIL.cleanupTestDir();
107  }
108
109  @BeforeEach
110  public void setUpTest() throws Exception {
111    setUpPrincipalAndConf();
112  }
113
114  /**
115   * This test is for HBASE-27924, before this JIRA, bytes sent by
116   * {@link NettyHBaseSaslRpcServerHandler} is ignored by {@link MetricsHBaseServer#sentBytes}.
117   */
118  @Test
119  public void test() throws Exception {
120    SecurityInfo securityInfoMock = Mockito.mock(SecurityInfo.class);
121    Mockito.when(securityInfoMock.getServerPrincipals())
122      .thenReturn(Collections.singletonList(HBaseKerberosUtils.KRB_PRINCIPAL));
123    SecurityInfo.addInfo("TestProtobufRpcProto", securityInfoMock);
124
125    NettyRpcServer rpcServer = new NettyRpcServer(null, getClass().getSimpleName(),
126      Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(SERVICE, null)),
127      new InetSocketAddress(HOST, 0), serverConf, new FifoRpcScheduler(serverConf, 1), true) {
128
129      @Override
130      public void start() {
131        metrics = Mockito.spy(metrics);
132        super.start();
133      }
134    };
135
136    rpcServer.start();
137    try (NettyRpcClient rpcClient =
138      new NettyRpcClient(clientConf, HConstants.DEFAULT_CLUSTER_ID.toString(), null, null)) {
139      BlockingInterface stub = newBlockingStub(rpcClient, rpcServer.getListenerAddress(),
140        User.create(UserGroupInformation.getCurrentUser()));
141
142      String response =
143        stub.echo(null, TestProtos.EchoRequestProto.newBuilder().setMessage("test").build())
144          .getMessage();
145      assertTrue("test".equals(response));
146    } finally {
147      rpcServer.stop();
148    }
149    Mockito.verify(rpcServer.metrics, Mockito.atLeast(2)).sentBytes(Mockito.anyLong());
150  }
151}