Al final de 04-01 vam deixar una promesa a mig complir. La política pol-mercadofresco-tienda exigeix
que cada miniatura es pugi amb s3:x-amz-server-side-encryption: aws:kms, i rol-lambda-miniaturas
té concedits kms:Decrypt i kms:GenerateDataKey sobre una clau identificada per un UUID. Però
aquella clau, alias/mercadofresco-datos, continua sent poc més que un nom: ningú no ha decidit qui
l'administra, qui la pot fer servir, cada quant rota, ni què passa exactament quan S3 «xifra» un
objecte.
I hi ha una raó de negoci al darrere. MercadoFresco guarda noms, adreces de repartiment, telèfons i historial de comandes de clients espanyols. Això són dades personals en el sentit del RGPD, i l'article 32 del reglament cita el xifratge explícitament com a mesura tècnica apropiada. Si un portàtil amb una còpia de la base de dades acaba al seient del darrere d'un taxi, la diferència entre «incident» i «bretxa notificable en 72 hores» sol ser si el contingut estava xifrat.
AWS Key Management Service (KMS) és el servei que custodia les claus de xifratge, controla qui
les pot fer servir i registra cada ús. En aquesta lliçó la Marta l'entén de debò —inclòs el mecanisme
del xifratge de sobre, que explica tota la resta— i xifra per fi les còpies de la base de dades,
els volums i la instància mercadofresco-pedidos.
Advertiment. Els exemples d'aquesta lliçó són didàctics. Tota configuració de xifratge, gestió de claus o compliment normatiu (RGPD, PCI DSS, ENS) que s'hagi d'aplicar sobre dades reals de clients ha de ser revisada per un professional de seguretat o de compliment abans d'arribar a producció. El xifratge mal implementat dona una falsa sensació de seguretat, i una clau mal esborrada destrueix dades de manera irreversible. Tots els identificadors i dades d'aquest curs són ficticis.
Contingut
- Per què xifrar: el RGPD i les dades de MercadoFresco
- En repòs i en trànsit
- Criptografia simètrica i asimètrica, el just
- Què és KMS i què no és
- Tipus de clau
- Claus multiregió, material importat i CloudHSM
- El xifratge de sobre
- El desxifratge, pas a pas
- Xifratge del costat del client i del costat del servidor
- SSE-S3, SSE-KMS i SSE-C
- Les claus de bucket d'S3 i el cost de les peticions
- La política de clau i la seva relació amb IAM
kms:ViaServicei el context de xifratge- Concessions (grants)
- Rotació automàtica i què significa realment
- Xifrar
mercadofresco-copias-basedatos - Xifrar volums d'EBS i snapshots
- Xifrar
mercadofresco-pedidos, que ja existeix sense xifrar - Compartir un snapshot xifrat amb un altre compte
- KMS des de boto3
- Límits, quotes i cost real per a MercadoFresco
- ACM no és KMS
- Eliminar una clau: els 7 a 30 dies d'espera
Per què xifrar: el RGPD i les dades de MercadoFresco
El xifratge no protegeix de tot. Protegeix d'un conjunt molt concret d'amenaces, i convé ser honest sobre quin:
| Amenaça | Ajuda el xifratge en repòs? |
|---|---|
| Algú roba un disc físic del centre de dades | Sí, totalment |
| Un snapshot o una còpia es comparteix per error amb un altre compte | Sí, si no té la clau |
| Un bucket queda exposat públicament | Sí amb SSE-KMS: a més del permís d'S3 cal el de KMS |
| Es compleix el requisit normatiu d'una auditoria | Sí, i a més amb registre de cada ús |
| Un atacant roba les credencials de l'aplicació | No: l'aplicació té permís per desxifrar |
| Una injecció SQL extreu la taula de clients | No: la base de dades retorna les dades ja en clar |
Aquella taula és important: el xifratge en repòs és una capa, no un escut màgic. Les dues últimes files són exactament les raons per les quals 04-01 existeix i per les quals 04-05 existirà.
Per a MercadoFresco hi ha tres conjunts de dades que s'han de xifrar sense discussió:
mercadofresco-copias-basedatos: còpies completes de la base de dadespedidos, amb noms, adreces i telèfons de tots els clients. És l'actiu més perillós del compte.- La instància
mercadofresco-pedidosi els seus snapshots automàtics. - Els volums d'EBS de les instàncies de la botiga i el volum
mercadofresco-fotos-01.
El catàleg de fotos públiques (productos/) no conté dades personals, però es xifra igualment perquè
el cost marginal és zero i no haver de pensar en què està xifrat i què no és en si mateix un avantatge
operatiu.
En repòs i en trànsit
Són dos problemes diferents, resolts per mecanismes diferents:
| En repòs | En trànsit | |
|---|---|---|
| Què protegeix | Dades desades al disc | Dades viatjant per la xarxa |
| Mecanisme | AES-256 sobre el volum, l'objecte o la fila | TLS 1.2/1.3 |
| Servei | KMS | ACM per als certificats |
| A MercadoFresco | S3, EBS, RDS, snapshots | HTTPS a CloudFront i a l'ALB (03-03, 03-05) |
| Com es força | Xifratge per defecte del bucket, kms: a la política |
Deny amb aws:SecureTransport: false |
El xifratge en trànsit ja està resolt des del mòdul 3: el certificat d'ACM a l'ALB i a CloudFront, i
el Deny que vam escriure a pol-mercadofresco-tienda quan aws:SecureTransport és fals. Aquesta
lliçó va de l'altre.
Criptografia simètrica i asimètrica, el just
No cal saber criptografia per fer servir KMS, però sí distingir dues famílies:
Simètrica. La mateixa clau xifra i desxifra. És rapidíssima: AES-256 xifra centenars de megabytes per segon en qualsevol CPU moderna. El seu problema és la distribució: cal fer arribar la clau a l'altre extrem sense que ningú la intercepti.
Asimètrica. Dues claus relacionades matemàticament: la pública xifra i la privada desxifra (o al revés, per signar). Resol la distribució —la pública es pot publicar— però és ordres de magnitud més lenta i només pot xifrar dades molt petites (una clau RSA de 2048 bits xifra com a molt 190 bytes).
| Simètrica | Asimètrica | |
|---|---|---|
| Claus | Una | Parell pública/privada |
| Velocitat | Molt ràpida | Lenta |
| Mida de dades | Il·limitada | Centenars de bytes |
| Algorisme típic | AES-256-GCM | RSA-2048, ECC |
| Ús a KMS | Per defecte, xifratge de dades | Signatura, xifratge entre parts sense secret compartit |
A KMS, si no demanes una altra cosa, totes les claus són simètriques AES-256. I la combinació de les dues idees —fer servir simètrica per a les dades i protegir aquella clau amb una altra clau— és exactament el xifratge de sobre que veiem d'aquí a dos apartats.
Què és KMS i què no és
KMS és un servei que:
- Genera i custodia claus mestres dins de mòduls de maquinari certificats FIPS 140-3 nivell 3, dels quals el material de la clau no surt mai en clar.
- Executa operacions criptogràfiques (
Encrypt,Decrypt,GenerateDataKey,Sign,Verify) sobre dades petites. - Controla qui pot fer servir cada clau, mitjançant polítiques.
- Registra cada crida a CloudTrail (05-03), inclòs qui va desxifrar què i quan.
KMS no és:
- Un magatzem de secrets: per a contrasenyes i cadenes de connexió hi ha Secrets Manager (04-03).
- Un servei per xifrar fitxers grans: hi ha un límit dur de 4 KB per crida a
Encrypt. - Una autoritat de certificació: això és ACM, i ho aclarim al final.
- Un lloc d'on puguis extreure la teva clau per endur-te-la. Amb les claus gestionades per KMS, el material no es pot exportar. És una garantia, no una limitació.
Aquesta última frase mereix aturar-s'hi: si el material no surt mai, com es xifren les dades? La resposta és el xifratge de sobre.
Tipus de clau
A KMS la unitat fonamental és la KMS key (abans anomenada CMK, Customer Master Key). Hi ha tres categories segons l'origen:
| Tipus | Qui la crea | Política | Rotació | Cost | Quan |
|---|---|---|---|---|---|
| Propietat d'AWS | AWS, compartida entre clients | No la veus | AWS ho decideix | Gratis | Xifratge per defecte d'S3 (SSE-S3) |
Gestionada per AWS (aws/s3, aws/rds, aws/ebs) |
AWS, una per servei i compte | No editable | Anual, obligatòria | Gratis (sí les peticions) | Començar de pressa, sense control fi |
| Gestionada pel client (CMK) | Tu | Editable | Opcional, configurable | 1 USD/mes | Quan necessites controlar qui fa servir la clau |
La diferència decisiva entre les dues últimes no és el preu, és el control:
- Amb una clau gestionada per AWS no pots editar la política de clau. Qualsevol principal del teu compte amb permisos d'S3 podrà desxifrar. No la pots fer servir des d'un altre compte ni denegar-ne l'ús a un rol concret.
- Amb una clau gestionada pel client decideixes exactament qui administra i qui fa servir, pots denegar-ne l'accés a un rol encara que tingui permisos d'S3, la pots compartir entre comptes i la pots desactivar, cosa que converteix totes les dades xifrades amb ella en il·legibles a l'instant. Això últim és un botó d'emergència molt potent.
Per a mercadofresco-copias-basedatos, que conté dades personals, la clau ha de ser gestionada pel
client. Aquest és el paper d'alias/mercadofresco-datos.
I una nota sobre els àlies: un àlies és un punter mutable a una clau. Fer servir
alias/mercadofresco-datos al codi en lloc de l'UUID permet canviar la clau subjacent sense tocar
l'aplicació. Cada àlies és regional i no es pot repetir dins de la regió.
Claus multiregió, material importat i CloudHSM
Tres variants que convé conèixer encara que MercadoFresco no les faci servir avui:
Claus multiregió. Una clau primària a eu-west-1 i rèpliques en altres regions que comparteixen
el mateix material criptogràfic i el mateix identificador (amb prefix mrk-). El que es xifra en
una regió es desxifra en una altra sense crides entre regions. És imprescindible per a còpies de
seguretat entre regions i per a recuperació davant de desastres. Trenca l'aïllament regional, així
que només quan de debò calgui.
Material importat (BYOK). Portes el teu propi material de clau i KMS només el custodia. Es fa servir quan una normativa exigeix que l'organització generi les claus. Té una contrapartida seriosa: si perds la teva còpia del material i expira a KMS, les dades són irrecuperables. I no admet rotació automàtica.
Magatzem de claus personalitzat sobre CloudHSM. El material viu en un clúster de CloudHSM de la teva propietat, dedicat, amb inquilí únic. És el que exigeixen alguns entorns financers o del sector públic. Costa de l'ordre d'1,50 USD per hora i HSM —més de 1.000 USD al mes per HSM, i se'n recomanen dos—, així que és una decisió de compliment, no d'enginyeria. Només ho esmentem.
El xifratge de sobre
Aquest és el concepte central de la lliçó. Si el material de la clau no surt mai de KMS i Encrypt
només admet 4 KB, com es xifra un snapshot de 200 GB?
La resposta és que les dades grans no viatgen mai a KMS. Es fan servir dos nivells de clau:
- La clau mestra (la KMS key) viu a KMS i no en surt mai.
- La clau de dades (data key) és una clau AES-256 d'un sol ús que KMS genera, lliura en dos formats i després oblida.
sequenceDiagram
participant A as Aplicacio / S3
participant K as KMS<br/>alias/mercadofresco-datos
participant D as Disc
Note over A,D: XIFRATGE
A->>K: GenerateDataKey(KeyId, KeySpec=AES_256)
K->>K: Genera una clau AES-256 aleatoria
K-->>A: Plaintext (clau en clar)<br/>+ CiphertextBlob (la mateixa, xifrada<br/>amb la clau mestra)
A->>A: Xifra els 200 GB amb Plaintext (AES local, rapid)
A->>A: ESBORRA Plaintext de memoria
A->>D: Desa: dades xifrades + CiphertextBlob juntes
Els passos, en paraules:
- L'aplicació demana a KMS una clau de dades. No envia les dades.
- KMS genera una clau AES-256 aleatòria i retorna dues versions de la mateixa clau: en clar
(
Plaintext) i xifrada amb la clau mestra (CiphertextBlob). - L'aplicació xifra els 200 GB localment amb la versió en clar. Va a velocitat de CPU, sense xarxa pel mig.
- L'aplicació esborra de memòria la versió en clar. Aquest pas és el que fa que el sistema sigui segur.
- Desa juntes les dades xifrades i el
CiphertextBlob. El blob és inútil per a qui no pugui cridarkms:Decryptsobre la clau mestra.
Avantatges d'aquest disseny, tots conseqüència del mateix truc:
| Avantatge | Per què |
|---|---|
| Rendiment | Les dades es xifren localment a velocitat de CPU, no de xarxa |
| Cost | Una crida a KMS per fitxer (o menys), no per byte |
| Sense límit de mida | El límit de 4 KB només afecta la clau de dades, que ocupa 32 bytes |
| Rotació barata | Rotar la mestra no obliga a tornar a xifrar les dades (ho veiem més endavant) |
| Traçabilitat | Cada GenerateDataKey i cada Decrypt queda a CloudTrail |
El desxifratge, pas a pas
sequenceDiagram
participant D as Disc
participant A as Aplicacio / S3
participant K as KMS
Note over D,K: DESXIFRATGE
D-->>A: dades xifrades + CiphertextBlob
A->>K: Decrypt(CiphertextBlob)
K->>K: Comprova la politica de clau<br/>i els permisos IAM de qui crida
alt Autoritzat
K-->>A: Plaintext (clau de dades en clar)
A->>A: Desxifra les dades localment
A->>A: ESBORRA Plaintext
else No autoritzat
K-->>A: AccessDeniedException
Note over A: Les dades no es poden llegir<br/>encara que tinguis el fitxer
end
Fixa't en el punt crític: per desxifrar no cal indicar quina clau es va fer servir. El
CiphertextBlob porta a dins l'identificador de la clau mestra, i KMS la localitza sola. Per això
Decrypt no necessita el paràmetre KeyId amb claus simètriques.
I fixa't en la branca else: qui tingui el fitxer però no permís sobre la clau es queda amb soroll.
Aquest és el motiu que un snapshot xifrat compartit per error continuï sent segur.
Xifratge del costat del client i del costat del servidor
| Del costat del servidor (SSE) | Del costat del client (CSE) | |
|---|---|---|
| Qui xifra | AWS, en rebre la dada | La teva aplicació, abans d'enviar-la |
| Què veu AWS | La dada en clar durant el processament | Només dades xifrades, mai en clar |
| Complexitat | Gairebé cap: una casella | Alta: gestiones el procés |
| Cerques, índexs | Funcionen | No funcionen sobre el que està xifrat |
| Quan | El 95 % dels casos | Confidencialitat extrema davant del proveïdor |
MercadoFresco fa servir del costat del servidor en tot. El xifratge del costat del client té sentit quan el model d'amenaça inclou el mateix proveïdor de núvol o quan una normativa ho exigeix; per a una botiga de producte fresc, la complexitat addicional no compensa. Si algun dia calgués, existeix l'AWS Encryption SDK i el client xifrat d'S3, que implementen el sobre per tu.
SSE-S3, SSE-KMS i SSE-C
S3 ofereix tres formes de xifratge del costat del servidor. La diferència és qui controla la clau:
| SSE-S3 | SSE-KMS | SSE-C | |
|---|---|---|---|
| Clau mestra | Propietat d'AWS | Teva, a KMS | Teva, l'envies a cada petició |
| Capçalera | AES256 |
aws:kms |
aws:kms no; capçaleres -customer- |
| Política d'accés | Només IAM d'S3 | IAM d'S3 i política de clau | La tens tu |
| Registre a CloudTrail | No | Sí, cada ús | No |
| Cost | Gratis | 1 USD/mes + peticions | Gratis a KMS |
| Rotació | Automàtica, invisible | Configurable i auditable | Manual, teva |
| Doble autorització | No | Sí | No |
| Quan | Dades no sensibles | Dades personals, compliment | Gairebé mai |
La fila decisiva és doble autorització. Amb SSE-KMS, per llegir un objecte calen dos permisos:
s3:GetObject i kms:Decrypt sobre la clau. Si un bucket amb dades personals quedés accidentalment
exposat al públic, l'atacant obtindria l'objecte xifrat i no el podria obrir, perquè no té permís
sobre la clau. És una xarxa de seguretat real que SSE-S3 no dona.
SSE-C, on tu envies la clau a cada petició i AWS la fa servir i l'oblida, obliga a gestionar la distribució de claus pel teu compte i no deixa registre. S'esmenta per completitud.
Decisió per a MercadoFresco:
| Bucket | Xifratge | Motiu |
|---|---|---|
mercadofresco-copias-basedatos |
SSE-KMS amb alias/mercadofresco-datos |
Dades personals, RGPD, auditoria |
mercadofresco-catalogo-fotos |
SSE-KMS | Coherència; ja ho exigeix la política de la botiga |
mercadofresco-informes-analitica |
SSE-KMS | Dades agregades de negoci |
mercadofresco-registros-web |
SSE-S3 | Volum alt, sense dades personals directes |
mercadofresco-tienda-web-desarrollo |
SSE-S3 | Contingut estàtic públic |
Les claus de bucket d'S3 i el cost de les peticions
Aquí hi ha un parany econòmic que enfonsa pressupostos. Sense res més, cada objecte que es puja o
es descarrega d'un bucket amb SSE-KMS genera una crida a KMS. mercadofresco-catalogo-fotos serveix
—abans de CloudFront— de l'ordre de 2 milions de peticions al mes. A 0,03 USD per cada 10.000
peticions, això són 6 USD al mes només en crides a KMS, més que la mateixa clau.
La solució és la clau de bucket d'S3 (S3 Bucket Key): S3 demana a KMS una clau de nivell de bucket, la manté en memòria cau unes hores i en deriva les claus dels objectes individuals.
| Sense clau de bucket | Amb clau de bucket | |
|---|---|---|
| Crides a KMS | Una per objecte | Una cada poques hores |
| Reducció de cost | — | Fins al 99 % |
| Registre a CloudTrail | Una entrada per objecte | Una entrada per clau de bucket |
| Cost afegit | — | Cap |
La contrapartida és la tercera fila: perds la traça per objecte a CloudTrail. Per a
mercadofresco-catalogo-fotos, amb milions de fotos públiques, és un intercanvi excel·lent. Per a
mercadofresco-copias-basedatos, on vols saber exactament qui va desxifrar quina còpia i quan, pot
interessar deixar-la desactivada: són poques peticions al mes i la traça val més que l'estalvi.
Activa-la sempre que no necessitis la traça per objecte. És gratis i estalvia un 99 %.
La política de clau i la seva relació amb IAM
Aquí hi ha l'excepció que vam anunciar a 04-01. A gairebé tots els serveis, al mateix compte n'hi ha prou que una de les dues polítiques concedeixi. A KMS no. Tota clau té una política de clau (una política basada en recurs) i:
Si la política de clau no ho permet, ningú no pot fer servir la clau. Ni l'administrador del compte, ni tan sols el root.
Això té una conseqüència que cal gravar-se a foc: si crees una clau per CLI amb una política que no inclou ningú, la clau queda inservible per sempre i només se'n pot programar l'eliminació. AWS ho evita a la consola, però no per CLI.
Hi ha dos models:
- La política de clau delega en IAM. S'hi inclou la declaració
"Principal": {"AWS": "arn:aws:iam::111122223333:root"}amb"Action": "kms:*", cosa que significa «les polítiques d'IAM d'aquest compte poden concedir accés a aquesta clau». És el que fa la consola per defecte. - La política de clau concedeix directament, nomenant rols concrets. Més restrictiu i més explícit.
MercadoFresco fa servir un model mixt: delega en IAM per a l'administració però nomena explícitament
qui fa servir la clau. Aquesta és la política completa d'alias/mercadofresco-datos:
{
"Version": "2012-10-17",
"Id": "politica-mercadofresco-datos",
"Statement": [
{
"Sid": "PermitirQueIAMGobierneLaClave",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "MartaAdministraLaClavePeroNoLaUsa",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:user/marta" },
"Action": [
"kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*",
"kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*",
"kms:TagResource", "kms:UntagResource", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "LosRolesDeAplicacionUsanLaClave",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::111122223333:role/rol-mercadofresco-tienda",
"arn:aws:iam::111122223333:role/rol-lambda-miniaturas"
]
},
"Action": [
"kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*",
"kms:GenerateDataKey*", "kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": ["s3.eu-west-1.amazonaws.com"]
}
}
},
{
"Sid": "PermitirQueRDSYEBSUsenLaClaveMedianteConcesiones",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:CreateGrant",
"Resource": "*",
"Condition": {
"Bool": { "kms:GrantIsForAWSResource": "true" },
"StringEquals": {
"kms:ViaService": ["rds.eu-west-1.amazonaws.com", "ec2.eu-west-1.amazonaws.com"]
}
}
},
{
"Sid": "ProhibirElUsoFueraDeEuWest1",
"Effect": "Deny",
"Principal": "*",
"Action": "kms:*",
"Resource": "*",
"Condition": {
"StringNotEquals": { "aws:RequestedRegion": "eu-west-1" }
}
}
]
}Declaració per declaració:
PermitirQueIAMGobierneLaClave: l'«interruptor» que fa que les polítiques d'IAM comptin per a aquesta clau. Sense ell, cap política d'identitat no hi tindria efecte. És el que evita quedar-te fora de la teva pròpia clau.MartaAdministraLaClavePeroNoLaUsa: la Marta pot habilitar, deshabilitar, etiquetar, canviar la política i programar l'eliminació... però no hi apareixkms:Decryptnikms:Encrypt. Aquesta és la separació de funcions: qui administra la clau no pot llegir les dades que protegeix. És un requisit habitual en auditories i aquí es veu implementat en dues línies.LosRolesDeAplicacionUsanLaClave: els dos rols que vam formalitzar a 04-01 poden xifrar i desxifrar, però només a través d'S3 gràcies akms:ViaService. Si algú roba les credencials de la instància i cridakms:Decryptdirectament contra un blob que va aconseguir per una altra via, KMS ho rebutja.PermitirQueRDSYEBSUsenLaClaveMedianteConcesiones: RDS i EBS no criden la clau directament; creen concessions en nom teu. La condiciókms:GrantIsForAWSResourcelimita aquesta capacitat als serveis d'AWS, no a persones.ProhibirElUsoFueraDeEuWest1: barrera de residència de dades. Encaixa amb l'argumentació de RGPD sobre mantenir el tractament dins de la UE.
I el rol de la botiga, a més, necessita a la seva política d'identitat els mateixos permisos de KMS —recorda: al mateix compte n'hi ha prou que una concedeixi, llevat que la de recurs denegui, però a KMS la de recurs sempre ha de permetre. A la pràctica s'escriuen totes dues.
kms:ViaService i el context de xifratge
Dos mecanismes que refinen el control i que apareixen constantment en polítiques reals.
kms:ViaService. Restringeix l'ús de la clau a peticions que arriben a través d'un servei
concret, i només quan el servei actua en nom del principal. Valors típics:
s3.eu-west-1.amazonaws.com, rds.eu-west-1.amazonaws.com, ec2.eu-west-1.amazonaws.com,
secretsmanager.eu-west-1.amazonaws.com. És la condició més útil de KMS: converteix una clau genèrica
en una clau «només per a S3».
Context de xifratge (encryption context). Un diccionari de parells clau-valor que s'associa a una operació de xifratge. No és secret —apareix als registres de CloudTrail en clar— però està autenticat: si en desxifrar no proporciones exactament el mateix context, l'operació falla.
Serveix per a dues coses:
- Auditoria llegible. A CloudTrail hi veus «s'ha desxifrat alguna cosa del component copias» en lloc d'un UUID opac.
- Autorització granular. Es pot condicionar la política de clau a un context concret:
{
"Sid": "SoloDescifrarCopias",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/rol-restauracion" },
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEquals": { "kms:EncryptionContext:componente": "copias" }
}
}Aquell rol pot desxifrar còpies de la base de dades i res més, encara que tot estigui xifrat amb la mateixa clau. S3 fa servir automàticament com a context l'ARN del bucket o de l'objecte, així que ja te'n beneficies sense fer res.
Concessions (grants)
Una concessió és un permís temporal i granular sobre una clau, pensat per a serveis i processos, no per a persones:
| Política de clau | Concessió | |
|---|---|---|
| Format | JSON | Crida a l'API |
| Durada | Permanent fins que s'editi | Es retira amb RetireGrant |
| Granularitat | Principal + acció + condició | Principal + operacions concretes + context |
| Qui les fa servir | Humans i rols | Serveis d'AWS, sobretot |
Quan crees una instància d'RDS xifrada, RDS crea una concessió sobre la clau per poder desxifrar el
volum a cada arrencada, a cada failover i a cada restauració de snapshot. Per això la política de clau
havia de permetre kms:CreateGrant amb kms:GrantIsForAWSResource.
Conseqüència pràctica molt important: si retires aquella concessió, la base de dades deixa d'arrencar. I si la concessió es retira mentre la base està aturada, no tornarà. No toquis les concessions que creen els serveis.
aws kms list-grants --key-id alias/mercadofresco-datos \
--query 'Grants[].[GranteePrincipal,Operations[0],Name]' --output table \
--profile mercadofresco-devRotació automàtica i què significa realment
Es pot activar la rotació anual amb una crida:
aws kms enable-key-rotation --key-id alias/mercadofresco-datos --profile mercadofresco-dev
aws kms get-key-rotation-status --key-id alias/mercadofresco-datos --profile mercadofresco-devI ara la part que gairebé tothom entén malament. Quan KMS rota una clau:
- Genera material criptogràfic nou i l'associa a la mateixa clau lògica i al mateix ARN.
- Conserva tot el material anterior, indefinidament.
- El material nou es fa servir per a les operacions noves de xifratge.
- Les dades ja xifrades no es tornen a xifrar. Continuen fent servir el seu material antic, que KMS localitza sol.
És a dir: la rotació és transparent i gratuïta, però no «rejoveneix» les dades antigues. Si un
atacant hagués obtingut d'alguna manera el material antic, les dades xifrades amb ell continuen
compromeses. Per renovar de debò les dades cal tornar-les a xifrar, copiant els objectes sobre si
mateixos o fent servir ReEncrypt.
| Rotació automàtica de KMS | Rexifratge real de les dades | |
|---|---|---|
| Què canvia | El material de les operacions noves | Les dades ja desades |
| Cost | Gratis | Peticions a KMS + temps |
| Compliment | Cobreix «rotació anual de claus» | Cobreix «renovació després d'un incident» |
| Esforç | Una ordre | Un procés per lots |
Des del 2024 el període de rotació és configurable entre 90 i 2.560 dies amb
--rotation-period-in-days. Per a MercadoFresco, la rotació anual per defecte és suficient i és el
que la majoria d'auditories esperen veure.
Xifrar mercadofresco-copias-basedatos
Primer, crear la clau amb la política de l'apartat anterior:
aws kms create-key \
--description "Clau de dades personals de MercadoFresco (RGPD)" \
--key-usage ENCRYPT_DECRYPT \
--key-spec SYMMETRIC_DEFAULT \
--policy file:///tmp/politica-clave.json \
--tags TagKey=Proyecto,TagValue=mercadofresco TagKey=Entorno,TagValue=produccion \
TagKey=Componente,TagValue=datos TagKey=Propietario,TagValue=marta \
TagKey=CentroCoste,TagValue=tecnologia \
--profile mercadofresco-dev
# Retorna KeyId: 1234abcd-12ab-34cd-56ef-1234567890ab
aws kms create-alias \
--alias-name alias/mercadofresco-datos \
--target-key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
--profile mercadofresco-dev
aws kms enable-key-rotation --key-id alias/mercadofresco-datos --profile mercadofresco-devDesprés, xifratge per defecte al bucket. Fixa't que aquí no activem la clau de bucket, perquè volem la traça per objecte:
aws s3api put-bucket-encryption \
--bucket mercadofresco-copias-basedatos \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:eu-west-1:111122223333:alias/mercadofresco-datos"
},
"BucketKeyEnabled": false
}]
}' \
--profile mercadofresco-devAl catàleg de fotos, en canvi, sí que l'activem:
aws s3api put-bucket-encryption \
--bucket mercadofresco-catalogo-fotos \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:eu-west-1:111122223333:alias/mercadofresco-datos"
},
"BucketKeyEnabled": true
}]
}' \
--profile mercadofresco-devI finalment, la política de bucket que rebutja qualsevol pujada sense xifrar, perquè el xifratge per defecte no depengui que ningú no el desactivi:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RechazarSubidasSinKMS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mercadofresco-copias-basedatos/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
},
{
"Sid": "RechazarOtraClave",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mercadofresco-copias-basedatos/*",
"Condition": {
"StringNotEqualsIfExists": {
"s3:x-amz-server-side-encryption-aws-kms-key-id":
"arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
}
}
}
]
}Important: el xifratge per defecte no xifra retroactivament. Els objectes que ja eren al bucket continuen com estaven. Per xifrar-los cal copiar-los sobre si mateixos:
aws s3 cp s3://mercadofresco-copias-basedatos/ s3://mercadofresco-copias-basedatos/ \
--recursive --sse aws:kms \
--sse-kms-key-id arn:aws:kms:eu-west-1:111122223333:alias/mercadofresco-datos \
--metadata-directive REPLACE \
--profile mercadofresco-devAmb versionatge actiu això crea una versió nova xifrada i deixa l'antiga sense xifrar. Cal eliminar les versions antigues després, o la feina no serveix de res. És un detall que s'oblida sovint i que una auditoria detecta de seguida.
Xifrar volums d'EBS i snapshots
El més senzill: activar el xifratge per defecte d'EBS a la regió. A partir d'aquell moment, tot volum nou es xifra sense que ningú se n'hagi de recordar.
aws ec2 enable-ebs-encryption-by-default --region eu-west-1 --profile mercadofresco-dev
aws ec2 modify-ebs-default-kms-key-id \
--kms-key-id alias/mercadofresco-datos --region eu-west-1 --profile mercadofresco-dev
aws ec2 get-ebs-default-kms-key-id --region eu-west-1 --profile mercadofresco-devPer a un volum ja existent sense xifrar —com mercadofresco-fotos-01, creat a 02-02— no es pot
xifrar en calent. El procediment és snapshot, còpia xifrada, volum nou:
# 1. Snapshot del volum sense xifrar
aws ec2 create-snapshot --volume-id vol-0abc123 \
--description "mercadofresco-fotos-01 previ al xifratge" \
--profile mercadofresco-dev
# 2. Copiar el snapshot XIFRANT durant el procés
aws ec2 copy-snapshot \
--source-region eu-west-1 --source-snapshot-id snap-0abc123 \
--encrypted --kms-key-id alias/mercadofresco-datos \
--description "mercadofresco-fotos-01 xifrat" \
--profile mercadofresco-dev
# 3. Crear el volum nou des del snapshot xifrat
aws ec2 create-volume --snapshot-id snap-0def456 \
--availability-zone eu-west-1a --volume-type gp3 \
--tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=mercadofresco-fotos-01},
{Key=Proyecto,Value=mercadofresco},{Key=Entorno,Value=produccion}]' \
--profile mercadofresco-dev
# 4. Aturar la instància, desmuntar el vell, muntar el nou, arrencarEl truc és al pas 2: copy-snapshot --encrypted és l'única operació d'EBS que converteix una cosa
sense xifrar en una cosa xifrada. Recorda-ho, perquè és la peça que falta a gairebé tots els intents.
I una regla que estalvia ensurts: d'un volum xifrat només en surten snapshots xifrats, i d'un snapshot xifrat només en surten volums xifrats. La propietat s'hereta i no es pot treure.
Xifrar mercadofresco-pedidos, que ja existeix sense xifrar
Aquesta és l'operació més delicada del mòdul, perquè implica temps d'inactivitat de la base de dades de producció. RDS no permet xifrar una instància existent. El camí és:
flowchart TD
A["mercadofresco-pedidos<br/>SENSE xifrar (produccio)"] --> B["1. Snapshot manual<br/>mercadofresco-pedidos-precifrado"]
B --> C["2. copy-db-snapshot --kms-key-id<br/>alias/mercadofresco-datos"]
C --> D["3. restore-db-instance-from-db-snapshot<br/>mercadofresco-pedidos-cifrada"]
D --> E["4. Verificar: dades, parametres,<br/>grup de subxarxes, SG"]
E --> F["5. Finestra de manteniment:<br/>aturar escriptures"]
F --> G["6. Reanomenar: la vella passa a -antigua,<br/>la nova a mercadofresco-pedidos"]
G --> H["7. Reactivar Multi-AZ i la replica<br/>mercadofresco-pedidos-lectura"]
H --> I["8. Conservar la vella 7 dies,<br/>despres eliminar"]
# 1 i 2
aws rds create-db-snapshot \
--db-instance-identifier mercadofresco-pedidos \
--db-snapshot-identifier mercadofresco-pedidos-precifrado \
--profile mercadofresco-dev
aws rds copy-db-snapshot \
--source-db-snapshot-identifier mercadofresco-pedidos-precifrado \
--target-db-snapshot-identifier mercadofresco-pedidos-cifrado \
--kms-key-id alias/mercadofresco-datos \
--profile mercadofresco-dev
# 3
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier mercadofresco-pedidos-cifrada \
--db-snapshot-identifier mercadofresco-pedidos-cifrado \
--db-subnet-group-name sng-mercadofresco-datos \
--db-parameter-group-name pg16-mercadofresco \
--multi-az \
--no-publicly-accessible \
--profile mercadofresco-devQuatre avisos de camp:
- La restauració no conserva el grup de paràmetres, els grups de seguretat ni la configuració Multi-AZ. Cal indicar-los explícitament, com a l'ordre de dalt, o la instància nova arrencarà amb els valors per defecte i quedarà mal configurada.
- El nom del punt d'enllaç canvia. Si l'aplicació apunta al DNS d'RDS, cal actualitzar-lo. Per
això a 03-05 vam crear la zona privada
interno.mercadofresco.example: si la botiga es connecta apedidos.interno.mercadofresco.example, n'hi ha prou amb canviar un CNAME. - La rèplica
mercadofresco-pedidos-lecturano es migra. Cal recrear-la des de la instància nova. - Fes l'assaig complet a desenvolupament abans. La Marta fa aquesta migració un dimarts a la nit, mai un dijous: el pic dels divendres no és moment per descobrir sorpreses.
Compartir un snapshot xifrat amb un altre compte
Un snapshot xifrat amb la clau gestionada per AWS (aws/rds) no es pot compartir. Només es
comparteixen els xifrats amb una clau gestionada pel client, i calen dos permisos:
# 1. Compartir el snapshot amb el compte de destinació
aws rds modify-db-snapshot-attribute \
--db-snapshot-identifier mercadofresco-pedidos-cifrado \
--attribute-name restore --values-to-add 444455556666 \
--profile mercadofresco-dev{
"Sid": "PermitirQueLaCuentaDeAuditoriaDescifreElSnapshot",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::444455556666:root" },
"Action": ["kms:Decrypt", "kms:DescribeKey", "kms:CreateGrant"],
"Resource": "*",
"Condition": {
"StringEquals": { "kms:ViaService": "rds.eu-west-1.amazonaws.com" }
}
}És a dir: compartir el snapshot i donar accés a la clau. Si només fas el primer, l'altre compte veurà el snapshot i no el podrà restaurar. I no oblidis que el compte de destinació també necessita permetre-ho a les seves pròpies polítiques d'identitat.
Aquest és, dit sigui de passada, el mecanisme que fa segura l'exposició accidental: compartir un snapshot sense compartir la clau no revela absolutament res.
KMS des de boto3
El cas d'ús típic —xifrar un fitxer de mida arbitrària amb el sobre, a mà:
import boto3
import os
from cryptography.fernet import Fernet # nomes per a l'exemple local
import base64
sessio = boto3.Session(profile_name="mercadofresco-dev", region_name="eu-west-1")
kms = sessio.client("kms")
CLAU = "alias/mercadofresco-datos"
CONTEXT = {"proyecto": "mercadofresco", "componente": "copias"}
def xifrar_fitxer(ruta_origen: str, ruta_desti: str) -> None:
"""Xifra un fitxer de qualsevol mida fent servir xifratge de sobre."""
# 1. Demanar una clau de dades: arriben les DUES versions
resposta = kms.generate_data_key(
KeyId=CLAU,
KeySpec="AES_256",
EncryptionContext=CONTEXT,
)
clau_en_clar = resposta["Plaintext"] # 32 bytes, per xifrar aqui
clau_xifrada = resposta["CiphertextBlob"] # es desa al costat del fitxer
# 2. Xifrar localment. Les dades NO surten mai cap a KMS.
f = Fernet(base64.urlsafe_b64encode(clau_en_clar))
with open(ruta_origen, "rb") as origen:
dades_xifrades = f.encrypt(origen.read())
# 3. Desar la clau xifrada + les dades xifrades al mateix fitxer
with open(ruta_desti, "wb") as desti:
desti.write(len(clau_xifrada).to_bytes(4, "big"))
desti.write(clau_xifrada)
desti.write(dades_xifrades)
# 4. Esborrar de memoria la versio en clar
del clau_en_clar
def desxifrar_fitxer(ruta_origen: str, ruta_desti: str) -> None:
with open(ruta_origen, "rb") as origen:
longitud = int.from_bytes(origen.read(4), "big")
clau_xifrada = origen.read(longitud)
dades_xifrades = origen.read()
# KMS dedueix la clau mestra del propi blob: no cal KeyId
resposta = kms.decrypt(
CiphertextBlob=clau_xifrada,
EncryptionContext=CONTEXT, # ha de coincidir EXACTAMENT
)
f = Fernet(base64.urlsafe_b64encode(resposta["Plaintext"]))
with open(ruta_desti, "wb") as desti:
desti.write(f.decrypt(dades_xifrades))
# Xifratge directe, nomes per a dades de menys de 4 KB
petit = kms.encrypt(KeyId=CLAU, Plaintext=b"dada curta", EncryptionContext=CONTEXT)
print(kms.decrypt(CiphertextBlob=petit["CiphertextBlob"],
EncryptionContext=CONTEXT)["Plaintext"])Punts que cal fixar de l'exemple:
generate_data_keyretorna les dues versions de la mateixa clau. Aquesta és l'essència del sobre.- El fitxer xifrat és autocontingut: porta a dins la clau xifrada. Es pot moure a qualsevol lloc i
només l'obrirà qui tingui permís sobre
alias/mercadofresco-datos. decryptno repKeyId: el blob el porta a dins.- L'
EncryptionContextha de coincidir caràcter a caràcter en desxifrar. Si no,InvalidCiphertext. - En producció no es fa servir
Ferneta mà: l'AWS Encryption SDK fa tot això correctament, inclosos l'esborrat segur de memòria i el format de missatge. L'exemple és per veure la mecànica.
Límits, quotes i cost real per a MercadoFresco
| Concepte | Preu |
|---|---|
| Clau gestionada pel client | 1,00 USD per clau i mes (prorratejat) |
| Peticions simètriques | 0,03 USD per cada 10.000 |
| Peticions RSA-2048 | 0,03 USD per cada 10.000 |
| Peticions ECC / RSA >2048 | 0,15 USD per cada 10.000 |
| Claus gestionades i propietat d'AWS | Gratis (les peticions sí que es cobren) |
| Capa gratuïta | 20.000 peticions al mes, sempre |
| Magatzem personalitzat (CloudHSM) | ~1,50 USD/hora per HSM, a part |
Quotes de peticions per segon a eu-west-1: de l'ordre de 50.000 per a Decrypt, GenerateDataKey
i Encrypt simètrics, i molt inferiors (uns quants centenars) per a operacions asimètriques. Es
comparteixen entre totes les claus del compte, així que un procés per lots agressiu pot provocar
ThrottlingException a tot el compte. Els SDK reintenten amb retrocés exponencial, però convé
saber-ho.
Càlcul per a MercadoFresco:
| Concepte | Quantitat | Cost mensual |
|---|---|---|
Clau alias/mercadofresco-datos |
1 | 1,00 USD |
mercadofresco-catalogo-fotos amb clau de bucket |
~2.000.000 peticions → ~700 crides | 0,00 USD (capa gratuïta) |
mercadofresco-copias-basedatos sense clau de bucket |
60 còpies × 2 (pujar + verificar) = 120 | 0,00 USD |
| EBS i RDS (concessions i arrencades) | ~500 | 0,00 USD |
| Total | 1,00 USD/mes |
Un dòlar al mes per xifrar totes les dades personals de l'empresa, amb auditoria de cada ús. És, de molt, la millor relació cost-benefici de tot el curs.
El contrast és útil: sense la clau de bucket, aquells 2 milions de peticions haurien generat 2 milions de crides a KMS, uns 6 USD al mes. No són diners, però a escala de 100 milions de peticions serien 300 USD mensuals per no haver marcat una casella.
ACM no és KMS
Confusió freqüent, perquè tots dos parlen de claus:
| AWS KMS | AWS Certificate Manager | |
|---|---|---|
| Protegeix | Dades en repòs | Dades en trànsit |
| Objecte | Claus de xifratge simètriques | Certificats X.509 |
| Cost | 1 USD/clau/mes | Gratis per a certificats públics |
| A MercadoFresco | alias/mercadofresco-datos |
Certificats de l'ALB i de CloudFront (03-03, 03-05) |
| Renovació | Rotació anual del material | Renovació automàtica via DNS |
Són serveis independents que resolen meitats diferents del mateix problema. El certificat de
mercadofresco.example que vam validar amb un CNAME a 03-05 no té res a veure amb
alias/mercadofresco-datos.
Eliminar una clau: els 7 a 30 dies d'espera
No es pot esborrar una clau de KMS de manera immediata, i és deliberat: esborrar-la destruiria de manera irreversible totes les dades xifrades amb ella. Només se'n pot programar l'eliminació amb un període d'espera d'entre 7 i 30 dies.
# Abans de res: la fa servir algú? Mira't CloudTrail (05-03)
aws kms schedule-key-deletion \
--key-id alias/mercadofresco-datos --pending-window-in-days 30 \
--profile mercadofresco-dev
# Cancel·lar mentre estigui pendent
aws kms cancel-key-deletion --key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
--profile mercadofresco-devUna alternativa molt més assenyada per provar l'impacte és deshabilitar la clau: és reversible a l'instant i produeix exactament el mateix efecte que esborrar-la —tot el que està xifrat deixa de poder-se llegir—, però sense destruir res.
aws kms disable-key --key-id alias/mercadofresco-datos --profile mercadofresco-dev
aws kms enable-key --key-id alias/mercadofresco-datos --profile mercadofresco-devDeshabilitar durant 30 dies, comprovar que res no es trenca i només llavors programar l'eliminació: aquest és el procediment correcte. I mentre la clau estigui deshabilitada es continua pagant el seu dòlar mensual.
Errors Habituals i Consells
Escriure una política de clau que deixa tothom fora. És l'error irreversible de KMS. Si crees la
clau per CLI amb una política que no inclou "Principal": {"AWS": "arn:aws:iam::111122223333:root"} amb kms:*, la clau queda inservible i només se'n pot programar
l'eliminació. Inclou-hi sempre aquella declaració.
Creure que el xifratge per defecte d'un bucket xifra el que ja hi havia. No ho fa. Els objectes existents continuen sense xifrar fins que els copiïs sobre si mateixos, i amb versionatge actiu cal purgar a més les versions antigues.
Oblidar kms:Decrypt al rol. El símptoma és confús: s3:GetObject està concedit, l'objecte
existeix i tot i així arriba AccessDenied. Amb SSE-KMS calen dos permisos. La primera
comprovació davant d'un AccessDenied en un bucket xifrat és sempre KMS.
No activar la clau de bucket en buckets de molt trànsit. Multiplica el cost de KMS pel nombre de peticions. Activa-la llevat que necessitis la traça per objecte.
Fer servir Encrypt per a fitxers grans. Falla amb ValidationException a partir de 4 KB. Per a
això hi ha GenerateDataKey i el sobre.
Confondre deshabilitar amb eliminar. Deshabilitar és reversible i continua costant 1 USD al mes; eliminar és irreversible i destrueix les dades. Comença sempre deshabilitant.
Retirar una concessió creada per RDS o EBS. La base de dades deixa d'arrencar. Les concessions que creen els serveis no es toquen.
Consell: fes servir àlies, mai UUID, al codi. alias/mercadofresco-datos és llegible i permet
canviar la clau subjacent sense desplegar. A les polítiques, en canvi, fes servir l'ARN de clau:
és inequívoc i no depèn d'on apunti l'àlies.
Consell: aplica separació de funcions des del primer dia. Que qui administra la clau no pugui
desxifrar les dades, com a la política d'alias/mercadofresco-datos. Costa dues línies i és el
primer que pregunta un auditor.
Consell: activa el xifratge per defecte d'EBS a la regió. Una ordre, gratis, i a partir d'aquí ningú no pot crear un volum sense xifrar per descuit.
Consell: posa una alarma sobre les crides a kms:Decrypt. Un pic anòmal de desxifratges és un
dels senyals més primerencs d'una exfiltració de dades. El muntarem amb CloudWatch a 05-01 sobre els
esdeveniments de CloudTrail de 05-03.
Exercicis
Exercici 1: dissenyar la política d'una clau nova
MercadoFresco crea una segona clau, alias/mercadofresco-analitica, per xifrar
mercadofresco-informes-analitica. Requisits:
- La Marta administra la clau però no pot desxifrar.
- La Sara (usuària
sara) pot desxifrar informes, però només a través d'S3 i només si el context de xifratge incloucomponente=informes. - Un rol
rol-mercadofresco-etlpot xifrar i desxifrar sense restricció de context, també només a través d'S3. - Ningú no pot fer servir la clau fora d'
eu-west-1. - Les polítiques d'IAM del compte han de poder concedir accés.
Escriu la política de clau completa.
Exercici 2: calcular el cost i decidir sobre la clau de bucket
MercadoFresco obre a Portugal i el catàleg passa a servir 40 milions de peticions al mes, de les
quals CloudFront n'absorbeix el 90 % (només el 10 % arriba a S3). A més, el bucket
mercadofresco-copias-basedatos rep 3 còpies diàries i mercadofresco-informes-analitica genera
50.000 objectes al mes.
Calcula el cost mensual de KMS en dos escenaris —amb i sense clau de bucket al catàleg— fent servir 2 claus gestionades pel client, i decideix quina configuració recomanaries per a cada bucket justificant el compromís entre cost i traçabilitat.
Exercici 3: diagnosticar un xifratge que falla
El Luis desplega una versió nova de la botiga. Les fotos es llegeixen bé, però en generar una
miniatura la funció mercadofresco-generar-miniaturas falla amb:
An error occurred (AccessDenied) when calling the PutObject operation:
User: arn:aws:sts::111122223333:assumed-role/rol-lambda-miniaturas/mercadofresco-generar-miniaturas
is not authorized to perform: kms:GenerateDataKey on resource:
arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
because no identity-based policy allows the kms:GenerateDataKey actionRespon: (a) per què falla en escriure si en llegir funcionava?; (b) en quins dos llocs
diferents cal mirar i en quin és el problema segons el missatge?; (c) escriu la correcció mínima; (d)
si l'error hagués dit with an explicit deny in a resource-based policy, què sospitaries, sabent que
la política de clau inclou kms:ViaService?
Solucions
Solució 1
{
"Version": "2012-10-17",
"Id": "politica-mercadofresco-analitica",
"Statement": [
{
"Sid": "PermitirQueIAMGobierneLaClave",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "MartaAdministra",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:user/marta" },
"Action": [
"kms:Describe*", "kms:Get*", "kms:List*", "kms:Enable*", "kms:Disable*",
"kms:Update*", "kms:Put*", "kms:Revoke*", "kms:TagResource", "kms:UntagResource",
"kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "SaraDescifraSoloInformes",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:user/sara" },
"Action": ["kms:Decrypt", "kms:DescribeKey"],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.eu-west-1.amazonaws.com",
"kms:EncryptionContext:componente": "informes"
}
}
},
{
"Sid": "ElProcesoETLCifraYDescifra",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/rol-mercadofresco-etl" },
"Action": ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey*", "kms:DescribeKey"],
"Resource": "*",
"Condition": {
"StringEquals": { "kms:ViaService": "s3.eu-west-1.amazonaws.com" }
}
},
{
"Sid": "ProhibirFueraDeEuWest1",
"Effect": "Deny",
"Principal": "*",
"Action": "kms:*",
"Resource": "*",
"Condition": {
"StringNotEquals": { "aws:RequestedRegion": "eu-west-1" }
}
}
]
}Punts clau: a la declaració de la Marta no hi apareixen kms:Encrypt, kms:Decrypt ni
kms:GenerateDataKey —separació de funcions—; la Sara només té Decrypt, mai Encrypt, i amb doble
condició; i el Deny final s'aplica a "Principal": "*", és a dir, també a la Marta i al root.
Solució 2
Peticions a KMS per bucket:
- Catàleg: 40.000.000 × 10 % = 4.000.000 peticions a S3 al mes.
- Sense clau de bucket: 4.000.000 crides a KMS.
- Amb clau de bucket: aproximadament una cada poques hores, de l'ordre de 250 al mes.
- Còpies: 3 diàries × 30 = 90 objectes → ~180 crides (escriptura + verificació).
- Informes: 50.000 objectes → 50.000 crides sense clau de bucket, ~250 amb ella.
Escenari A, sense clau de bucket enlloc:
- Peticions: 4.000.000 + 180 + 50.000 = 4.050.180. Menys 20.000 de capa gratuïta = 4.030.180.
- Cost: 4.030.180 ÷ 10.000 × 0,03 = 12,09 USD
- Claus: 2 × 1,00 = 2,00 USD
- Total: 14,09 USD/mes
Escenari B, amb clau de bucket a catàleg i informes, sense ella a còpies:
- Peticions: 250 + 180 + 250 = 680, molt per sota de la capa gratuïta de 20.000.
- Cost de peticions: 0,00 USD
- Claus: 2,00 USD
- Total: 2,00 USD/mes
Recomanació. Estalvi de 12,09 USD al mes, uns 145 USD l'any, i a més escala creix linealment. Configuració proposada:
| Bucket | Clau de bucket | Justificació |
|---|---|---|
mercadofresco-catalogo-fotos |
Sí | Milions de peticions, fotos públiques, la traça per objecte no aporta res |
mercadofresco-informes-analitica |
Sí | 50.000 objectes al mes, dades agregades sense identificadors personals |
mercadofresco-copias-basedatos |
No | 90 objectes al mes: l'estalvi és zero i la traça de qui va desxifrar cada còpia de dades personals és exactament el que demanarà una auditoria de RGPD |
El raonament general: activa la clau de bucket llevat que el volum sigui baix i la traçabilitat per objecte tingui valor de compliment.
Solució 3
(a) Perquè llegir i escriure requereixen permisos diferents de KMS. Descarregar un objecte
xifrat amb SSE-KMS necessita kms:Decrypt; pujar-ne un de nou necessita kms:GenerateDataKey, perquè
S3 ha de demanar una clau de dades nova per xifrar-lo. A 04-01 vam concedir tots dos a
rol-lambda-miniaturas, així que aquí el que ha passat és que algú ha desplegat una versió de la
política amb només kms:Decrypt, o el bucket ha canviat de clau.
(b) Cal mirar en dos llocs: la política d'identitat del rol i la política de clau
d'alias/mercadofresco-datos. El missatge ho resol: because no identity-based policy allows
assenyala inequívocament la política d'identitat del rol, i a més indica denegació implícita
—falta un Allow—, no un Deny explícit.
(c) Afegir a rol-lambda-miniaturas l'acció que falta:
{
"Sid": "UsarLaClaveDelBucket",
"Effect": "Allow",
"Action": ["kms:Decrypt", "kms:GenerateDataKey"],
"Resource": "arn:aws:kms:eu-west-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
"Condition": {
"StringEquals": { "kms:ViaService": "s3.eu-west-1.amazonaws.com" }
}
}El mínim és kms:GenerateDataKey; s'hi inclou kms:Decrypt perquè la funció també llegeix
l'original. No cal kms:Encrypt: amb el xifratge de sobre, S3 no la fa servir mai.
(d) Sospitaria de la condició kms:ViaService. Si la funció hagués passat a cridar KMS
directament —per exemple perquè algú va canviar el codi per xifrar abans de pujar, en lloc de
deixar que ho faci S3—, la petició ja no arribaria «a través d'S3», la condició no es compliria i la
política de clau la rebutjaria. També podria ser el Deny d'aws:RequestedRegion si el client de
boto3 s'hagués creat apuntant a una altra regió. En tots dos casos l'arranjament no és ampliar
permisos, sinó corregir com s'està cridant.
Conclusió
alias/mercadofresco-datos ha deixat de ser un nom. Ara és una clau gestionada pel client, amb
política pròpia, rotació anual activada, etiquetes de projecte i una separació de funcions explícita:
la Marta l'administra però no pot desxifrar; rol-mercadofresco-tienda i rol-lambda-miniaturas
la fan servir però només a través d'S3, gràcies a kms:ViaService; RDS i EBS poden crear
concessions perquè són serveis d'AWS; i ningú, ni el root, no la pot fer servir fora d'eu-west-1.
Entens el mecanisme que ho sosté tot, el xifratge de sobre: KMS genera una clau de dades i la
retorna en dos formats —en clar i xifrada amb la mestra—, l'aplicació xifra localment a velocitat de
CPU, esborra la versió en clar i desa el CiphertextBlob al costat de les dades. Per això les
dades grans no viatgen mai a KMS, per això el límit de 4 KB d'Encrypt no és un problema real, i
per això Decrypt no necessita que li diguis quina clau ha de fer servir. Saps també què fa i què no
fa la rotació automàtica: canvia el material per al que és nou, conserva l'antic per sempre i no
torna a xifrar el que ja està desat.
Distingeixes SSE-S3, SSE-KMS i SSE-C, i saps que l'avantatge real de SSE-KMS és la doble
autorització —s3:GetObject i kms:Decrypt—, que converteix una exposició accidental en un
ensurt en lloc d'una bretxa. Saps que les claus de bucket d'S3 retallen fins a un 99 % les crides
a KMS a canvi de perdre la traça per objecte, i has decidit activar-les a
mercadofresco-catalogo-fotos i no a mercadofresco-copias-basedatos, on la traça val més que
l'estalvi.
En el pla pràctic, MercadoFresco ha xifrat el bucket de còpies amb una política de bucket que
rebutja qualsevol pujada sense KMS, ha activat el xifratge per defecte d'EBS a eu-west-1, sap
convertir un volum sense xifrar mitjançant copy-snapshot --encrypted —l'única operació que fa
aquest salt— i ha migrat mercadofresco-pedidos a una instància xifrada pel camí de snapshot, còpia
xifrada i restauració, sense oblidar que la restauració no conserva el grup de paràmetres ni Multi-AZ
i que el punt d'enllaç canvia. Tot això per 1,00 USD al mes, la millor relació cost-benefici del
curs. I saps que eliminar una clau és irreversible, que el camí assenyat és deshabilitar-la
primer i que el període d'espera de 7 a 30 dies existeix precisament per salvar-te.
Queda, però, el forat més incòmode de tots, i és dels que no s'arreglen amb criptografia. La
contrasenya de l'usuari mfadmin de mercadofresco-pedidos continua sent on no ha de ser: va
passar pel user data de la plantilla lt-mercadofresco-tienda, viu en un fitxer de configuració del
servidor i hi ha una còpia al .env que el Luis va compartir per xat quan va muntar l'entorn de
desenvolupament. Tant li fa que la base de dades estigui xifrada amb AES-256: qualsevol que llegeixi
aquell fitxer entra amb credencials vàlides, i el xifratge, com vam veure a la primera taula d'aquesta
lliçó, no protegeix d'això. A la lliçó 04-03, «Secrets Manager i Parameter Store», aquella
contrasenya sortirà per fi d'on és: veurem la diferència entre configuració i secret, el Parameter
Store per al primer i el Secrets Manager per al segon, com es consumeix des de l'aplicació
sense tornar-la a escriure mai en un fitxer, i sobretot la rotació automàtica cada 30 dies amb una
Lambda gestionada, amb el seu cicle createSecret / setSecret / testSecret / finishSecret —que
s'ancora, precisament, en la clau que acabes de construir.
Curs d'AWS
Mòdul 1: Introducció a AWS
- Què és AWS?
- Configuració del teu compte d'AWS
- Infraestructura global d'AWS
- Consola d'administració d'AWS
- AWS CLI i SDK
Mòdul 2: Serveis principals d'AWS
Mòdul 3: Xarxes i lliurament de contingut
- Amazon VPC
- Grups de seguretat i llistes de control d'accés
- Elastic Load Balancing
- Amazon CloudFront
- Route 53
Mòdul 4: Seguretat i identitat
- AWS Identity and Access Management (IAM)
- AWS Key Management Service (KMS)
- Secrets Manager i Parameter Store
- AWS Shield
- AWS WAF
Mòdul 5: Monitoratge i gestió
- Amazon CloudWatch
- AWS X-Ray i traçabilitat distribuïda
- AWS CloudTrail
- AWS Config
- AWS Trusted Advisor
Mòdul 6: Bases de dades
- Com triar la base de dades adequada
- Amazon DynamoDB
- Amazon Aurora
- Amazon Redshift
- Amazon ElastiCache
Mòdul 7: Integració d'aplicacions
- Amazon SQS
- Amazon SNS
- Amazon EventBridge
- AWS Step Functions
- Patrons d'integració: idempotència, reintents i cues de missatges fallits
