ЁЯФС рдзрдбрд╛ 08 тАФ Secrets рдЖрдгрд┐ config as a service: рдХрд┐рд▓реНрд▓реНрдпрд╛рдВрдЪреЗ рдХрдкрд╛рдЯ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 08 ┬╖ рдорд╛рдЧреАрд▓: lesson-07-paved-pipelines ┬╖ рдкреБрдвреАрд▓: lesson-09-policy-guardrails
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ07, рдЖрдгрд┐ secrets рдЖрдгрд┐ configuration as a service. Secrets рдПрдХрд╛рдЪ store рдордзреНрдпреЗ,
рдкреНрд░рддреНрдпреЗрдХ team рдЪреНрдпрд╛ рд╕реНрд╡рддрдВрддреНрд░ path рдЦрд╛рд▓реА рд░рд╛рд╣рддрд╛рдд; team рдлрдХреНрдд рд╕реНрд╡рддрдГрдЪреЗрдЪ рд╡рд╛рдЪреВ рд╢рдХрддреЗ; рдкреНрд░рддреНрдпреЗрдХ рдмрджрд▓рд╛рддреВрди рдирд╡реЗ
version рдмрдирддреЗ; rotation рдирдВрддрд░ store рджрд╛рдЦрд╡рддреЗ рдХреА рдХреЛрдгрддреЗ consumers рдЕрдЬреВрди рдЬреБрдиреЗ version рд╡рд╛рдкрд░рдд рдЖрд╣реЗрдд.
Configuration layers рдордзреНрдпреЗ рдпреЗрддреЗ тАФ рдЖрдзреА defaults, рдордЧ environment, рдордЧ service тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ
рдЕрдВрддрд┐рдо value рд╕рд╛рдВрдЧрддреЗ рдХреА рддреЗ рдХреЛрдгрддреНрдпрд╛ layer рдиреЗ рдард░рд╡рд▓реЗ. SecretStore рдЖрдгрд┐ layered_config()
idp/selfserve.py рдордзреНрдпреЗ, secrets()
idp/demo.py рдордзреНрдпреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╕реБрд╡рд┐рдзрд╛ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдд рдПрдХ рдХрд┐рд▓реНрд▓реНрдпрд╛рдВрдЪреЗ рдХрдкрд╛рдЯ рдЖрд╣реЗ. ЁЯФС рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рдЪрд╛ рд╕реНрд╡рддрдГрдЪрд╛ рдЦреБрдВрдЯрд╛ рдЖрд╣реЗ: science рдЪреНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛ science рдЪреНрдпрд╛ рдЦреБрдВрдЯреНрдпрд╛рд╡рд░, maths рдЪреНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛ maths рдЪреНрдпрд╛ рдЦреБрдВрдЯреНрдпрд╛рд╡рд░.
рдХрддрд░рд┐рдирд╛ science lab рдЪреА рдХрд┐рд▓реНрд▓реА рдорд╛рдЧрддреЗ: тЬЕ "рд╣реА рдШреНрдпрд╛ тАФ рдХрд┐рд▓реНрд▓реА version 1." рддреА maths рдЪреНрдпрд╛ рднрд╛рдВрдбрд╛рд░рдЦреЛрд▓реАрдЪреА рдХрд┐рд▓реНрд▓реА рдорд╛рдЧрддреЗ: тЭМ "рддреА maths рдЪреНрдпрд╛ рдЦреБрдВрдЯреНрдпрд╛рд╡рд░ рдЖрд╣реЗ. maths рд▓рд╛ рддреА рджреНрдпрд╛рдпрд▓рд╛ рд╕рд╛рдВрдЧрд╛."
рдЕрдзреВрдирдордзреВрди рджреАрдкрд┐рдХрд╛ рдХреБрд▓реВрдк рдмрджрд▓рддреЗ (рдореНрд╣рдгрдЬреЗ rotation) рдЖрдгрд┐ рдХрд┐рд▓реНрд▓реА version 2 рдЯрд╛рдВрдЧрддреЗ. рдЬреБрдиреА рдХрд┐рд▓реНрд▓реА рдХреЛрдгреА рдХреЛрдгреА рдиреЗрд▓реА рдпрд╛рдЪреА рдпрд╛рджреА рддреА рдареЗрд╡рддреЗ. Exam-results рдЪрд╛ рдХрд╛рд░рдХреВрди рдирд╡реА рдХрд┐рд▓реНрд▓реА рдШреНрдпрд╛рдпрд▓рд╛ рдкрд░рдд рдпреЗрддреЛ тЬЕ. Lab worker рдЕрдЬреВрди рдкрд░рдд рдЖрд▓реЗрд▓рд╛ рдирд╛рд╣реА тЪая╕П. рдореНрд╣рдгреВрди lab worker рдХрдбреЗрд╣реА рдирд╡реА рдХрд┐рд▓реНрд▓реА рдпреЗрдИрдкрд░реНрдпрдВрдд рджреАрдкрд┐рдХрд╛ рдЬреБрдиреЗ рдХреБрд▓реВрдк рдлреЗрдХреВрди рджреЗрдд рдирд╛рд╣реА.
рдЖрдгрд┐ рдХрд╛рд░реНрдпрд╛рд▓рдп рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрд▓реАрд╕рд╛рдареА рдПрдХ settings рдкрддреНрд░рдХ рдареЗрд╡рддреЗ: рдЖрдзреА рд╢рд╛рд│реЗрдЪрд╛ default ("рджрд┐рд╡реЗ рдиреЗрд╣рдореАрд╕рд╛рд░рдЦреЗ"), рдордЧ рдЗрдорд╛рд░рддреАрдЪрд╛ рдирд┐рдпрдо ("рдкрд░реАрдХреНрд╖рд╛ рд╣реЙрд▓рдордзреНрдпреЗ 2 рдирд╡реНрд╣реЗ, 3 рд╕рдлрд╛рдИ рдХрд░реНрдордЪрд╛рд░реА"), рдордЧ рдЦреЛрд▓реАрдЪреА рд╕реНрд╡рддрдГрдЪреА рдЗрдЪреНрдЫрд╛ ("рдирд╡рд╛ grades board: рдЪрд╛рд▓реВ"). рдХреЛрдгреАрд╣реА рдкрддреНрд░рдХ рд╡рд╛рдЪреВрди рдкреНрд░рддреНрдпреЗрдХ рдУрд│ рдХреЛрдгрддреНрдпрд╛ рдирд┐рдпрдорд╛рдиреЗ рдард░рд╡рд▓реА рддреЗ рдкрд╛рд╣реВ рд╢рдХрддреЛ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
subgraph store["ЁЯФС secret store"]
s1["teams/science/results-db-password<br/>v1 тЖТ v2 (rotated)"]
s2["teams/maths/timetable-api-key"]
end
sci["ЁЯзк science"] -->|"тЬЕ own path"| s1
sci -.->|"тЭМ denied"| s2
s1 --> er["exam-results: reloaded v2"]
s1 --> lw["lab-worker: still on v1 тЪая╕П"]
subgraph cfg["ЁЯУД config layers"]
d["defaults: replicas 2"] --> p["production: replicas 3"] --> sv["exam-results: feature_new_grades on"]
end
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/platform-engineering/lesson-diagrams.html#l08
тЭУ рдХрд╛рдп
- Secret тАФ рдкреНрд░рд╡реЗрд╢ рджреЗрдгрд╛рд░реЗ value: password, API key, private key, token. рддреЗ Git рдордзреНрдпреЗ, logs рдордзреНрдпреЗ рдХрд┐рдВрд╡рд╛ container image рдордзреНрдпреЗ рдЕрд╕рддрд╛ рдХрд╛рдорд╛ рдирдпреЗ.
- Secret store / secrets manager тАФ secrets encrypt рдХрд░реВрди рдареЗрд╡рдгрд╛рд░реА, рддреА рдХреЛрдг рд╡рд╛рдЪреВ рд╢рдХрддреЗ рд╣реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдгрд╛рд░реА рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ access рдЪреА рдиреЛрдВрдж рдареЗрд╡рдгрд╛рд░реА service. рдЙрджрд╛рд╣рд░рдгреЗ: HashiCorp Vault, AWS Secrets Manager, Google Secret Manager, Azure Key Vault.
- Path-based access тАФ secrets path рдиреБрд╕рд╛рд░ рдорд╛рдВрдбрд▓реЗрд▓реЗ рдЕрд╕рддрд╛рдд (
teams/science/...) рдЖрдгрд┐ рдПрдХ policy рдкреНрд░рддреНрдпреЗрдХ team рд▓рд╛ рдлрдХреНрдд рддрд┐рдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ subtree рд╡рд░ read access рджреЗрддреЗ. рдкреНрд░рддреНрдпреЗрдХ team рд╕рд╛рдареА least privilege. - Versioning тАФ рдкреНрд░рддреНрдпреЗрдХ write рдЬреБрдиреЗ value рдЖрдзреАрдЪреНрдпрд╛ version рдореНрд╣рдгреВрди рдЬрдкрддреЗ (Vault рдЪреЗ KV version 2 рдЖрдгрд┐ AWS Secrets Manager рджреЛрдиреНрд╣реА versions рдареЗрд╡рддрд╛рдд), рддреНрдпрд╛рдореБрд│реЗ рдЪреБрдХреАрдЪрд╛ рдмрджрд▓ рдорд╛рдЧреЗ рдШреЗрддрд╛ рдпреЗрддреЛ.
- Rotation тАФ secret рдард░рд▓реЗрд▓реНрдпрд╛ рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рдиреБрд╕рд╛рд░ рдХрд┐рдВрд╡рд╛ leak рдирдВрддрд░ рдмрджрд▓рдгреЗ. рд╕реБрд░рдХреНрд╖рд┐рдд рдХреНрд░рдо: рдЖрдзреА рдирд╡реЗ value рдмрдирд╡рд╛, рдкреНрд░рддреНрдпреЗрдХ consumer рд▓рд╛ рддреНрдпрд╛рд╡рд░ рдЬрд╛рдК рджреНрдпрд╛, рдордЧ рдЬреБрдиреЗ revoke рдХрд░рд╛. рдЖрдзреА revoke рдХреЗрд▓реЗ рддрд░ рдЬреБрдиреЗ value рд╡рд╛рдкрд░рдгрд╛рд░реЗ рд╕рдЧрд│реЗ рдмрдВрдж рдкрдбрддрд╛рдд.
- Platform рдордзреНрдпреЗ sync рдХрд░рдгреЗ тАФ рдЕрдиреЗрдХ teams code рдордзреВрди store рд▓рд╛ рдереЗрдЯ call рдХрд░рдд рдирд╛рд╣реАрдд. External
Secrets Operator рд╕рд╛рд░рдЦреЗ tool value рд▓рд╛ Kubernetes
SecretрдордзреНрдпреЗ copy рдХрд░рддреЗ рдЖрдгрд┐ рдард░рд╛рд╡рд┐рдХ рдЕрдВрддрд░рд╛рдиреЗ рддреЗ refresh рдХрд░рддреЗ. - Layered configuration тАФ secret рдирд╕рд▓реЗрд▓реНрдпрд╛ settings (log level, replica count, feature flags) layers рдордзреВрди рдмрдирддрд╛рдд, рдЬрд┐рдереЗ рдирдВрддрд░рдЪрд╛ layer рдЬрд┐рдВрдХрддреЛ: organisation defaults тЖТ environment тЖТ service. Helm values files рдЖрдгрд┐ Kustomize overlays рдпрд╛рдЪ рдкрджреНрдзрддреАрдиреЗ рдХрд╛рдо рдХрд░рддрд╛рдд.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рд╣рд╛рддрд╛рдиреЗ рд╕рд╛рдВрднрд╛рд│рд▓реЗрд▓реЗ secrets leak рд╣реЛрддрд╛рдд: chat рдордзреНрдпреЗ paste рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд, "рдереЛрдбреНрдпрд╛ рд╡реЗрд│рд╛рд╕рд╛рдареА" commit рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд, laptop рд╡рд░ copy рдХрд░реВрди рд╡рд┐рд╕рд░рд▓реЗ рдЬрд╛рддрд╛рдд. рдЖрдгрд┐ рд╣рд╛рддрд╛рдиреЗ рдХреЗрд▓реЗрд▓реЗ rotation рдХреНрд╡рдЪрд┐рддрдЪ рд╣реЛрддреЗ, рдХрд╛рд░рдг рддреЗ рднреАрддреАрджрд╛рдпрдХ рдЕрд╕рддреЗ тАФ рдЬреБрдиреЗ value рдХреЛрдг рд╡рд╛рдкрд░рддреЗ рд╣реЗ рдХреЛрдгрд╛рд▓рд╛рдЪ рдорд╛рд╣реАрдд рдирд╕рддреЗ. рдкреНрд░рддреНрдпреЗрдХ team рд╕рд╛рдареА store, versions рдЖрдгрд┐ consumers рдЪреА рдпрд╛рджреА рдпрд╛рдВрдореБрд│реЗ rotation рдиреЗрд╣рдореАрдЪреЗ рдХрд╛рдо рдмрдирддреЗ. "рдХреЛрдгреА рдард░рд╡рд▓реЗ" рд╣реЗ рдЙрддреНрддрд░ рджреЗрдгрд╛рд▒реНрдпрд╛ layered config рдореБрд│реЗ "production рдордзреНрдпреЗ рд╣реЗ 3 рдХрд╛ рдЖрд╣реЗ?" рд╣рд╛ рдкреНрд░рд╢реНрди рддрдкрд╛рд╕рд╛рдЪрд╛ рд╡рд┐рд╖рдп рди рд░рд╛рд╣рддрд╛ рдлрдХреНрдд рдкрд╛рд╣рдгреНрдпрд╛рдЪрд╛ рд╡рд┐рд╖рдп рд╣реЛрддреЛ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
idp/selfserve.py рдордзрд▓реЗ SecretStore рдкреНрд░рддреНрдпреЗрдХ path рд╕рд╛рдареА values рдЪреА рдпрд╛рджреА
рдареЗрд╡рддреЗ. get(team, path, consumer) teams/<team>/ рдЪреНрдпрд╛ рдмрд╛рд╣реЗрд░рдЪрд╛ рдХреЛрдгрддрд╛рд╣реА path рдирд╛рдХрд╛рд░рддреЗ, рдлрдХреНрдд
version рдЖрдгрд┐ length рдкрд░рдд рджреЗрддреЗ (value рдХрдзреАрдЪ рдЫрд╛рдкрд▓реЗ рдЬрд╛рдд рдирд╛рд╣реА), рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ consumer рдХрдбреЗ рдХреЛрдгрддреЗ version
рдЖрд╣реЗ рдпрд╛рдЪреА рдиреЛрдВрдж рдареЗрд╡рддреЗ. rotate() рдирд╡реЗ version рдЬреЛрдбрддреЗ; stale() рд╕рд░реНрд╡рд╛рдд рдирд╡реНрдпрд╛ version рдкреЗрдХреНрд╖рд╛ рдЬреБрдиреЗ version
рдзрд░реВрди рдареЗрд╡рд▓реЗрд▓реНрдпрд╛ consumers рдЪреА рдпрд╛рджреА рджреЗрддреЗ. layered_config(*layers) (name, dict) layers рдбрд╛рд╡реАрдХрдбреВрди
рдЙрдЬрд╡реАрдХрдбреЗ merge рдХрд░рддреЗ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ key рд╕рд╛рдареА value рдЖрдгрд┐ рддреЗ рдард░рд╡рдгрд╛рд░рд╛ layer рдЬрдкреВрди рдареЗрд╡рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 idp/demo.py secrets
python3 - <<'EOF'
import sys; sys.path.insert(0, "idp"); from selfserve import SecretStore, layered_config
st = SecretStore()
st.put("teams/library/search-token", "tok-one-for-the-search")
print(st.get("library", "teams/library/search-token", consumer="library-search"))
print(st.get("library", "teams/library/missing"))
print(st.get("maths", "teams/library/search-token"))
st.rotate("teams/library/search-token", "tok-two"); st.rotate("teams/library/search-token", "tok-three")
print("after two rotations, stale:", st.stale(), "┬╖", st.get("library", "teams/library/search-token", consumer="library-search")[1])
cfg = layered_config(("defaults", {"log_level": "info", "replicas": 2}), ("preview", {"replicas": 1, "log_level": "debug"}),
("library-search", {"log_level": "warning"}))
for k, (v, src) in cfg.items(): print(f"{k} = {v} (from {src})")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
secrets рд╣реЗ рдЫрд╛рдкрддреЗ:
science reads teams/science/results-db-password тЖТ ok ┬╖ teams/science/results-db-password v1 (22 characters, value hidden)
science reads teams/maths/timetable-api-key тЖТ denied ┬╖ science may read teams/science/* only тАФ ask the owner of teams/maths/timetable-api-key to share it
тФАтФА rotation: the password is now v2; consumers still on the old version: ['exam-results', 'lab-worker']
exam-results reloads тЖТ still stale: ['lab-worker'] ┬╖ keep v1 valid until nobody uses it, then revoke
replicas = 3 (from production)
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
('ok', 'teams/library/search-token v1 (22 characters, value hidden)')
('missing', 'no secret at teams/library/missing')
('denied', 'maths may read teams/maths/* only тАФ ask the owner of teams/library/search-token to share it')
after two rotations, stale: ['library-search'] ┬╖ teams/library/search-token v3 (9 characters, value hidden)
log_level = warning (from library-search)
replicas = 1 (from preview)
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
Store рдиреЗ рддреАрди рд╡реЗрдЧрд╡реЗрдЧрд│реА рдЙрддреНрддрд░реЗ рджрд┐рд▓реА тАФ ok, missing, denied тАФ рдЖрдгрд┐ рдХрдзреАрдЪ value рдЫрд╛рдкрд▓реЗ рдирд╛рд╣реА. рджреЛрди
rotations рдореБрд│реЗ v3 рдмрдирд▓реЗ; library-search рдкреБрдиреНрд╣рд╛ рд╡рд╛рдЪреЗрдкрд░реНрдпрдВрдд stale рд╣реЛрддреЗ, рдЖрдгрд┐ v3 рдЖрдгрдгрд╛рд▒реНрдпрд╛ рддреНрдпрд╛рдЪ
call рдиреЗ рддреЗ рд╕рд╛рдл рдХреЗрд▓реЗ. Config рдордзреНрдпреЗ log_level рддреАрди рд╡реЗрд│рд╛ рдард░рд╡рд▓реЗ рдЧреЗрд▓реЗ рдЖрдгрд┐ рд╢реЗрд╡рдЯрдЪрд╛ layer рдЬрд┐рдВрдХрд▓рд╛;
replicas preview рдордзреВрди рдЖрд▓реЗ, рдЖрдгрд┐ output рддрд╕реЗ рд╕рд╛рдВрдЧрддреЛ. "Stale consumers" рдЪреА рдпрд╛рджреАрдЪ рдЬреБрдиреЗ
value revoke рдХрд░рдгреЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдмрдирд╡рддреЗ.
ЁЯУП рд╢рд┐рдХрд╡рдгреНрдпрд╛рд╕рд╛рдареАрдЪрд╛ рдирдореБрдирд╛: рдЦрд░рд╛ store values encrypt рдХрд░рддреЛ, рдкреНрд░рддреНрдпреЗрдХ read рдЪреА рдиреЛрдВрдж рдареЗрд╡рддреЛ рдЖрдгрд┐ рд╢рдХреНрдп рддрд┐рдереЗ рдереЛрдбреНрдпрд╛ рдХрд╛рд│рд╛рдЪреЗ credentials рджреЗрддреЛ. рд╣рд╛ lab рдлрдХреНрдд paths, versions рдЖрдгрд┐ рдХреЛрдгрд╛рдХрдбреЗ рдХреЛрдгрддреЗ version рдЖрд╣реЗ рдПрд╡рдвреЗрдЪ рджрд╛рдЦрд╡рддреЛ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- Kubernetes
Secretencrypted рдЕрд╕рддреЛ рдЕрд╕реЗ рд╕рдордЬрдгреЗ тАФ default рдордзреНрдпреЗ рддреНрдпрд╛рдЪрд╛ data рдлрдХреНрдд base64-encoded рдЕрд╕рддреЛ; encryption at rest рдЪрд╛рд▓реВ рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧрддреЗ, рдЖрдгрд┐ RBAC рдиреЗ рддреЛ рдХреЛрдг рд╡рд╛рдЪреВ рд╢рдХрддреЗ рд╣реЗ рдорд░реНрдпрд╛рджрд┐рдд рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧрддреЗ - рдкреНрд░рддреНрдпреЗрдХ consumer рдХрдбреЗ рдирд╡реЗ secret рдпреЗрдгреНрдпрд╛рдЖрдзреАрдЪ рдЬреБрдиреЗ revoke рдХрд░рдгреЗ
- рдкреНрд░рддреНрдпреЗрдХ team рд╡рд╛рдЪреВ рд╢рдХреЗрд▓ рдЕрд╕рд╛ рдПрдХрдЪ рд╕рд╛рдорд╛рдпрд┐рдХ "platform" secret path
- CI logs рдХрд┐рдВрд╡рд╛ error messages рдордзреНрдпреЗ secrets рдЫрд╛рдкрдгреЗ
- environments рдордзреНрдпреЗ рд╡реЗрдЧрд│реЗ рдЕрд╕рд▓реЗрд▓реЗ config values, рдЖрдгрд┐ рддреЗ рдХрд╛ рд╡реЗрдЧрд│реЗ рдЖрд╣реЗрдд рдпрд╛рдЪреА рдХреЛрдгрддреАрд╣реА рдиреЛрдВрдж рдирд╕рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
HashiCorp Vault (KV version 2), рдЦрд▒реНрдпрд╛ server рд╡рд░:
vault kv put secret/teams/science/results-db-password value='тАж'
vault kv get -version=1 secret/teams/science/results-db-password # an older version
Science рд▓рд╛ рдлрдХреНрдд рддрд┐рдЪрд╛рдЪ subtree рд╡рд╛рдЪреВ рджреЗрдгрд╛рд░реА policy (KV v2 API paths рдордзреНрдпреЗ рдЬреЛрдбрддреЛ рддреЛ data/ рднрд╛рдЧ
рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛):
path "secret/data/teams/science/*" {
capabilities = ["read"]
}
External Secrets Operator Kubernetes Secret рд▓рд╛ store рд╢реА sync рдареЗрд╡рддреЛ (рдЬреБрдиреНрдпрд╛
releases рдордзреНрдпреЗ apiVersion: external-secrets.io/v1beta1 рд╡рд╛рдкрд░рддрд╛рдд):
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: results-db
namespace: science
spec:
refreshInterval: 1h
secretStoreRef: {name: vault-science, kind: SecretStore}
target: {name: results-db}
data:
- secretKey: password
remoteRef: {key: teams/science/results-db-password, property: value}
AWS Secrets Manager rotation function рд╡рд╛рдкрд░реВрди рдХрд╛рд╣реА database secrets рдард░рд▓реЗрд▓реНрдпрд╛ рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рдиреЗ rotate рдХрд░реВ рд╢рдХрддреЛ, рдпрд╛рдд "alternating users" strategy рдкрдг рдЖрд╣реЗ рдЬреА рдПрдХ credentials рд╕рдВрдЪ рдЪрд╛рд▓реВ рдареЗрд╡рддреЗ рдЖрдгрд┐ рджреБрд╕рд░рд╛ рдмрджрд▓рддреЗ.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдЧрд░рдЬ рдкрдбрдгреНрдпрд╛рдЖрдзреАрдЪ rotation рдЪрд╛ рд╕рд░рд╛рд╡ рдХрд░рд╛. Secret рдХреЛрдг рд╡рд╛рдкрд░рддреЗ рд╣реЗ рдХреЛрдгрд╛рд▓рд╛рдЪ рд╕рд╛рдВрдЧрддрд╛ рдЖрд▓реЗ рдирд╛рд╣реА, рддрд░ рдкрд╣рд┐рд▓рд╛ рдЦрд░рд╛ leak рд╣рд╛ outage рдкрдг рдард░рддреЛ.
тПня╕П рдкреБрдвреЗ
рднрд╛рдЧ 2 рдкреВрд░реНрдг рдЭрд╛рд▓рд╛: teams рд╕реНрд╡рддрдГрдЪреА рдорджрдд рд╕реНрд╡рддрдГ рдХрд░реВ рд╢рдХрддрд╛рдд. рднрд╛рдЧ 3 рд╡рд┐рдЪрд╛рд░рддреЛ рдХреА 'рдирд╛рд╣реА' рдЪреА рднрд┐рдВрдд рди рдмрдирддрд╛ рд╣реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдХрд╕реЗ рдареЗрд╡рд╛рдпрдЪреЗ тАФ рджреБрд░реБрд╕реНрддреА рд╕рдордЬрд╛рд╡реВрди рд╕рд╛рдВрдЧрдгрд╛рд░реЗ guardrails.
git checkout lesson-09-policy-guardrails