Chuyển đến nội dung chính

Bài 12: LDAP, OIDC và JWT Auth Methods

LDAP Auth Method (cấu hình LDAP/Active Directory, group mapping, policies), OIDC Auth Method (cấu hình với Keycloak, Azure AD, Okta, Google), JWT Auth Method (cho CI/CD — GitHub Actions OIDC, GitLab CI JWT), Bound claims, Claim mappings, allowed_redirect_uris.

🔒 DevSecOps — Bài 12 Bài 12: LDAP, OIDC và JWT Auth Methods

HashiCorp Vault từ Cơ bản đến Nâng cao

Phần 3: Auth Methods - Xác thực và Ủy quyền

xdev.asia

1. LDAP Auth Method

LDAP Auth Method cho phép Vault xác thực users bằng LDAP directory (Active Directory, OpenLDAP, FreeIPA). Đây là phương pháp phổ biến nhất trong enterprise để xác thực human users vì hầu hết tổ chức đã có sẵn LDAP/AD infrastructure.

Kiến trúc

┌──────────┐   1. Login           ┌──────────────┐
│   User   │ ───────────────────▶ │    Vault     │
│          │                      │  LDAP Auth   │
│          │   4. Vault Token     │              │
│          │ ◀─────────────────── │              │
└──────────┘                      └──────┬───────┘
                                         │
                                2. LDAP Bind (verify password)
                                3. Search groups
                                         │
                                         ▼
                                  ┌──────────────┐
                                  │  LDAP Server │
                                  │  (AD / LDAP) │
                                  └──────────────┘

Cấu hình với Active Directory

# Enable LDAP auth
vault auth enable ldap

# Cấu hình kết nối Active Directory
vault write auth/ldap/config \
  url="ldaps://ad.company.com:636" \
  userdn="OU=Users,DC=company,DC=com" \
  userattr="sAMAccountName" \
  groupdn="OU=Groups,DC=company,DC=com" \
  groupattr="cn" \
  groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" \
  binddn="CN=vault-svc,OU=ServiceAccounts,DC=company,DC=com" \
  bindpass="VaultServiceP@ss" \
  starttls=false \
  insecure_tls=false \
  certificate=@/etc/vault/ldap-ca.pem \
  token_ttl=8h \
  token_max_ttl=24h

Cấu hình với OpenLDAP

vault write auth/ldap/config \
  url="ldaps://ldap.company.com:636" \
  userdn="ou=people,dc=company,dc=com" \
  userattr="uid" \
  groupdn="ou=groups,dc=company,dc=com" \
  groupattr="cn" \
  groupfilter="(|(memberUid={{.Username}})(member={{.UserDN}}))" \
  binddn="cn=vault,ou=services,dc=company,dc=com" \
  bindpass="LdapBindP@ss" \
  certificate=@/etc/vault/ldap-ca.pem

Group → Policy Mapping

# Map LDAP group "DevOps" → Vault policies
vault write auth/ldap/groups/DevOps \
  policies="devops-admin,kv-devops,pki-issue"

# Map LDAP group "Developers" → Vault policies
vault write auth/ldap/groups/Developers \
  policies="dev-readonly,kv-dev"

# Map LDAP group "DBA" → Vault policies
vault write auth/ldap/groups/DBA \
  policies="db-admin,db-rotate"

# Map specific user → additional policies
vault write auth/ldap/users/john.doe \
  policies="team-lead-extra" \
  groups="DevOps,Developers"

# Liệt kê groups
vault list auth/ldap/groups

Login với LDAP

# CLI login
vault login -method=ldap username=john.doe
# Password (will be hidden): ****

# API login
curl -s --request POST \
  --data '{"password": "userPassword"}' \
  ${VAULT_ADDR}/v1/auth/ldap/login/john.doe | jq .

2. OIDC Auth Method

OIDC (OpenID Connect) Auth Method cho phép Vault xác thực qua các Identity Providers hỗ trợ OIDC — Keycloak, Azure AD (Entra ID), Okta, Google Workspace, Auth0. Đây là phương pháp hiện đại nhất cho human authentication vì hỗ trợ SSO, MFA, và browser-based login.

OIDC Authentication Flow

┌──────────┐   1. vault login       ┌──────────────┐
│   User   │ ─────────────────────▶ │    Vault     │
│ (Browser)│                        │  OIDC Auth   │
│          │   2. Redirect to IdP   │              │
│          │ ◀───────────────────── │              │
│          │                        └──────────────┘
│          │   3. Login at IdP
│          │ ─────────────────────▶ ┌──────────────┐
│          │                        │  Keycloak/   │
│          │   4. Auth code         │  Azure AD    │
│          │ ◀───────────────────── │              │
│          │                        └──────────────┘
│          │   5. Auth code → Vault
│          │ ─────────────────────▶ ┌──────────────┐
│          │                        │    Vault     │
│          │   6. Exchange code     │              │
│          │      for tokens        │              │
│          │   7. Vault Token       │              │
│          │ ◀───────────────────── │              │
└──────────┘                        └──────────────┘

Cấu hình với Keycloak

# Enable OIDC auth
vault auth enable oidc

# Cấu hình OIDC với Keycloak
vault write auth/oidc/config \
  oidc_discovery_url="https://keycloak.company.com/realms/company" \
  oidc_client_id="vault" \
  oidc_client_secret="vault-client-secret" \
  default_role="default"

# Tạo OIDC role
vault write auth/oidc/role/default \
  bound_audiences="vault" \
  allowed_redirect_uris="https://vault.company.com/ui/vault/auth/oidc/oidc/callback" \
  allowed_redirect_uris="http://localhost:8250/oidc/callback" \
  user_claim="preferred_username" \
  groups_claim="groups" \
  token_policies="default" \
  token_ttl=8h \
  token_max_ttl=24h \
  oidc_scopes="openid,profile,email,groups"

# Tạo role cho admin với bound claims
vault write auth/oidc/role/admin \
  bound_audiences="vault" \
  allowed_redirect_uris="https://vault.company.com/ui/vault/auth/oidc/oidc/callback" \
  allowed_redirect_uris="http://localhost:8250/oidc/callback" \
  user_claim="preferred_username" \
  groups_claim="groups" \
  bound_claims='{"department": "IT", "role": "admin"}' \
  claim_mappings='{"email": "email", "department": "department"}' \
  token_policies="admin,kv-admin" \
  token_ttl=4h \
  token_max_ttl=8h

Cấu hình với Azure AD (Entra ID)

vault write auth/oidc/config \
  oidc_discovery_url="https://login.microsoftonline.com/<tenant-id>/v2.0" \
  oidc_client_id="<application-id>" \
  oidc_client_secret="<client-secret>" \
  default_role="azure-default"

vault write auth/oidc/role/azure-default \
  bound_audiences="<application-id>" \
  allowed_redirect_uris="https://vault.company.com/ui/vault/auth/oidc/oidc/callback" \
  allowed_redirect_uris="http://localhost:8250/oidc/callback" \
  user_claim="email" \
  groups_claim="groups" \
  token_policies="default" \
  oidc_scopes="openid,profile,email"

Login với OIDC

# Browser-based login (mở browser tự động)
vault login -method=oidc role=default

# Chỉ định port cho callback
vault login -method=oidc port=8250 role=default

# Qua Vault UI: chọn OIDC → Sign in → redirect đến IdP

3. JWT Auth Method

JWT Auth Method xác thực bằng JSON Web Tokens. Khác với OIDC (browser-based), JWT auth phù hợp cho machine authentication khi client đã có sẵn JWT token — đặc biệt cho CI/CD pipelines.

JWT vs OIDC Auth

Tiêu chíJWT AuthOIDC Auth
Login flowClient gửi JWT trực tiếpBrowser-based redirect
Đối tượngMachines, CI/CDHuman users
Token sourceClient đã có JWTVault lấy từ IdP
MFA supportKhôngCó (qua IdP)

GitHub Actions OIDC → Vault JWT Auth

GitHub Actions cung cấp OIDC tokens cho mỗi workflow run, cho phép xác thực với Vault mà không cần lưu secrets:

# Enable JWT auth cho GitHub Actions
vault auth enable -path=github-actions jwt

# Cấu hình JWT auth với GitHub OIDC Provider
vault write auth/github-actions/config \
  oidc_discovery_url="https://token.actions.githubusercontent.com" \
  bound_issuer="https://token.actions.githubusercontent.com"

# Tạo role cho repository cụ thể
vault write auth/github-actions/role/my-app \
  role_type="jwt" \
  bound_audiences="https://github.com/my-org" \
  bound_claims_type="glob" \
  bound_claims='{"repository": "my-org/my-app", "ref": "refs/heads/main"}' \
  user_claim="repository" \
  token_policies="my-app-deploy" \
  token_ttl=10m \
  token_max_ttl=30m

# Tạo role cho toàn bộ organization
vault write auth/github-actions/role/org-readonly \
  role_type="jwt" \
  bound_audiences="https://github.com/my-org" \
  bound_claims_type="glob" \
  bound_claims='{"repository": "my-org/*"}' \
  user_claim="repository" \
  token_policies="org-readonly" \
  token_ttl=5m

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: Deploy with Vault OIDC
on:
  push:
    branches: [main]

permissions:
  id-token: write   # Required cho OIDC token
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Authenticate to Vault
        uses: hashicorp/vault-action@v3
        with:
          url: https://vault.company.com
          method: jwt
          path: github-actions
          role: my-app
          jwtGithubAudience: https://github.com/my-org
          secrets: |
            secret/data/production/db username | DB_USER ;
            secret/data/production/db password | DB_PASS

      - name: Deploy
        run: ./deploy.sh

GitLab CI JWT Auth

# Enable JWT auth cho GitLab CI
vault auth enable -path=gitlab-ci jwt

# Cấu hình
vault write auth/gitlab-ci/config \
  jwks_url="https://gitlab.company.com/-/jwks" \
  bound_issuer="https://gitlab.company.com"

# Tạo role
vault write auth/gitlab-ci/role/deploy \
  role_type="jwt" \
  bound_claims='{"project_id": "42", "ref_protected": "true"}' \
  user_claim="project_path" \
  token_policies="gitlab-deploy" \
  token_ttl=10m
# .gitlab-ci.yml
deploy:
  stage: deploy
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.company.com
  script:
    - |
      VAULT_TOKEN=$(vault write -field=token auth/gitlab-ci/login \
        role=deploy \
        jwt="${VAULT_ID_TOKEN}")
      export VAULT_TOKEN
      DB_PASS=$(vault kv get -field=password secret/production/db)
      ./deploy.sh

4. Bound Claims và Claim Mappings

Bound Claims

Bound claims giới hạn JWT tokens nào được phép login vào một role:

# Exact match
vault write auth/jwt/role/strict-role \
  bound_claims='{"department": "engineering", "team": "platform"}'

# Glob pattern matching
vault write auth/jwt/role/glob-role \
  bound_claims_type="glob" \
  bound_claims='{"repository": "my-org/*", "ref": "refs/heads/main"}'

# Multiple values (OR logic)
vault write auth/jwt/role/multi-role \
  bound_claims='{"group": ["devops", "sre", "platform"]}'

Claim Mappings

Claim mappings map JWT claims vào Vault identity metadata:

vault write auth/oidc/role/mapped-role \
  claim_mappings='{"email": "email", "department": "dept", "employee_id": "emp_id"}'

# Metadata available in policies:
# {{identity.entity.aliases.<mount_accessor>.metadata.email}}
# {{identity.entity.aliases.<mount_accessor>.metadata.dept}}

5. Best Practices

LDAP

  • Luôn sử dụng LDAPS (port 636) hoặc StartTLS

  • Service account cho Vault bind nên có quyền read-only

  • Map groups thay vì individual users để dễ quản lý

  • Test cấu hình LDAP filter kỹ trước khi áp dụng production

OIDC

  • Giới hạn allowed_redirect_uris chỉ cho Vault URL thực tế

  • Sử dụng bound_claims để restrict access theo department/role

  • Enable MFA tại IdP (Keycloak, Azure AD)

  • Rotate oidc_client_secret định kỳ

JWT

  • Ưu tiên OIDC tokens từ CI/CD thay vì static secrets (AppRole)

  • Bound claims nên càng specific càng tốt (repo, branch, environment)

  • Token TTL ngắn (5-15 phút) cho CI/CD

  • Sử dụng bound_audiences để prevent token misuse

6. Tổng kết

  • LDAP Auth — lựa chọn enterprise cho human users, tận dụng AD/LDAP infrastructure sẵn có

  • OIDC Auth — hiện đại nhất cho human users, SSO, MFA, browser-based login

  • JWT Auth — lý tưởng cho CI/CD (GitHub Actions OIDC, GitLab CI JWT), không cần lưu static secrets

Bài tiếp theo sẽ tập trung vào Kubernetes, AWS và Cloud Auth Methods — xác thực dựa trên workload identity.