LoginSignup
3

More than 5 years have passed since last update.

[Python] kerberos認証でHDFSへリクエストする

Last updated at Posted at 2018-08-01

概要

pythonで、kerberos認証でhdfsに接続する方法についてです。

pythonのhdfsパッケージを利用してリクエストする方法と、
hdfsパッケージを使わずにrequestsパッケージでWebHDFS REST APIを叩く方法の2つを書きます。

  1. 事前準備(共通)
  2. hdfs + requests_kerberosを使う方法
  3. requestsパッケージでWebHDFS REST APIを叩く方法

以下の2つの環境で動作確認済です。

  • Python 2.7.5
  • Python 3.6.5

ケルベロス認証とは

手順に入る前に、ケルベロス認証について、以下のサイトがとても参考になるので貼っておきます。
http://www.infraexpert.com/study/security18.html

表をそのまま拝借しますが、以下の用語は覚えておいたほうがよいです。

ケルベロスの用語 説明
KDC(Key Distribution Center) サーバとユーザに関する信頼関係の情報を一括管理する中央データベース
AS(Authentication Server) 認証サーバ。ユーザからの認証を受け付けるサーバ
TGS(Ticket Granting Server) チケット発行サーバ。各サーバを利用するためのチケットを発行するサーバ
プリンシパル(principal) KDCが認証を行うユーザやサーバのこと
レルム(realm) 同じKDCの配下にあるシステムをグループとして定義する論理ネットワーク

事前準備(共通)

こちらは、どちらの方法でも必要になります。

以下のファイルが必要になります。

  • kerberos認証を利用するためのkeytabファイル
  • SSLのCA証明書が必要な場合はCA証明書(必要な場合のみ)

krb5のインストール

kerberosのインストールをします。

$ sudo yum install -y krb5-workstation
$ sudo yum install -y krb5-devel
$ sudo yum install -y krb5-libs

設定ファイル

/etc/krb5/krb5.confの設定を行います。

/etc/krb5.conf
[logging]
 # kdcのログ
 kdc = FILE:/var/log/krb5kdc.log
 # admin_serverのログ
 admin_server = FILE:/var/log/kadmind.log
 # その他のログ
 default = FILE:/var/log/krb5libs.log

# Kerberos 認証のデフォルト値を設定します。default_realm を設定する必要があります。
[libdefaults]
 default_realm = MYDOMAIN.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

# 各 Kerberos レルムの KDC を設定します。1 つのレルムに複数の kdc を設定できます。
# デフォルトのポート 88 を使用する場合はポートの指定を省略できます。
# ドメイン名を大文字にしたものをレルム名にするのが慣例です。
[realms]
 MYDOMAIN.COM = {
  kdc = mykdc.mydomain.com
  # administrative server。通常はKerberosのマスターサーバー
  admin_server = mykdc.mydomain.com
  # プリンシパルとlocal user nameのマッピングルールを作れる
    auth_to_local = RULE:[1:$1@$0](.*@MYDOMAIN.COM)s/@.*//
 }

 # 複数ある場合は更に記述
 EXAMPLE.COM = {
  kdc = kerberos.example.com
  admin_server = kerberos.example.com
 }


# ドメインやホストをrealmと結びつける設定。
# Active Directory ドメインを Kerberos レルムにマップします。
[domain_realm]
 .example.com = MYDOMAIN.COM
 example.com = MYDOMAIN.COM

各項目の説明をだいたい書いてありますが、詳しくは以下のサイトを参考にしてください。

kinit(kerobers認証をする)

以下のコマンドを叩くと、kdc.conf ファイルに指定されている最長有効期限値 (max_life)の時間、kerberos認証されている状態が続きます。
定期的に実行するために、cronなどに設定しておくと便利です。

$ kinit -kt /secrets/keytab username

SSL CA証明書のパスを通す(必要な場合のみ)

接続にCA証明書が必要な場合は、以下の環境変数名でパスを設定しておく必要があります。

$ export REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt

これで事前準備は完了です。

hdfs + requests_kerberosを使う方法

hdfsパッケージのインストール

参考: http://hdfscli.readthedocs.io/en/latest/

hdfsパッケージ

$ pip install hdfs

kerberos認証に必要

$ pip install requests_kerberos

依存パッケージ

$ pip install requests

~/.hdfscli.cfgの設置

環境ごとに認証方式を変更したりできます。
以下の例では、prodではkerberos認証を使い、devでは使わない設定にしてあります。

参考: http://hdfscli.readthedocs.io/en/latest/api.html#module-hdfs.ext.kerberos

~/.hdfscli.cfg
# 全体的な設定
[global]
# defaultのalias
default.alias = dev
# kerberos moduleをautoloadする
autoload.modules = hdfs.ext.kerberos

# devの設定
[dev.alias]
# devのhdfsのurl
url = https://dev.namenode:port

# prodの設定
[prod.alias]
# prodのhdfsのurl
url = https://prod.namenode:port
# kerberos認証をする
client = KerberosClient
# pathを指定するときのTOP階層の定義
# この場合はhttps://prod.namenode:port/webhdfs/v1/がトップになる
root = /

サンプルコード

ディレクトリの中身を確認する処理を作ります。
以下のコードを実行することで、結果を得られます。

環境によってはSSLのSubjectAltNameWarningを表示され場合がありますが、一時的にwarningを非表示にするには、SSLのSubjectAltNameWarningを非表示にする場合は追記の部分をコメントインしてください。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import logging
import hdfs
from hdfs import Config

# SSLのSubjectAltNameWarningを非表示にする場合は追記
'''
import requests
from requests.packages.urllib3.exceptions import SubjectAltNameWarning
requests.packages.urllib3.disable_warnings(SubjectAltNameWarning)
'''

# logger
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

try:
    '''
    https://prod.namenode:port/webhdfs/v1/ の下から定義する
    ~/.hdfscli.cfgのrootの定義によって変わる
    '''
    path = 'user/sample'

    '''
    ~/.hdfscli.cfgで定義した環境のdev, prodのどちらかを入力
    prodを指定した場合、これだけでkerberos認証になる
    '''
    client = Config().get_client('prod')
    result = client.list(path)
    logger.debug(result)

except hdfs.util.HdfsError as e:
    logger.error(str(e))

requestsパッケージでWebHDFS REST APIを叩く方法

こちらはhdfsパッケージは使わずに、requestsパッケージでWebHDFS REST APIを叩く方法です。

サンプルコード

以下もディレクトリの中身を確認する処理です。
こちらを実行することで結果が得られます。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import logging
import os
import requests
from requests_kerberos import HTTPKerberosAuth

# SSLのSubjectAltNameWarningを非表示にする場合は追記
'''
from requests.packages.urllib3.exceptions import SubjectAltNameWarning
requests.packages.urllib3.disable_warnings(SubjectAltNameWarning)
'''

# logger
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)


method = 'GET'
url = 'https://prod.namenode:port/webhdfs/v1/user/sample?op=liststatus'

session = requests.Session()
response = session.request(
    method=method,
    url=url,
    timeout=60,
    headers={'content-type': 'application/octet-stream'},
    # これが必要
    auth=HTTPKerberosAuth()
)

logger.debug(response.status_code)
logger.debug(response.text)

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3