sqoop 使用過程中提供密碼的幾種方式詳解

概述

本博文基於Sqoop1.4.6版本講解在使用Sqoop工具從關係型數據庫中導入導出數據過程中管理關係型數據庫密碼的幾種方式。

這裏我們通過講解sqoopimport命令來說明:

sqoop import在實際應用中主要用於將數據從關係型數據庫(比如MySQL,SqlServer,Oracle等)導入到大數據集羣文件系統(比如HDFS文件系統,HBase列式存儲系統以及Hive數據倉庫等)。關係型數據庫中的每行數據在HDFS上表示爲單獨的記錄。如果數據保存爲textfile文件格式,那麼數據庫表的一行記錄對應textfile文件中一行記錄;如果數據導入到HBase中,關係型數據庫表中的一行記錄被作爲一個Put對象進行緩存和持久化。

我們首先來看一下Sqoop官方網站對於sqoop import工具的一些通用的命令參數:


我們可以看到在導入命令使用中關於密碼使用的三種方式:
(1) --password
(2) -P
(3) --password-file

關於密碼使用的第四種方法我們可以通過sqoop 官方網站的以下描述得到:











根據英文描述,從Hadoop2.6.0開始提供了單獨的API用於將密碼存儲和應用分離。具體的API就是hadoop credential, 關於該命令在密碼生成和存儲上的使用,我們將在下文具體說明。從上面的英文介紹,我們得到第四種密碼使用方式:
(4) –password-alias

到此,我們整理出來現有的四種密碼提供和使用方式,接下來我們配合腳本示例來詳細說明每種方式的使用和注意事項。

方式一:--password [明文方式]

--password:基於這個通用控制參數的使用方法最簡單也最不安全,這種方式通過在命令中以明文的方式提供數據庫訪問密碼來訪問數據庫進而將數據從關係型數據導入到HDFS上。

因爲密碼以明文的方式出現在sqoop import命令中,所以其他用戶可以通過ps 命令讀取到你的數據庫訪問密碼,所以這種方式也是最不安全的方式。

這裏我們舉個例子來說明如何使用:
sqoop import \
	--connect jdbc:mysql://mdp5:3306/precmarket \
	--username sqoop \
	--password sqoop \
	--table d_area \
	--as-textfile \
	--target-dir /sqoop_training/d_area_1.textfile \
	--compress \
	--null-string '\\N' \
	--null-non-string '\\N' \
	--num-mappers 1 \
	--delete-target-dir \
	--direct

方式二:-P [交互方式]

-P:這個參數指定命令執行通過交互式方式提示用戶輸入密碼。

這種方式避免了數據庫密碼直接以明文的形式出現,因而防止了密碼的泄露,但是它只能在終端狀態下使用,一般也只用於命令行中提交一些簡單的測試任務,無法應用於後臺自動執行這樣的應用場景下。

這裏我們舉個例子來說明如何使用:

sqoop import \
--connect jdbc:mysql://mdp5:3306/precmarket \
--username sqoop \
-P \
--table d_area \
--as-textfile \
--target-dir /sqoop_training/d_area_1.textfile \
--compress \
--null-string '\\N' \
--null-non-string '\\N' \
--num-mappers 1 \
--delete-target-dir \
--direct
命令提交以後會出現提示輸入密碼,輸入密碼後回車,命令提交成功。

方式三:--password-file [文件方式]

--password-file:這個控制參數通過指定一個保存密碼的文件路徑來提供數據庫數據訪問密碼。

這種方式是比較安全的密碼提供方式之一,但是需要保證以下三點:
(1) 保存密碼的文件創建並保存在當前用戶的home目錄下
(2) 保存密碼的文件的訪問權限設置成400,即只有當前用戶自己可以訪問,其他用戶無任何訪問權限
(3) 由於Sqoop將讀取保存密碼的文件中的全部內容作爲密碼。這將包括任何尾部的空白字符,比如換行或者其他編輯器默認添加的結尾字符。所以需要保證存入該文件中的字符完完整整是你的密碼字符串。我們可以通過使用echo –n “secret” > password.file 方式來去除尾部多餘的空白結束符。

這裏需要強調一點的是,sqoop在執行命令過程中將讀取密碼文件傳遞到MapReduce 集羣,這個保存密碼的文件可以保存在本地也可以保存在HDFS上;如果是本地需要在指定—password-file參數時加file:/// 路徑前綴;如果是保存在HDFS上,在指定—password-file參數值時需要指定hdfs://文件系統路徑前綴。具體例子如下:

(1) 首先我們創建用於保存密碼的文件password.file, 我們假設當前用戶是mnt, 數據庫密碼是sqoop。
    
[mnt /home/mnt] echo –n “mnt_password” > /home/mnt/.password.file
(2) 如果是基於本地密碼文件的方式,命令使用如下:

sqoop import \
--connect jdbc:mysql://mdp5:3306/precmarket \
--username sqoop \
--password-file file:///home/mnt/.password.file \
--as-textfile \
--target-dir /sqoop_training/d_area_1_password_file.textfile \
--compress \
--null-string '\\N' \
--null-non-string '\\N' \
--num-mappers 4 \
--delete-target-dir \
--direct \
--query 'select * from d_area where id > 10000 and $CONDITIONS' \
--split-by 'id'
(3) 首先我們將步驟(1) 中創建的.password.file 上傳到hfds的/usr/mnt目錄下
      
[mnt /home/mnt] hadoop fs –copyFromLocal /home/mnt/.password.file /user/mnt
(4) 基於HDFS文件系統指定密碼文件的方式,命令如下:
     
sqoop import \
--connect jdbc:mysql://mdp5:3306/precmarket \
--username sqoop \
--password-file hdfs://user/mnt/.password.file \
--as-textfile \
--target-dir /sqoop_training/d_area_1_password_file.textfile \
--compress \
--null-string '\\N' \
--null-non-string '\\N' \
--num-mappers 4 \
--delete-target-dir \
--direct \
--query 'select * from d_area where id > 10000 and $CONDITIONS' \
--split-by 'id'

方式四:--password-alias [別名方式]

Hadoop2.6.0 之後的版本提供了一個API用於將密碼存儲和應用程序分離。這個API被稱爲憑證提供的API,並提供了一個新的命令行工具來管理密碼及其別名。密碼及其別名一起被存儲在密碼保護的密鑰庫中。密鑰庫密碼可以通過控制檯交互提示輸入提供給應用程序或者作爲代碼中的變量來提供。

一旦在密鑰庫中存儲了密碼及其別名,在應用程序中便可以選擇使用別名代替實際密碼,並在運行時解析別名以使用密碼。這樣只有別名在配置文件或者命令中是可見的,這樣可以防止密碼的泄露。Sqoop基於Hadoop提供的這種功能豐富了密碼管理功能,只要底層hadoop支持通過使用密鑰庫來管理密碼及其別名,那麼通過使用—password-alias 指定密碼對應的別名即可。

這裏我們通過腳本來說明具體的步驟:
(1) 首先生成jceks文件,支持本地存儲模式和HDFS文件系統存儲模式:
  • 本地密鑰庫模式:
hadoop credential create mydb.password.alias -provider localjceks://file/tmp/mysql.password.jceks
命令行提示輸入密碼:sqoop [Enter]
確認密碼:sqoop [Enter]
完成。
  • HDFS密鑰庫模式:
  (i) 上傳本地生成好的密鑰庫到HDFS指定目錄:

hadoop fs -copyFromLocal /tmp/mysql.password.jceks  /user/sqoop/ 
 (ii)  命令直接生成基於HDFS存儲的密鑰庫:

hadoop credential create mysql.pwd.alias -provider jceks://hdfs/user/password/mysql.pwd.jceks
命令行提示輸入密碼:sqoop [Enter]
確認密碼:sqoop [Enter]
完成。

(2) 通過使用—password-alias參數指定密碼對應的別名來指定sqoop import任務:
  •  本地密鑰庫模式:
sqoop import \
-Dhadoop.security.credential.provider.path=localjceks://file/tmp/mysql.password.jceks \
--connect 'jdbc:mysql://mdp5:3306/precmarket' \
--table d_area  \
--username sqoop \
--password-alias mydb.password.alias \
--delete-target-dir \
--target-dir /sqoop_training/2.textfile
  •  HDFS密鑰庫存儲模式:
sqoop import \
-Dhadoop.security.credential.provider.path=jceks://hdfs/user/sqoop/mysql.password.jceks \
--connect 'jdbc:mysql://mdp5:3306/precmarket' \
--table d_area  \
--username sqoop \
--password-alias mydb.password.alias \
--delete-target-dir \
--target-dir /sqoop_training/3.textfile
注意:基於HDFS文件系統生成的密鑰庫,在執行sqoop import任務時會出現以下異常:


Sqoop 任務執行日誌:空指針異常


其實這個是Hadoop的一個bug,jira上的參考地址是:
https://issues.apache.org/jira/browse/HADOOP-13353

所以在使用密鑰庫提供密碼的方式時,需要注意以下幾點:
(1)基於HDFS存儲密鑰庫的方式,需要在本地生成密鑰庫之後上傳到hdfs指定目錄,之後通過—password-alias指定具體的密碼別名,使用-Dhadoop.security.credential.provider.path 控制參數來指定hdfs文件系統上的密鑰庫文件路徑
(2)基於本地文件系統存儲密鑰庫方式。
通過—password-alias 指定具體的密碼別名,使用-Dhadoop.security.credential.provider.path 控制參數來指定本地文件系統上的密鑰庫文件路徑

參考資料:Sqoop官網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章