相信大家對 JWT 都很熟悉了,不熟的可以到這裡複習一下Hashicorp Vault Server 支援 JWT Authentication Method,話不多說,客倌上碼。
開發環境
- Windows 11 Home
- Windows Terminal 1.20.11781.0
- Vault 1.17.6
建立 Vault Server 開發環境
vault server -dev
設定環境變數
$Env:VAULT_ADDR = "http://127.0.0.1:8200"
建立 JWT
在 JSON Web Tokens - jwt.io 產生 JWT
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "RS256",
"typ": "JWT"
}
Vault 不支援 HS256
PAYLOAD:DATA
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022,
"aud":"https://my-app.com",
"exp": "2024-12-25T00:00:00Z"
}
Public Key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u
+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh
kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ
0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg
cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc
mwIDAQAB
-----END PUBLIC KEY-----
Private Key
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7VJTUt9Us8cKj
MzEfYyjiWA4R4/M2bS1GB4t7NXp98C3SC6dVMvDuictGeurT8jNbvJZHtCSuYEvu
NMoSfm76oqFvAp8Gy0iz5sxjZmSnXyCdPEovGhLa0VzMaQ8s+CLOyS56YyCFGeJZ
qgtzJ6GR3eqoYSW9b9UMvkBpZODSctWSNGj3P7jRFDO5VoTwCQAWbFnOjDfH5Ulg
p2PKSQnSJP3AJLQNFNe7br1XbrhV//eO+t51mIpGSDCUv3E0DDFcWDTH9cXDTTlR
ZVEiR2BwpZOOkE/Z0/BVnhZYL71oZV34bKfWjQIt6V/isSMahdsAASACp4ZTGtwi
VuNd9tybAgMBAAECggEBAKTmjaS6tkK8BlPXClTQ2vpz/N6uxDeS35mXpqasqskV
laAidgg/sWqpjXDbXr93otIMLlWsM+X0CqMDgSXKejLS2jx4GDjI1ZTXg++0AMJ8
sJ74pWzVDOfmCEQ/7wXs3+cbnXhKriO8Z036q92Qc1+N87SI38nkGa0ABH9CN83H
mQqt4fB7UdHzuIRe/me2PGhIq5ZBzj6h3BpoPGzEP+x3l9YmK8t/1cN0pqI+dQwY
dgfGjackLu/2qH80MCF7IyQaseZUOJyKrCLtSD/Iixv/hzDEUPfOCjFDgTpzf3cw
ta8+oE4wHCo1iI1/4TlPkwmXx4qSXtmw4aQPz7IDQvECgYEA8KNThCO2gsC2I9PQ
DM/8Cw0O983WCDY+oi+7JPiNAJwv5DYBqEZB1QYdj06YD16XlC/HAZMsMku1na2T
N0driwenQQWzoev3g2S7gRDoS/FCJSI3jJ+kjgtaA7Qmzlgk1TxODN+G1H91HW7t
0l7VnL27IWyYo2qRRK3jzxqUiPUCgYEAx0oQs2reBQGMVZnApD1jeq7n4MvNLcPv
t8b/eU9iUv6Y4Mj0Suo/AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDU
AhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn//LiH1B3rXhcdyo3/vIttEk
48RakUKClU8CgYEAzV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD/ISL
DY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnK
xt1Il2HgxOBvbhOT+9in1BzA+YJ99UzC85O0Qz06A+CmtHEy4aZ2kj5hHjECgYEA
mNS4+A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2+cwPLhPIzIuwytXywh
2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfz
et6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEsCgYAnM3DQf3FJoSnXaMhr
VBIovic5l0xFkEHskAjFTevO86Fsz1C2aSeRKSqGFoOQ0tmJzBEs1R6KqnHInicD
TQrKhArgLXX4v3CddjfTRJkFWDbE/CkvKZNOrcf1nhaGCPspRJj2KUkj1Fhl9Cnc
dn/RsYEONbwQSjIfMPkvxF+8HQ==
-----END PRIVATE KEY-----
JWT 如下
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiYXVkIjoiaHR0cHM6Ly9teS1hcHAuY29tIiwiZXhwIjoiMjAyNC0xMi0yNVQwMDowMDowMFoifQ.atqlh56aWxhRQUp6Ewr4P4JaMW4dCP8gTKa5hLo1dYk4wFy6j_hDF4GUFSoS2iU8JTbDGzUcRg5IHOEAqvN4l2ivMlskdyRL-75C0BwOcDPAfY0r5T9OLmR79zvCOuTfP-jZ-J7VpnH3vdHLfQtPpLe-9tz1Bq0ZbgAmiQqtV62_qap5xXMV-DteK4h98niyDNGOxrKRW5GBEYTIJhrrvSX2L8lY1VDxN2MfaHtc6m4MHJKu9hjTVH0KOyLKUE-K6ZCj1n5ewx2MUr0C8nYaBFEtseSCvmJtG0tTVJYgENMQjyyKXIam-SbjbAoXAAaRb95qTi9l0DGFSe3Y41Fs9g
Vault CLI
啟用 JWT
PS C:\Users\yao> vault auth enable jwt
Success! Enabled jwt auth method at: jwt/
設定 Policy
$policy = @"
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/job/dream-team/*" {
capabilities = ["create", "update", "read"]
}
"@
$policy | Out-File -FilePath "my-policy.hcl" -Encoding utf8
vault policy write my-policy "my-policy.hcl"
PS C:\Users\yao> $policy = @"
>> # Dev servers have version 2 of KV secrets engine mounted by default, so will
>> # need these paths to grant permissions:
>> path "secret/data/job/dream-team/*" {
>> capabilities = ["create", "update", "read"]
>> }
>> "@
PS C:\Users\yao> $policy | Out-File -FilePath "my-policy.hcl" -Encoding utf8
PS C:\Users\yao> vault policy write my-policy "my-policy.hcl"
Success! Uploaded policy: my-policy
建立 JWT Role
vault write auth/jwt/role/my-role `
role_type="jwt" `
bound_audiences="https://my-app.com" `
user_claim="sub" `
policies="default,my-policy" `
ttl="1h"
PS C:\Users\yao> vault write auth/jwt/role/my-role `
>> role_type="jwt" `
>> bound_audiences="https://my-app.com" `
>> user_claim="sub" `
>> policies="default,my-policy" `
>> ttl="1h"
Success! Data written to: auth/jwt/role/my-role
這裡指定了以下幾個參數:
- role_type="jwt":指定這是 JWT 認證方法的角色。
- bound_audiences:JWT 中的 aud(Audience)必須符合此值。
- user_claim="sub":Vault 使用 JWT 中的 sub 字段作為識別使用者。
- policies:當 JWT 驗證成功後,Vault 將授予的策略。
設定 JWT
vault write auth/jwt/config `
jwt_supported_algs="RS256" `
jwt_validation_pubkeys="-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u
+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh
kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ
0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg
cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc
mwIDAQAB
-----END PUBLIC KEY-----"
PS C:\Users\yao> vault write auth/jwt/config `
>> jwt_supported_algs="RS256" `
>> jwt_validation_pubkeys="-----BEGIN PUBLIC KEY-----
>> MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
>> 4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u
>> +qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyeh
>> kd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ
>> 0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdg
>> cKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbc
>> mwIDAQAB
>> -----END PUBLIC KEY-----"
Success! Data written to: auth/jwt/config
取得 Token
$jwt="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiYXVkIjoiaHR0cHM6Ly9teS1hcHAuY29tIiwiZXhwIjoyNTAyMzI1MzkxfQ.D2JxyzxI40fz72mUQP4Y8imjIF9cyt1qTpaPJS8bX1sJHnLHNQlRwRMMqcc-aurs9yoYB99r_KbL2cIoS64DenTt1ZYy1_xrwmDbU069to0D6I28dG9QozwLWnKoRziqxfuo8yXb6Z-pezfh1jW2NeFw43Jcu6_ZrIa2SQfRcI4WcjlGpDyH1ct1_dRkFozniT9OS3_bIGkWtvDzc0VgGIBsNZzeSXEAH4M14e0_DHpAwY5DwRzmXO8y5etxoWp36pqge3SrpsFWFUNrKKHYcv-ksX4ml1s4fQZtHNJqVh0OJh4RmCHqBta7rkgf53zkk3djoi_5CWCm-Br2jnTnqQ"; `
vault write auth/jwt/login `
role="my-role" `
jwt=$jwt
PS C:\Users\yao> $jwt="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiYXVkIjoiaHR0cHM6Ly9teS1hcHAuY29tIiwiZXhwIjoyNTAyMzI1MzkxfQ.D2JxyzxI40fz72mUQP4Y8imjIF9cyt1qTpaPJS8bX1sJHnLHNQlRwRMMqcc-aurs9yoYB99r_KbL2cIoS64DenTt1ZYy1_xrwmDbU069to0D6I28dG9QozwLWnKoRziqxfuo8yXb6Z-pezfh1jW2NeFw43Jcu6_ZrIa2SQfRcI4WcjlGpDyH1ct1_dRkFozniT9OS3_bIGkWtvDzc0VgGIBsNZzeSXEAH4M14e0_DHpAwY5DwRzmXO8y5etxoWp36pqge3SrpsFWFUNrKKHYcv-ksX4ml1s4fQZtHNJqVh0OJh4RmCHqBta7rkgf53zkk3djoi_5CWCm-Br2jnTnqQ"; `
PS C:\Users\yao> vault write auth/jwt/login `
>> role="my-role" `
>> jwt=$jwt
Key Value
--- -----
token hvs.CAESIJxYi5OkbdXFH-YjZ2QqOdWRttyOgUYU8SoCZHhIpViFGh4KHGh2cy5UV1RDeFJCYzRVb3RqN0ZYQXlLT1FBOVA
token_accessor Fj2rRZVgCXEcKhn0kn4esLkG
token_duration 1h
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
token_meta_role my-role
登入
PS C:\Users\yao> vault login hvs.CAESIJxYi5OkbdXFH-YjZ2QqOdWRttyOgUYU8SoCZHhIpViFGh4KHGh2cy5UV1RDeFJCYzRVb3RqN0ZYQXlLT1FBOVA
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.CAESIJxYi5OkbdXFH-YjZ2QqOdWRttyOgUYU8SoCZHhIpViFGh4KHGh2cy5UV1RDeFJCYzRVb3RqN0ZYQXlLT1FBOVA
token_accessor Fj2rRZVgCXEcKhn0kn4esLkG
token_duration 59m17s
token_renewable true
token_policies ["default" "my-policy"]
identity_policies []
policies ["default" "my-policy"]
token_meta_role my-role
讀 KV
PS C:\Users\yao> vault kv get -mount="secret" "job/dream-team/my-secret"
============ Secret Path ============
secret/data/job/dream-team/my-secret
======= Metadata =======
Key Value
--- -----
created_time 2024-10-10T03:22:24.5812039Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 5
====== Data ======
Key Value
--- -----
User admin
password 1234567890
心得
本以為 JWT Authentication Method 應該可以不會再卡關了,但還是小卡了一下,根據錯誤訊息搭配 ChatGPT 都有順利的解決問題,ChatGPT 真的棒
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET