日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hadoop安全实践

發布時間:2025/3/21 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hadoop安全实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在2014年初,我們將線上使用的 Hadoop 1.0 集群切換到?Hadoop 2.2.0 穩定版, 與此同時部署了 Hadoop 的安全認證。本文主要介紹在 Hadoop 2.2.0 上部署安全認證的方案調研實施以及相應的解決方法。

背景

集群安全措施相對薄弱

最早部署Hadoop集群時并沒有考慮安全問題,隨著集群的不斷擴大, 各部門對集群的使用需求增加,集群安全問題就顯得頗為重要。說到安全問題,一般包括如下方面:

  • 用戶認證(Authentication)
    即是對用戶身份進行核對, 確認用戶即是其聲明的身份, 這里包括用戶和服務的認證。

  • 用戶授權(Authorization)
    即是權限控制,對特定資源, 特定訪問用戶進行授權或拒絕訪問。用戶授權是建立再用戶認證的基礎上, 沒有可靠的用戶認證談不上用戶授權。

未開啟安全認證時,Hadoop 是以客戶端提供的用戶名作為用戶憑證, 一般即是發起任務的Unix 用戶。一般線上機器部署服務會采用統一賬號,當以統一賬號部署集群時,所有執行 Hadoop 任務的用戶都是集群的超級管理員,容易發生誤操作。即便是以管理員賬號部署集群,惡意用戶在客戶端仍然可以冒充管理員賬號執行。

集群整體升級到 hadoop 2.0

2013年10月份 Hadoop 2.2.0 發布,作為 Apache Hadoop 2.X 的 GA 版本。我們考慮將集群整體升級 Hadoop 2.2.0,進入 yarn 時代。與此同時,我們計劃在升級過程中一并把集群安全工作做到位,主要基于以下考慮:

  • 與升級工作一樣,安全同樣是基礎工作,把安全搞好會方便我們后續的工作,否則會成為下一個阻礙。
  • 所謂基礎工作,就是越往后改動越難的工作,目前不做,將來依賴更多,開展代價更大。

綜上,我們的需求是在低版本hadoop升級到Yarn的過程中部署Hadoop安全認證,做好認證之后我們可以在此之上開啟適當的權限控制(hdfs, 隊列)。

方案調研

在方案調研之前先明確以下安全實踐的原則,如下:

  • 做為一個后端服務平臺,部署安全的主要目的是防止用戶誤操作導致的事故(比如誤刪數據,誤操作等)
  • 做安全是為了開放,開放的前提是保證基本的安全,數據安全與平臺安全
  • 在保證安全的前提下,盡量簡化運維

分析我們遇到的問題,這里我們需要調研:

  • 賬號拆分與相應管理方案
  • 開啟 Hadoop 安全認證
  • 客戶端針對安全認證的相應調整

賬號拆分與相應管理方案

集群賬號管理

原先我們使用單一賬號作為集群管理員,且這一賬號為線上統一登錄賬號, 這存在極大的安全隱患。我們需要使用特殊賬號來管理集群。這里涉及的問題是,我們需要幾個運維賬號呢?
一種簡單的做法是使用一個特殊運維賬號(比如 hadoop),?CDH?和?Apache官方?都推薦按服務劃分分賬號來啟動集群:

User:GroupDaemons
hdfs:hadoopNameNode, Secondary NameNode, Checkpoint Node, Backup Node, DataNode
yarn:hadoopResourceManager, NodeManager
mapred:hadoopMapReduce JobHistory Server

考慮到精細化控制可以有效避免誤操作,這里我們遵循官方的建議使用多賬號。
在從單一運維賬號遷移到多個賬號部署時,需要考慮相關文件權限問題,包括本地以及hdfs兩部分,這可以在安全部署上線時完成相應改動。

用戶賬號管理

美團很多小組都有使用 Hadoop 來進行大數據處理需求, 故需要一定程度的多租戶環境, 這里主要考慮其中的數據和操作的權限問題。hdfs 本身僅提供類 Unix 的權限系統, 默認的組概念也相對雞肋。鑒于此,在多用戶的管理上可以有簡單粗暴的方案:

不同組有各自的根目錄,使用不同的賬號,對組內文件有全部權限。不同組之間相互不能訪問數據(除非手動修改)。

在一個集中的數據倉庫環境下,又要生產各個部門的統計數據的話,上述策略不夠靈活。目前Cloudera 有一個精細化權限控制的解決方案?sentry, 支持 Role based 的權限管理。由于其定制化較高,不方便使用, 故暫未考慮。

開啟 Hadoop 安全認證

Hadoop 的安全認證是基于?Kerberos?實現的。 Kerberos 是一個網絡身份驗證協議,用戶只需輸入身份驗證信息,驗證通過獲取票據即可訪問多個接入 Kerberos 的服務, 機器的單點登錄也可以基于此協議完成的。 Hadoop 本身并不創建用戶賬號,而是使用 Kerberos 協議來進行用戶身份驗證,從Kerberos憑證中的用戶信息獲取用戶賬號, 這樣一來跟實際用戶運行的賬號也無關。

這里我們從 YARN 上的 MR 任務提交過程簡單說明一下:

  • 用戶執行任務前,先通過KDC認證自己,獲取TGT(Ticket Granting Ticket)。KDC是 Kerberos 認證的中心服務,存儲用戶和服務的認證信息。
  • 用戶通過 TGT 向 KDC 請求訪問服務的Ticket, KDC 生成 session key 后一并發給客戶端。
  • 客戶端通過 service ticket 向服務認證自己,完成身份認證。
  • 完成身份認證后客戶端向服務請求若干token供后續任務執行認證使用(比如 HDFS NameNode Delegation Token, YARN ResourceManager Delegation Token)
  • 客戶端連同獲取到的 token 一并提交任務,后續任務執行使用 token 進行來自服務的認證
  • 從上可以看出,出于性能的考慮,Hadoop 安全認證體系中僅在用戶跟服務通信以及各個服務之間通信適用 Kerberos 認證,在用戶認證后任務執行,訪問服務,讀取/寫入數據等均采用特定服務(NameNode, Resource Manager)發起訪問token,讓需求方憑借 token 訪問相應服務和數據。這里 token 的傳遞,認證以及更新不做深入討論。

    關于開啟 Hadoop 安全認證,?Cloudera?有詳細的文檔介紹。由于自身環境以及部署運維的考慮,最終的部署方案有些許出入, 一一說明。

    Kerberos 部署

    Hadoop 安全認證需要一個 Kerberos 集群,?部署 Kerberos?需要部署KDC。 由于我們的環境中使用?freeIPA?進行主機認證相關的權限控制,已經集成 Kerberos 服務, 故不需要另外部署。
    Kerberos 相關的運維操作, 比如添加用戶,服務,導出keytab,均可以通過 ipa 相關接口來進行。

    Container 的選擇

    從上圖可以看出用戶發起的任務是在特定的容器(Container)內執行的, 一開始我們考慮使用DefaultContainer 而不是官方推薦的 LinuxContainer, 缺點是對任務之間的物理隔離以及防范惡意任務方面會有缺陷, 不過方便部署,使用LinuxContainer需要在集群各臺機器上部署用戶賬號。
    實際測試發現由于MAPREDUCE-5208的引入,在 hadoop 2.2.0 上開啟安全認證后無法使用 DefaultContainer。
    這里不希望對代碼有過多定制化的修改,我們考慮還是使用 LinuxContainer, 需要解決一下問題:

    • 用戶賬號創建
      我們需要在集群內添加所有可能的任務發起用戶賬號。借助 freeipa 的統一的用戶管理 , 我們只需要在 freeipa 上添加相應用戶即可。
    • container-executor 和 container-executor.cfg 的部署
      container-executor?作為Yarn 的 container 執行程序,有一系列的權限要求:

      Be owned by root
      Be owned by a group that contains only the user running the YARN daemons
      Be setuid
      Be group readable and executable

      配置 container-executor.cfg 不僅需要是owned by root,且其所在目錄同樣需要?owned by root。這兩者都給自動化部署帶來不便,鑒于此部分比較獨立且基本不會改變,我們可以將其加入集群機器的 puppet 管理當中。

    DataNode 啟動方式

    CDH 推薦的datanode 的啟動方式需要使用低端口并且使用jsvc發布, 在運維方面也不太方便。這里我們通過配置ignore.secure.ports.for.testing=true來啟動datanode, 規避這些約束。

    客戶端針對安全認證的相應調整

    集群開啟安全認證之后, 依賴集群的客戶端(腳本, 服務)都需要做相應修改,不過改動基本無異。大部分服務都已包括對 Kerberos 認證的相應處理, 基本不需要修改。

    這里首先得說明一下開啟安全認證后的認證方式:

    • 使用密碼認證
      使用用戶密碼通過kinit認證, 獲取到的TGT存在本地憑證緩存當中, 供后續訪問服務認證使用。一般在交互式訪問中使用。
    • 使用?keytab?認證
      用戶通過導出的keytab 可以免密碼進行用戶認證, 后續步驟一致。一般在應用程序中配置使用。

    Kerberos 憑證(ticket) 有兩個屬性,?ticket_lifetime?和?renew_lifetime。其中?ticket_lifetime?表明憑證生效的時限,一般為24小時。在憑證失效前部分憑證可以延期失效時間(即Renewable),?renew_lifetime?表明憑證最長可以被延期的時限,一般為一個禮拜。當憑證過期之后,對安全認證的服務的后續訪問則會失敗。這里第一個問題就是如何處理憑證過期。

    憑證過期處理策略

    在最早的?Security features for Hadoop?設計中提出這樣的假設:

    A Hadoop job will run no longer than 7 days (configurable) on a MapReduce cluster or accessing HDFS from the job will fail.

    對于一般的任務, 24小時甚至延遲到一周的憑證時限是足夠充分的。所以大部分時間我們只需要在執行操作之前使用 kinit 認證一遍,再起后臺任務進行周期性憑證更新即可。

    while true ; do kinit -R; sleep $((3600 * 6)) ; done &

    不過對于需要常駐的訪問Hadoop集群的服務來說,上述假設就不成立了。這時候我們可以

  • 擴大?ticket_lifetime?和?renew_lifetime?時限
    擴大憑證存活時限可以解決此問題,但由于Kerberos跟我們線上用戶登陸認證綁定,會帶來安全隱患,故不方便修改。

  • 定期重新進行kinit 認證更新憑證
    不僅僅是定期延長認證時間,可以直接定期重新認證以延長憑證有限期限。一般我們需要導出 keytab 來進行定期認證的操作。

  • Hadoop 將 Kerberos 認證部分進行了一定的封裝,實際上并不需要那么復雜, 這里重點可以看看UserGroupInformation?這個類。

    UserGroupInformation

    UserGroupInformation?這個類在?JAAS?框架上封裝了 Hadoop 的用戶信息, 更確切地說是對 Subject 做了一層封裝。

    UserGroupInformation(Subject subject) {this.subject = subject;this.user = subject.getPrincipals(User.class).iterator().next();this.isKeytab = !subject.getPrivateCredentials(KerberosKey.class).isEmpty();this.isKrbTkt = !subject.getPrivateCredentials(KerberosTicket.class).isEmpty();}

    JAAS 是 Java 認證和授權服務(Java Authentication and Authorization Service)的縮寫, 主要包含以下幾個實體:

    • Subject
      Subject 是一個不可繼承的實體類,它標志一個請求的來源, 包含相關的憑證標識(Principal) 和 公開和私有的憑據(Credential)。
    • Principal
      憑證標識,認證成功后,一個 Subject 可以被關聯多個Principal。
    • Credential
      憑據,有公有憑據以及私有憑據。

    JAAS的認證過程如下:

  • An application instantiates a LoginContext.
  • The LoginContext consults a Configuration to load all of the LoginModules configured for that application.
  • The application invokes the LoginContext's login method.
  • The login method invokes all of the loaded LoginModules. Each LoginModule attempts to authenticate the subject. Upon success, LoginModules associate relevant Principals and credentials with a Subject object that represents the subject being authenticated.
  • The LoginContext returns the authentication status to the application.
  • If authentication succeeded, the application retrieves the Subject from the LoginContext.
  • 需要認證的代碼片段可以包裝在?doPrivileged?當中, 可以直接使用?Subject.doAs?方法,支持嵌套。

    在安全模式下,UGI 支持不同LoginContext 配置, 均是通過 HadoopConfiguration 類動態產生:

    • hadoop-user-kerberos
      使用kerberos緩存憑證登陸的配置,?useTicketCache?置為 true.
    • hadoop-keytab-kerberos
      使用keytab登陸的配置,?useKeyTab?置為 true.

    UGI 當中有多處認證, getLoginUser 方法使用?hadoop-user-kerberos?配置認證:

  • 通過配置生成 LoginContext
  • 調用 LoginContext.login 方法完成登陸, 通過 ticket cache 中憑證完成登陸
  • 判斷是否需要其他用戶身份(proxy user)執行
  • 將?HADOOP_TOKEN_FILE_LOCATION?中的 token 加入 Credentials 集合當中
  • 另起一個線程做周期性的憑證更新?spawnAutoRenewalThreadForUserCreds
  • 步驟5可以看出當我們存在憑證后并不需要主動做周期性地憑證更新。

    而 loginUserFromKeytab 方法使用?hadoop-kerberos?配置認證:

  • 通過配置生成 LoginContext
  • 調用 LoginContext.login 方法完成登陸, 使用keytab完成登陸
  • loginUserFromKeytab 沒有對憑證做周期的更新, 那怎么保證憑證不會過期呢?

  • 在訪問集群執行相關操作前, 可以調用?checkTGTAndReloginFromKeytab?來嘗試更新憑證(實際上是重新登陸了)
  • 在憑證過期時,創建 IPC 失敗會觸發調用?reloginFromKeytab?來重新登陸
  • Client.java

    private synchronized void handleSaslConnectionFailure(final int currRetries, final int maxRetries, final Exception ex,final Random rand, final UserGroupInformation ugi) throws IOException,InterruptedException {ugi.doAs(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws IOException, InterruptedException {final short MAX_BACKOFF = 5000;closeConnection();disposeSasl();if (shouldAuthenticateOverKrb()) {if (currRetries < maxRetries) {if(LOG.isDebugEnabled()) {LOG.debug("Exception encountered while connecting to "+ "the server : " + ex);}// try re-loginif (UserGroupInformation.isLoginKeytabBased()) {UserGroupInformation.getLoginUser().reloginFromKeytab();} else {UserGroupInformation.getLoginUser().reloginFromTicketCache();}

    可見如果是使用 keytab 認證的話,認證是長期有效的。

    從上述代碼中可以看到,不論是否是keytab認證,創建IPC失敗均會嘗試重新登陸。

    基于keytab 的Kerberos認證方式

    為了讓用戶免于記憶密碼,我們可以考慮導出并交付keytab給相關用戶(前提是用戶數量可控, 比如是以虛擬用戶為單位)。
    這樣,用戶的Hadoop任務認證方式可以有:

    • 直接使用 keytab kinit 之后訪問
    • 或者調用?loginUserFromKeytab?完成登錄,然后將代碼片段包裹在 UGI 的?doAs?方法當中執行

    上線部署

    確定了部署方案之后, 我們在升級 hadoop 版本的同時完成了安全認證的部署。在部署和使用中我們遇到若干問題,這里一一說明。

    JCE 部署

    開啟安全認證時發現 Kerberos 認證不通過:

    Client failed to SASL authenticate: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)]

    由于我們部署的Kerberos默認使用 AES-256 加密, 需要在Hadoop環境(集群以及客戶端)上安裝?Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy File, 否則Kerberos認證不通過。可以通過此?gist?驗證改動是否生效。此步驟可以添加到puppet當中。

    SNN getimage 返回 NPE

    開啟安全認證發現 SNN 持續由于 getimage 報錯NPE 退出, 相關錯誤如下。

    2013-12-29 23:56:19572 DEBUG org.apache.hadoop.security.authentication.server.AuthenticationFilter: Request [http://XXX.com:50070/getimage?getimage=1&txid=8627&storageInfo=-47:200271 8265:0:CID-3dce02cb-a1c2-4ab8-8b12-f23bbefd7bcc] triggering authentication 2013-12-29 23:56:19580 WARN org.apache.hadoop.security.authentication.server.AuthenticationFilter: Authentication exception: GSSException: Failure unspecified at GSS-API level (Mechanism level: Specifiedversion of key is not available (44)) org.apache.hadoop.security.authentication.client.AuthenticationException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Specified version of key is not available (44))at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.authenticate(KerberosAuthenticationHandler.java:360)at org.apache.hadoop.security.authentication.server.AuthenticationFilter.doFilter(AuthenticationFilter.java:349)

    根據報錯信息?Specified version of key is not available?發現是由于同一個 HTTP 憑證被導出多遍導致之前的keytab中的憑證失效了,重新生成部署所需的 keytab 即可。
    這里的提醒就是不要重復導出相同的憑證, 以防止已經分發使用的keytab中的憑證失效。

    Balancer 執行過長導致認證過期

    在部署安全認證之后, 我們對hdfs數據進行 balance 就需要預先認證一下再執行, 這樣就會遇到我們之前說的認證期限的問題。
    這里有兩種方式可以解決此問題:

    • 添加外部定時任務重新認證, 刷新憑證緩存, 延遲憑證有效期限。
    • 可以寫一個小代碼對 balance 的入口?org.apache.hadoop.hdfs.server.balancer.Balancer?進行一點封裝,將其封裝在一個 doAs 當中, 類似?hue 中的 SudoFsShell 一樣的思路

    sssd 服務認證異常

    sssd?是指我們用于線上登陸認證的一個底層服務,在過去一段時間內經常出現問題退出,導致用戶登錄動作hang住,進而導致相關任務執行失敗。部署Hadoop安全認證之后相關 kerberos 認證也走這個服務,增大了服務異常退出的概率。目前看起來sssd服務問題是由于系統版本過低sssd服務代碼有bug導致,解決方案最方便的是升級系統或切換服務到新的機器。

    "KDC can't fulfill requested option while renewing credentials"

    應用執行日志偶爾會報如下錯誤:

    2014-03-12 21:30:03593 WARN security.UserGroupInformation (UserGroupInformation.java:run(794)) - Exception encountered while running the renewal command. Aborting renew thread. org.apache.hadoop.util.Shell$ExitCodeException: kinit(v5): KDC can't fulfill requested option while renewing credentials

    表示 UGI的憑證更新線程失敗退出了。目前HADOOP-10041?記錄了此問題,主要原因是由于憑證無法更新導致, 一般不需要特殊處理。

    參考資料

    • Hadoop, Hbase, Zookeeper安全實踐
    • YARN & HDFS2 安裝和配置Kerberos
    • CDH4 Security Guide
    • Kerberos , the network authentication protocol
    • Kerberos Overview
    • Hadoop Kerberos安全機制介紹
    • Security Hadoop is here
    • Hadoop Security Analysis
    • The Role of Delegation Tokens in Apache Hadoop Security
    from:?http://tech.meituan.com/hadoop-security-practice.html

    總結

    以上是生活随笔為你收集整理的Hadoop安全实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。