iT邦幫忙

2024 iThome 鐵人賽

DAY 25
1
Software Development

微服務奇兵:30天Quarkus特訓營系列 第 25

開發觀念建置-微服務中的資料庫權限管理:服務即使用者

  • 分享至 

  • xImage
  •  

在前面章節中,微服務部份我們討論了從單體架構到微服務架構的轉換,並以一個範例介紹了如何進行業務邏輯和數據的拆分。但如同結尾提到,其實微服務設計上,會面臨不同的問題。這部分我會再針對此部分做一個go through介紹。但今天我想針對微服務架構中的資料庫權限管理進行介紹,並基於具體實例來說明如何實作。

本文亦致敬我的職涯同事 Clarke,與他共事期間,特別是在微服務的資料庫設計與權限拆分上學習了許多寶貴的知識。希望透過這篇文章,分享他所教導的經驗和設計思路。

閱讀完後大致會對Schema與User細微度的設計會稍微有感跟理解一個初步脈絡

微服務中的資料庫權限管理:服務即使用者

在微服務的設計中,我們通常會根據不同服務對資料庫(DB)的需求,為各服務設置資料庫 Schema 的使用權限,並依此設計相應的 API Service。在過去,我的經驗大多在工廠的設備控制與生產服務串接,由於工廠端系統較為簡單,DB 實例(DB Instance)建置完成後,通常不需要為多個 API Service 特別規劃 Schema 的使用權限管理。常見做法是直接使用一個 Root 使用者來進行所有操作。然而,這在微服務架構中並不是一個好的設計。這樣會導致每個服務擁有過多的權限,增加潛在的安全風險。

在為服務實際應用中,應該根據不同服務的資料需求,設置其專屬的權限範圍,並將這些權限分配至不同的資料庫 Schema。接著,針對每個 Schema 設計對應的 API Service 來存取資料。

資料庫 Schema 是一種組織方式,允許將表格、視圖、索引等物件分類與管理。在這樣的架構下,每個微服務通過其專屬的 API Service 存取資料庫,而其操作的範圍僅限於指定的 Schema。這樣可以有效防止服務擁有過多的資料庫權限,從而降低安全風險。

情境:設計登入與圖片上傳服務

在台北受訓那時期,新人專題要設計一個雲端系統,須具備登入和圖片上傳功能。如果不採用微服務架構,單一的 API Service 連接到一個資料庫實例的 Schema 即可完成。但按照微服務的設計原則,應將這兩個功能拆分為兩個獨立的 API Service,一個處理圖片上傳,另一個處理登入功能。

在這樣的設計中,我們將資料庫 Schema 進行拆分:

  • PROCESS Schema 用於圖片上傳服務。
  • SECURITY Schema 用於登入服務。

接著,針對這兩個 Schema 設計不同的角色和權限,確保每個服務只擁有執行其職責所需的權限,這樣可以有效地提升系統的安全性和可管理性。

schema 是一種將數據庫物件(如表格、視圖、索引、數據類型、函數等)組織在一起的命名空間。每個數據庫都可以有一個或多個 schema,每個 schema 都有一個名稱,該名稱在其數據庫中必須是唯一的。

資料庫權限與角色設計

以下將通過 SQL 範例來說明如何為微服務設計資料庫權限管理。具體步驟包括:

  1. 設置 Schema 和角色:為不同的服務創建獨立的 Schema,並賦予不同的角色相應的權限。
  2. 創建 API 使用者:為每個服務創建專屬的 API 使用者,並確保每個使用者僅能操作指定的 Schema。
  3. 配置角色與權限:為不同的操作(查詢、修改、執行程序)設置對應的角色,並分配相應的權限。
  4. 分配角色給 API 使用者:最後,將設置好的角色分配給對應的 API 使用者。

Step 1 : 設置 Schema 和角色

首先,為兩個功能分別創建角色 HW_PROCESSHW_SECURITY,並設置資料庫 Schema 來隔離各自的權限。每個角色都有自己的登入憑證,並且只被授權訪問自己的 Schema。

-- 創建角色
CREATE ROLE HW_PROCESS;
CREATE ROLE HW_SECURITY;

-- 授權
GRANT HW_PROCESS TO POSTGRES;
GRANT HW_SECURITY TO POSTGRES;

-- 創建 Schema 並授權
CREATE SCHEMA AUTHORIZATION HW_PROCESS;
CREATE SCHEMA AUTHORIZATION HW_SECURITY;

-- 設置角色的登入權限和密碼
ALTER ROLE HW_PROCESS WITH LOGIN PASSWORD 'hwprocess';
ALTER ROLE HW_SECURITY WITH LOGIN PASSWORD 'hwsecurity';

此段指令完成以下幾個步驟

  1. 創建了兩個角色 HW_PROCESSHW_SECURITY
  2. HW_PROCESSHW_SECURITY 角色授予給 POSTGRES 超級使用者。
  3. 創建了兩個 Schema,並將它們的擁有權分別賦予 HW_PROCESSHW_SECURITY 角色。簡單來說HW_PROCESSHW_SECURITY 分別是這兩個 Schema 的擁有者。
  4. HW_PROCESSHW_SECURITY 角色設置了登入權限和各自的密碼

Step 2 : 創建 API 使用者

接著根據不同的服務需求,創建對應的 API 使用者 HWSAPHWPAP,並設置密碼以便使用這些使用者進行服務連接。

-- 創建 API 使用者
CREATE ROLE HWSAP LOGIN PASSWORD 'HWSAP123'; -- 用於 SECURITY Schema
CREATE ROLE HWPAP LOGIN PASSWORD 'HWSAP123'; -- 用於 PROCESS Schema

Step 3 : 設定角色與權限

接著,為每個 Schema 設置不同的角色(Role Group),並分別授予不同的操作權限。角色依據操作職責進行細分:

  • SELECT 權限:授予讀取資料的權限。
  • MODIFY 權限:授予插入、更新、刪除資料的權限。
  • EXECUTE 權限:授予執行儲存程序的權限。
-- HW_PROCESS 角色組設置
CREATE ROLE RL_HW_PROCESS_SEL; -- 查詢
CREATE ROLE RL_HW_PROCESS_MOD; -- 修改
CREATE ROLE RL_HW_PROCESS_EXE; -- 執行

-- 賦予相應權限
GRANT SELECT ON ALL TABLES IN SCHEMA HW_PROCESS TO RL_HW_PROCESS_SEL;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES TO RL_HW_PROCESS_MOD;
GRANT EXECUTE ON ALL PROCEDURES TO RL_HW_PROCESS_EXE;

-- HW_SECURITY 角色組設置
CREATE ROLE RL_HW_SECURITY_SEL; -- 查詢
CREATE ROLE RL_HW_SECURITY_MOD; -- 修改
CREATE ROLE RL_HW_SECURITY_EXE; -- 執行

-- HW_PROCESS 角色設置
GRANT SELECT ON ALL TABLES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_SEL;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_MOD;
GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_EXE;
  1. HW_PROCESS Schema 創建三個角色:

    • RL_HW_PROCESS_SEL:主要負責查詢HW_PROCESS 資料。
    • RL_HW_PROCESS_MOD:主要負責修改HW_PROCESS 資料(如插入、更新、刪除)。
    • RL_HW_PROCESS_EXE:主要負責執行HW_PROCESS 存儲程序(Stored Procedures)。

    賦予相應的權限

    • RL_HW_PROCESS_SEL 被授予對 HW_PROCESS Schema 中所有資料表的 SELECT 權限,代表角色只能查詢資料,不能修改。
    • RL_HW_PROCESS_MOD 被授予 INSERTUPDATEDELETE 權限,讓該角色可以插入、更新和刪除資料表中的資料。
    • RL_HW_PROCESS_EXE 被授予對 HW_PROCESS Schema 中所有存儲程序的 EXECUTE 權限,允許該角色執行資料庫中的存儲程序。
  2. HW_SECURITY Schema 創建三個角色 :

    • RL_HW_SECURITY_SEL:負責查詢 HW_SECURITY Schema 中的資料。
    • RL_HW_SECURITY_MOD:負責修改 HW_SECURITY Schema 中的資料。
    • RL_HW_SECURITY_EXE:負責執行 HW_SECURITY Schema 中的程序。

    賦予相應的權限

    • RL_HW_SECURITY_SEL 被授予對 HW_SECURITY Schema 中所有資料表的 SELECT 權限,讓該角色可以查詢資料。
    • RL_HW_SECURITY_MOD 被授予對 HW_SECURITY Schema 中所有資料表的 INSERTUPDATEDELETE 權限,這允許修改資料。
    • RL_HW_SECURITY_EXE 被授予對 HW_SECURITY Schema 中所有程序的 EXECUTE 權限,可以執行存儲程序。

Step 4 : 分配角色組給 API 使用者

最後,將角色組賦予對應的 API 使用者,讓每個使用者僅能執行其服務所需的操作。

-- 為 HWSAP 分配 HW_SECURITY 角色
GRANT RL_HW_SECURITY_SEL, RL_HW_SECURITY_MOD, RL_HW_SECURITY_EXE TO HWSAP;

-- 為 HWPAP 分配 HW_PROCESS 角色
GRANT RL_HW_PROCESS_SEL, RL_HW_PROCESS_MOD, RL_HW_PROCESS_EXE TO HWPAP;

整體SQL與法如下

-- SCHEMA & TABLE SETTING
 CREATE ROLE HW_PROCESS;
 CREATE ROLE HW_SECURITY;
 
 GRANT HW_PROCESS TO POSTGRES;
 GRANT HW_SECURITY TO POSTGRES;
 
 CREATE SCHEMA AUTHORIZATION HW_PROCESS;
 CREATE SCHEMA AUTHORIZATION HW_SECURITY;
 
 ALTER ROLE HW_PROCESS WITH LOGIN PASSWORD 'hwprocess';
 ALTER ROLE HW_SECURITY WITH LOGIN PASSWORD 'hwsecurity';
 
 -- CREATE AP USER
 
 -- AP USER
 CREATE ROLE HWSAP LOGIN PASSWORD 'HWSAP123';
 CREATE ROLE HWPAP LOGIN PASSWORD 'HWSAP123';
 
 -- CREATE ROLE GROUP
 
 -- HW_PROCESS
 CREATE ROLE RL_HW_PROCESS_SEL;
 CREATE ROLE RL_HW_PROCESS_MOD;
 CREATE ROLE RL_HW_PROCESS_EXE;
 
 GRANT SELECT ON ALL TABLES IN SCHEMA HW_PROCESS TO RL_HW_PROCESS_EXE;
 GRANT INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA HW_PROCESS TO RL_HW_PROCESS_MOD
 GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA HW_PROCESS TO RL_HW_PROCESS_EXE;
 
 -- HW_SECURITY
 CREATE ROLE RL_HW_SECURITY_SEL;
 CREATE ROLE RL_HW_SECURITY_MOD;
 CREATE ROLE RL_HW_SECURITY_EXE;
 
 GRANT SELECT ON ALL TABLES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_SEL;
 GRANT INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_MOD;
 GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA HW_SECURITY TO RL_HW_SECURITY_EXE;
 
 -- GRANT ROLE GROUP TO USER
 GRANT RL_HW_SECURITY_SEL, RL_HW_SECURITY_MOD, RL_HW_SECURITY_EXE TO HWSAP;
 GRANT RL_HW_PROCESS_SEL, RL_HW_PROCESS_MOD, RL_HW_PROCESS_EXE TO HWPAP;

角色關係

根據上述設計,角色和權限的關係可以簡單整理如下:

主要角色

  • HW_PROCESS:負責處理圖片上傳的 Schema 及其操作。
  • HW_SECURITY:負責處理登入的 Schema 及其操作。

API 使用者

  • HWSAP:負責與 HW_SECURITY 相關的服務,擁有 SELECT、MODIFY 和 EXECUTE 權限。
  • HWPAP:負責與 HW_PROCESS 相關的服務,擁有 SELECT、MODIFY 和 EXECUTE 權限。

角色組(Role Group)

  • 每個主要角色下設置三種不同的角色組:
    • RL_HW_PROCESS_SEL / RL_HW_SECURITY_SEL:查詢權限。
    • RL_HW_PROCESS_MOD / RL_HW_SECURITY_MOD:資料修改權限。
    • RL_HW_PROCESS_EXE / RL_HW_SECURITY_EXE:執行儲存程序的權限。

這樣的設計能夠實現細粒度的資料庫權限控制,保證每個服務只擁有其職責範圍內的權限,確保系統的安全性與可管理性。但其實以目前的專案情境,角色Group組員微度可能應用不上,但我覺得是一個很好的觀念做此紀錄。

權限設定比較表

稍微簡單比較一下簡單權限設定細部權限控管的兩種方案,從便利性、安全性、實作速度、權限控制及維護成本等多個面向進行對照。

比較項目 簡單權限設定 細部權限控管
便利性 高:一次設定,所有服務共用 低:需針對每個服務獨立設定
實作速度 快:適合小型應用或測試階段 較慢:需考量每個服務的需求與權限
安全性 低:每個服務擁有過多權限,風險高 高:遵循最小權限原則,降低安全風險
權限控制 無法細緻控制,所有服務共用 精細控制,每個服務只擁有其需要的權限
問題追蹤 難以追蹤,無法區分個服務執行了操作 容易追溯,所有操作可追蹤至具體服務
維護成本 低:初期設定簡單 高:需針對各服務進行權限管理
適用場景 小型、簡單或短期應用 大型、長期維護且具擴展性應用
  • 簡單權限設定適合小型或測試階段的應用,操作快速、簡單,但會因為授予過多權限而導致安全風險提升,且當出現問題時,難以精確追溯到具體的服務。
  • 細部權限控管更適合大型且需長期維護的微服務系統,雖然初期設置較為繁瑣,且實作速度較慢,但能有效提升系統的安全性,遵循最小權限原則,降低過度授權的風險,並便於故障排查與系統管理。

JDBC連線示意

資料庫連線設置部分,Quarkus支援JDBC連線,通常透過quarkus.datasource屬性來配置資料來源。Quarkus具備兩種主要資料庫連線方式:使用阻塞(JDBC)或非阻塞(反應式)的方式來與資料庫交互。以下是JDBC連線設定配置

單一資料來源配置示意如下

# 全域資料來源配置
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=service_user
quarkus.datasource.password=service_password
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydb
quarkus.datasource.jdbc.max-size=15
quarkus.datasource.jdbc.min-size=2

如果以上述範例拆服務配置如下

# 對於登入服務 (Security)
quarkus.datasource.security.db-kind=postgresql
quarkus.datasource.security.username=HWSAP
quarkus.datasource.security.password=HWSAP123
quarkus.datasource.security.jdbc.url=jdbc:postgresql://localhost:5432/securitydb
quarkus.datasource.security.jdbc.max-size=8
quarkus.datasource.security.jdbc.min-size=2

# 對於圖片上傳服務 (Process)
quarkus.datasource.process.db-kind=postgresql
quarkus.datasource.process.username=HWPAP
quarkus.datasource.process.password=HWPAP123
quarkus.datasource.process.jdbc.url=jdbc:postgresql://localhost:5432/processdb
quarkus.datasource.process.jdbc.max-size=8
quarkus.datasource.process.jdbc.min-size=2

設計考量與最佳實踐

根據上述過一遍權限與角色分隔設置上,整理出以下關鍵點

  1. 細粒度權限控制:在許多情況下,你可能不希望你的應用程式服務有權限去做所有事情。例如,一個應用程式可能只需要讀取資料,而不需要寫入或刪除。透過為這些服務創建特定的角色,你可以確定他們只有他們實際需要的權限。

  2. 最小權限原則:一種常見的安全最佳實踐,只賦予完成任務所需的最小權限。如果你的應用程式服務只需要讀取資料,那麼給它們賦予寫入或修改的權限可能會引入不必要的風險。

  3. 角色分隔:透過為不同的應用程式服務創建不同的角色,可以更容易地追蹤和管理哪個服務正在做什麼。這也使得審計和問題排查變得更容易。

  4. 避免使用 schema 擁有者進行操作:在許多數據庫系統中,schema 擁有者(在這種情況下為**HW_PROCESS** 和 HW_SECURITY)擁有對其 schema 中的所有對象的所有權限。如果應用程式以 schema 擁有者的身份運行,那麼任何可能的漏洞或配置錯誤都可能導致整個 schema 的數據被修改或刪除。

為你的應用程式服務創建專門的角色可以提供更精確的控制,並降低可能的安全風險。


上一篇
開發觀念建置-關於加密機制
下一篇
開發觀念建置-var使用
系列文
微服務奇兵:30天Quarkus特訓營30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言