MySQL的儲存過程,沒錯,看起來好生僻的使用場景。問題源於一個開發同學提交了許可權申請的工單,需要開通一些許可權。
本來是一個很正常的操作,但在我來看是比較著急且緊迫的,說來慚愧,忙著方向規劃和開發的事情,這個基礎的操作功能竟然給忽略了,所以看到目前的一些實現方式,還是希望能夠做一些細小的事情把這些重複性的工作給解放了。
當然我決定把一些基礎性的工作接過來,一方面是給同事減壓,另一方面是在做一個完整的體驗,因為很多需求和痛點透過實踐是能夠很容易捕捉到重點的,如果我覺得不合理,那麼這個過程中勢必會有一些改進的地方。比如部署安裝,比如許可權開通。資料庫的許可權開通就是一個相對典型的案例,而儲存過程的許可權開通甚至都有點讓人懷疑人生了。
問題的場景還是很基礎的,開發同學需要開通一些基礎的許可權,在標記許可權的時候宣告需要增刪改查的許可權,還有DDL的許可權,比如drop,alter,create等等。看到這裡,我就感覺不太妥了,什麼樣的操作竟然需要這麼大的許可權呢。
簡單宣告瞭下立場,開發同學的想法是能夠方便管理,於是乎我就直接招過去了,簡單溝通下,其實發現他們的需求場景還是很常規的,他們需要動態建立一些日表,那麼需要create許可權在評估之後是可以給與的,而對於一般的使用者而言,create的許可權是不建議開放的,主要的出發點就是能夠對SQL進行一些基本的稽核,哪怕是人工稽核還是平臺稽核都是一個需要的過程。所以溝通了一圈發現,開通的許可權就可以迅速裁剪,對他們而言,修改儲存過程的邏輯也是需要的,因為在一些特定的場景下,他們對邏輯的控制希望能夠更加靈活。
好了,基礎的背景介紹完了。賦予基本的表的許可權,賦予儲存過程的許可權,儲存過程的這個地方需要注意一個重要的點是SQL SECURITY,預設建立是definer,如果需要開放給其他的使用者呼叫,則建議是設定為invoker.
所以很簡單的一句:
grant execute,alter procedure on xxx.xxx to xxx@'xxxx';
但是很不幸的,開發同學反饋,他們透過SQLyog或者是Navicator開啟的時候,竟然看不到儲存過程的內容。
因為我們沒有select procedure或者view procedure的許可權,所以我們幾乎再無從干預了。
使用命令列的方式能夠復現出這個問題:
沒有儲存過程的實質性內容。在那兒折騰了好一會,發現是個老問題了,10多年前的老問題了。
問題的解決其實很簡單,就是需要這樣一句:
grant select on mysql.proc to xxxx@'xxxx'即可
所以細粒度的許可權控制就是這麼糾結,但是確實有效。
比如我們舉一反三一下,我們知道MySQL裡的all privileges算是一個很大的許可權,但是裡面包含多少種許可權,可能我們沒有清晰的概念。
我們就完全可以透過細粒度的許可權控制來反推。
比如建立一個使用者,賦予all privileges的許可權。
mysql> grant all privileges on test.* to 'jeanron'@'%' identified by 'jeanron100';
Query OK, 0 rows affected, 1 warning (0.00 sec)
包含的許可權如下:
mysql> show grants for jeanron;
+---------------------------------------------------+
| Grants for jeanron@% |
+---------------------------------------------------+
| GRANT USAGE ON *.* TO 'jeanron'@'%' |
| GRANT ALL PRIVILEGES ON `test`.* TO 'jeanron'@'%' |
+---------------------------------------------------+
2 rows in set (0.00 sec)
我們做一下收縮。
mysql> revoke insert on test.* from jeanron@'%';
Query OK, 0 rows affected (0.00 sec)
喏,all privileges的許可權就現出原形了。
mysql> show grants for jeanron;
| Grants for jeanron@%
+------------------------------------------------------------------------------------------------------
| GRANT USAGE ON *.* TO 'jeanron'@'%'
| GRANT SELECT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `test`.* TO 'jeanron'@'%' |
所以在上面的問題中,其實如果select on *.*其實已經包含了我們需要的細粒度許可權mysql.proc,如果要抽絲剝繭,基本就是這樣的套路。