Գաղտնիքների կառավարում և Vault
Գաղտնաբառերը, բանալիները և token-ները պահեք կոդից դուրս և դարձրեք դրանք կարճաժամկետ, աուդիտվող և հեշտ rotate արվող։
30 վայրկյանում
Գաղտնիքները այն գաղտնաբառերը, API key-երը, սերտիֆիկատներն ու token-ներն են, որոնք ձեր ծրագրին պետք են այլ համակարգերի հետ հաղորդակցվելու համար։ Գաղտնիքների կառավարումը նշանակում է դրանք պահել մեկ պաշտպանված տեղում, յուրաքանչյուր հավելվածին տալ միայն այն, ինչ նրան պետք է, log անել յուրաքանչյուր հասանելիություն և պարբերաբար փոխել դրանք։ HashiCorp Vault-ի, OpenBao-ի և cloud secret manager-ների նման գործիքները կարող են նույնիսկ ըստ պահանջի ստեղծել կարճաժամկետ credentials, այնպես որ գողանալու գրեթե բան չի մնում։
Իմ ամենօրյա stack-ում չէ․ գիտեմ հիմնական գաղափարները և մանրամասները կսովորեմ, երբ նախագիծը դա պահանջի։
Ինչու է սա կարևոր
- Արտահոսած credentials-ը breach-երի ամենատարածված մեկնակետերից են, իսկ Git-ում commit արված կամ chat-երում տեղադրված գաղտնիքները տարիներով մնում են գտնելի։
- Կենտրոնացված գաղտնիքները տալիս են մեկ տեղ, որտեղ կարելի է պատասխանել «ո՞վ կարող է կարդալ production բազայի գաղտնաբառը, և ո՞վ է կարդացել» հարցին, ինչին ցրված .env ֆայլերը չեն կարող պատասխանել։
- Rotation-ը դառնում է սովորական գործընթաց՝ վախեցնող ձեռքով նախագծի փոխարեն, ինչը կարևոր է, երբ աշխատակիցը հեռանում է կամ vendor-ը կոտրվում է։
- Թիմին secret manager պետք է, երբ այն ունի մի քանի միջավայր, ծառայություն կամ production հասանելիությամբ մարդ․ մեկ server-ի վրա աշխատող միայնակ հավելվածը կարող է սկսել լավ պաշտպանված environment ֆայլերով։
Ինչպես է աշխատում
01Ինչն է համարվում գաղտնիք, և ինչու .env ֆայլերը բավարար չեն
Գաղտնիքն այն ամենն է, ինչ հասանելիություն է տալիս՝ բազայի գաղտնաբառեր, վճարային կամ email provider-ների API key-եր, OAuth client secret-ներ, JWT ստորագրման բանալիներ, TLS private key-եր, SSH key-եր, գաղտնագրման բանալիներ և webhook-ի ստորագրման գաղտնիքներ։ Twelve-Factor մոտեցումը՝ կոնֆիգուրացիան environment փոփոխականներում դնելը, մեծ քայլ էր hard-code անելու համեմատ, և server-ի վրա .env ֆայլերը դեռ խելամիտ սկիզբ են։ Բայց համակարգի աճին զուգընթաց խնդիրներ են հայտնվում՝ նույն .env-ի պատճեններ laptop-ներում, CI-ում և server-ներում, գրանցում չկա, թե ով ինչ է կարդացել, հեշտ rotation չկա, գաղտնիքները տեսանելի են process-ների ցուցակներում, crash dump-երում կամ սխալների էջերում, և ֆայլը commit անելու մշտական ռիսկը։ Գաղտնիքների կառավարումը սա լուծում է՝ գաղտնիքներին վերաբերվելով որպես տվյալների՝ սեփականատիրոջով, մուտքի քաղաքականությամբ, audit log-ով և կյանքի ցիկլով։
- Երբեք Git-ում, Docker image-ներում, client bundle-ներում կամ log-երում
- Յուրաքանչյուր գաղտնիք ունի սեփականատեր, scope և rotation-ի պլան
- Հասանելիությունը տրվում է ըստ ինքնության և գրանցվում է
02Ինչպես է աշխատում secret manager-ը
Պատկերացրեք բանկային պահոց՝ պահակով և մատյանով։ Secret manager-ը գաղտնիքները պահում է at rest գաղտնագրված՝ սովորաբար cloud KMS-ով կամ hardware security module-ով պաշտպանված բանալու ներքո։ Հավելվածները authenticate են անում ինքնությամբ՝ cloud IAM role, Kubernetes service account, CI job-ի OIDC token կամ AppRole, ընդհանուր գաղտնաբառի փոխարեն։ Քաղաքականությունները ինքնությունները կապում են այն ուղիների հետ, որոնք նրանք կարող են կարդալ․ orders ծառայությունը կարող է կարդալ secret/prod/orders/* և ուրիշ ոչինչ։ Յուրաքանչյուր կարդալ և գրել գրանցվում է audit log-ում։ Հիմնական տարբերակները՝ HashiCorp Vault (2023-ից source-available BSL լիցենզիայով, այժմ IBM-ի մաս), OpenBao (Vault-ի open-source fork Linux Foundation-ի ներքո), cloud ծառայություններ, ինչպիսիք են AWS Secrets Manager-ը, Google Secret Manager-ը և Azure Key Vault-ը, և ծրագրավորողների վրա կենտրոնացած պլատֆորմներ, ինչպիսիք են Doppler-ը, Infisical-ը կամ 1Password Secrets Automation-ը։
03Vault-ի հիմունքներ՝ KV գաղտնիքներ և քաղաքականություններ
Vault-ը ամեն ինչ կազմակերպում է ըստ ուղիների։ Key/value (KV) secrets engine-ը պահում է ստատիկ գաղտնիքներ՝ տարբերակավորմամբ, այնպես որ կարող եք rollback անել։ HCL-ով գրված քաղաքականությունները ուղիների վրա տալիս են capabilities, ինչպիսիք են read, create, update կամ list։ Հավելվածները մուտք են գործում auth method-ով, որը համապատասխանում է նրան, թե որտեղ են աշխատում՝ kubernetes, aws, jwt/oidc CI-ի համար կամ approle, և ստանում են կարճաժամկետ Vault token՝ սահմանափակված քաղաքականությամբ։ Development ռեժիմը (vault server -dev) միայն սովորելու համար է․ այն աշխատում է հիշողության մեջ, unsealed, root token-ով։ Production-ին պետք են storage (integrated Raft storage-ը տարածված ընտրություն է), TLS, auto-unseal cloud KMS-ով կամ HSM-ով, միացված audit device-ներ, և root token-ը revoke արված կարգավորումից հետո։ Նույն հրամանները աշխատում են OpenBao-ի bao CLI-ով։
# Store and read a versioned secret (KV v2)
vault kv put secret/prod/orders db_password='use-a-generated-value'
vault kv get -field=db_password secret/prod/orders
# orders-policy.hcl — read-only access to one app's secrets
path "secret/data/prod/orders/*" {
capabilities = ["read"]
}
vault policy write orders orders-policy.hcl
vault audit enable file file_path=/var/log/vault_audit.log
04Dynamic secrets՝ credentials, որոնք ինքնուրույն ժամկետանց են դառնում
Vault-ի ամենաուժեղ գաղափարը dynamic secrets-ն է։ Բոլոր instance-ների կողմից կիսվող մեկ երկարաժամկետ բազայի գաղտնաբառի փոխարեն Vault-ը հավելվածի յուրաքանչյուր instance-ի համար ըստ պահանջի ստեղծում է եզակի բազայի օգտատեր՝ lease-ով, ասենք՝ մեկ ժամ։ Երբ lease-ի ժամկետն ավարտվում է կամ այն revoke է արվում, Vault-ը ջնջում է այդ օգտատիրոջը։ Արտահոսած credential-ը շուտով դառնում է անօգուտ, յուրաքանչյուր կապ վերագրելի է մեկ instance-ի, իսկ կոտրված ծառայության հասանելիությունը revoke անելը մեկ հրաման է։ Նույն սխեման կա cloud credentials-ի (ժամանակավոր AWS key-եր), PKI-ի (կարճաժամկետ TLS սերտիֆիկատներ) և SSH-ի (ստորագրված սերտիֆիկատներ authorized key-երի փոխարեն) համար։ Cloud provider-ները նման գաղափարներ առաջարկում են native կերպով՝ workload-ների IAM role-երը և IAM database authentication-ը ընդհանրապես խուսափում են պահված գաղտնաբառերից։ Հավելվածները պետք է մշակեն renewal-ը, ինչը ձեր փոխարեն անում են client գրադարանները և agent-ները, ինչպիսին է Vault Agent-ը։
# One-time setup by an admin
vault secrets enable database
vault write database/config/app-db plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db.internal:5432/app" \
allowed_roles="orders-ro" username="vault_admin" password="initial-admin-pass"
vault write -force database/rotate-root/app-db # Vault now owns the admin password
vault write database/roles/orders-ro db_name=app-db default_ttl=1h max_ttl=24h \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
# Each app instance asks for its own short-lived user
vault read database/creds/orders-ro
05Գաղտնիքները հավելվածներին հասցնելը
Կա առաքման երեք տարածված սխեմա։ Direct API՝ հավելվածն օգտագործում է SDK՝ գաղտնիքները startup-ի ժամանակ կարդալու և lease-երը թարմացնելու համար՝ ճկուն է, բայց կոդը կապում է vault-ին։ Sidecar կամ agent՝ Vault Agent-ը (կամ cloud համարժեքը) authenticate է անում, ստանում գաղտնիքները և render անում դրանք ֆայլի կամ environment-ի մեջ հավելվածի համար՝ ավտոմատ թարմացնելով, հավելվածը պարզապես կարդում է ֆայլը։ Platform sync՝ Kubernetes-ում External Secrets Operator-ը կամ Secrets Store CSI driver-ը համաժամեցնում են secret manager-ից pod-երի մեջ։ CI/CD-ում ընդհանրապես խուսափեք երկարաժամկետ cloud key-եր պահելուց․ GitHub Actions-ը, GitLab-ը և այլք կարող են յուրաքանչյուր job-ի համար թողարկել OIDC token, որը cloud-ը կամ Vault-ը փոխանակում է կարճաժամկետ credentials-ի հետ։ VPS-ի վրա Docker Compose-ի համար պարզ, հիմնավոր սխեմա է root-ին պատկանող env ֆայլերը mode 600-ով repository-ից դուրս, կամ Docker secrets՝ mount արված որպես ֆայլեր։
# GitHub Actions: no stored cloud keys — exchange the job's OIDC token
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/deploy-prod
aws-region: eu-central-1
- run: aws secretsmanager get-secret-value --secret-id prod/orders --query SecretString --output text > /dev/null
06Rotation, least privilege և արտահոսքի արձագանք
Rotation-ը նշանակում է գաղտնիքը փոխարինել նորով՝ ըստ ժամանակացույցի և ցանկացած կասկածելի բացահայտումից հետո։ Առանց downtime-ի rotate անելու համար միաժամանակ աջակցեք երկու վավեր տարբերակ՝ ստեղծեք նոր credential-ը, deploy արեք այն, համոզվեք, որ ոչինչ չի օգտագործում հինը, հետո revoke արեք հինը։ Cloud secret manager-ները կարող են ավտոմատացնել rotation-ը բազաների համար, երրորդ կողմի API key-երի համար rotation-ը սովորաբար script արված runbook է։ Least privilege-ը նշանակում է, որ յուրաքանչյուր ծառայություն, մարդ և pipeline ստանում է միայն իրեն անհրաժեշտ գաղտնիքները, իրեն անհրաժեշտ միջավայրում, իդեալում՝ միայն կարդալու համար։ Կանխարգելում՝ աշխատեցրեք secret scanner-ներ, ինչպիսիք են gitleaks-ը կամ TruffleHog-ը, pre-commit hook-երում և CI-ում և միացրեք ձեր Git host-ի push protection-ը։ Երբ գաղտնիքն արտահոսում է, կարգը կարևոր է՝ սկզբում revoke կամ rotate արեք այն, հետո հեռացրեք պատմությունից, որովհետև Git-ի պատմությունը վերագրելը «հետ չի բերում» արդեն clone կամ scrape արված բանալին։
- Rotate՝ ստեղծել նորը → deploy → ստուգել → revoke անել հինը
- Scan՝ pre-commit + CI + push protection
- Արտահոսք՝ սկզբում revoke, հետո մաքրել պատմությունը, հետո վերանայել access log-երը
Օգտագործեք, երբ
- Մի քանի ծառայություն կամ միջավայր, որոնք կիսում են credentials, որտեղ .env ֆայլերի պատճենները տարածվում են։
- Compliance-ի կամ հաճախորդների պահանջներ audit log-երի, հասանելիության վերանայումների և rotation-ի համար (SOC 2, ISO 27001, PCI DSS)։
- Համակարգեր, որոնք օգուտ են քաղում կարճաժամկետ credentials-ից՝ բազաներ, cloud հասանելիություն, ներքին TLS սերտիֆիկատներ։
- Թիմեր, որտեղ մարդիկ միանում և հեռանում են, ուստի հասանելիությունը պետք է արագ տրվի և հանվի յուրաքանչյուր մարդու համար։
Մի՛ օգտագործեք, երբ
- Փոքր, մեկ server-ի վրա աշխատող հավելված, որը վարում է մեկ մարդ․ պաշտպանված environment ֆայլերը, secret scanner-ը և լավ backup-ները առայժմ կարող են բավարար լինել։
- Self-hosted Vault աշխատեցնել՝ առանց այն շահագործելու կարողության․ unsealed, patch չարված կամ backup չունեցող Vault-ը single point of failure է, managed cloud secret manager-ն ավելի անվտանգ է։
- Ոչ գաղտնի կոնֆիգուրացիա, ինչպիսիք են feature flag-երը կամ URL-ները, որոնց տեղը սովորական config-ում է։
Այլընտրանքներ
- Cloud secret manager-ներ
AWS Secrets Manager, Google Secret Manager, Azure Key Vault՝ կառավարվող, IAM-ի հետ ինտեգրված, rotation hook-երով, կապված մեկ cloud-ի հետ։
- OpenBao
Vault-ի open-source fork՝ համատեղելի API-ով, այն թիմերի համար, որոնք ուզում են Vault-ի հնարավորությունները open-source լիցենզիայով։
- SOPS + age/KMS
Գաղտնագրում է գաղտնի արժեքները Git-ում commit արված ֆայլերի ներսում․ պարզ GitOps workflow, բայց առանց dynamic secrets-ի կամ ամեն ընթերցման audit-ի։
- Ծրագրավորողների secret պլատֆորմներ
Doppler, Infisical, 1Password՝ հեշտ համաժամեցում հավելվածների և CI-ի հետ, լավ UX, ավելի քիչ առաջադեմ dynamic հնարավորություններ։
Լավագույն պրակտիկաներ
- Workload-ները authenticate արեք պլատֆորմի ինքնությամբ (IAM role-եր, Kubernetes service account-ներ, CI OIDC), ոչ թե պահված master գաղտնաբառերով։
- Որտեղ նպատակային համակարգն աջակցում է, նախընտրեք կարճաժամկետ կամ dynamic credentials երկարաժամկետ ստատիկ գաղտնիքների փոխարեն։
- Գրեք նեղ քաղաքականություններ յուրաքանչյուր ծառայության և միջավայրի համար․ production գաղտնիքները երբեք չեն կարդացվում development-ից։
- Միացրեք audit logging և alert դրեք անսովոր հասանելիության վրա, օրինակ՝ երբ մարդը կարդում է production բազայի credentials-ը։
- Ավտոմատացրեք rotation-ը և փորձարկեք այն, ներառյալ երկու տարբերակի համընկնումը zero-downtime փոփոխությունների համար։
- Secret scanning աշխատեցրեք pre-commit-ում, CI-ում և Git push protection-ում։
- Գաղտնիքները պահեք log-երից, սխալների էջերից, Docker image-ի շերտերից և frontend bundle-ներից դուրս։
Տարածված սխալներ
- Commit անել .env ֆայլեր կամ բանալիներ, հետո «ուղղել» ֆայլը ջնջելով՝ առանց գաղտնիքը revoke անելու։
- Գաղտնիքները Docker image-ների մեջ «թխել» ENV-ով կամ COPY-ով, որտեղ image ունեցող ցանկացած մեկը կարող է կարդալ դրանք։
- Մեկ ընդհանուր admin credential, որն օգտագործում են բոլոր ծառայությունները, ուստի ոչ մի հասանելիություն չի կարող revoke արվել անկախ։
- Vault-ը աշխատեցնել dev ռեժիմով կամ root token-ը ամենօրյա օգտագործման մեջ պահել։
- Երբեք ոչինչ rotate չանել, որովհետև ոչ ոք չգիտի, թե որ համակարգերն են օգտագործում բանալին։
Խորը վերլուծություն
07Vault-ի ճարտարապետություն՝ seal, storage և high availability
Vault-ի անվտանգության մոդելը հենվում է barrier-ի վրա․ այն ամենը, ինչ Vault-ից գնում է storage, գաղտնագրված է keyring-ով, որը պաշտպանված է root key-ով։ Sealing-ը նշանակում է, որ Vault-ը հիշողության մեջ բանալիներ չի պահում։ Shamir unseal-ի դեպքում root key-ը բաժանվում է share-երի (օրինակ՝ հինգ, որոնցից երեքն են պետք), որոնք պահում են տարբեր մարդիկ, auto-unseal-ի դեպքում cloud KMS-ը կամ HSM-ը ավտոմատ վերծանում է այն startup-ի ժամանակ, ինչը production-ում նորմ է, որովհետև restart-ները չպետք է գիշերը մարդկանց կարիք ունենան։ Integrated storage-ը (Raft) տվյալները replicate է անում սովորաբար երեք կամ հինգ node-երի միջև․ մեկը leader է, մյուսները standby-եր են, որոնք փոխանցում են հարցումները, և գրելու համար քվորում է պահանջվում։ Backup արեք Raft snapshot-ներով և փորձարկեք վերականգնումը։ Enterprise և HCP տարբերակները ավելացնում են performance և disaster-recovery replication տարածաշրջանների միջև։ Շահագործման տեսանկյունից Vault-ը tier-zero ենթակառուցվածք է․ եթե այն չի աշխատում, հավելվածները չեն կարող մեկնարկել, ուստի պլանավորեք քեշավորում, խելամիտ lease-ի երկարություններ և մոնիթորինգ seal-ի կարգավիճակի, leader-ի փոփոխությունների և lease-երի քանակի համար։
# Production-style server config (excerpt)
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault/tls/vault.crt"
tls_key_file = "/etc/vault/tls/vault.key"
}
seal "awskms" {
region = "eu-central-1"
kms_key_id = "alias/vault-unseal"
}
api_addr = "https://vault-1.internal:8200"
cluster_addr = "https://vault-1.internal:8201"
08Secret zero՝ ինչպես է վստահվում առաջին credential-ը
Գաղտնիքների յուրաքանչյուր համակարգ բախվում է «secret zero» խնդրին․ գաղտնիքներ ստանալու համար հավելվածը նախ պետք է authenticate անի, ուստի ի՞նչ գաղտնիք է նա օգտագործում դրա համար։ Ժամանակակից պատասխանն է ապավինել այն ինքնությանը, որն արդեն ապացուցում է պլատֆորմը։ AWS-ում instance-ի կամ task-ի role-ը ստորագրում է հարցում, որը Vault-ը կամ Secrets Manager-ը կարող են ստուգել։ Kubernetes-ում pod-ի projected service-account token-ը ստուգվում է cluster-ի դեմ։ CI-ում job-ի OIDC token-ը ստորագրված է CI provider-ի կողմից։ Մերկ VPS server-ների վրա այդպիսի պլատֆորմային ինքնություն չկա, ուստի տարբերակներից են AppRole-ը՝ կոնֆիգուրացիայի մեջ ներդրված role id-ով և deploy գործիքի կողմից մեկ անգամ առաքված secret id-ով՝ կարճ TTL-ով և միանգամյա օգտագործմամբ, կամ provisioning-ի ժամանակ թողարկված TLS client certificate։ Ինչ էլ ընտրեք, ինքնությունը կապեք նեղ քաղաքականությունների և կարճ token-ների հետ, և bootstrap credential-ը դարձրեք անարժեք առաջին օգտագործումից հետո։
09Encryption as a service և envelope encryption
Գաղտնիքներ պահելուց բացի, Vault-ի transit engine-ը և cloud KMS ծառայությունները գաղտնագրում են տվյալներ հավելվածների համար՝ երբեք չբացահայտելով բանալին։ Հավելվածն ուղարկում է plaintext, ստանում ciphertext և պահում այն իր սեփական բազայում, վերծանումը պահանջում է քաղաքականությամբ ստուգվող կանչ։ Բանալիները կարող են rotate արվել, և հին ciphertext-ները մնում են վերծանելի և կարող են re-wrap արվել նոր տարբերակով։ Մեծ տվյալների համար օգտագործեք envelope encryption՝ գեներացրեք պատահական data key, դրանով լոկալ գաղտնագրեք տվյալները (օրինակ՝ AES-256-GCM), հետո data key-ը գաղտնագրեք KMS key-ով և պահեք տվյալների կողքին։ Ստանում եք արագ լոկալ գաղտնագրում, կենտրոնական audit trail և մեկ master key-ն անջատելով հասանելիությունը կտրելու հնարավորություն։ Այս սխեման ընկած է անձնական տվյալների field-level գաղտնագրման, գաղտնագրված backup-ների և GitOps գործիքներում, ինչպիսին է SOPS-ը, գաղտնիքների հիմքում։
# Transit: the app never sees the key
vault secrets enable transit
vault write -f transit/keys/customer-pii
vault write transit/encrypt/customer-pii plaintext=$(printf '%s' 'AM12345678' | base64)
# -> ciphertext: vault:v1:8SDd3WHDOjf7mq69CyCqYjBXAiQQAVZRkFM13ok481zoCmHnSeDX9vyf7w==
vault write transit/decrypt/customer-pii ciphertext='vault:v1:8SDd3WHDOjf7...'
vault write -f transit/keys/customer-pii/rotate # new version, old data still readable
10Kubernetes secrets՝ ինչ չէ base64-ը
Kubernetes Secret-ը base64-encoded է, ոչ թե գաղտնագրված․ ցանկացած մեկը, ով կարող է namespace-ում կարդալ Secret-ները կամ կարդալ etcd-ի backup-ները, տեսնում է արժեքները։ Ամրացրեք այն շերտերով։ Միացրեք encryption at rest etcd-ի համար, իդեալում՝ KMS provider-ով։ Սահմանափակեք RBAC-ը, որպեսզի միայն Secret-ների կարիք ունեցող workload-ները և մի քանի օպերատորներ կարողանան get կամ list անել դրանք․ Secret-ների վրա «list»-ը փաստացի բացահայտում է բոլորը։ Խուսափեք Secret manifest-ները Git-ում commit անելուց․ օգտագործեք External Secrets Operator՝ կենտրոնական manager-ից համաժամեցնելու համար, կամ Sealed Secrets կամ SOPS՝ GitOps-ի համար, որտեղ արժեքները գաղտնագրված են repository-ում։ Նախընտրեք գաղտնիքները mount անել որպես ֆայլեր՝ environment փոփոխականների փոխարեն, որպեսզի արժեքները կարողանան rotate արվել առանց restart-ի և ավելի քիչ հավանական լինի, որ հայտնվեն crash dump-երում։ Վերջապես, օգտագործեք workload identity, որպեսզի pod-երը կարողանան կանչել cloud API-ներ և secret manager-ներ՝ ընդհանրապես առանց Secret-ներում ստատիկ բանալիների։
Իրական իրավիճակներ
Աճող թիմի տեղափոխումը ընդհանուր .env ֆայլերից
Խնդիր
Հինգ ծրագրավորող production .env ֆայլերը կիսում են chat-ով։ Երեք ծառայություն աշխատում են երկու VPS server-ի վրա Docker Compose-ով, և ոչ ոք չգիտի, թե որ API key-երն են դեռ օգտագործվում։
Ինչպես լուծել
Սկսեք գույքագրումից՝ թվարկեք յուրաքանչյուր գաղտնիք, դրա սեփականատիրոջը, որտեղ է այն օգտագործվում և երբ է վերջին անգամ rotate արվել։ Այս չափի համար ընտրեք managed secret manager կամ ծրագրավորողների secrets պլատֆորմ՝ Vault-ը self-host անելու փոխարեն։ Ստեղծեք առանձին նախագծեր յուրաքանչյուր միջավայրի համար, ծրագրավորողներին տվեք միայն development-ի հասանելիություն և production-ը սահմանափակեք deploy pipeline-ներով և մեկ-երկու սպասարկողով։ Գաղտնիքները server-ներին հասցրեք deploy-ի ժամանակ՝ որպես root-ին պատկանող ֆայլեր mode 600-ով։ Միգրացիայի ընթացքում rotate արեք production-ի յուրաքանչյուր գաղտնիք, քանի որ հները ապրել են chat-ում։ Ավելացրեք gitleaks pre-commit-ում և CI-ում։
Բազայի գաղտնաբառը պետք է փոխվի zero downtime-ով
Խնդիր
Անվտանգությունը պահանջում է production բազայի գաղտնաբառը rotate անել եռամսյակը մեկ։ Վերջին անգամ դա 20 րոպեանոց outage առաջացրեց, որովհետև ծառայությունները restart եղան տարբեր ժամանակներում։
Ինչպես լուծել
Անցեք երկու օգտատիրոջ rotation-ի։ Ստեղծեք բազայի երկու օգտատեր՝ նույնական grant-ներով։ Ծառայությունները ընթացիկ username-ը և գաղտնաբառը կարդում են secret manager-ից։ Rotate անելու համար ոչ ակտիվ օգտատիրոջ վրա դրեք նոր գաղտնաբառ, թարմացրեք գաղտնիքը, որպեսզի մատնանշի նրան, և ծառայությունները թարմացրեք աստիճանաբար․ կապերը նոր credentials-ը վերցնում են վերամիացման ժամանակ։ Ստուգելուց հետո, որ ոչ մի session չի օգտագործում հին օգտատիրոջը (ստուգեք pg_stat_activity-ն), lock արեք կամ նոր գաղտնաբառ դրեք նրա վրա։ Քայլերը ավտոմատացրեք cloud provider-ի rotation ֆունկցիայով կամ անցեք Vault-ի dynamic credentials-ին, որպեսզի յուրաքանչյուր instance ստանա իր սեփական կարճաժամկետ օգտատիրոջը։
API key-ը հայտնվել է public repository-ում
Խնդիր
Secret scanner-ը alert է տալիս, որ վճարային provider-ի live API key-ը տասը րոպե առաջ push է արվել public repository-ում՝ թեստային script-ի մեջ։
Ինչպես լուծել
Գործեք այս հերթականությամբ։ Անմիջապես revoke կամ roll արեք բանալին provider-ի dashboard-ում և deploy արեք փոխարինողը secret manager-ից։ Վերանայեք provider-ի log-երը push-ից ի վեր հին բանալիով կատարված ցանկացած կանչի համար։ Հեռացրեք ֆայլը և մաքրեք այն պատմությունից git filter-repo-ով, հետո force-push արեք, անհրաժեշտության դեպքում կապվեք Git host-ի հետ քեշերը մաքրելու համար։ Գրեք կարճ incident note՝ ժամանակագրությամբ, ազդեցությամբ և ուղղմամբ։ Կանխեք կրկնությունը՝ միացրեք push protection, ավելացրեք pre-commit scanning և ծրագրավորողներին տվեք սահմանափակ test-mode բանալիներ, որպեսզի live բանալիները երբեք չլինեն laptop-ներում։
Արագ ուղեցույց
- Մեկնարկել ժամանակավոր dev server (երբեք prod)
vault server -dev- Գրել KV գաղտնիք
vault kv put secret/prod/app api_key='generated-value'- Կարդալ մեկ դաշտ
vault kv get -field=api_key secret/prod/app- Ստանալ dynamic DB credentials
vault read database/creds/orders-ro- Revoke անել ուղու տակ գտնվող բոլոր lease-երը
vault lease revoke -prefix database/creds/orders-ro- Կարդալ AWS Secrets Manager-ից
aws secretsmanager get-secret-value --secret-id prod/app --query SecretString --output text- Repository-ն սկանավորել արտահոսած գաղտնիքների համար
gitleaks detect --source . --verbose- Գաղտնագրել ֆայլ SOPS + age-ով
sops --encrypt --age age1yourpublickey secrets.yaml > secrets.enc.yaml- Server-ի վրա env ֆայլը պաշտպանել
chown root:root /etc/app/.env && chmod 600 /etc/app/.env
Հարցեր և պատասխաններ
Q1Ինչու՞ պարզապես environment փոփոխականներ չօգտագործել։
Environment փոփոխականները լավ առաքման մեխանիզմ են և շատ ավելի լավ, քան hard-code անելը, բայց դրանք կառավարման համակարգ չեն։ Դրանք ոչինչ չեն ասում այն մասին, թե որտեղ է պահված արժեքը, ով կարող է կարդալ այն, ով է փոխել այն կամ ինչպես է այն rotate արվում։ Պատճենները տարածվում են laptop-ներով, CI կարգավորումներով և server-ներով։ Դրանք կարող են արտահոսել process-ների ստուգման, crash report-ների կամ debug էջերի միջոցով, որոնք dump են անում environment-ը։ Secret manager-ը դառնում է ճշմարտության աղբյուր՝ մուտքի քաղաքականություններով, audit log-երով և rotation-ով, և դեռ կարող է արժեքները հավելվածին հասցնել որպես environment փոփոխականներ կամ ֆայլեր։
Q2Ի՞նչ են dynamic secrets-ը։
Dynamic secrets-ը credentials են, որոնք ըստ պահանջի գեներացվում են կոնկրետ client-ի համար՝ ներկառուցված ժամկետով։ Օրինակ՝ երբ ծառայությունը մեկնարկում է, Vault-ը նրա համար ստեղծում է եզակի բազայի օգտատեր՝ վավեր մեկ ժամ, և ջնջում այն, երբ lease-ի ժամկետն ավարտվում է կամ այն revoke է արվում։ Օգուտներ՝ արտահոսելու երկարաժամկետ գաղտնաբառ չկա, յուրաքանչյուր credential հետևելի է մինչև մեկ սպառող, և կոտրված ծառայության revoke-ը ակնթարթային է՝ առանց մյուսների վրա ազդելու։ Արժեքն այն է, որ հավելվածը կամ նրա կողքի agent-ը պետք է թարմացնի credentials-ը և մշակի վերամիացումը, իսկ նպատակային համակարգը պետք է աջակցի օգտատերերի ծրագրային կառավարումը։
Q3Ի՞նչ եք անում, եթե գաղտնիքը commit է արվել Git-ում։
Ենթադրեք, որ այն կոտրված է, նույնիսկ private repository-ում, որովհետև clone-երը, fork-երը և CI log-երը կարող են արդեն պարունակել այն։ Նախ revoke կամ rotate արեք գաղտնիքը provider-ի մոտ և deploy արեք նոր արժեքը։ Հետո ստուգեք provider-ի log-երը բացահայտման ժամանակահատվածում չարաշահման համար։ Դրանից հետո հեռացրեք այն repository-ի պատմությունից git filter-repo-ով կամ BFG-ով և force-push արեք, խնդրեք համագործակիցներին նորից clone անել, բայց դրան վերաբերվեք որպես մաքրման, ոչ թե ուղղման։ Վերջապես, ավելացրեք secret scanning pre-commit-ում և CI-ում, որպեսզի դա չկրկնվի։
Q4Ինչպե՞ս է Vault-ը պաշտպանում իր պահած գաղտնիքները։
Vault-ը բոլոր տվյալները գաղտնագրում է նախքան storage-ում գրելը՝ օգտագործելով գաղտնագրման բանալի, որն ինքը պաշտպանված է root key-ով։ Երբ Vault-ը մեկնարկում է, այն sealed է․ այն չի կարող որևէ բան վերծանել, մինչև unseal չարվի՝ կա՛մ մի քանի օպերատորների պահած key share-երով (Shamir secret sharing), կա՛մ ավտոմատ cloud KMS-ով կամ HSM-ով (auto-unseal)։ Client-ները authenticate են անում և ստանում քաղաքականություններով սահմանափակված token-ներ, իսկ յուրաքանչյուր հարցում կարող է գրանցվել audit device-ների կողմից՝ զգայուն արժեքները log-ում hash արված։ Այսպիսով, միայն storage backend-ը կարդալը ոչ մի օգտագործելի բան չի բացահայտում։
Q5Ինչպե՞ս են CI/CD pipeline-ները անվտանգ ստանում գաղտնիքները։
Ընթացիկ լավագույն սխեման workload identity federation-ն է․ CI համակարգը յուրաքանչյուր job-ի համար թողարկում է կարճաժամկետ OIDC token, որը նկարագրում է repository-ն, branch-ը և միջավայրը։ Cloud provider-ը կամ Vault-ը վստահում է այդ issuer-ին և token-ը փոխանակում ժամանակավոր credentials-ի հետ՝ սահմանափակված պայմաններով, ինչպես՝ «միայն այս repository-ի main branch-ը»։ CI-ում ընդհանրապես երկարաժամկետ cloud key-եր չեն պահվում։ Երբ ստատիկ գաղտնիքներն անխուսափելի են, պահեք դրանք CI համակարգի պաշտպանված environment secret-ներում, սահմանափակեք պաշտպանված branch-երով, production deploy-երի համար պահանջեք հաստատում և mask արեք դրանք log-երում։
Q6Որքա՞ն հաճախ պետք է rotate անել գաղտնիքները։
Rotate արեք անմիջապես ցանկացած կասկածելի բացահայտումից հետո կամ երբ հասանելիություն ունեցող մեկը հեռանում է, հակառակ դեպքում հետևեք ռիսկի վրա հիմնված ժամանակացույցի․ տարածված քաղաքականություններն են 30-ից 90 օր բարձր արժեք ունեցող ստատիկ գաղտնիքների համար, իսկ որոշ compliance framework-ներ պահանջում են սահմանված ժամկետներ։ Ավելի լավ պատասխանն է rotation-ը դարձնել այնքան հեշտ, որ հաճախականությունը դադարի կարևոր լինել՝ ավտոմատացրեք այն, անցման ընթացքում աջակցեք երկու վավեր տարբերակ և նախընտրեք dynamic կամ կարճաժամկետ credentials, որոնք ժամկետանց են դառնում ժամերի ընթացքում։ Ստորագրման համար օգտագործվող բանալիները, ինչպիսիք են JWT key-երը, rotate են արվում համընկնումով՝ հրապարակեք նոր բանալին, սկսեք ստորագրել դրանով և հինը հանեք token-ների ժամկետի ավարտից հետո։
Սենիոր մակարդակի հարցեր
S1Self-hosted Vault, թե՞ cloud secret manager․ ինչպե՞ս եք որոշում։
Cloud secret manager-ը default է, երբ workload-ը հիմնականում ապրում է մեկ cloud-ում՝ աշխատեցնելու server-ներ չկան, IAM ինտեգրացիա, KMS-ով ապահովված գաղտնագրում, rotation hook-եր և audit log-եր cloud-ի trail-ի միջոցով՝ ըստ գաղտնիքի և ըստ կանչի գնով և lock-in-ով։ Vault-ը (կամ OpenBao-ն) արդարացնում է իր շահագործման արժեքը, երբ ընդգրկում եք մի քանի cloud կամ on-premise, ձեզ պետք են dynamic secrets բազմաթիվ համակարգերի համար, PKI և SSH սերտիֆիկատների թողարկում, transit գաղտնագրում կամ մեկ հետևողական քաղաքականության մոդել պլատֆորմների միջև։ Այն աշխատեցնելը նշանակում է պատասխանատու լինել high availability-ի, unseal-ի, թարմացումների, backup-ների համար և լինել tier-zero incident-ների ժամանակ․ HCP Vault-ը վճարի դիմաց հեռացնում է դրա մեծ մասը։ VPS server-ների վրա փոքր թիմերի համար managed ծրագրավորողների secrets պլատֆորմը կամ cloud manager-ը գումարած ֆայլերի կարգապահ իրավունքները սովորաբար պրագմատիկ ընտրությունն են։
S2Ինչպե՞ս կնախագծեիք գաղտնիքների մշակումը multi-tenant SaaS-ի համար, որը պահում է հաճախորդների երրորդ կողմի credentials-ը։
Հաճախորդների credentials-ը՝ նրանց payment gateway-ի բանալիները կամ ERP գաղտնաբառերը, ձեր սեփական ենթակառուցվածքի գաղտնիքներից տարբեր դաս են։ Ես դրանք կպահեի գաղտնագրված ըստ tenant-ի՝ envelope encryption-ով՝ յուրաքանչյուր tenant-ի data key, որը wrap է արված KMS-ով կամ Vault transit key-ով, ciphertext-ը հավելվածի բազայում, իսկ վերծանումը՝ միայն այն ծառայությունում, որը կանչում է երրորդ կողմին։ Հասանելիությունը ստուգվում է tenant-ի դեմ յուրաքանչյուր decrypt-ի ժամանակ և log է արվում։ Plaintext-ը երբեք չի գնում log-եր, admin UI-ներ կամ support գործիքներ․ էկրանները ցույց են տալիս միայն վերջին նիշերը։ Աջակցեք rotation հաճախորդի կողմից և անմիջական ջնջում offboarding-ի ժամանակ՝ ոչնչացնելով tenant-ի data key-ը (crypto-shredding)։ Փոխզիջումներ՝ KMS կանչերը ավելացնում են latency և արժեք, ուստի վերծանված բանալիները կարճ ժամանակով քեշավորեք հիշողության մեջ, իսկ յուրաքանչյուր tenant-ի բանալիները մեծացնում են բանալիների կառավարման overhead-ը, բայց կտրուկ փոքրացնում են blast radius-ը։
S3Ինչպե՞ս եք մշակում JWT-ների կամ webhook-ների ստորագրման բանալիների rotation-ը՝ առանց client-ները կոտրելու։
Օգտագործեք համընկնող բանալիներ՝ նույնականացված key id-ով։ JWT-ների համար նախ նոր public key-ը հրապարակեք JWKS-ում հնի կողքին, սպասեք, մինչև verifier-ների քեշերը թարմանան, հետո սկսեք ստորագրել նոր բանալիով և դրա kid-ով։ Հին public key-ը պահեք հրապարակված, մինչև դրանով ստորագրված յուրաքանչյուր token-ի ժամկետն ավարտվի, հետո հեռացրեք այն։ Private key-երը ապրում են KMS-ում, HSM-ում կամ Vault transit-ում, որպեսզի երբեք չլքեն պաշտպանված պահոցը։ Webhook-ի ստորագրման գաղտնիքների համար rotation-ի ընթացքում յուրաքանչյուր endpoint-ի համար աջակցեք երկու ակտիվ գաղտնիք՝ ստորագրեք նորով, ստորագրության header-ում ներառեք տարբերակը և թույլ տվեք ստացողներին սահմանված ժամանակահատվածում ընդունել ցանկացածը։ Փոխզիջումը բանալիների բաշխման և քեշավորման բարդությունն է, որը շատ ավելի էժան է, քան միանվագ rotation-ը, որն անվավեր է դարձնում բոլոր session-ները կամ կորցնում գործընկերների webhook-ները։
Բառարան
- Secret
- Ցանկացած արժեք, որը հասանելիություն է տալիս, օրինակ՝ գաղտնաբառ, API key, token, սերտիֆիկատի բանալի կամ գաղտնագրման բանալի։
- Secret manager
- Ծառայություն, որը գաղտնիքները պահում է գաղտնագրված, հասանելիությունը վերահսկում է ըստ ինքնության և log է անում յուրաքանչյուր օգտագործում։
- Dynamic secret
- Credential, որը ըստ պահանջի ստեղծվում է մեկ client-ի համար՝ ավտոմատ ժամկետով։
- Lease
- Vault-ի ժամանակային սահմանափակումը գաղտնիքի կամ token-ի վրա, որից հետո այն revoke է արվում, եթե չի թարմացվում։
- Seal / unseal
- Vault-ի կողպված վիճակը, որում այն չի կարող վերծանել տվյալները, և դրա բանալիները բեռնելու գործընթացը։
- Rotation
- Գաղտնիքի փոխարինում նոր արժեքով և հնի հանում՝ ըստ ժամանակացույցի կամ բացահայտումից հետո։
- Secret zero
- Առաջին credential-ը, որը հավելվածին պետք է հենց secret manager-ում authenticate անելու համար։
- Envelope encryption
- Տվյալների գաղտնագրում data key-ով, հետո այդ բանալու գաղտնագրում KMS-ում պահվող master key-ով։
- Workload identity
- Հավելվածի ինքնության ապացուցում իր պլատֆորմով (cloud role, pod, CI job)՝ պահված բանալիների փոխարեն։
Շարունակեք սովորել
Պրոդուկտի գաղափար ունե՞ք։Եկեք ստեղծենք այն։
Պատմեք ձեր գաղափարի, պրոդուկտի կամ թիմի մասին։ Սովորաբար պատասխանում եմ մեկ աշխատանքային օրվա ընթացքում։