ЁЯЪк рдзрдбрд╛ 06 тАФ Authorization рдЖрдгрд┐ IDOR: рдХрд╛рдп рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА, рдХреЛрдгрддреНрдпрд╛ record рд╡рд░
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 16 рдкреИрдХреА рдзрдбрд╛ 06 ┬╖ рдорд╛рдЧреЗ: lesson-05-oauth-oidc ┬╖ рдкреБрдвреЗ: lesson-07-secrets-kms
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ05, рдЖрдгрд┐ рдУрд│рдЦрдкрддреНрд░ рдЦрд┐рдбрдХреАрдЪрд╛ рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛. рдПрдЦрд╛рджреА рд╡реНрдпрдХреНрддреА рдХреЛрдг рдЖрд╣реЗ рд╣реЗ рдорд╛рд╣реАрдд рдЕрд╕рд▓реНрдпрд╛рдиреЗ
рддреА рдХрд╛рдп рдХрд░реВ рд╢рдХрддреЗ рд╣реЗ рдХрд│рдд рдирд╛рд╣реА. рддреБрдореНрд╣реА RBAC (roles тЖТ permissions) рд▓рд┐рд╣рд┐рддрд╛, рдордЧ рддреЗ рдкреБрд░реЗрд╕реЗ рдХрд╛ рдирд╛рд╣реА рддреЗ рдкрд╛рд╣рддрд╛:
рджреАрдкрд┐рдХрд╛ рдкрд╛рд▓рдХ рдЖрд╣реЗ, рдкрд╛рд▓рдХ grades рд╡рд╛рдЪреВ рд╢рдХрддрд╛рдд тАФ рдкрдг рдХреЛрдгрд╛рдЪреНрдпрд╛ grades? Object-level рддрдкрд╛рд╕рдгреА
рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрддреЗ, рдЖрдгрд┐ IDOR / BOLA рдерд╛рдВрдмрд╡рддреЗ. sec/demo.py рдордзрд▓реЗ authz() рд╣реЗ рджрд╛рдЦрд╡рддреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рджреАрдкрд┐рдХрд╛ рдкрд╛рд▓рдХ рдЖрд╣реЗ. рддрд┐рдЪреНрдпрд╛ badge рд╡рд░ PARENT рд▓рд┐рд╣рд┐рд▓реЗ рдЖрд╣реЗ. рдкрд╛рд▓рдХ рдкреНрд░рдЧрддреАрдкреБрд╕реНрддрдХреЗ рдкрд╛рд╣реВ рд╢рдХрддрд╛рдд. рдореНрд╣рдгреВрди records room рддрд┐рд▓рд╛ рдЖрдд рдпреЗрдК рджреЗрддреЗ.
рдкреНрд░рдЧрддреАрдкреБрд╕реНрддрдХреЗ рдХреНрд░рдорд╛рдВрдХ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЦрдгрд╛рдВрдордзреНрдпреЗ рдЖрд╣реЗрдд. рджреАрдкрд┐рдХрд╛ "aishwarya" рдЦрдг рдорд╛рдЧрддреЗ тАФ рддрд┐рдЪреНрдпрд╛ рдореБрд▓реАрдЪрд╛. рдареАрдХ рдЖрд╣реЗ.
рдордЧ рддреА "katrina" рдЦрдг рдорд╛рдЧрддреЗ. рддрд┐рдЪреНрдпрд╛ badge рд╡рд░ рдЕрдЬреВрдирд╣реА PARENT рдЖрд╣реЗ. рдХрд╛рд░рдХреВрди рдлрдХреНрдд badge рдкрд╛рд╣рдд рдЕрд╕реЗрд▓, рддрд░ рддреЛ рдЦрдг рдЙрдШрдбрддреЛ. рд╣реАрдЪ рдЪреВрдХ рдЖрд╣реЗ. Badge "рдкрд╛рд▓рдХ рдкреНрд░рдЧрддреАрдкреБрд╕реНрддрдХреЗ рд╡рд╛рдЪреВ рд╢рдХрддрд╛рдд рдХрд╛?" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрддреЛ. "рд╣реЗ рдкреНрд░рдЧрддреАрдкреБрд╕реНрддрдХ рддрд┐рдЪреЗ рдЖрд╣реЗ рдХрд╛?" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рддреЛ рджреЗрдд рдирд╛рд╣реА.
рдореНрд╣рдгреВрди security office рджреБрд╕рд░рд╛ рдкреНрд░рд╢реНрди рдЬреЛрдбрддреЗ, рдкреНрд░рддреНрдпреЗрдХ рдЦрдгрд╛рд╕рд╛рдареА, рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА: "рдпрд╛ рдЦрдгрд╛рддрд▓реА рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреА рддреБрдордЪреНрдпрд╛ рдореБрд▓рд╛рдВрдкреИрдХреА рдПрдХ рдЖрд╣реЗ рдХрд╛?" рдХрддрд░рд┐рдирд╛ рджреАрдкрд┐рдХрд╛рдЪреА рдореБрд▓рдЧреА рдирд╛рд╣реА тЖТ рдЦрдг рдмрдВрджрдЪ рд░рд╛рд╣рддреЛ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
d["ЁЯСй Dipika<br/>role: parent<br/>children: aishwarya"]
d --> r1["GET /grades/aishwarya"]
d --> r2["GET /grades/katrina"]
r1 --> rb{"RBAC<br/>parent тЖТ grades:read?"}
r2 --> rb
rb -->|"yes for both"| obj{"object check<br/>pupil in her children?"}
obj -->|"aishwarya: yes"| ok["тЬЕ 200 тАФ her daughter's record"]
obj -->|"katrina: no"| no["тЭМ 404 тАФ stops IDOR / BOLA"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/security/lesson-diagrams.html#l06
тЭУ рдХрд╛рдп
- Authorization тАФ authenticated user рдХрд╛рдп рдХрд░реВ рд╢рдХрддреЛ рддреЗ рдард░рд╡рдгреЗ. рдЗрдерд▓реНрдпрд╛ рдЪреБрдХрд╛ рдореНрд╣рдгрдЬреЗ A01:2021 тАУ Broken Access Control, OWASP Top 10 (2021) рдордзреНрдпреЗ рдкрд╣рд┐рд▓реНрдпрд╛ рдХреНрд░рдорд╛рдВрдХрд╛рд╡рд░.
- RBAC (role-based access control) тАФ users рдирд╛ roles рдорд┐рд│рддрд╛рдд, roles рдирд╛ permissions рдорд┐рд│рддрд╛рдд.
ROLESparent тЖТ {grades:read},teacher тЖТ {grades:read, grades:write},admin тЖТ {тАж, users:manage}рдЕрд╕реЗ рдЬреЛрдбрддреЗ. рд╡рд╛рдЪрд╛рдпрд▓рд╛ рдЖрдгрд┐ audit рдХрд░рд╛рдпрд▓рд╛ рд╕реЛрдкреЗ. Default рдиреЗ рдирдХрд╛рд░: рдЕрдиреЛрд│рдЦреА role рд▓рд╛ рдХрд╛рд╣реАрдЪ рдорд┐рд│рдд рдирд╛рд╣реА. - ABAC (attribute-based access control) тАФ рдирд┐рд░реНрдгрдп user, resource рдЖрдгрд┐ request рдЪреНрдпрд╛ attributes рд╡рд╛рдкрд░рддреЛ: owner, рд╡рд░реНрдЧ, рд╢рд╛рд│рд╛, рджрд┐рд╡рд╕рд╛рдЪреА рд╡реЗрд│. "Teacher рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рд╡рд░реНрдЧрд╛рд╕рд╛рдареА grades рд▓рд┐рд╣реВ рд╢рдХрддреЗ" рд╣реЗ ABAC рдЖрд╣реЗ. рдЬрд╛рд╕реНрдд рдЕрдЪреВрдХ, test рдХрд░рд╛рдпрд▓рд╛ рдЬрд╛рд╕реНрдд рдХрдареАрдг.
- Object-level authorization тАФ рдпрд╛ record рд╡рд░рдЪреА рддрдкрд╛рд╕рдгреА: рд╣рд╛ user рддреНрдпрд╛рдЪрд╛ рдорд╛рд▓рдХ рдЖрд╣реЗ рдХрд╛, рдХрд┐рдВрд╡рд╛
рддреНрдпрд╛рдЪреНрдпрд╛рд╢реА рддреНрдпрд╛рдЪреЗ рдирд╛рддреЗ рдЖрд╣реЗ рдХрд╛?
can_read_record()тАФ рдкрд╛рд▓рдХ рдлрдХреНрдд рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдореБрд▓рд╛рдВрд╕рд╛рдареА, teacher рдлрдХреНрдд рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рд╡рд░реНрдЧрд╛рдВрд╕рд╛рдареА. - IDOR (insecure direct object reference) / BOLA (broken object level authorization) тАФ
API client рдХрдбреВрди id рдШреЗрддреЗ (
/grades/katrina,/invoices/1043) рдЖрдгрд┐ object-level рддрдкрд╛рд╕рдгреАрд╢рд┐рд╡рд╛рдп object рдкрд░рдд рджреЗрддреЗ. Id рдмрджрд▓рд▓рд╛ рдХреА рджреБрд╕рд▒реНрдпрд╛ рдХреЛрдгрд╛рдЪрд╛ data рджрд┐рд╕рддреЛ. OWASP API Security Top 10 рдордзреНрдпреЗ BOLA API1:2023 рдЖрд╣реЗ. - рддрдкрд╛рд╕рдгреА рдХреБрдареЗ рд░рд╛рд╣рддреЗ тАФ server рд╡рд░, рдПрдХрд╛рдЪ рдард┐рдХрд╛рдгреА (policy function, query filter, рдХрд┐рдВрд╡рд╛ database row-level security), рдкреНрд░рддреНрдпреЗрдХ request рд╕рд╛рдареА тАФ updates, deletes, exports рдЖрдгрд┐ "рд▓рдкрд╡рд▓реЗрд▓реЗ" admin endpoints рд╕реБрджреНрдзрд╛.
- 404 рдХреА 403? тАФ user рдиреЗ рдкрд╛рд╣реВ рдирдпреЗрдд рдЕрд╢рд╛ records рд╕рд╛рдареА рдЕрдиреЗрдХ APIs 404 рдЙрддреНрддрд░ рджреЗрддрд╛рдд, рдореНрд╣рдгрдЬреЗ record рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЖрд╣реЗ рд╣реЗ рдЙрдШрдб рд╣реЛрдд рдирд╛рд╣реА.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рд╣рд╛ bug tests рдордзреВрди рд╕реБрдЯрддреЛ. рддреНрдпрд╛рддрд▓реА рдкреНрд░рддреНрдпреЗрдХ request рдпреЛрдЧреНрдпрд░рд┐рддреНрдпрд╛ login рдХреЗрд▓реЗрд▓реА рдЕрд╕рддреЗ, рдпреЛрдЧреНрдп role рдЕрд╕рд▓реЗрд▓реА рдЕрд╕рддреЗ, рдЖрдгрд┐ рдЦрд▒реНрдпрд╛ endpoint рд╡рд░ рдЬрд╛рддреЗ. рдлрдХреНрдд id рд╡реЗрдЧрд│рд╛ рдЕрд╕рддреЛ. Automated scanners рддреЗ рдХреНрд╡рдЪрд┐рддрдЪ рд╢реЛрдзрддрд╛рдд тАФ record 1043 рджреБрд╕рд▒реНрдпрд╛ рдХреЛрдгрд╛рдЪрд╛ рдЖрд╣реЗ рд╣реЗ рддреНрдпрд╛рдВрдирд╛ рдорд╛рд╣реАрдд рдирд╕рддреЗ. рдЖрдгрд┐ ids рдмрджрд▓рдгреЗ рд╕реЛрдкреЗ рдЕрд╕рддреЗ: URL рдордзрд▓рд╛ рдПрдХ number, JSON рдордзрд▓реЗ рдПрдХ field, рд▓рдкрд╡рд▓реЗрд▓реА form value. Random ids (UUIDs) рдореБрд│реЗ рдЕрдВрджрд╛рдЬ рдХрд░рдгреЗ рдХрдареАрдг рд╣реЛрддреЗ, рдкрдг рддреА рддрдкрд╛рд╕рдгреА рдирд╛рд╣реА.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
sec/identity.py рдордзреНрдпреЗ: can(role, permission) permission
ROLES рдордзреНрдпреЗ рд╢реЛрдзрддреЗ (рдЕрдиреЛрд│рдЦреА role рд▓рд╛ рд░рд┐рдХрд╛рдорд╛ set рдорд┐рд│рддреЛ). can_read_record(user, record) рд╣реА
object-level рддрдкрд╛рд╕рдгреА рдЖрд╣реЗ: parent тЖТ record["pupil"] in user["children"]; teacher тЖТ
record["class"] in user["classes"]; рдлрдХреНрдд admin рд▓рд╛ рд╕рдЧрд│реЗ рджрд┐рд╕рддреЗ.
sec/demo.py рдордзрд▓реЗ authz() рджреЛрдиреНрд╣реА requests рд╕рд╛рдареА RBAC рдкрд╛рд╕ рд╣реЛрддрд╛рдирд╛, рдЖрдгрд┐ object рддрдкрд╛рд╕рдгреА
рдирд┐рд░реНрдгрдп рдШреЗрддрд╛рдирд╛ рджрд╛рдЦрд╡рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 sec/demo.py authz
python3 - <<'EOF'
import sys; sys.path.insert(0, "sec"); from identity import can, can_read_record
people = {"Dipika (parent)": dict(role="parent", children={"aishwarya"}),
"teacher of 3A": dict(role="teacher", classes={"3A"}),
"teacher of 4B": dict(role="teacher", classes={"4B"}),
"office admin": dict(role="admin")}
records = [dict(pupil="aishwarya", **{"class": "3A"}), dict(pupil="katrina", **{"class": "4B"})]
for who, u in people.items():
rows = " ┬╖ ".join(f"{r['pupil']} {can_read_record(u, r)}" for r in records)
print(f"{who:<16} grades:read {can(u['role'], 'grades:read')!s:<5} тЖТ {rows}")
print("unknown role 'visitor' grades:read тЖТ", can("visitor", "grades:read"))
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
authz рд╣реЗ print рдХрд░рддреЗ:
тФАтФА RBAC: parent may grades:read True ┬╖ grades:write False ┬╖ teacher grades:write True
тФАтФА GET /grades/{id}: the role check passes for both тАФ the OBJECT check is what matters
Dipika (parent of Aishwarya) reads Aishwarya's record тЖТ True
Dipika changes the id in the URL to Katrina's record тЖТ False (without this check: IDOR / BOLA)
check ownership on the server for every object, every time тАФ never trust an id from the client
рддреБрдордЪрд╛ snippet рд╣реЗ print рдХрд░рддреЛ:
Dipika (parent) grades:read True тЖТ aishwarya True ┬╖ katrina False
teacher of 3A grades:read True тЖТ aishwarya True ┬╖ katrina False
teacher of 4B grades:read True тЖТ aishwarya False ┬╖ katrina True
office admin grades:read True тЖТ aishwarya True ┬╖ katrina True
unknown role 'visitor' grades:read тЖТ False
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдЪрд╛рд░рд╣реА users role рддрдкрд╛рд╕рдгреА рдкрд╛рд╕ рдХрд░рддрд╛рдд тАФ role column рдкреНрд░рддреНрдпреЗрдХрд╛рд╕рд╛рдареА True рдореНрд╣рдгрддреЛ.
рддреНрдпрд╛рдВрдирд╛ рд╡реЗрдЧрд│реЗ рдХрд░рддреЗ рддреА object рддрдкрд╛рд╕рдгреА: рдкреНрд░рддреНрдпреЗрдХ teacher рд▓рд╛ рдлрдХреНрдд рд╕реНрд╡рддрдГрдЪрд╛ рд╡рд░реНрдЧ рджрд┐рд╕рддреЛ, рдкрд╛рд▓рдХрд╛рд▓рд╛
рдлрдХреНрдд рддрд┐рдЪреЗ рд╕реНрд╡рддрдГрдЪреЗ рдореВрд▓. RBAC "рдХреЛрдгрддреНрдпрд╛ рдкреНрд░рдХрд╛рд░рдЪреА рдХреГрддреА" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрддреЗ; object рддрдкрд╛рд╕рдгреА "рдХреЛрдгрддреНрдпрд╛
record рд╡рд░" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрддреЗ. API рд▓рд╛ рджреЛрдиреНрд╣реА рд▓рд╛рдЧрддрд╛рдд.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- URL рдордзрд▓реНрдпрд╛ id рд╕рд╣
SELECT * FROM grades WHERE id = ?тАФ рдЖрдгрд┐ рджреБрд╕рд░реЗ рдХрд╛рд╣реАрдЪ рдирд╛рд╣реА GETрд╡рд░ ownership рддрдкрд╛рд╕рдгреЗ, рдкрдгPUT,DELETEрдХрд┐рдВрд╡рд╛ CSV export рд╡рд░ рдирд╛рд╣реА- UI рдордзрд▓реЗ button рд▓рдкрд╡рдгреЗ рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ "access control" рдореНрд╣рдгрдгреЗ
- request body рдордзреНрдпреЗ рдкрд╛рдард╡рд▓реЗрд▓реНрдпрд╛
user_idрдХрд┐рдВрд╡рд╛rolefield рд╡рд░ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдареЗрд╡рдгреЗ - рдкреНрд░рддреНрдпреЗрдХ staff member рд╕рд╛рдареА рдПрдХрдЪ рдкреНрд░рдЪрдВрдб
adminrole, рдХрд╛рд░рдг roles рдХрдзреА рд╡рд┐рднрд╛рдЧрд▓реЗрдЪ рдирд╛рд╣реАрдд - рдПрдХрдореЗрд╡ рд╕рдВрд░рдХреНрд╖рдг рдореНрд╣рдгреВрди random ids (UUIDs)
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ ownership query рдордзреНрдпреЗрдЪ рдареЗрд╡рд╛, рдореНрд╣рдгрдЬреЗ рдирд╕рд▓реЗрд▓рд╛ record рдЖрдгрд┐ рдордирд╛рдИ рдЕрд╕рд▓реЗрд▓рд╛ record рд╕рд╛рд░рдЦреЗрдЪ рджрд┐рд╕рддрд╛рдд (Python + psycopg):
cur.execute("""
SELECT g.subject, g.grade FROM grades g
JOIN guardians gu ON gu.pupil_id = g.pupil_id
WHERE g.pupil_id = %s AND gu.parent_id = %s""", (pupil_id, current_user.id))
rows = cur.fetchall()
if not rows: abort(404)
Django ORM рд╕рд╣ рд╣реЗрдЪ тАФ filter рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА user рдЕрд╕рддреЛ:
grade = get_object_or_404(Grade, pk=pk, pupil__guardians__user=request.user)
рдХрд┐рдВрд╡рд╛ PostgreSQL row-level security рдиреЗ database рд▓рд╛рдЪ рд╣реЗ enforce рдХрд░реВ рджреНрдпрд╛ тАФ рд╡рд┐рд╕рд░рд▓реЗрд▓рд╛ filter рд╕реБрджреНрдзрд╛ рджреБрд╕рд▒реНрдпрд╛ рдХреБрдЯреБрдВрдмрд╛рдЪреНрдпрд╛ rows рдкрд░рдд рджреЗрдК рд╢рдХрдд рдирд╛рд╣реА:
ALTER TABLE grades ENABLE ROW LEVEL SECURITY;
CREATE POLICY parent_reads_own ON grades FOR SELECT
USING (pupil_id IN (SELECT pupil_id FROM guardians
WHERE parent_id = current_setting('app.user_id')::int));
-- at the start of each request, in the same transaction, the app runs:
-- SELECT set_config('app.user_id', %s, true) with the user id as a bound parameter
рддрдкрд╛рд╕рдгреА рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЖрд╣реЗ рд╣реЗ рд╕рд┐рджреНрдз рдХрд░рдгрд╛рд░реА test (pytest) тАФ рдПрдХ user, рджреБрд╕рд▒реНрдпрд╛ user рдЪрд╛ id:
def test_parent_cannot_read_other_pupil(client, login_as):
login_as("dipika")
assert client.get("/grades/aishwarya").status_code == 200
assert client.get("/grades/katrina").status_code == 404
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: object рддрдкрд╛рд╕рдгреА рд╡рд┐рд╕рд░рдгреЗ рдЕрд╢рдХреНрдп рдХрд░рд╛ тАФ рдиреЗрд╣рдореА рд╕рдзреНрдпрд╛рдЪрд╛ user рдШреЗрдгрд╛рд░реА repository method, рдХрд┐рдВрд╡рд╛ row-level security тАФ рдЖрдгрд┐ id рдШреЗрдгрд╛рд▒реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ endpoint рд╕рд╛рдареА рдПрдХ "рджреБрд╕рд▒реНрдпрд╛ user рдЪрд╛ id" test рдЬреЛрдбрд╛. рдЕрдиреЗрдХ services рдордзреНрдпреЗ рдмрд╛рд░реАрдХ ABAC рд╕рд╛рдареА, policy engine (Open Policy Agent, Cedar / Amazon Verified Permissions) рдирд┐рдпрдо рдПрдХрд╛рдЪ test рдХреЗрд▓реЗрд▓реНрдпрд╛ рдард┐рдХрд╛рдгреА рдареЗрд╡рддреЗ.
тПня╕П рдкреБрдвреЗ
рдУрд│рдЦрдкрддреНрд░ рдЦрд┐рдбрдХреА рдкреВрд░реНрдг рдЭрд╛рд▓реА. рдЖрддрд╛ рдЗрдорд╛рд░рдд рдЦрд┐рдбрдХреА: рдкреВрд░реНрдг рдЗрдорд╛рд░рддреАрдЪреНрдпрд╛ рдХрд┐рд▓реНрд▓реНрдпрд╛. Database passwords рдЖрдгрд┐ encryption keys рдХреБрдареЗ рд░рд╛рд╣рддрд╛рдд тАФ рдЖрдгрд┐ code рдордзреНрдпреЗ рдХрдзреАрдЪ рдХрд╛ рдирд╛рд╣реАрдд?
git checkout lesson-07-secrets-kms