- 如何證明你是你 - SPIFEE
| Abstract | 如何證明你是你 |
|---|---|
| Authors | Walter Fan |
| Category | learning note |
| Status | v1.0 |
| Updated | 2025-01-18 |
| License | CC-BY-NC-ND 4.0 |
如何證明你是你 - SPIFEE
在數(shù)字世界里,證明“你是你”這個(gè)問(wèn)題聽起來(lái)有點(diǎn)像哲學(xué)問(wèn)題,但實(shí)際上,它是現(xiàn)代軟件架構(gòu)中的一個(gè)核心挑戰(zhàn)。想象一下,你是一個(gè)微服務(wù),每天要和成千上萬(wàn)的其他微服務(wù)打交道,每個(gè)服務(wù)都需要確認(rèn)你的身份,確保你不是一個(gè)冒名頂替者。
SPIFFE 就是這樣解決“如何證明你是你”問(wèn)題的協(xié)議, 如果你只在一個(gè)云環(huán)境中, 傳統(tǒng)的 AWS IAM 可以解決身份認(rèn)證的問(wèn)題, 而在多種不同的混合云 (公有云, 私有云, 不同的云提供商) 環(huán)境中,SPIFFE 就可以解決統(tǒng)一身份認(rèn)證的問(wèn)題, 有點(diǎn)象護(hù)照, 比身份證更通用, 可以跨國(guó)認(rèn)證你就是你.
1. 你是誰(shuí)?— 身份認(rèn)證的挑戰(zhàn)
在分布式系統(tǒng)中,每個(gè)服務(wù)都需要證明自己的身份。這就像你去參加一個(gè)派對(duì),門口的保安會(huì)問(wèn)你:“你是誰(shuí)?”如果你能出示一張有效的身份證,保安就會(huì)讓你進(jìn)去。在數(shù)字世界里,這張“身份證”就是你的身份憑證。
例如 AWS IAM(Identity and Access Management)是亞馬遜云服務(wù)提供的一個(gè)強(qiáng)大的身份和訪問(wèn)管理工具。它允許你創(chuàng)建和管理用戶、組和角色,并控制他們對(duì) AWS 資源的訪問(wèn)權(quán)限。簡(jiǎn)單來(lái)說(shuō),IAM 就是 AWS 的“保安”,它負(fù)責(zé)驗(yàn)證你的身份,并決定你能做什么。
在 AWS 中,實(shí)例(Instance)和應(yīng)用程序(Application)身份認(rèn)證是通過(guò)多種機(jī)制來(lái)實(shí)現(xiàn)的,其中最重要的兩個(gè)是 IAM Roles 和 AWS Security Token Service (STS)。
它的具體實(shí)現(xiàn)方法和機(jī)制主要是通過(guò) AWS IAM Role 和 AWS Security Token Service:
AWS IAM Role
它是一種用于委托權(quán)限的 AWS 資源,允許 EC2 實(shí)例或其他 AWS 服務(wù)在不需要硬編碼憑據(jù)的情況下訪問(wèn) AWS 資源。
工作原理:
- IAM Role 的創(chuàng)建:管理員在 AWS IAM 中創(chuàng)建一個(gè)角色,定義允許的權(quán)限(通過(guò) IAM 策略)。
-
實(shí)例配置角色:
- 啟動(dòng) EC2 實(shí)例時(shí),關(guān)聯(lián)一個(gè) IAM Role。
- 或在實(shí)例啟動(dòng)后,通過(guò) AWS CLI 或 SDK 將角色附加到實(shí)例。
-
元數(shù)據(jù)服務(wù)提供臨時(shí)憑證:
- 實(shí)例訪問(wèn)
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>獲取臨時(shí)憑證。 - 這些憑證包括
Access Key ID、Secret Access Key和Session Token,并具有短時(shí)間有效期(默認(rèn) 6 小時(shí),可配置)。
- 實(shí)例訪問(wèn)
優(yōu)勢(shì):
- 無(wú)需將 AWS 憑證硬編碼在代碼中。
- 臨時(shí)憑證會(huì)自動(dòng)輪換,降低憑證泄露風(fēng)險(xiǎn)。
- 細(xì)粒度權(quán)限控制(通過(guò) IAM 策略)。
AWS Security Token Service (STS)
它提供臨時(shí)安全憑證,用于跨賬戶、跨區(qū)域或在有限時(shí)間內(nèi)訪問(wèn) AWS 服務(wù)。
使用場(chǎng)景:
- EC2 實(shí)例或 Lambda 函數(shù)需要臨時(shí)訪問(wèn)權(quán)限。
- 跨賬戶訪問(wèn) AWS 資源。
- 使用聯(lián)合身份(如 SAML 或 OpenID Connect)訪問(wèn) AWS。
工作流程:
- 應(yīng)用程序使用
AWS SDK或AWS CLI調(diào)用AssumeRole或AssumeRoleWithWebIdentityAPI。 - STS 返回一組臨時(shí)憑證(
Access Key、Secret Key和Session Token)。 - 應(yīng)用程序使用這些憑證調(diào)用 AWS 服務(wù)。
- 憑證會(huì)在指定時(shí)間后過(guò)期(默認(rèn) 1 小時(shí))。
2. 你是你嗎?— SPIFFE 的登場(chǎng)
雖然 IAM 在 AWS 生態(tài)系統(tǒng)中非常強(qiáng)大,但在跨云或混合云環(huán)境中,IAM 就顯得有些力不從心了。這時(shí)候,SPIFFE(Secure Production Identity Framework for Everyone)就登場(chǎng)了。
SPIFFE(Secure Production Identity Framework for Everyone)是一個(gè)開源框架,旨在為分布式系統(tǒng)中的服務(wù)提供可驗(yàn)證的身份。它的核心組成包括:
SPIFFE ID
它定義了一種機(jī)制,使得服務(wù)能夠在不依賴傳統(tǒng)憑據(jù)(如密碼或 API 密鑰)的情況下,證明它們的身份并進(jìn)行相互認(rèn)證。
類似于身份證的唯一標(biāo)識(shí)符,例如:spiffe://example.org/service-a。
每個(gè) Workload 工作負(fù)載(比如一個(gè)微服務(wù))都可以擁有一個(gè)唯一的身份標(biāo)識(shí)符 - SPIFFE ID。
SPIFFE 提供了以下主要功能:
- 統(tǒng)一身份表示:通過(guò) URI(如 spiffe://example.org/service-name)表示身份。
- 身份驗(yàn)證:支持基于證書的互相驗(yàn)證,而無(wú)需共享密碼或其他敏感憑據(jù)。
SVID(SPIFFE Verifiable Identity Document)
SVID(SPIFFE Verifiable Identity Document) 可驗(yàn)證身份文檔是 SPIFFE 的身份實(shí)現(xiàn),它是服務(wù)的身份憑證。SVID 通常由 X.509 證書形式表示,包含以下內(nèi)容:
- SPIFFE ID:存儲(chǔ)在證書的 Subject Alternative Name (SAN) 字段中,表示服務(wù)的身份。
- 公共密鑰:用于加密和簽名,保證通信安全。
- 有效期:定義身份的生效和失效時(shí)間。
在分布式環(huán)境中,SVID 用于在服務(wù)間進(jìn)行安全通信??梢詫?SVID 類比為情報(bào)機(jī)構(gòu)頒發(fā)的“特工證”:
- SPIFFE ID 是特工的“身份號(hào)碼”,存儲(chǔ)在證書中。
- 私鑰和公鑰 是特工的“密鑰對(duì)”,用于加密信息和簽名。
- 有效期 就像特工證的“過(guò)期日期”,超過(guò)時(shí)間后必須更新。
通過(guò)這種設(shè)計(jì),所有特工(服務(wù))可以通過(guò) SVID 相互識(shí)別并安全通信,而無(wú)需依賴傳統(tǒng)的“暗號(hào)”或密碼。這種機(jī)制在現(xiàn)代分布式系統(tǒng)中尤其重要,用于構(gòu)建零信任安全模型。
信任域(Trust Domain)
一組共享信任的服務(wù),通常通過(guò)一個(gè)共同的根證書(Root Certificate)管理。
SPIFFE 的核心目標(biāo)是確保服務(wù)之間的身份認(rèn)證不依賴固定的網(wǎng)絡(luò)配置或共享密鑰。
3. 如何證明你是你?— AWS IAM 與 SPIFFE 的結(jié)合
現(xiàn)在,我們來(lái)看看如何將 AWS IAM 和 SPIFFE 結(jié)合起來(lái),解決“如何證明你是你”的問(wèn)題。
步驟 1:創(chuàng)建 IAM 角色
首先,你需要在 AWS IAM 中創(chuàng)建一個(gè)角色,并為這個(gè)角色分配適當(dāng)?shù)臋?quán)限。這個(gè)角色將代表你的微服務(wù)在 AWS 中的身份。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
步驟 2:生成 SPIFFE ID
接下來(lái),你需要為你的微服務(wù)生成一個(gè) SPIFFE ID。這個(gè) ID 通常是一個(gè) URI,格式如下:
spiffe://example.org/my-service
步驟 3:將 SPIFFE ID 與 IAM 角色關(guān)聯(lián)
現(xiàn)在,你需要將 SPIFFE ID 與 IAM 角色關(guān)聯(lián)起來(lái)。這可以通過(guò) AWS IAM 的 AssumeRole 操作來(lái)實(shí)現(xiàn)。具體來(lái)說(shuō),你可以創(chuàng)建一個(gè)信任策略,允許具有特定 SPIFFE ID 的實(shí)體(即你的微服務(wù))來(lái)扮演這個(gè) IAM 角色。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "spiffe://example.org/my-service"
},
"Action": "sts:AssumeRole"
}
]
}
步驟 4:驗(yàn)證身份
當(dāng)你的微服務(wù)需要訪問(wèn) AWS 資源時(shí),它會(huì)使用 SPIFFE ID 來(lái)請(qǐng)求一個(gè)臨時(shí)的安全令牌。AWS IAM 會(huì)驗(yàn)證這個(gè) SPIFFE ID,并生成一個(gè)臨時(shí)的訪問(wèn)令牌。這個(gè)令牌可以用來(lái)訪問(wèn) AWS 資源,比如 S3 存儲(chǔ)桶。
import boto3
# 使用 SPIFFE ID 請(qǐng)求臨時(shí)安全令牌
sts_client = boto3.client('sts')
response = sts_client.assume_role_with_web_identity(
RoleArn='arn:aws:iam::123456789012:role/my-role',
RoleSessionName='my-service',
WebIdentityToken='spiffe://example.org/my-service'
)
# 使用臨時(shí)令牌訪問(wèn) S3
s3_client = boto3.client(
's3',
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken']
)
# 獲取 S3 對(duì)象
response = s3_client.get_object(Bucket='my-bucket', Key='my-key')
print(response['Body'].read())
實(shí)際應(yīng)用中, 我們可能需要 AWS Identity and Access Management (IAM) Roles Anywhere,
這個(gè)工具允許用戶的本地服務(wù)器或外部環(huán)境(如私有云、數(shù)據(jù)中心)使用 IAM 角色 授權(quán)訪問(wèn) AWS 服務(wù),而無(wú)需在這些環(huán)境中存儲(chǔ)長(zhǎng)期憑證(如訪問(wèn)密鑰和密鑰對(duì)):
- 配置信任關(guān)系 Trust Relationships
用戶在 AWS 中創(chuàng)建 IAM 角色,并允許 AWS Roles Anywhere 假設(shè)該角色(AssumeRole)。
- 配置信任錨點(diǎn) Trust Anchors
信任錨點(diǎn)是 AWS Roles Anywhere 用來(lái)驗(yàn)證外部環(huán)境的公鑰證書(通常由認(rèn)證機(jī)構(gòu) CA 簽發(fā)的 X.509 證書)。
用戶將 CA 的根證書上傳到 AWS Roles Anywhere 作為信任錨點(diǎn)。
- 客戶端憑證請(qǐng)求 Client Certificates
本地服務(wù)器或外部系統(tǒng)使用其簽名的證書,向 Roles Anywhere 服務(wù)請(qǐng)求臨時(shí)憑證。
- 頒發(fā)臨時(shí)憑證 Generate Temporary Credentials
Roles Anywhere 驗(yàn)證證書和信任錨點(diǎn),確定請(qǐng)求者身份。
根據(jù)配置的 IAM 角色和策略,生成臨時(shí)憑證(Access Key、Secret Key 和 Session Token)。
- 訪問(wèn) AWS 服務(wù)
臨時(shí)憑證被返回給本地服務(wù)器, 一般包括 Access Key、Secret Key 和 Session Token。
本地服務(wù)器使用這些憑證訪問(wèn) AWS 資源。
4. SVID 的簽發(fā)和驗(yàn)證過(guò)程
我寫了一個(gè)小程序, 演示一下如何簽發(fā)和驗(yàn)證 SVID:
4.1 生成 SVID
函數(shù) generate_svid 通過(guò)以下步驟生成一個(gè) SVID:
-
生成私鑰:
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)創(chuàng)建 2048 位的 RSA 密鑰,用于簽署證書。
-
構(gòu)造證書信息:
subject = issuer = x509.Name([...]) san = x509.SubjectAlternativeName([ x509.UniformResourceIdentifier(spiffe_id), ])-
subject和issuer定義證書的主體和頒發(fā)者信息(自簽名證書中,主體和頒發(fā)者相同)。 -
san定義 SPIFFE ID,存儲(chǔ)在證書的 Subject Alternative Name 字段中。
-
-
簽署證書:
certificate = ( x509.CertificateBuilder() .subject_name(subject) .issuer_name(issuer) .public_key(private_key.public_key()) .serial_number(x509.random_serial_number()) .not_valid_before(datetime.now(timezone.utc)) .not_valid_after(datetime.now(timezone.utc) + timedelta(days=365)) .add_extension(san, critical=False) .sign(private_key, hashes.SHA256()) )- 證書有效期為 1 年。
- 使用私鑰簽名,生成完整的 X.509 證書。
-
保存證書和私鑰:
with open(f"{output_path}_key.pem", "wb") as key_file: key_file.write(private_key.private_bytes(...)) with open(f"{output_path}_cert.pem", "wb") as cert_file: cert_file.write(certificate.public_bytes(Encoding.PEM))
4.2解析證書
函數(shù) parse_certificate 提取并打印證書的詳細(xì)信息,包括:
- Subject 和 Issuer:主體和頒發(fā)者信息。
- Serial Number:證書的唯一序列號(hào)。
- Public Key:公鑰算法。
- Extensions:擴(kuò)展字段(如 SAN)。
4.3 驗(yàn)證 SVID
函數(shù) verify_svid 驗(yàn)證 SVID 的有效性,主要包括:
-
提取 SPIFFE ID:
san = certificate.extensions.get_extension_for_class(x509.SubjectAlternativeName) spiffe_id = san.value.get_values_for_type(x509.UniformResourceIdentifier) -
驗(yàn)證簽名:
public_key.verify( certificate.signature, certificate.tbs_certificate_bytes, padding.PKCS1v15(), certificate.signature_hash_algorithm )確保證書的簽名匹配。
-
檢查有效期:
now = datetime.utcnow() if certificate.not_valid_before <= now <= certificate.not_valid_after: print("certificate is valid")
完成代碼參見 generate_svid.py
5. 總結(jié)
通過(guò)將 AWS IAM 和 SPIFFE 結(jié)合起來(lái),你可以輕松地在分布式系統(tǒng)中證明“你是你”。IAM 提供了強(qiáng)大的身份和訪問(wèn)管理功能,而 SPIFFE 則為跨云和混合云環(huán)境提供了一個(gè)統(tǒng)一的身份框架。兩者的結(jié)合,就像是在數(shù)字世界里為你打造了一張全球通用的身份證,無(wú)論你走到哪里,都能證明自己的身份。
所以,下次有人問(wèn)你“如何證明你是你”時(shí),你可以自信地回答:“我有我的 SPIFFE ID 和 IAM 角色,我就是我,不一樣的煙火!”
本作品采用知識(shí)共享署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際許可協(xié)議進(jìn)行許可。