多租戶系統資料隔離

#cognito #ec2 #multi-tenant #mysql #rds

一般專案只需要一台 DB,然後用 project_id 區隔資料就好
不過因為公司的新專案對資安有很高需求,開始導入多租戶系統的概念,
這篇文章會講解在 DB 上各種資料隔離的模式,以及 Cognito、EC2 要如何搭配實現



一般來說,都是架一台 DB、一份 schema,在透過每一筆資料上的 project_id 或 tenant_id 做過濾

Multi-tenancy architecture of a relational databaseSingle database, discriminator column for data partitioning

這種作法大概有以下的缺點:

平時開發專案都是用這種作法,因為 data-isolation 的要求並不高,真的需要做跨專案分析時也很方便。
但以手頭上這專案的資安要求來說,這種做法應該是不行的🥲



那麼還有哪些方式呢?

  1. 1 db instance、1 schema、tenant_id column(上面說的)

  2. 1 db instance、n schema(幾個專案就有幾個 schema,各自做 migration)

  3. n db instance(幾個專案就開幾台機器)

我覺得第二種做法是在 cost-efficiency 跟 security 比較平衡的做法



MySQL (RDS) 如何搭配多租戶模式

承第二種作法(1 db instance、n schema

每當要建立新專案的時候,假設 tenant_id = foobar:

  1. Create schema named mycoolsys-foobar

  2. Create user named user-foobar

  3. Grant schema access for user created in previous step

  4. Migration

  5. (Optional) Store username and password of user-foobar in vault service(e.g. Secrets Manager)

在 Terraform 中自動化上述程序

如果能把每次部屬新專案需要的資源打包成 module,
就可以寫 Lambda 用 admin account 進 DB 下指令,並用 aws_lambda_invocation 執行



Cognito 如何搭配多租戶模式

官方文件其實有特別提到各種實作方式包括:

  1. n user-pool

  2. 1 user-pool、n client

  3. 1 user-pool、1 client、n group

  4. 1 user-pool、1 client、custom-attribute based multi-tenancy

就看自己需要決定要哪種囉

不過!
如果你要用 n user-pool 搭配 API Gateway,記得 Do not use HTTP API, use REST API instead
因為 HTTP API 的 JWT Issuer 只能設定一組(除非你願意 n user-pool 🤝 n api-gateway)
反而 REST API 可以直接設定多組 provider



EC2 如何搭配多租戶模式

承第二種作法(1 db instance、n schema

每一個專案就開一台 ec2 instance,並且指定他用下面的資訊連到 MySQL:

DB_HOST     = "domain to your instance"
DB_SCHEMA   = "mycoolsys_foobar"
DB_USERNAME = "user_foobar"
DB_PASSWORD = ""

此時還能搭配 EC2 不用密碼連線到 RDS (MySQL) 這篇文章中所說 RDS Proxy 的架構( ec2 instance 只能使用特定一組在 RDS Proxy 事先綁定的 DB secrets 並連線到 RDS,再透過 RDS Instance 內對該 db user 加上 privilege 限制),以實現特定租戶的 ec2 instance 只能存取自己的 schema。