Kerberos之Beeline客户端参数解析

  在Kerberos认证体系下,Beeline客户端连接HiveServer2的参数一般是这样的:beeline -u "jdbc:hive2://<URL>:10000/default;principal=hive/_HOST@<realm>;hive.server2.proxy.user=<username>"。在初学Kerberos的时候,关于连接参数中的principal始终是百思不得其解,为什么一定要写成principal=hive/_HOST@<realm>这种形式?hive换成其他的可不可以?中间的这个_HOST又是怎么确定的?这个principal到底是用户的principal还是服务的principal?
  这些问题的答案可能对于大部分人来说是显而易见的,然而对于我这只小菜就来说就很容易想不明白。而我对于感兴趣的问题又喜欢一追到底,有点钻牛角尖儿。
  下面我来说一下针对上述问题,自己一些浅显的理解。可能不对,欢迎大家批评指正。

HiveConnection的openTransport()方法解析

  接上文Kyuubi服务源码解析:FrontendService,文末提到了HiveConnection的openTransport()方法,来看一下openTransport()做了什么。

HiveConnection.java:

  • openTransport()方法
  private void openTransport() throws Exception {
    assumeSubject =
        JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE_FROM_SUBJECT.equals(sessConfMap
            .get(JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE));
    //一般来说是调用createBinaryTransport()方法
    transport = isHttpTransportMode() ? createHttpTransport() : createBinaryTransport();
    if (!transport.isOpen()) {
      transport.open();
    }
    logZkDiscoveryMessage("Connected to " + connParams.getHost() + ":" + connParams.getPort());
  }
  • createBinaryTransport()方法
  /**
   * Create transport per the connection options
   * Supported transport options are:
   *   - SASL based transports over
   *      + Kerberos
   *      + Delegation token
   *      + SSL
   *      + non-SSL
   *   - Raw (non-SASL) socket
   *
   *   Kerberos and Delegation token supports SASL QOP configurations
   * @throws SQLException, TTransportException
   */
  private TTransport createBinaryTransport() throws SQLException, TTransportException {
    try {
      TTransport socketTransport = createUnderlyingTransport();
      // handle secure connection if specified
      if (!JdbcConnectionParams.AUTH_SIMPLE.equals(sessConfMap.get(JdbcConnectionParams.AUTH_TYPE))) {
        // If Kerberos
        Map<String, String> saslProps = new HashMap<String, String>();
        SaslQOP saslQOP = SaslQOP.AUTH;
        if (sessConfMap.containsKey(JdbcConnectionParams.AUTH_QOP)) {
          ***省略部分代码***
        } else {
          // If the client did not specify qop then just negotiate the one supported by server
          saslProps.put(Sasl.QOP, "auth-conf,auth-int,auth");
        }
        saslProps.put(Sasl.SERVER_AUTH, "true");
        //即JDBC连接参数中“principal=hive/_HOST@realms”
        if (sessConfMap.containsKey(JdbcConnectionParams.AUTH_PRINCIPAL)) {
          transport = KerberosSaslHelper.getKerberosTransport(
              //这里的principal获取的是JDBC连接参数中的principal
              sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), host,
              socketTransport, saslProps, assumeSubject);
        } else {
          // If there's a delegation token available then use token based connection
          String tokenStr = getClientDelegationToken(sessConfMap);
          if (tokenStr != null) {
            transport = KerberosSaslHelper.getTokenTransport(tokenStr,
                host, socketTransport, saslProps);
          } else {
            // we are using PLAIN Sasl connection with user/password
            String userName = getUserName();
            String passwd = getPassword();
            // Overlay the SASL transport on top of the base socket transport (SSL or non-SSL)
            transport = PlainSaslHelper.getPlainTransport(userName, passwd, socketTransport);
          }
        }
      } else {
        // Raw socket connection (non-sasl)
        transport = socketTransport;
      }
    } catch (SaslException e) {
      throw new SQLException("Could not create secure connection to "
          + jdbcUriString + ": " + e.getMessage(), " 08S01", e);
    }
    return transport;
  }

该方法内部调用了KerberosSaslHelper.getKerberosTransport()方法。
KerberosSaslHelper.getKerberosTransport()中的调用关系如下所示:

KerberosSaslHelper.getKerberosTransport()方法

createClientTransport()方法定义:
createClientTransport方法

  从createClientTransport()方法的注释中,可以看出principalConfig(也就是JDBC连接参数中的“principal=hive/_HOST@realms”)指的是服务器的principal,就是JDBC客户端请求服务的principal,当然这个服务的principal是在hive-site.xml中已经配置好的(见如下两张图)。那么这里的_HOST就应为请求的服务所在机器的hostname,因为如果principal中的_HOST对应的机器都没有开启要请求的服务,又怎么访问服务呢?所以Beeline客户端连接参数中principal的_HOST所指的服务器一定要确认开启了要请求的服务
hive-site.xml中metastore服务Kerberos配置

hive-site.xml中hiveserver2服务Kerberos配置

  上面两张图中metastore和hiveserver2服务的名字都叫hive,难免有些困惑,这个我后续会调研清楚。
  上面啰嗦了一大堆,可能理解的不对,但初衷还是要讲明白JDBC连接参数中principal的真正含义。这对于在HiveServer2或者Kyuubi业务场景下理解Kerberos认证流程至关重要。

  • HadoopThriftAuthBridge.Client的createClientTransport()方法
    public TTransport createClientTransport(
        String principalConfig, String host,
        String methodStr, String tokenStrForm, final TTransport underlyingTransport,
        final Map<String, String> saslProps) throws IOException {
      final AuthMethod method = AuthMethod.valueOf(AuthMethod.class, methodStr);

      TTransport saslTransport = null;
      switch (method) {
      case DIGEST:
        ***省略部分代码***

      case KERBEROS:
        String serverPrincipal = SecurityUtil.getServerPrincipal(principalConfig, host);
        final String names[] = SaslRpcServer.splitKerberosName(serverPrincipal);
        if (names.length != 3) {
          throw new IOException(
              "Kerberos principal name does NOT have the expected hostname part: "
                  + serverPrincipal);
        }
        try {
          return UserGroupInformation.getCurrentUser().doAs(
              new PrivilegedExceptionAction<TUGIAssumingTransport>() {
                @Override
                public TUGIAssumingTransport run() throws IOException {
                  TTransport saslTransport = new TSaslClientTransport(
                    method.getMechanismName(),
                    null,
                    names[0], names[1],
                    saslProps, null,
                    underlyingTransport);
                  return new TUGIAssumingTransport(saslTransport, UserGroupInformation.getCurrentUser());
                }
              });
        } catch (InterruptedException | SaslException se) {
          throw new IOException("Could not instantiate SASL transport", se);
        }

      default:
        throw new IOException("Unsupported authentication method: " + method);
      }
    }

这段代码中你看到了什么?UGI。对,UGI。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容