MLSQL 編譯時許可權控制
前言
許可權控制,對於MLSQL而言的重要程度可以說是生命線。 MLSQL面對了各式各樣的資源(聯邦制),比如MySQL, Oracle,HDFS,
Hive,Kafka,Sorl,ElasticSearch,Redis,API,Web等等,不同使用者對這些資料來源(以及表,列)的許可權是不一樣的。
傳統模式是,每個使用者都需要有個proxy user,然後到每個資料來源裡面給這個proxy user進行授權。 這看起來就是麻煩點,但是在實際操作中,基本是不可能的,因為不同的資料來源在不同的團隊裡面,那麼整個申請流程可能要天甚至周計了。
其實上面的至少還是可以執行的,但對於採用Hive做數倉的公司,因為Hive的授權模式是跟著Linux使用者走的,也就是Spark啟動使用者是誰,誰就有許可權訪問,這個對於多租戶的MLSQL應用來說,是完全不可行的了,因為比如啟動Spark的是sparkUser,但是真正執行的人,其實可能是張三,李四等等。Hive就無法知道是具體哪個人完成的,只知道是sparkUser,這肯定是不行的。
另外,對於需要在一個腳本里,訪問多個數據源,跑了一個小時,然後其中有個資料來源因為沒有許可權,然後被拒絕,這也是一件極度讓人惱火的事情。
問題來了
那麼,怎麼才能在指令碼執行前,就知道指令碼有沒有授權資料來源(表,列)?
答案
題外話:標題不嚴謹,因為MLSQL本質是個解釋性執行語言,不需要編譯,所以嚴格意義上時,解析時許可權控制。 MLSQL如果開啟了許可權驗證,他會先掃描整個指令碼,然後提取必要的資訊,這些資訊就包含了各種資料來源的詳細資訊,從而在執行前就可以知道你是不是訪問了未經授權的庫表。那麼MLSQL是怎麼做到的呢?我們來看下面的資訊:
connect jdbc where driver="com.mysql.jdbc.Driver" and url="jdbc:mysql://${ip}:${host}/db1?${MYSQL_URL_PARAMS}" and user="${user}" and password="${password}" as db1_ref; load jdbc.`db1_ref .people` as people; save append people as jdbc.`db1_ref.spam` ;
因為MLSQL要求任何資料來源,都需要使用load語句進行載入,在解析load語句時,MLSQL知道,使用者現在要訪問的是基於JDBC協議的資料來源訪問,他通過url拿到了這些資訊:
db: db1 table: people operateType: load sourceType: mysql tableType: JDBC
當然,這個指令碼使用者還會寫入一張spam表,也一樣會被提取資訊:
db: db1 table: people operateType: save sourceType: mysql tableType: JDBC
然後還有一張臨時表people,所以這個指令碼總共有三張表資訊,之後這些資訊會被髮送到AuthCenter裡進行判斷,AuthCenter會告訴MLSQL那張表是沒有對當前使用者授權的,如果發現未經授權的表,MLSQL會直接丟擲異常。整個過程中,完全不會執行任何物理計劃,只是對指令碼的資訊抽取。
在MLSQL中,我們不能在select語句裡訪問hive表,只能通過load語句載入,比如下面的句子會報錯:
select * from public.abc as table1;
我們無權在select語句中訪問public.abc庫,如果需要使用,你可以通過如下方式完成:
load hive.`public.abc ` as abc; select * from abc as table1;
總結
MLSQL通過一些有效的限制,,可以在語法解析層面直接提取了所有資料來源相關資訊,並且將其傳送給到配套的許可權中心進行判斷,避免在執行時發現授權拒絕問題。MLSQL此舉意義重大,使得MLSQL系統不再完全依賴於底層系統的許可權控制,從而讓問題得到了極大的簡化。