公司運營、BI以及財務不同部門不同人員需要hive數據查詢服務,所以需要分配不同的權限給相關人員
權限配置主要涉及兩項:
- 認證(authentication):驗證用戶所用的身份是否是對的
- 授權(authorization):驗證用戶所用身份操作是否有權限
cloudera集成的hive認證支持常用的LDAP和kerberos,授權使用的是他自家的sentry,sentry目前還處在孵化中。爲了推廣他自家的產品,屏蔽了hive的授權管理
針對我的需求,用戶統一在hue界面操作hive,分配不同表權限給不同的用戶,權限的授予只需要一個管理員賬戶;授權使用hive原生的
配置
認證配置
hive默認所有用戶都可以做權限的更改,配置爲只有管理員(如admin)才能修改權限
使用鉤子做身份攔截,如果用戶不爲admin且操作權限管理操作,拒絕,代碼示例如下:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">import</span> org.apache.commons.logging.Log; <span class="hljs-keyword">import</span> org.apache.commons.logging.LogFactory; <span class="hljs-keyword">import</span> org.apache.hadoop.hive.ql.parse.ASTNode; <span class="hljs-keyword">import</span> org.apache.hadoop.hive.ql.parse.AbstractSemanticAnalyzerHook; <span class="hljs-keyword">import</span> org.apache.hadoop.hive.ql.parse.HiveSemanticAnalyzerHookContext; <span class="hljs-keyword">import</span> org.apache.hadoop.hive.ql.parse.SemanticException; <span class="hljs-keyword">import</span> org.apache.hadoop.hive.ql.session.SessionState; <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HiveAdmin</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractSemanticAnalyzerHook</span> {</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String admin = <span class="hljs-string">"admin"</span>; <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Log LOG = LogFactory.getLog(HiveAdmin.class); <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> ASTNode <span class="hljs-title">preAnalyze</span>(HiveSemanticAnalyzerHookContext context, ASTNode ast) <span class="hljs-keyword">throws</span> SemanticException { String userName = <span class="hljs-keyword">null</span>; String Authenticator=<span class="hljs-string">"null"</span>; <span class="hljs-keyword">switch</span> (ast.getToken().getType()) { <span class="hljs-keyword">case</span> <span class="hljs-number">692</span>: <span class="hljs-comment">//grant</span> <span class="hljs-keyword">case</span> <span class="hljs-number">646</span>:<span class="hljs-comment">// CREATE ROLE amengzi;</span> <span class="hljs-keyword">case</span> <span class="hljs-number">675</span>:<span class="hljs-comment">// DROP ROLE amengzi</span> <span class="hljs-keyword">case</span> <span class="hljs-number">694</span>: <span class="hljs-comment">//GRANT ROLE amengzi to user amengzi;</span> <span class="hljs-keyword">case</span> <span class="hljs-number">793</span>:<span class="hljs-comment">// REVOKE ROLE amengzi FROM user amengzi;</span> <span class="hljs-comment">// case 647://create table test11(id string)</span> <span class="hljs-comment">// case 676://drop table test;</span> <span class="hljs-comment">// case 783://select * from test;</span> <span class="hljs-comment">// case 817://show grant</span> <span class="hljs-comment">// case 671: //drop database;</span> <span class="hljs-keyword">if</span> (SessionState.get() != <span class="hljs-keyword">null</span> && SessionState.get().getAuthenticator() != <span class="hljs-keyword">null</span>) { Authenticator = SessionState.get().getAuthenticator().toString(); userName = SessionState.get().getAuthenticator().getUserName(); } <span class="hljs-keyword">if</span> (!admin.equalsIgnoreCase(userName)) { System.out.println(<span class="hljs-string">"===================can't use ADMIN options, except"</span>); <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> SemanticException(userName + <span class="hljs-string">" can't use ADMIN options, except "</span> + admin + <span class="hljs-string">"."</span>); } <span class="hljs-keyword">break</span>; <span class="hljs-keyword">default</span>: <span class="hljs-keyword">break</span>; } <span class="hljs-keyword">int</span> tokeType=ast.getToken().getType(); LOG.error(<span class="hljs-string">"tokeType:"</span>+tokeType+<span class="hljs-string">"=======user "</span> + SessionState.get().getAuthenticator().getUserName()+<span class="hljs-string">" Authenticator "</span>+SessionState.get().getAuthenticator().toString()); System.out.println(<span class="hljs-string">"tokeType:"</span>+tokeType+<span class="hljs-string">"===================user: "</span> + SessionState.get().getAuthenticator().getUserName()+<span class="hljs-string">" Authenticator "</span>+SessionState.get().getAuthenticator().toString()); <span class="hljs-keyword">return</span> ast; <span class="hljs-comment">// return super.preAnalyze(context, ast);</span> } <span class="hljs-comment">// @Override</span> <span class="hljs-comment">// public void postAnalyze(HiveSemanticAnalyzerHookContext context,</span> <span class="hljs-comment">// List<Task<? extends Serializable>> rootTasks)</span> <span class="hljs-comment">// throws SemanticException {</span> <span class="hljs-comment">// console.printInfo("!! SimpleSemanticPreAnalyzerHook postAnalyze called !!");</span> <span class="hljs-comment">// super.postAnalyze(context, rootTasks);</span> <span class="hljs-comment">// }</span> }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li></ul>
在使用客戶端hive時,會顯示向控制檯輸出的語句,便於調試
在hue上操作時,logger的輸出會在hiveserver2日誌中輸出
授權配置
cloudera默認用org.apache.hadoop.hive.ql.parse.authorization.RestrictedHiveAuthorizationTaskFactoryImpl
替換hive的org.apache.hadoop.hive.ql.parse.authorization.HiveAuthorizationTaskFactoryImpl
做權限屏蔽,需要通過配置文件使用原生hive類
從CM界面放入以下配置於hive-site.xml 的 Hive 客戶端高級配置代碼段(安全閥)和hive-site.xml 的 HiveServer2 高級配置代碼段(安全閥)
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>hive.security.authorization.enabled<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">value</span>></span>true<span class="hljs-tag"></<span class="hljs-title">value</span>></span> <span class="hljs-tag"><<span class="hljs-title">description</span>></span>enable or disable the hive client authorization<span class="hljs-tag"></<span class="hljs-title">description</span>></span> <span class="hljs-tag"></<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>hive.security.authorization.createtable.owner.grants<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">value</span>></span>ALL<span class="hljs-tag"></<span class="hljs-title">value</span>></span> <span class="hljs-tag"><<span class="hljs-title">description</span>></span>the privileges automatically granted to the owner whenever a table gets created. An example like"select,drop" will grant select and drop privilege to the owner of the table<span class="hljs-tag"></<span class="hljs-title">description</span>></span> <span class="hljs-tag"></<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>hive.security.authorization.task.factory<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">value</span>></span>org.apache.hadoop.hive.ql.parse.authorization.HiveAuthorizationTaskFactoryImpl<span class="hljs-tag"></<span class="hljs-title">value</span>></span> <span class="hljs-tag"></<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">property</span>></span> <span class="hljs-tag"><<span class="hljs-title">name</span>></span>hive.semantic.analyzer.hook<span class="hljs-tag"></<span class="hljs-title">name</span>></span> <span class="hljs-tag"><<span class="hljs-title">value</span>></span>HiveAdmin<span class="hljs-tag"></<span class="hljs-title">value</span>></span> <span class="hljs-tag"></<span class="hljs-title">property</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul>
注意:後續hdfs權限需要做相應修改
在namenode活動節點創建需要的用戶賬戶
如果使用hue,linux賬戶和hue的賬戶可以同步hue useradmin_sync_with_unix
啓用了hive權限之後發現hue和hive客戶端都沒有創建數據庫的權限,我需要客戶端能過創建數據酷,所以“hive-site.xml 的 Hive 客戶端高級配置代碼段(安全閥)“不作配置,這樣HiveAdmin的jar包只需放到hiveserver2所在主機/opt/cloudera/parcels/CDH-5.4.4-1.cdh5.4.4.p0.4/lib/hive/lib/
下就可以,如果hive-site客戶端也配置了權限,則jar需要放到hive lib下
如果想後端也加上權限,又想可以創建數據庫,則方案可以配置爲單獨一臺機子不做權限配置,用來做數據庫創建
hue和hive有一個坑導致不能相同授權重複,所以授權操作需要通過hive客戶端來操作