[譯]PostgreSQL中更安全的應用使用者
原文地址: https://blog.crunchydata.com/blog/safer-application-users-in-postgres
原文作者:
“我們刪了資料庫”
兩年前的一個週五下午4點左右,我讓客戶開了一張支援票。客戶認為他們是在開發環境中執行測試元件,但實際上是在生產環境中執行。在一些測試元件的早期步驟之一就是保證有一個乾淨的環境:
-
Drop
所有的表,刪除schema
- 從頭開始
CREATE
有了 故障恢復和 基於時間點恢復,我們可以將資料庫回滾到過去的任何時間點。所以我們得到時間戳後,他們執行了命令,將他們數TB的資料庫恢復到了之前那個時刻。週五下午壓力很大,但是沒有資料丟失。
你可能會思考各種方法來防止這種情況。當連線到生產環境時將你的shell顏色設定為為紅色。不允許公共網路訪問生產。只允許
CI-驅動
的部署。還有一個有助於降低生產風險的選項:不允許生產環境的應用使用者刪除資料。
在生產中阻止app 使用者刪除資料
在生產環境中為了防止應用使用者刪除資料,我們需要降低風險,限制應用使用者進行如下操作:
-
DROP
表 -
TRUNCATE
表
該方法需要結合最佳實踐和適當的配置。開始前,讓我們先建立使用者!
超級使用者
超級使用者負責建立資料庫的schema和表(資料定義語言, DDL)
讓我們建立這個例子中的超級使用者:
postgres=# CREATE USER admin with PASSWORD 'correcthorsebatterystaple' SUPERUSER; CREATE ROLE postgres=# \du admin List of roles Role name | Attributes | Member of -----------+------------+----------- admin | Superuser | {}
應用使用者
應用使用者通常只能執行一些定義在資料庫表和schema上的操作(資料操縱語言, DML)
不要給應用使用者賦予
DROP
和
TRUNCATE
許可權。
生產的應用應該僅需要新增和更新資料的許可權。一個典型的生產應用程式通過以下方式增長:
- 向表中增加列
- 增加行
- 更新行記錄
如果應用程式遵循上述的設計模式,你可能不會給應用使用者賦予
DROP
、
TRUNCATE
、
DELETE
表的許可權
在下面的例子中,我們將會使用名為‘myappuser’的應用使用者。所以讓我們建立它:
postgres=# CREATE USER myappuser WITH PASSWORD 'verygoodpasswordstring'; CREATE ROLE
超級使用者建立表
現在角色已經被建立,讓我們設定場景。
我們只能通過超級使用者建立生產環境的表。預設情況下,表的建立者是表的所有者。只有owner和超級使用者可以執行
DROP TABLE
等操作。這可以防止應用使用者意外刪除生產表中的資料。應用使用者只能
drop
屬於自己的表。
在製作生產的沙盒之前,讓我們確保是正確的管理員:
postgres=# SELECT current_user; current_user -------------- admin (1 row)
建立一個生產的
SCHEMA
並
GRANT
合適的許可權:
postgres=# CREATE SCHEMA prod; CREATE SCHEMA postgres=# GRANT USAGE ON SCHEMA prod TO myappuser; GRANT
現在我們為生產資料建立一張表,開始測試一些概念:
postgres=# CREATE TABLE prod.userdata (col1 integer, col2 text, col3 text); CREATE TABLE
myappuser
使用者登入時,不能
drop
表:
postgres=# \c postgres myappuser Password for user myappuser: You are now connected to database 'postgres' as user 'myappuser'. postgres=> DROP TABLE prod.userdata; ERROR: must be owner of table userdata
最小許可權
我們已經展示瞭如何阻止應用使用者
DROP
表。為了防止刪除表中的資料,我們需要做更多的工作。應用使用者應該只能訪問其所需內容。
為此,綜上所述,我們僅
GRANT
應用使用者需要的許可權:
postgres=> \c postgres admin Password for user admin: You are now connected to database 'postgres' as user 'admin'. postgres=# GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA prod TO myappuser; GRANT
如果已經存在了一些應用使用者,可以
REVOKE
不想要的生產許可權:
postgres=# REVOKE DELETE, TRUNCATE ON ALL TABLES IN SCHEMA prod FROM myappuser; REVOKE
現在我們的應用使用者刪除不了資料:
postgres=# \c postgres myappuser Password for user myappuser: You are now connected to database 'postgres' as user 'myappuser'. postgres=> DELETE FROM prod.userdata *; ERROR: permission denied for table userdata postgres=> TRUNCATE TABLE prod.userdata; ERROR: permission denied for table userdata
我們已經縮小了許可權,但是怎麼能知道是否有遺漏呢?
檢查訪問許可權
在使用角色和許可權時,最好進行檢查訪問許可權。我推薦使用 crunchy_check_access擴充套件來遍歷訪問和許可權樹。
使用超級使用者登入,檢視賦予應用使用者的許可權:
postgres=# SELECT base_role,objtype,schemaname,objname,privname FROM all_access() WHERE base_role = 'myappuser' AND schemaname = 'prod'; base_role | objtype | schemaname | objname | privname -----------+---------+------------+----------+---------- myappuser | schema | prod | prod | USAGE myappuser | table | prod | userdata | SELECT myappuser | table | prod | userdata | INSERT myappuser | table | prod | userdata | UPDATE (4 rows)
應用使用者刪除記錄
在資料庫中,我們已經回收許可權,防止了“意外”刪除資料的錯誤,但是應用使用者仍然需要刪除資料。對於刪除應用資料,來看一個更安全的可替代的設計。
應用刪除資料的一種普遍的模式是標記元組,而不是徹底刪除。
我們修改上面建立的表,增加名為
deleted
的
timestamp
列。有兩個好處:
- 資料實際上沒有被刪除,所以上述的問題不用擔心
- 每個時刻都有一個記錄快照,可以快速、輕鬆的回滾應用級別的狀態
增加
deleted
列
假設生產表已經建立,可以使用如下方法增加
deleted
列;
postgres=# ALTER TABLE prod.userdata ADD COLUMN deleted timestamp; ALTER TABLE
提示:上述的
ADD COLUMN
語法需要花費很高的代價,因為它會在表上持有
Exclusive Lock
。
正常表的
insert
和
update
操作會採取相同的形式:
INSERT INTO prod.userdata VALUES (generate_series(1,10), md5(random()::text), md5(random()::text)) ; INSERT 0 10
現在可以選擇更新一行,將其標記為刪除。假設應用想要刪除所有
where col1 < 3
的記錄:
postgres=> UPDATE prod.userdata SET deleted = now() WHERE col1 < 3; UPDATE 2
檢視所有被保留的記錄:
postgres=> SELECT * from prod.userdata WHERE deleted IS NULL; col1 | col2 | col3 | deleted ------+----------------------------------+----------------------------------+--------- 3 | 828748efff06ce5b6f0f8e8931429bd3 | e50fe6654ee497de8ad75746849fba0f | 4 | 4241511ee0a8f7f76976f0bab43b47f0 | d08e31ba79f972a2983301832ec67b94 | 5 | 93de032bc9157362593a0259a8558514 | 6cd1639323a0c1a96fb3e781283e19d3 | 6 | af1e1d81ef68dbd5ac14a0ae55195e2a | a4e500cf2c3ecd24c0a745c42b5af939 | 7 | bcd0c74ca0d416b3f1b3e7ffda375615 | 361ed5d6bff759df7c138daf4b4b0e1b | 8 | 35856a2d5b0e5b3e1d3ea4e09f0f88fe | a6d0977908e08626bad8278e965e9315 | 9 | 43de7e949e9777969248b9b1d751d44e | 196390d618931a8dd3d5473cc23869fa | 10 | 3fc5661e900a25b96b708f3c22cf1d59 | 2f29a28b25e1a1e25fc10b45fc22bc91 | (8 rows)
也可以通過時間戳篩選。我們要刪除更多的記錄,假設要刪除沒有被刪除並且
where col1 < 6
的列:
postgres=> UPDATE prod.userdata SET deleted = now() WHERE deleted IS NULL AND col1 < 6; UPDATE 3 postgres=> SELECT * from prod.userdata; col1 | col2 | col3 | deleted ------+----------------------------------+----------------------------------+---------------------------- 6 | af1e1d81ef68dbd5ac14a0ae55195e2a | a4e500cf2c3ecd24c0a745c42b5af939 | 7 | bcd0c74ca0d416b3f1b3e7ffda375615 | 361ed5d6bff759df7c138daf4b4b0e1b | 8 | 35856a2d5b0e5b3e1d3ea4e09f0f88fe | a6d0977908e08626bad8278e965e9315 | 9 | 43de7e949e9777969248b9b1d751d44e | 196390d618931a8dd3d5473cc23869fa | 10 | 3fc5661e900a25b96b708f3c22cf1d59 | 2f29a28b25e1a1e25fc10b45fc22bc91 | 1 | b4fb51aff93bf865c6bc8c5f32b306cf | 49d37b3934e2c44f20ddd87019bc525e | 2022-02-03 16:30:49.445571 2 | e53507d91f39905f6bcd193636b13c3d | 66066e4c78a3eb701086391052c19b56 | 2022-02-03 16:30:49.445571 3 | 828748efff06ce5b6f0f8e8931429bd3 | e50fe6654ee497de8ad75746849fba0f | 2022-02-03 16:34:19.953742 4 | 4241511ee0a8f7f76976f0bab43b47f0 | d08e31ba79f972a2983301832ec67b94 | 2022-02-03 16:34:19.953742 5 | 93de032bc9157362593a0259a8558514 | 6cd1639323a0c1a96fb3e781283e19d3 | 2022-02-03 16:34:19.953742 (10 rows)
現在,我們可以使用上次的刪除時間戳恢復狀態:
postgres=> SELECT * from prod.userdata WHERE deleted IS NULL OR deleted >= timestamp '2022-02-03 16:34:19.953742'; col1 | col2 | col3 | deleted ------+----------------------------------+----------------------------------+---------------------------- 6 | af1e1d81ef68dbd5ac14a0ae55195e2a | a4e500cf2c3ecd24c0a745c42b5af939 | 7 | bcd0c74ca0d416b3f1b3e7ffda375615 | 361ed5d6bff759df7c138daf4b4b0e1b | 8 | 35856a2d5b0e5b3e1d3ea4e09f0f88fe | a6d0977908e08626bad8278e965e9315 | 9 | 43de7e949e9777969248b9b1d751d44e | 196390d618931a8dd3d5473cc23869fa | 10 | 3fc5661e900a25b96b708f3c22cf1d59 | 2f29a28b25e1a1e25fc10b45fc22bc91 | 3 | 828748efff06ce5b6f0f8e8931429bd3 | e50fe6654ee497de8ad75746849fba0f | 2022-02-03 16:34:19.953742 4 | 4241511ee0a8f7f76976f0bab43b47f0 | d08e31ba79f972a2983301832ec67b94 | 2022-02-03 16:34:19.953742 5 | 93de032bc9157362593a0259a8558514 | 6cd1639323a0c1a96fb3e781283e19d3 | 2022-02-03 16:34:19.953742 (8 rows)
更安全的應用使用者總結
我們已經展示如何降低意外刪除生產資料的風險,通過下面的操作:
- 確保超級使用者是物件的所有者
- 應用使用者僅有新增更新資料的操作許可權
- 通過使用
deleted
時間戳列,可以更安全的刪除資料
現在我們可以放心的休息了,因為我們的生產資料不會受到那些討厭的測試指令碼的影響了!
- 有關限制資料庫使用者許可權的更多資訊,請檢視 Creating a Read-Only Postgres User博文
- PostgreSQL的許可權環境非常複雜。最小許可權通常要比表面上看到的要多。要更深的研究複雜性,檢視 PostgreSQL Defaults and Impact on Security部落格系列
- 如果對保護使用者資料方面感興趣,請檢視 Crunchy Hardened PostgreSQL的增強型RBAC 和超級使用者鎖定功能。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70012788/viewspace-2856454/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android O 讓安裝應用更安全Android
- KubeVela 1.4:讓應用交付更安全、上手更簡單、過程更透明
- [譯]構建現代Web應用的安全指南Web
- 安卓應用安全指南翻譯完成安卓
- Setapp:57% 的 Mac 使用者在購買新應用程式的時候會更優先考慮安全APPMac
- [譯] WebAssembly中的記憶體(為什麼它比你想象的更安全)Web記憶體
- [譯] Flutter 中的原生應用程式狀態Flutter
- 為 Node.js 應用建立一個更安全的沙箱環境Node.js
- JavaScript 中更安全的 URL 讀寫JavaScript
- 中興陳河堆:PostgreSQL在5G網管中的應用SQL
- 在 Android 12 中構建更現代的應用 WidgetAndroid
- 更相減損術的應用
- PostgreSQL的generate_series函式應用SQL函式
- 物聯網在公共安全中的應用
- web開發安全框架中的Apache Shiro的應用Web框架Apache
- 用 AI 讓資料分析更智慧 - Amazon Q 在 Amazon Quicksight 中的應用AIUI
- 應用安全
- [譯] 為使用者提供安全可靠的體驗
- 阿里雲應用身份服務 IDaaS 重磅升級,雲原生、高安全、更經濟,極致使用者體驗!阿里
- [譯] Xcode 中的使用者斷點XCode斷點
- 「譯」有限狀態機在 CSS 動畫中的應用CSS動畫
- Java中的編譯器外掛開發與應用Java編譯
- 應用程式安全的看法
- 【go】【應用編譯】Go編譯
- 你第一個Electron應用 | Electron in Action(中譯)
- SplitMetrics:使用者在應用商店中的行為調查
- [譯] 更為詳細的地圖、導航和助手功能 —— Google I/O 2018 的 Android 應用更新地圖GoAndroid
- PostgreSQL的單使用者模式SQL模式
- 區塊鏈技術在網路安全中的應用區塊鏈
- 數字證書及其在安全測試中的應用
- [譯] 使用智慧 CSS 基於使用者滾動位置應用樣式CSS
- [譯] 響應式 Web 應用(四)Web
- [譯] 響應式 Web 應用(五)Web
- 讓容器應用管理更快更安全,Dragonfly 釋出 Nydus 容器映象加速服務Go
- 用PostgreSQL執行檔案中的SQL程式SQL
- [譯] 設計 QA 在應用程式設計中的重要性程式設計
- 【譯】十二因子應用(四)
- YouGov:52%的中國人優先考慮應用的安全性Go