CloudTrail va tancar la lliçó anterior amb una limitació concreta i honesta: detecta esdeveniments,
no estats. Sap que algú va cridar DeleteBucketEncryption aquest matí. No sap que
mercadofresco-registros-web fa cinc mesos que no té xifratge perquè no es va configurar mai. No sap
que hi ha un grup de seguretat amb 0.0.0.0/0 al port 22 des d'una prova de març que ningú no va
desfer. No pot dir quants recursos del compte incompleixen l'etiquetatge obligatori de MercadoFresco.
I, per descomptat, no pot arreglar res.
Aquesta és la cinquena i última pregunta que va deixar oberta el mòdul 4: res no avisa si algú desactiva el xifratge d'un bucket o obre un grup de seguretat al món.
AWS Config és la resposta. La seva idea és diferent de tot el que hem vist en aquest mòdul: en lloc de registrar el que passa, fotografia contínuament com està configurat cada recurs, desa l'historial d'aquestes fotografies i avalua cadascuna contra un conjunt de regles. Quan una configuració es desvia del que hauria de ser, Config ho marca com a no conforme, avisa i —si l'hi permets— ho corregeix sol.
És la diferència entre una càmera de seguretat que grava qui entra i un inventari que, cada nit, comprova que totes les portes estan tancades.
Avís de cost. AWS Config és, juntament amb la ingesta de registres de CloudWatch, el servei d'aquest mòdul que es dispara amb més facilitat. Cobra per cada element de configuració enregistrat i per cada avaluació de regla. Un compte amb un grup d'autoescalat que rota instàncies tot el dia pot generar desenes de milers d'elements al mes. Hi ha una secció sencera amb el càlcul i les cinc maneres de controlar-lo.
Avís de compliment. Aquest material és didàctic. Els paquets de conformitat que s'hi esmenten (CIS, PCI DSS) són ajudes, no certificacions: activar un conformance pack no et fa conforme amb PCI DSS. Qualsevol ús de Config amb finalitat de compliment normatiu real l'ha de validar un professional de compliment.
Contingut
- Què és la configuració d'un recurs
- L'element de configuració i la línia temporal
- Config enfront de CloudTrail
- El flux complet: enregistrador, regles i remediació
- Activar l'enregistrador de configuració
- El canal de lliurament: S3 i SNS
- Triar quins tipus de recurs s'enregistren
- Regles: el cor del servei
- Les regles gestionades que activa MercadoFresco
- Activació per canvi enfront d'activació periòdica
- L'etiquetatge obligatori amb
required-tags - Regles personalitzades amb Lambda
- Regles personalitzades amb Guard
- Remediació automàtica amb Systems Manager
- Els dos casos reals: xifratge de bucket i SG obert
- L'advertència de provar primer en mode manual
- Paquets de conformitat
- El quadre de compliment de MercadoFresco
- Consultes avançades per inventariar
- Agregadors multicompte
- Security Hub i GuardDuty: on encaixa cadascun
- Cost real i com no disparar-lo
- Neteja
Què és la configuració d'un recurs
La configuració d'un recurs és el conjunt de propietats que el defineixen en un moment donat. No les seves dades, no el seu trànsit: els seus ajustos.
| Recurs | La seva configuració inclou… |
|---|---|
mercadofresco-catalogo-fotos (S3) |
Xifratge, versionatge, política, bloqueig públic, cicle de vida, etiquetes |
sg-mercadofresco-basedatos |
Regles d'entrada i sortida, VPC, descripció, etiquetes |
mercadofresco-pedidos (RDS) |
Classe, Multi-AZ, xifratge, retenció de còpies, versió del motor, finestra |
rol-mercadofresco-tienda (IAM) |
Polítiques adjuntes, política de confiança, límit de permisos |
mercadofresco-tienda-01 (EC2) |
Tipus, AMI, subxarxa, SG, rol d'instància, volums, etiquetes |
alb-mercadofresco-tienda |
Oients, certificats, esquema, grups de destinació |
Config és capaç d'enregistrar la configuració de més de 250 tipus de recurs de desenes de serveis, i de mantenir l'historial complet dels seus canvis.
L'element de configuració i la línia temporal
Un element de configuració (CI, configuration item) és una fotografia completa d'un recurs en un instant concret. Config en crea un cada vegada que detecta un canvi.
{
"configurationItemVersion": "1.3",
"configurationItemCaptureTime": "2026-07-28T09:14:33.412Z",
"configurationItemStatus": "OK",
"configurationStateId": "1785142473412",
"awsAccountId": "111122223333",
"resourceType": "AWS::S3::Bucket",
"resourceId": "mercadofresco-registros-web",
"resourceName": "mercadofresco-registros-web",
"ARN": "arn:aws:s3:::mercadofresco-registros-web",
"awsRegion": "eu-west-1",
"resourceCreationTime": "2026-03-02T11:20:01.000Z",
"tags": {
"Proyecto": "mercadofresco",
"Entorno": "produccion",
"Componente": "registros",
"Propietario": "marta",
"CentroCoste": "plataforma"
},
"relationships": [
{ "resourceType": "AWS::KMS::Key",
"resourceId": "8f2c1a9b-4d3e-4f6a-9c1b-2e5d7a8f3c04",
"relationshipName": "Is encrypted with" }
],
"configuration": {
"name": "mercadofresco-registros-web",
"bucketVersioningConfiguration": { "status": "Enabled" },
"publicAccessBlockConfiguration": {
"blockPublicAcls": true, "ignorePublicAcls": true,
"blockPublicPolicy": true, "restrictPublicBuckets": true
},
"serverSideEncryptionConfiguration": {
"rules": [{
"applyServerSideEncryptionByDefault": {
"sseAlgorithm": "aws:kms",
"kmsMasterKeyID": "arn:aws:kms:eu-west-1:111122223333:alias/mercadofresco-datos"
}
}]
}
},
"supplementaryConfiguration": {
"BucketPolicy": { "policyText": "{...}" },
"IsRequesterPaysEnabled": false
}
}Tres camps mereixen una atenció especial:
relationships: Config no desa recursos aïllats, desa el graf. Sap que aquest bucket està xifrat amb aquella clau KMS, que aquella instància és en aquella subxarxa, que aquell SG està associat a aquell ALB. Quan vulguis saber què es trenca si esborres una clau, això és el que respon.supplementaryConfiguration: propietats que no arriben a la cridaDescribeprincipal i que Config recull a part. La política del bucket, per exemple.configurationItemStatus:OK,ResourceDiscovered,ResourceDeleted. Sí: Config també enregistra l'esborrament, així que pots veure com estava configurat un recurs que ja no existeix.
La línia temporal (configuration timeline) és la seqüència de tots els CI d'un recurs. És la vista més potent de la consola de Config i respon a la pregunta que a operacions es fa cada setmana: «això funcionava divendres; què ha canviat?»
timeline
title Linia temporal de sg-mercadofresco-basedatos
2026-03-02 : Creat amb regla 5432 des de sg-mercadofresco-tienda : CONFORME
2026-05-14 : Afegida regla 22 des de 0.0.0.0-0 : NO CONFORME
2026-05-14 : Remediacio automatica revoca la regla : CONFORME
2026-07-09 : Afegida regla 5432 des de sg-mercadofresco-admin : CONFORME
I la consulta:
aws configservice get-resource-config-history \
--resource-type AWS::EC2::SecurityGroup \
--resource-id sg-0a1b2c3d4e5f6a7b8 \
--limit 10 \
--query 'configurationItems[].[configurationItemCaptureTime,configurationItemStatus]' \
--output table \
--profile mercadofresco-dev --region eu-west-1Config enfront de CloudTrail
Són complementaris i es confonen constantment. La taula:
| CloudTrail (05-03) | AWS Config | |
|---|---|---|
| Enregistra | La crida a l'API | L'estat del recurs |
| Pregunta | Qui ha fet què, quan i des d'on? | Com està configurat ara? Compleix? |
| Unitat | Esdeveniment | Element de configuració |
| Veu l'estat previ | No | Sí: abans i després |
| Detecta desviacions existents | No | Sí |
| Avalua contra regles | No | Sí |
| Corregeix | No | Sí (remediació) |
| Veu canvis fets fora de l'API | No | Sí, en l'avaluació periòdica |
| Cost | Gairebé zero | Per CI i per avaluació |
| Primera còpia gratuïta | Sí | No |
L'exemple que ho fixa. Algú afegeix una regla SSH oberta a sg-mercadofresco-basedatos:
- CloudTrail: un esdeveniment
AuthorizeSecurityGroupIngress, amb la identitat, l'hora i la IP de qui ho va fer. No diu com va quedar el grup de seguretat, només què es va demanar. - Config: un CI nou amb la configuració completa del grup després del canvi, la
comparació amb el CI anterior (el diff), l'avaluació de la regla
restricted-sshmarcant-lo com aNON_COMPLIANT, i —si està configurada— la remediació que revoca la regla.
S'usen junts, i de fet Config depèn de CloudTrail: fa servir els seus esdeveniments per saber que alguna cosa ha canviat i disparar l'enregistrament d'un CI nou.
El flux complet: enregistrador, regles i remediació
flowchart TD
R["Recurs d'AWS<br/>bucket, SG, RDS, rol..."] -->|"canvi"| CT["CloudTrail<br/>detecta la crida"]
CT --> G["ENREGISTRADOR DE CONFIGURACIO<br/>crea un element de configuracio"]
G --> H["Historial a S3<br/>mercadofresco-config-historial"]
G --> E["Motor de REGLES"]
E -->|"COMPLIANT"| OK["Res a fer"]
E -->|"NON_COMPLIANT"| N["Marcat com a no conforme"]
N --> SNS["Notificacio SNS<br/>alertas-mercadofresco"]
N --> EB["Esdeveniment d'EventBridge<br/>07-03"]
N --> REM["REMEDIACIO<br/>document de SSM Automation"]
REM -->|"corregeix"| R
G --> SH["Security Hub<br/>agregacio de troballes"]
Cinc peces i el seu ordre:
- Enregistrador de configuració (configuration recorder): el procés que crea els CI. Només pot haver-hi un per compte i regió.
- Canal de lliurament (delivery channel): on es dipositen els CI (un bucket de S3) i on es notifiquen els canvis (un tema d'SNS). També un per compte i regió.
- Regles: les condicions que s'avaluen.
- Remediació: l'acció correctiva, executada per Systems Manager Automation.
- Agregador: la vista consolidada de diversos comptes i regions (09-04).
Activar l'enregistrador de configuració
Pas 1: el bucket de l'historial.
aws s3api create-bucket \
--bucket mercadofresco-config-historial \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1 \
--profile mercadofresco-dev
aws s3api put-public-access-block \
--bucket mercadofresco-config-historial \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" \
--profile mercadofresco-dev
aws s3api put-bucket-encryption \
--bucket mercadofresco-config-historial \
--server-side-encryption-configuration '{
"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},
"BucketKeyEnabled":true}]}' \
--profile mercadofresco-devAmb la seva política:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ConfigComprobarAcl",
"Effect": "Allow",
"Principal": { "Service": "config.amazonaws.com" },
"Action": ["s3:GetBucketAcl", "s3:ListBucket"],
"Resource": "arn:aws:s3:::mercadofresco-config-historial",
"Condition": {
"StringEquals": { "AWS:SourceAccount": "111122223333" }
}
},
{
"Sid": "ConfigEscribir",
"Effect": "Allow",
"Principal": { "Service": "config.amazonaws.com" },
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::mercadofresco-config-historial/AWSLogs/111122223333/Config/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control",
"AWS:SourceAccount": "111122223333"
}
}
}
]
}Pas 2: el rol de servei. Config necessita permís per llegir la configuració de tot:
aws iam create-role \
--role-name rol-aws-config-mercadofresco \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "config.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "AWS:SourceAccount": "111122223333" }
}
}]
}' \
--profile mercadofresco-dev
aws iam attach-role-policy \
--role-name rol-aws-config-mercadofresco \
--policy-arn arn:aws:iam::aws:policy/service-role/AWS_ConfigRole \
--profile mercadofresco-devLa política gestionada AWS_ConfigRole concedeix només lectura sobre desenes de serveis. Config
no necessita escriure res: la remediació l'executa Systems Manager amb un altre rol diferent, que
és on hi haurà els permisos perillosos. Aquesta separació és deliberada i bona.
Pas 3: l'enregistrador.
aws configservice put-configuration-recorder \
--configuration-recorder '{
"name": "grabador-mercadofresco",
"roleARN": "arn:aws:iam::111122223333:role/rol-aws-config-mercadofresco",
"recordingGroup": {
"allSupported": false,
"includeGlobalResourceTypes": false,
"resourceTypes": [
"AWS::S3::Bucket",
"AWS::EC2::SecurityGroup",
"AWS::EC2::Instance",
"AWS::EC2::Volume",
"AWS::EC2::NetworkAcl",
"AWS::EC2::VPC",
"AWS::EC2::Subnet",
"AWS::RDS::DBInstance",
"AWS::RDS::DBSnapshot",
"AWS::Lambda::Function",
"AWS::IAM::Role",
"AWS::IAM::Policy",
"AWS::IAM::User",
"AWS::KMS::Key",
"AWS::SecretsManager::Secret",
"AWS::ElasticLoadBalancingV2::LoadBalancer",
"AWS::CloudFront::Distribution",
"AWS::CloudTrail::Trail",
"AWS::Logs::LogGroup",
"AWS::WAFv2::WebACL"
]
},
"recordingMode": {
"recordingFrequency": "CONTINUOUS",
"recordingModeOverrides": [
{
"description": "Les instancies del grup ASG roten molt: diari ja es suficient",
"resourceTypes": ["AWS::EC2::Instance", "AWS::EC2::Volume"],
"recordingFrequency": "DAILY"
}
]
}
}' \
--profile mercadofresco-dev --region eu-west-1Dues decisions que aquí valen diners:
allSupported: falseamb llista explícita. Enregistrar els 250+ tipus admesos en un compte viu genera un volum de CI enorme, i molts no aporten res.recordingModeOverridesambDAILYper a instàncies i volums. Aquesta és l'optimització més important de tota la lliçó. L'ASGasg-mercadofresco-tiendallança i acaba instàncies a cada pic dels divendres; cada llançament genera CI de la instància, dels seus volums, de les seves interfícies de xarxa. En mode continu són milers de CI al mes per un recurs efímer amb una configuració sempre idèntica —ve delt-mercadofresco-tienda—. En mode diari, un.
Pas 4: el canal de lliurament.
aws configservice put-delivery-channel \
--delivery-channel '{
"name": "canal-mercadofresco",
"s3BucketName": "mercadofresco-config-historial",
"s3KeyPrefix": "config",
"snsTopicARN": "arn:aws:sns:eu-west-1:111122223333:alertas-mercadofresco",
"configSnapshotDeliveryProperties": {
"deliveryFrequency": "TwentyFour_Hours"
}
}' \
--profile mercadofresco-dev --region eu-west-1Pas 5: engegar-lo. Igual que amb CloudTrail, crear no és engegar:
aws configservice start-configuration-recorder \
--configuration-recorder-name grabador-mercadofresco \
--profile mercadofresco-dev --region eu-west-1
# Comprovar
aws configservice describe-configuration-recorder-status \
--query 'ConfigurationRecordersStatus[].[name,recording,lastStatus]' \
--output table \
--profile mercadofresco-dev --region eu-west-1I una advertència sobre el tema d'SNS: si connectes totes les notificacions de Config a
alertas-mercadofresco, rebràs un missatge per cada canvi de configuració del compte. Amb l'ASG
rotant, això és soroll pur que farà que la gent deixi de llegir els avisos. La manera correcta és
enviar per SNS només les notificacions de no conformitat, i això es fa amb EventBridge (07-03)
filtrant el tipus d'esdeveniment, o amb un tema separat per al soroll. MercadoFresco fa servir el tema
aquí únicament perquè el canal ho exigeix, i filtra a EventBridge el que arriba a les persones.
Triar quins tipus de recurs s'enregistren
La taula de decisió de MercadoFresco, que és el patró que cal copiar:
| Tipus de recurs | Enregistrar? | Freqüència | Motiu |
|---|---|---|---|
AWS::S3::Bucket |
Sí | Contínua | Xifratge, accés públic: crític |
AWS::EC2::SecurityGroup |
Sí | Contínua | La porta d'entrada |
AWS::RDS::DBInstance |
Sí | Contínua | Xifratge, Multi-AZ, còpies |
AWS::IAM::Role / Policy / User |
Sí | Contínua | És global: només en una regió |
AWS::KMS::Key |
Sí | Contínua | Rotació, política |
AWS::CloudTrail::Trail |
Sí | Contínua | Que ningú no el desactivi |
AWS::Logs::LogGroup |
Sí | Contínua | Retenció (el problema de 05-01) |
AWS::EC2::Instance |
Sí | Diària | Roten constantment |
AWS::EC2::Volume |
Sí | Diària | Ídem |
AWS::EC2::NetworkInterface |
No | — | Pur soroll de l'ASG |
AWS::SSM::ManagedInstanceInventory |
No | — | Volum enorme, valor baix |
AWS::Config::ResourceCompliance |
No | — | Config enregistrant Config |
Les tres últimes files són les que més diners estalvien en comptes reals. NetworkInterface i
ManagedInstanceInventory són, de bon tros, els dos tipus que més CI generen per accident.
Recursos globals: IAM i CloudFront són globals. Si actives includeGlobalResourceTypes en diverses
regions, pagaràs el mateix CI diverses vegades. S'activa en una sola regió —MercadoFresco fa
servir eu-west-1— i s'enregistren explícitament els tipus d'IAM tal com hem fet més amunt.
Regles: el cor del servei
Una regla de Config avalua recursos i els assigna un estat:
| Estat | Significa |
|---|---|
COMPLIANT |
Compleix |
NON_COMPLIANT |
No compleix |
NOT_APPLICABLE |
La regla no s'aplica a aquell recurs |
INSUFFICIENT_DATA |
No s'ha pogut avaluar |
Hi ha tres classes de regla:
| Classe | Qui l'escriu | Cost d'avaluació |
|---|---|---|
| Gestionada per AWS | AWS. N'hi ha més de 300 | 0,001 USD |
| Personalitzada amb Lambda | Tu, en codi | 0,001 USD + cost de Lambda |
| Personalitzada amb Guard | Tu, en llenguatge declaratiu | 0,001 USD |
Comença sempre per les gestionades: cobreixen el 90 % del que necessites i no cal mantenir-les.
Les regles gestionades que activa MercadoFresco
| Regla | Què comprova | Per què la necessita MercadoFresco | Activació |
|---|---|---|---|
s3-bucket-server-side-encryption-enabled |
Xifratge per defecte als buckets | La pregunta del mòdul 4 | Canvi |
s3-bucket-public-read-prohibited |
Que no es pugui llegir públicament | mercadofresco-copias-basedatos públic seria catastròfic |
Canvi |
s3-bucket-public-write-prohibited |
Que no s'hi pugui escriure | Ídem | Canvi |
s3-bucket-versioning-enabled |
Versionatge actiu | Recuperació davant esborraments | Canvi |
s3-bucket-ssl-requests-only |
Política que exigeix TLS | Dades en trànsit | Canvi |
rds-storage-encrypted |
Xifratge d'RDS | mercadofresco-pedidos amb alias/mercadofresco-datos (04-02) |
Canvi |
rds-instance-public-access-check |
RDS no accessible des d'internet | Ha de ser a subxarxes de dades (03-01) | Canvi |
rds-multi-az-support |
Multi-AZ actiu | El vam muntar a 02-04; que ningú no el tregui | Canvi |
db-instance-backup-enabled |
Còpies automàtiques actives | PITR de 02-04 | Canvi |
restricted-ssh |
Port 22 no obert a 0.0.0.0/0 |
L'altra pregunta del mòdul 4 | Canvi |
restricted-common-ports |
3389, 5432, 3306, 6379… tancats | Que ningú no exposi PostgreSQL | Canvi |
vpc-default-security-group-closed |
El SG per defecte sense regles | L'oblit clàssic de 03-02 | Canvi |
vpc-flow-logs-enabled |
Flow logs actius a la VPC | flowlogs-mercadofresco (03-01) |
Periòdica |
iam-user-mfa-enabled |
MFA a tots els usuaris IAM | 04-01 | Periòdica (24 h) |
iam-root-access-key-check |
L'arrel sense claus d'accés | 04-01 | Periòdica (24 h) |
iam-password-policy |
Política de contrasenyes robusta | 04-01 | Periòdica |
access-keys-rotated |
Claus rotades cada 90 dies | Exercici 2 de 05-03 | Periòdica |
iam-policy-no-statements-with-admin-access |
Sense "Action": "*" |
Mínim privilegi (04-01) | Canvi |
cloudtrail-enabled |
Existeix un trail actiu | trail-mercadofresco (05-03) |
Periòdica |
cloud-trail-log-file-validation-enabled |
Validació d'integritat | 05-03 | Periòdica |
cloud-trail-encryption-enabled |
Trail xifrat amb KMS | 05-03 | Periòdica |
cw-loggroup-retention-period-check |
Retenció configurada | L'error de 610 USD de 05-01 | Canvi |
encrypted-volumes |
Volums EBS xifrats | 04-02 | Canvi |
ec2-imdsv2-check |
IMDSv2 obligatori a EC2 | Protegeix el rol d'instància | Canvi |
elb-tls-https-listeners-only |
ALB només amb HTTPS | 03-03 | Canvi |
kms-cmk-not-scheduled-for-deletion |
Cap clau marcada per esborrar | L'esdeveniment més destructiu (05-03) | Periòdica |
required-tags |
Etiquetatge obligatori | La política de MercadoFresco | Canvi |
lambda-function-public-access-prohibited |
Lambdes no invocables per qualsevol | 02-05 | Canvi |
secretsmanager-rotation-enabled-check |
Rotació activa als secrets | 04-03 | Periòdica |
Són 29 regles. Activar-les:
# La que respon a la pregunta del modul 4
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-s3-cifrado",
"Description": "Tots els buckets han de tenir xifratge per defecte",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
},
"Scope": { "ComplianceResourceTypes": ["AWS::S3::Bucket"] }
}' --profile mercadofresco-dev --region eu-west-1
# L'altra: SSH obert al mon
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-ssh-restringido",
"Description": "Cap SG amb el port 22 obert a 0.0.0.0/0",
"Source": { "Owner": "AWS", "SourceIdentifier": "INCOMING_SSH_DISABLED" },
"Scope": { "ComplianceResourceTypes": ["AWS::EC2::SecurityGroup"] }
}' --profile mercadofresco-dev --region eu-west-1
# Ports comuns, amb parametres
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-puertos-restringidos",
"Source": { "Owner": "AWS", "SourceIdentifier": "RESTRICTED_INCOMING_TRAFFIC" },
"Scope": { "ComplianceResourceTypes": ["AWS::EC2::SecurityGroup"] },
"InputParameters": "{\"blockedPort1\":\"22\",\"blockedPort2\":\"3389\",\"blockedPort3\":\"5432\",\"blockedPort4\":\"3306\",\"blockedPort5\":\"6379\"}"
}' --profile mercadofresco-dev --region eu-west-1
# Retencio dels grups de registres: l'error de 05-01
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-retencion-registros",
"Description": "Tot grup de registres ha de tenir retencio configurada",
"Source": { "Owner": "AWS", "SourceIdentifier": "CW_LOGGROUP_RETENTION_PERIOD_CHECK" },
"InputParameters": "{\"MinRetentionTime\":\"7\"}"
}' --profile mercadofresco-dev --region eu-west-1I la consulta de l'estat general:
aws configservice describe-compliance-by-config-rule \
--query 'ComplianceByConfigRules[?Compliance.ComplianceType==`NON_COMPLIANT`].[ConfigRuleName,Compliance.ComplianceContributorCount.CappedCount]' \
--output table \
--profile mercadofresco-dev --region eu-west-1
# I el detall d'una regla concreta
aws configservice get-compliance-details-by-config-rule \
--config-rule-name mercadofresco-s3-cifrado \
--compliance-types NON_COMPLIANT \
--query 'EvaluationResults[].EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId' \
--output table \
--profile mercadofresco-dev --region eu-west-1Activació per canvi enfront d'activació periòdica
| Per canvi de configuració | Periòdica | |
|---|---|---|
| Quan avalua | En detectar un CI nou | Cada 1, 3, 6, 12 o 24 hores |
| Latència de detecció | Minuts | Fins a 24 hores |
| Cost | Una avaluació per canvi | Una avaluació per període |
| Per a què | Recursos concrets | Comprovacions de compte |
| Exemple | restricted-ssh |
iam-user-mfa-enabled, cloudtrail-enabled |
La distinció no és arbitrària. Una regla per canvi necessita un recurs a què associar-se. Regles
com cloudtrail-enabled o iam-password-policy avaluen una propietat del compte, no d'un
recurs concret, així que només poden ser periòdiques.
I hi ha un matís de cost important: una regla per canvi sobre un tipus de recurs que canvia molt —instàncies EC2 amb l'ASG rotant— s'avalua moltíssimes vegades. Una regla periòdica cada 24 hores s'avalua 30 vegades al mes i prou. Quan una comprovació no necessiti detecció immediata, posa-la periòdica.
Es pot combinar:
{
"ConfigRuleName": "mercadofresco-volumenes-cifrados",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "ENCRYPTED_VOLUMES",
"SourceDetails": [
{ "EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification" },
{ "EventSource": "aws.config",
"MessageType": "ScheduledNotification",
"MaximumExecutionFrequency": "TwentyFour_Hours" }
]
}
}Avalua en canviar i un cop al dia, que és la xarxa de seguretat per si s'ha perdut algun CI.
L'etiquetatge obligatori amb required-tags
L'etiquetatge de MercadoFresco és Proyecto, Entorno, Componente, Propietario, CentroCoste.
Fins ara era una norma escrita que ningú no comprovava. Config la converteix en una regla:
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-etiquetado-obligatorio",
"Description": "Els recursos han de portar les cinc etiquetes de MercadoFresco",
"Source": { "Owner": "AWS", "SourceIdentifier": "REQUIRED_TAGS" },
"InputParameters": "{\"tag1Key\":\"Proyecto\",\"tag1Value\":\"mercadofresco\",\"tag2Key\":\"Entorno\",\"tag2Value\":\"produccion,preproduccion,desarrollo\",\"tag3Key\":\"Componente\",\"tag4Key\":\"Propietario\",\"tag5Key\":\"CentroCoste\"}",
"Scope": {
"ComplianceResourceTypes": [
"AWS::EC2::Instance",
"AWS::EC2::Volume",
"AWS::S3::Bucket",
"AWS::RDS::DBInstance",
"AWS::Lambda::Function",
"AWS::ElasticLoadBalancingV2::LoadBalancer"
]
},
"MaximumExecutionFrequency": "TwentyFour_Hours"
}' --profile mercadofresco-dev --region eu-west-1Detalls de la sintaxi que no són evidents:
tagNKeysensetagNValueexigeix que l'etiqueta existeixi, amb qualsevol valor. Així estanComponente,PropietarioiCentroCoste: els seus valors són lliures.tagNValueamb una llista separada per comes exigeix que el valor sigui un d'aquests.Entornonomés pot serproduccion,preproduccionodesarrollo.- Màxim 6 etiquetes per regla. Si en necessites més, dues regles.
I el resultat la primera vegada que s'executa, que és el moment més instructiu:
| Tipus | Total | Conformes | No conformes | Què falta |
|---|---|---|---|---|
| Buckets S3 | 6 | 4 | 2 | mercadofresco-registros-web sense CentroCoste |
| Instàncies EC2 | 2 | 2 | 0 | — |
| Volums EBS | 4 | 1 | 3 | Els creats per l'ASG no hereten etiquetes |
| Lambdes | 2 | 2 | 0 | — |
| RDS | 2 | 2 | 0 | — |
| ALB | 1 | 1 | 0 | — |
La fila dels volums és la troballa real, i és un problema que gairebé tothom té sense saber-ho: els volums EBS creats automàticament per un ASG no hereten les etiquetes de la instància llevat que es configuri explícitament a la plantilla de llançament:
{
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{ "Key": "Proyecto", "Value": "mercadofresco" },
{ "Key": "Entorno", "Value": "produccion" },
{ "Key": "Componente", "Value": "tienda" },
{ "Key": "Propietario", "Value": "marta" },
{ "Key": "CentroCoste", "Value": "tienda-online" }
]
},
{
"ResourceType": "volume",
"Tags": [
{ "Key": "Proyecto", "Value": "mercadofresco" },
{ "Key": "Entorno", "Value": "produccion" },
{ "Key": "Componente", "Value": "tienda" },
{ "Key": "Propietario", "Value": "marta" },
{ "Key": "CentroCoste", "Value": "tienda-online" }
]
}
]
}Conseqüència directa i mesurable: al mòdul 11, quan la Sara reparteixi el cost per CentroCoste, els
volums de la botiga apareixerien com a «sense assignar». Una regla de Config ha trobat un forat
a la comptabilitat de costos que ningú no havia vist en mesos. És el millor argument per activar
required-tags des del primer dia.
Regles personalitzades amb Lambda
Quan cap regla gestionada no serveix. El cas de MercadoFresco: cap bucket de dades de negoci pot tenir una regla de cicle de vida que esborri objectes abans de 30 dies, perquè la Sara necessita poder recalcular informes del mes.
"""Regla de Config personalitzada: cicle de vida segur als buckets de negoci.
L'esdeveniment que rep la funcio conte l'element de configuracio
complet del recurs avaluat.
"""
import json
import boto3
config = boto3.client("config")
s3 = boto3.client("s3")
BUCKETS_DE_NEGOCI = (
"mercadofresco-informes-analitica",
"mercadofresco-copias-basedatos",
)
DIES_MINIMS = 30
def avaluar(element):
"""Retorna (estat, motiu) per a un element de configuracio."""
nom = element["resourceName"]
if not nom.startswith(BUCKETS_DE_NEGOCI):
return "NOT_APPLICABLE", "No es un bucket de dades de negoci"
try:
cicle = s3.get_bucket_lifecycle_configuration(Bucket=nom)
except s3.exceptions.ClientError as e:
if "NoSuchLifecycleConfiguration" in str(e):
return "COMPLIANT", "Sense regles de cicle de vida: no s'esborra res"
raise
for regla in cicle.get("Rules", []):
if regla.get("Status") != "Enabled":
continue
expiracio = regla.get("Expiration", {})
dies = expiracio.get("Days")
if dies is not None and dies < DIES_MINIMS:
return ("NON_COMPLIANT",
f"La regla '{regla.get('ID')}' expira objectes als {dies} dies "
f"(minim exigit: {DIES_MINIMS})")
return "COMPLIANT", f"Cap regla no expira abans de {DIES_MINIMS} dies"
def handler(esdeveniment, context):
invocacio = json.loads(esdeveniment["invokingEvent"])
element = invocacio["configurationItem"]
token = esdeveniment["resultToken"]
# Un recurs esborrat no s'avalua.
if element["configurationItemStatus"] in ("ResourceDeleted",
"ResourceDeletedNotRecorded"):
estat, motiu = "NOT_APPLICABLE", "Recurs esborrat"
else:
estat, motiu = avaluar(element)
config.put_evaluations(
Evaluations=[{
"ComplianceResourceType": element["resourceType"],
"ComplianceResourceId": element["resourceId"],
"ComplianceType": estat,
"Annotation": motiu[:256], # limit de 256 caracters
"OrderingTimestamp": element["configurationItemCaptureTime"],
}],
ResultToken=token,
)
return {"estat": estat, "motiu": motiu}Quatre coses que cal fer bé i que s'obliden:
- Retornar
NOT_APPLICABLEper al que no aplica, noCOMPLIANT. Si retornesCOMPLIANTper a tots els buckets del món, el quadre de compliment menteix: semblarà que 40 buckets compleixen una regla que només s'aplica a dos. - Tractar
ResourceDeleted. Avaluar un recurs que ja no existeix deixa registres orfes marcats com a no conformes per sempre. Annotationés el text que es veu a la consola al costat del recurs no conforme. Un bon missatge aquí estalvia mitja hora d'investigació. Màxim 256 caràcters.ResultTokencal retornar-lo tal qual. És el que associa la resposta amb l'avaluació.
I el registre de la regla:
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-ciclo-vida-seguro",
"Description": "Els buckets de negoci no poden expirar objectes abans de 30 dies",
"Source": {
"Owner": "CUSTOM_LAMBDA",
"SourceIdentifier": "arn:aws:lambda:eu-west-1:111122223333:function:mercadofresco-regla-ciclo-vida",
"SourceDetails": [{
"EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification"
}]
},
"Scope": { "ComplianceResourceTypes": ["AWS::S3::Bucket"] }
}' --profile mercadofresco-dev --region eu-west-1Cost: 0,001 USD per avaluació més el cost de la invocació de Lambda. Amb pocs buckets és menyspreable; amb una regla personalitzada sobre instàncies EC2 en un compte amb molt moviment, pot sorprendre.
Regles personalitzades amb Guard
AWS CloudFormation Guard és un llenguatge declaratiu de regles, molt més curt que una Lambda per a comprovacions sobre la configuració. Les regles de Config escrites en Guard s'anomenen Custom Policy rules i no requereixen cap funció: no hi ha codi a mantenir, ni rol, ni cost de Lambda.
La mateixa idea d'abans, en Guard, comprovant que els buckets de negoci estan xifrats amb la clau de MercadoFresco i no amb la d'AWS:
# Regla: els buckets de negoci han de fer servir alias/mercadofresco-datos
rule buckets_negoci_amb_clau_propia when
resourceType == "AWS::S3::Bucket"
{
let nom = resourceName
when %nom == /^mercadofresco-(informes-analitica|copias-basedatos)/ {
configuration.serverSideEncryptionConfiguration.rules[*]
.applyServerSideEncryptionByDefault.sseAlgorithm == "aws:kms"
<<
Els buckets de dades de negoci s'han de xifrar amb KMS,
no amb AES256 gestionat per S3.
>>
configuration.serverSideEncryptionConfiguration.rules[*]
.applyServerSideEncryptionByDefault.kmsMasterKeyID
== /mercadofresco-datos/
<<
Cal fer servir la clau alias/mercadofresco-datos (04-02).
>>
}
}
# Regla: cap grup de registres sense retencio
rule grups_registres_amb_retencio when
resourceType == "AWS::Logs::LogGroup"
{
configuration.retentionInDays EXISTS
<< Tot grup de registres ha de tenir retencio (05-01). >>
configuration.retentionInDays <= 400
<< Les retencions superiors a 400 dies s'han de justificar. >>
}El bloc entre << i >> és el missatge d'error, que apareix com a anotació a la consola.
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mercadofresco-cifrado-buckets-negocio",
"Source": {
"Owner": "CUSTOM_POLICY",
"SourceDetails": [{
"EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification"
}],
"CustomPolicyDetails": {
"PolicyRuntime": "guard-2.x.x",
"PolicyText": "<contingut del fitxer .guard>",
"EnableDebugLogDelivery": true
}
},
"Scope": { "ComplianceResourceTypes": ["AWS::S3::Bucket"] }
}' --profile mercadofresco-dev --region eu-west-1| Lambda | Guard | |
|---|---|---|
| Escrius | Codi Python/Node | Regles declaratives |
| Pots cridar altres API | Sí | No |
| Cost extra | Invocacions de Lambda | Cap |
| Manteniment | Runtime, dependències, rol | Cap |
| Complexitat admesa | Qualsevol | El que hi hagi al CI |
| Recomanació | Només si necessites lògica externa | Per defecte |
La diferència pràctica: Guard només pot mirar el que hi ha a l'element de configuració. Si la teva
comprovació necessita cridar una altra API —com l'exemple de Lambda, que consultava
get_bucket_lifecycle_configuration—, necessites Lambda. Per a tota la resta, Guard.
Remediació automàtica amb Systems Manager
Detectar és bo. Corregir sol és millor, i és el que converteix Config en una eina operativa i no en un informe més que ningú no llegeix.
La remediació s'executa amb un document de Systems Manager Automation: un procediment
predefinit amb passos i paràmetres. AWS proporciona dotzenes de documents AWS-* a punt per fer servir.
El rol de remediació. Aquí és on hi ha els permisos perillosos, i per això és un rol a part del de Config, amb el mínim estricte:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CifrarBuckets",
"Effect": "Allow",
"Action": [
"s3:PutEncryptionConfiguration",
"s3:GetEncryptionConfiguration"
],
"Resource": "arn:aws:s3:::mercadofresco-*"
},
{
"Sid": "CerrarGruposDeSeguridad",
"Effect": "Allow",
"Action": [
"ec2:RevokeSecurityGroupIngress",
"ec2:DescribeSecurityGroups"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:ResourceTag/Proyecto": "mercadofresco" }
}
},
{
"Sid": "PonerRetencionEnRegistros",
"Effect": "Allow",
"Action": ["logs:PutRetentionPolicy", "logs:DescribeLogGroups"],
"Resource": "arn:aws:logs:eu-west-1:111122223333:log-group:*"
}
]
}Fixa't en tres decisions de mínim privilegi, totes del manual de 04-01:
s3:PutEncryptionConfigurationnomés sobremercadofresco-*. El rol no pot tocar buckets aliens.- Condició d'etiqueta a les accions sobre SG: només actua sobre recursos del projecte.
- No hi ha
ec2:AuthorizeSecurityGroupIngress. El rol pot treure regles, mai afegir-ne. Si algú comprometés aquest rol, el pitjor que podria fer és tancar coses. Aquesta asimetria és deliberada i és el tipus de detall que separa una configuració segura d'una de perillosa.
Els dos casos reals: xifratge de bucket i SG obert
Cas 1: reactivar el xifratge d'un bucket.
aws configservice put-remediation-configurations \
--remediation-configurations '[{
"ConfigRuleName": "mercadofresco-s3-cifrado",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-EnableS3BucketEncryption",
"TargetVersion": "1",
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 300,
"Parameters": {
"AutomationAssumeRole": {
"StaticValue": {
"Values": ["arn:aws:iam::111122223333:role/rol-remediacion-mercadofresco"]
}
},
"BucketName": {
"ResourceValue": { "Value": "RESOURCE_ID" }
},
"SSEAlgorithm": {
"StaticValue": { "Values": ["AES256"] }
}
}
}]' \
--profile mercadofresco-dev --region eu-west-1El ResourceValue: RESOURCE_ID és la peça clau: li diu a la remediació que el nom del bucket
sigui el del recurs que ha fallat l'avaluació. Sense això, la remediació no sabria sobre què actuar.
Cronologia completa del que passa ara si algú desactiva el xifratge:
| Moment | Què passa |
|---|---|
T+0 s |
Algú executa DeleteBucketEncryption |
T+2 s |
CloudTrail registra l'esdeveniment (05-03) |
T+3 min |
Config crea un CI nou del bucket |
T+3 min |
La regla mercadofresco-s3-cifrado avalua: NON_COMPLIANT |
T+3 min |
S'emet un esdeveniment d'EventBridge i una notificació a SNS |
T+4 min |
La remediació executa AWS-EnableS3BucketEncryption |
T+5 min |
El xifratge està restaurat |
T+8 min |
Nova avaluació: COMPLIANT |
T+8 min |
La Marta rep l'avís amb tot el cicle al registre |
Vuit minuts, sense intervenció humana. I amb el rastre complet: CloudTrail sap qui el va desactivar, Config sap com va quedar, la remediació ho va arreglar, i la línia temporal ho explica sencer. Aquesta és la resposta a l'última pregunta del mòdul 4.
Cas 2: revocar una regla de grup de seguretat oberta al món.
aws configservice put-remediation-configurations \
--remediation-configurations '[{
"ConfigRuleName": "mercadofresco-ssh-restringido",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWSConfigRemediation-RemoveUnrestrictedSourceIngressRules",
"TargetVersion": "1",
"Automatic": true,
"MaximumAutomaticAttempts": 5,
"RetryAttemptSeconds": 60,
"Parameters": {
"AutomationAssumeRole": {
"StaticValue": {
"Values": ["arn:aws:iam::111122223333:role/rol-remediacion-mercadofresco"]
}
},
"GroupId": { "ResourceValue": { "Value": "RESOURCE_ID" } }
}
}]' \
--profile mercadofresco-dev --region eu-west-1Aquest document revoca totes les regles d'entrada amb origen 0.0.0.0/0 o ::/0 del grup, no
només la del 22. És agressiu, i cal saber-ho: si el teu ALB públic és en un grup de seguretat que
legítimament permet 0.0.0.0/0 al 443, aquesta remediació el tombaria.
Per això MercadoFresco acota l'abast de la regla, no el de la remediació:
{
"ConfigRuleName": "mercadofresco-ssh-restringido",
"Source": { "Owner": "AWS", "SourceIdentifier": "INCOMING_SSH_DISABLED" },
"Scope": {
"ComplianceResourceTypes": ["AWS::EC2::SecurityGroup"],
"TagKey": "Componente",
"TagValue": "basedatos"
}
}Amb TagKey/TagValue, la regla —i per tant la remediació— només s'aplica als grups de
seguretat etiquetats com a Componente=basedatos. sg-mercadofresco-alb, que ha d'estar obert al
món al 443, en queda fora. És el mateix raonament de l'abast mínim que apliquem a les
exclusions de WAF a 04-05.
Cas 3, el més rendible: posar retenció als grups de registres.
aws configservice put-remediation-configurations \
--remediation-configurations '[{
"ConfigRuleName": "mercadofresco-retencion-registros",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWSConfigRemediation-SetCloudWatchLogGroupRetention",
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 300,
"Parameters": {
"AutomationAssumeRole": { "StaticValue": { "Values": [
"arn:aws:iam::111122223333:role/rol-remediacion-mercadofresco"] } },
"LogGroupName": { "ResourceValue": { "Value": "RESOURCE_ID" } },
"RetentionInDays": { "StaticValue": { "Values": ["30"] } }
}
}]' \
--profile mercadofresco-dev --region eu-west-1Aquesta és la que hauria evitat l'incident dels 610 USD de l'exercici 3 de 05-01. Qualsevol grup de registres nou —creat per una Lambda, per l'agent, per un servei— rep 30 dies de retenció automàticament en qüestió de minuts. És la remediació amb millor relació cost-benefici de tot el mòdul.
L'advertència de provar primer en mode manual
No activis mai Automatic: true en una remediació que no hagis provat. Una remediació és codi
amb permisos que modifica la teva producció sense que ningú no ho aprovi. Si està malament, ho fa molt ràpid i
arreu.
El procediment de MercadoFresco, i és innegociable:
Fase 1 — Només detecció, 1 setmana. La regla, sense remediació. S'observa quins recursos marca. Aquí surten els falsos positius: recursos que incompleixen la lletra de la regla per bones raons.
Fase 2 — Remediació manual, 2 setmanes. Automatic: false. La remediació existeix però cal
llançar-la a mà des de la consola, recurs a recurs:
aws configservice start-remediation-execution \
--config-rule-name mercadofresco-s3-cifrado \
--resource-keys resourceType=AWS::S3::Bucket,resourceId=mercadofresco-registros-web \
--profile mercadofresco-dev --region eu-west-1S'executa sobre un recurs poc crític, es comprova que fa exactament el que s'espera i res més, i es revisa el registre de l'execució a Systems Manager.
Fase 3 — Automàtica, amb abast acotat. Automatic: true, però primer només sobre els recursos
etiquetats Entorno=desarrollo. Una setmana. Després, producció.
Fase 4 — Amb límits. MaximumAutomaticAttempts i RetryAttemptSeconds són un fre important:
si la remediació falla 3 vegades, Config deixa d'intentar-ho en lloc d'entrar en bucle. Un bucle de
remediació pot generar milers de crides a l'API i una factura considerable.
I tres tipus de remediació que MercadoFresco NO automatitza mai:
| Remediació | Per què no |
|---|---|
| Esborrar recursos no conformes | Irreversible. Una regla mal escrita esborra producció |
| Aturar instàncies EC2 | Talla el servei. La regla pot estar malament |
| Modificar polítiques d'IAM | Pot deixar tothom sense accés, inclosa la mateixa remediació |
La regla mental: automatitza el que afegeix seguretat i és reversible (activar xifratge, posar retenció, treure accés públic). No automatitzis mai el que treu disponibilitat o és irreversible.
Paquets de conformitat
Un conformance pack és una plantilla que desplega un conjunt de regles i remediacions de cop, com una unitat, i que es pot aplicar a tota una organització.
AWS publica plantilles alineades amb marcs coneguts:
| Paquet | Regles aprox. | Per a què |
|---|---|---|
| Operational Best Practices for CIS AWS Foundations Benchmark v1.4 | ~50 | L'estàndard de partida més habitual |
| Operational Best Practices for PCI DSS 3.2.1 | ~90 | Comerços que processen targetes |
| Operational Best Practices for NIST 800-53 | ~200 | Sector públic nord-americà |
| Operational Best Practices for GDPR | ~60 | Ajuda per al RGPD |
| Operational Best Practices for Amazon S3 | ~15 | Només S3 |
| Security Best Practices | ~120 | Generalista d'AWS |
# paquete-mercadofresco.yaml
Parameters:
RetencionMinimaRegistros:
Type: String
Default: '7'
Resources:
S3CifradoActivado:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: paq-mercadofresco-s3-cifrado
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
Scope:
ComplianceResourceTypes: [ 'AWS::S3::Bucket' ]
S3SinLecturaPublica:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: paq-mercadofresco-s3-sin-lectura-publica
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
Scope:
ComplianceResourceTypes: [ 'AWS::S3::Bucket' ]
RdsCifrado:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: paq-mercadofresco-rds-cifrado
Source:
Owner: AWS
SourceIdentifier: RDS_STORAGE_ENCRYPTED
RetencionRegistros:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: paq-mercadofresco-retencion-registros
InputParameters:
MinRetentionTime: !Ref RetencionMinimaRegistros
Source:
Owner: AWS
SourceIdentifier: CW_LOGGROUP_RETENTION_PERIOD_CHECKaws configservice put-conformance-pack \
--conformance-pack-name paquete-mercadofresco-base \
--template-body file://paquete-mercadofresco.yaml \
--delivery-s3-bucket mercadofresco-config-historial \
--delivery-s3-key-prefix conformance \
--profile mercadofresco-dev --region eu-west-1
aws configservice describe-conformance-pack-compliance \
--conformance-pack-name paquete-mercadofresco-base \
--profile mercadofresco-dev --region eu-west-1L'advertència que cal repetir. Desplegar el paquet de PCI DSS no et fa conforme amb PCI DSS. És una ajuda: comprova automàticament un subconjunt de controls tècnics. La conformitat real inclou processos, formació, contractes, avaluacions i una auditoria formal per un avaluador qualificat. Presentar un quadre verd de Config com a prova de conformitat és un error greu. Aquestes decisions les valida un professional de compliment, no un curs.
Cost: un paquet no costa res per si mateix; costen les regles que conté. Un paquet de PCI DSS amb 90 regles avaluant-se sobre centenars de recursos és la manera més ràpida de multiplicar la factura de Config per deu. Llegeix-lo abans de desplegar-lo.
El quadre de compliment de MercadoFresco
El primer resultat, tres dies després d'activar-ho tot. Aquest és el moment realment valuós, perquè treu a la llum el que feia mesos que era allà:
| Regla | Estat | Recursos no conformes | Comentari |
|---|---|---|---|
mercadofresco-s3-cifrado |
NO CONFORME | 1 | mercadofresco-registros-web sense xifratge des del març |
mercadofresco-ssh-restringido |
NO CONFORME | 1 | Un SG de proves amb el 22 obert des del maig |
mercadofresco-etiquetado-obligatorio |
NO CONFORME | 5 | 3 volums EBS + 2 buckets |
mercadofresco-retencion-registros |
NO CONFORME | 4 | 4 grups «no expira mai» |
mercadofresco-puertos-restringidos |
CONFORME | 0 | La feina de 03-02 aguanta |
mercadofresco-rds-cifrado |
CONFORME | 0 | 04-02 |
mercadofresco-rds-multi-az |
CONFORME | 0 | 02-04 |
mercadofresco-iam-mfa |
NO CONFORME | 1 | Un usuari de servei sense MFA |
mercadofresco-cloudtrail-activo |
CONFORME | 0 | 05-03 |
mercadofresco-claves-rotadas |
NO CONFORME | 1 | Clau de 412 dies |
mercadofresco-vpc-flow-logs |
CONFORME | 0 | 03-01 |
mercadofresco-sg-defecto-cerrado |
NO CONFORME | 1 | El SG per defecte de la VPC, amb regles |
Sis regles no conformes, 14 recursos. I cap d'aquests catorze no havia disparat mai una alarma de CloudWatch ni havia aparegut en una investigació de CloudTrail, perquè cap no era un esdeveniment: eren estats. Feia mesos que eren allà.
Les tres troballes que la Marta no esperava:
mercadofresco-registros-websense xifratge des del març. Es va crear a mà a 03-03 per als registres de l'ALB, abans que existís la política de xifratge de 04-02, i ningú no hi va tornar.- El SG amb el 22 obert des d'una prova de maig. La regla es va afegir «un moment» per depurar i s'hi va quedar tres mesos.
- El grup de seguretat per defecte de
vpc-mercadofrescoamb regles. És el clàssic de 03-02: ningú no el fa servir, però hi és, permissiu, esperant que algú llanci una instància sense especificar grup.
El pla de correcció, ordenat per risc:
| Prioritat | Recurs | Acció | Com |
|---|---|---|---|
| 1 | SG amb el 22 obert | Revocar la regla | Remediació automàtica |
| 2 | SG per defecte | Buidar-ne les regles | Manual, amb revisió |
| 3 | mercadofresco-registros-web |
Activar xifratge | Remediació automàtica |
| 4 | 4 grups de registres | Posar retenció de 30 dies | Remediació automàtica |
| 5 | Clau de 412 dies | Rotar i desactivar l'antiga | Manual, coordinat |
| 6 | Usuari sense MFA | Substituir per rol (04-01) | Manual, canvi de disseny |
| 7 | Etiquetes de volums | Corregir lt-mercadofresco-tienda |
Manual, canvi de plantilla |
Fixa't en el patró: les quatre primeres s'automatitzen perquè afegeixen seguretat i són reversibles. Les tres últimes requereixen criteri humà, i per això no s'automatitzen.
Consultes avançades per inventariar
Config inclou un motor de consultes SQL sobre l'inventari actual de tots els recursos enregistrats. És una de les seves funcions més infravalorades.
# Tots els buckets sense xifratge
aws configservice select-resource-config \
--expression "
SELECT resourceId, resourceName, awsRegion
WHERE resourceType = 'AWS::S3::Bucket'
AND supplementaryConfiguration.ServerSideEncryptionConfiguration NOT LIKE '%aws:kms%'
" \
--profile mercadofresco-dev --region eu-west-1
# Instancies EC2 per tipus, per a l'analisi de cost del modul 11
aws configservice select-resource-config \
--expression "
SELECT configuration.instanceType, COUNT(*)
WHERE resourceType = 'AWS::EC2::Instance'
GROUP BY configuration.instanceType
" \
--profile mercadofresco-dev --region eu-west-1
# Recursos SENSE l'etiqueta CentroCoste: el forat de la comptabilitat
aws configservice select-resource-config \
--expression "
SELECT resourceType, resourceId, resourceName, tags
WHERE tags.key != 'CentroCoste'
" \
--profile mercadofresco-dev --region eu-west-1
# Volums EBS sense xifrar
aws configservice select-resource-config \
--expression "
SELECT resourceId, configuration.size, configuration.volumeType
WHERE resourceType = 'AWS::EC2::Volume'
AND configuration.encrypted = false
" \
--profile mercadofresco-dev --region eu-west-1
# Grups de seguretat amb regles obertes al mon
aws configservice select-resource-config \
--expression "
SELECT resourceId, resourceName, configuration.ipPermissions
WHERE resourceType = 'AWS::EC2::SecurityGroup'
AND configuration.ipPermissions.ipRanges = '0.0.0.0/0'
" \
--profile mercadofresco-dev --region eu-west-1Aquest motor respon en segons a preguntes que altrament requeririen recórrer desenes de crides
Describe paginades. I a diferència d'Athena sobre CloudTrail (05-03), no costa res per
consulta: forma part del servei.
Una consulta que la Marta executa cada mes i que ja ha justificat el cost de Config diverses vegades:
# Volums EBS sense associar a cap instancia: diners llencats
aws configservice select-resource-config \
--expression "
SELECT resourceId, configuration.size, configuration.createTime, tags
WHERE resourceType = 'AWS::EC2::Volume'
AND configuration.state.value = 'available'
" \
--profile mercadofresco-dev --region eu-west-1Un volum available és un volum que existeix, que es paga cada mes, i que no està connectat a
res. Solen quedar d'instàncies acabades. És exactament una de les troballes que també reporta
Trusted Advisor, que és la lliçó següent.
Agregadors multicompte
Un agregador consolida les dades de Config de diversos comptes i regions en una sola vista.
aws configservice put-configuration-aggregator \
--configuration-aggregator-name agregador-mercadofresco \
--account-aggregation-sources '[{
"AccountIds": ["111122223333"],
"AllAwsRegions": true
}]' \
--profile mercadofresco-dev --region eu-west-1Amb AWS Organizations es fa servir --organization-aggregation-source i l'agregador recull
automàticament tots els comptes de l'organització, inclosos els que es creïn en el futur. Aquesta
és la configuració correcta per a qualsevol empresa amb diversos comptes, i és la lliçó 09-04.
MercadoFresco té un compte avui, així que l'agregador només aporta la vista multiregió —útil per detectar recursos oblidats en regions on no s'hauria de tenir res, el cas de l'exercici 3 de 05-03—.
Security Hub i GuardDuty: on encaixa cadascun
És fàcil confondre aquestes tres eines. La taula que les separa:
| AWS Config | Amazon GuardDuty | AWS Security Hub | |
|---|---|---|---|
| Què fa | Avalua configuracions | Detecta amenaces | Agrega troballes |
| Font de dades | Elements de configuració | CloudTrail, DNS, flow logs, S3, EKS | Config, GuardDuty, Inspector, Macie… |
| Detecta | Un bucket sense xifrar | Una IP maliciosa parlant amb la teva instància | Totes dues coses, en un tauler |
| Basat en | Les teves regles | Aprenentatge i intel·ligència d'amenaces | Estàndards (CIS, PCI, AWS FSBP) |
| Corregeix | Sí (remediació) | No | Via accions personalitzades |
| Cost | Per CI i avaluació | Per GB analitzat i esdeveniments | Per comprovació i troballa |
| Pregunta | Està ben configurat? | Hi ha algú a dins? | Quina és la meva postura global? |
Exemples concrets que aclareixen la divisió del treball:
- Config: «
mercadofresco-registros-webno té xifratge.» És un problema de configuració. - GuardDuty: «Una instància d'
asg-mercadofresco-tiendaestà resolent dominis associats a mineria de criptomonedes» o «credencials del rol d'instància usades des d'una IP externa a AWS». És un problema d'intrusió, i cap regla de configuració no ho detectaria. - Security Hub: «El teu compte compleix el 82 % del CIS Benchmark; aquestes 14 troballes són crítiques», amb les troballes de Config i de GuardDuty a la mateixa llista prioritzada.
Recomanació pràctica: si vas a activar els tres, activa'ls en aquest ordre —Config primer, perquè és la base i perquè Security Hub consumeix les seves regles; GuardDuty després, perquè és el que detecta el que Config no pot veure; Security Hub al final, com a capa d'agregació—. I tingues present que els tres costen diners i els tres generen troballes que algú ha de llegir. Activar els tres i no mirar-los és pitjor que activar només Config i revisar-lo mensualment.
Cost real i com no disparar-lo
| Concepte | Preu a eu-west-1 |
|---|---|
| Element de configuració enregistrat | 0,003 USD cadascun |
| Avaluació de regla (primeres 100.000/mes) | 0,001 USD cadascuna |
| Avaluacions 100.001-500.000 | 0,0008 USD |
| Consultes avançades | Gratuïtes |
| Paquets de conformitat | Només les regles que contenen |
| Execució de remediació (SSM Automation) | Gratuïta al nivell estàndard |
| Emmagatzematge a S3 | 0,023 USD/GB/mes |
| Agregador | Gratuït |
Càlcul per a MercadoFresco:
| Concepte | Quantitat/mes | Cost |
|---|---|---|
| CI de recursos estables (S3, RDS, IAM, KMS, SG, ALB…) | ~450 | 1,35 USD |
| CI d'instàncies i volums (mode diari) | ~180 | 0,54 USD |
| Avaluacions de regles per canvi (29 regles) | ~4.200 | 4,20 USD |
| Avaluacions periòdiques (10 regles × 30 dies) | 300 | 0,30 USD |
| Emmagatzematge a S3 | ~0,3 GB | 0,01 USD |
| Total | ~6,40 USD/mes |
I ara el mateix càlcul sense les optimitzacions, que és el que li passa a la majoria dels comptes:
| Concepte | Quantitat/mes | Cost |
|---|---|---|
allSupported: true amb instàncies en mode continu |
~28.000 CI | 84,00 USD |
| Avaluacions sobre tots aquests recursos | ~140.000 | 132,00 USD |
| Total | ~216,00 USD/mes |
Trenta-quatre vegades més car, i amb exactament la mateixa capacitat de detecció dels problemes que importen. La diferència és tota en tres decisions de configuració.
Les cinc maneres de disparar la factura de Config, per freqüència real:
allSupported: trueen un compte amb autoescalat. Cada llançament d'instància genera CI de la instància, els seus volums, les seves interfícies de xarxa i les seves associacions. Milers al mes.- No fer servir
recordingFrequency: DAILYper a recursos efímers. L'optimització més rendible i la menys coneguda. - Enregistrar recursos globals (IAM) en diverses regions. Es paga el mateix CI tantes vegades com
regions tinguin l'enregistrador amb
includeGlobalResourceTypes. - Desplegar un conformance pack de 200 regles sense llegir-lo. Cada regla s'avalua contra cada recurs aplicable, a cada canvi.
- Regles personalitzades amb Lambda sobre tipus de recurs molt canviants. Es paga l'avaluació i la invocació.
Les cinc defenses:
- Llista explícita de
resourceTypes, maiallSupported. recordingFrequency: DAILYper aAWS::EC2::Instance,AWS::EC2::Volumei tot el que sigui efímer.- Recursos globals en una sola regió.
- Regles periòdiques cada 24 h en lloc de per canvi sempre que no necessitis detecció immediata.
- Un pressupost d'AWS Budgets filtrat per servei = Config (mòdul 11), amb avís al 80 %.
Neteja
# 1. Treure les remediacions ABANS que les regles
aws configservice delete-remediation-configuration \
--config-rule-name mercadofresco-s3-cifrado \
--profile mercadofresco-dev --region eu-west-1
# 2. Esborrar les regles
for R in mercadofresco-s3-cifrado mercadofresco-ssh-restringido \
mercadofresco-puertos-restringidos mercadofresco-retencion-registros \
mercadofresco-etiquetado-obligatorio mercadofresco-ciclo-vida-seguro \
mercadofresco-cifrado-buckets-negocio; do
aws configservice delete-config-rule --config-rule-name "$R" \
--profile mercadofresco-dev --region eu-west-1
done
# 3. El paquet de conformitat
aws configservice delete-conformance-pack \
--conformance-pack-name paquete-mercadofresco-base \
--profile mercadofresco-dev --region eu-west-1
# 4. ATURAR L'ENREGISTRADOR: aixo es el que talla la despesa
aws configservice stop-configuration-recorder \
--configuration-recorder-name grabador-mercadofresco \
--profile mercadofresco-dev --region eu-west-1
# 5. Canal i enregistrador
aws configservice delete-delivery-channel --delivery-channel-name canal-mercadofresco \
--profile mercadofresco-dev --region eu-west-1
aws configservice delete-configuration-recorder \
--configuration-recorder-name grabador-mercadofresco \
--profile mercadofresco-dev --region eu-west-1
# 6. El bucket de l'historial (revisa abans si hi ha obligacio de conservar-lo)
aws s3 rm s3://mercadofresco-config-historial --recursive --profile mercadofresco-dev
aws s3api delete-bucket --bucket mercadofresco-config-historial --profile mercadofresco-devEl pas 4 és l'important. Esborrar regles no atura la despesa: els CI es continuen enregistrant
mentre l'enregistrador estigui actiu. Aturar l'enregistrador és el que talla la facturació. I si en
algun moment veus un càrrec de Config que no esperes, comença sempre per
describe-configuration-recorder-status a totes les regions: un enregistrador oblidat en una regió
que no fas servir és un clàssic.
Errors Comuns i Consells
1. Activar allSupported: true sense pensar-hi. És l'error de cost número u del servei. Llista
explícita, sempre.
2. No fer servir recordingFrequency: DAILY per a instàncies i volums. Amb un ASG actiu, és la
diferència entre 6 i 216 USD al mes.
3. Enregistrar recursos globals en diverses regions. Es paga el mateix CI diverses vegades. IAM i CloudFront en una sola regió.
4. Activar Automatic: true en una remediació sense provar-la. Detecció una setmana, remediació
manual dues setmanes, automàtica en desenvolupament una setmana, i després producció. Sense dreceres.
5. Automatitzar remediacions destructives. Esborrar recursos, aturar instàncies o modificar IAM automàticament pot convertir una regla mal escrita en una caiguda. Automatitza només el que afegeix seguretat i és reversible.
6. Confondre Config amb CloudTrail. «Qui ho ha canviat?» → CloudTrail. «Com està i compleix?» → Config. Es fan servir junts.
7. Retornar COMPLIANT en lloc de NOT_APPLICABLE en una regla personalitzada. El quadre de
compliment queda inflat i deixa de ser útil.
8. Connectar totes les notificacions de Config a SNS. Un missatge per cada canvi de configuració és soroll garantit, i el soroll fa que la gent deixi de llegir els avisos importants. Filtra amb EventBridge (07-03) i envia a les persones només les no conformitats.
9. Creure que un conformance pack et certifica. No. Comprova controls tècnics; la conformitat real inclou processos, contractes i una auditoria formal. Que ho validi un professional de compliment.
10. Aplicar una remediació de SG sense acotar l'abast de la regla.
RemoveUnrestrictedSourceIngressRules sobre sg-mercadofresco-alb tombaria la botiga. Acota amb
TagKey/TagValue.
11. Esborrar regles creient que s'atura la despesa. El que factura són els CI de l'enregistrador.
stop-configuration-recorder.
12. Oblidar start-configuration-recorder. Com amb CloudTrail, crear no és engegar.
13. Escriure una regla amb Lambda quan n'hi havia prou amb Guard. Si la comprovació només mira l'element de configuració, Guard és més curt, més barat i no cal mantenir cap runtime.
Consell final: activa Config amb poques regles i ben triades abans que amb un paquet de conformitat complet. Deu regles que algú revisa cada mes valen infinitament més que dues-centes que generen un quadre vermell permanent al qual tothom s'acostuma. L'objectiu no és tenir moltes regles: és arribar a zero no conformitats i que qualsevol de nova sigui un senyal real.
Exercicis
Exercici 1: dissenyar la configuració de Config amb pressupost
MercadoFresco vol activar Config amb un pressupost màxim de 12 USD al mes. Inventari real del compte:
| Tipus de recurs | Quantitat | Canvis/mes estimats |
|---|---|---|
AWS::S3::Bucket |
7 | 4 |
AWS::EC2::SecurityGroup |
6 | 8 |
AWS::EC2::Instance |
2-4 (ASG) | 620 (rotació) |
AWS::EC2::Volume |
4-8 | 640 |
AWS::EC2::NetworkInterface |
4-8 | 1.280 |
AWS::RDS::DBInstance |
2 | 3 |
AWS::IAM::Role |
9 | 6 |
AWS::IAM::Policy |
12 | 5 |
AWS::Lambda::Function |
2 | 20 (desplegaments) |
AWS::Logs::LogGroup |
9 | 12 |
AWS::KMS::Key |
1 | 1 |
Requisits: cal detectar en menys de 15 minuts que un bucket perd el xifratge o que un SG s'obre al món; cal comprovar l'etiquetatge obligatori; cal vigilar la retenció dels grups de registres.
Dissenya: la llista de resourceTypes amb la seva recordingFrequency, el conjunt de regles amb el seu tipus
d'activació, i calcula el cost total. Justifica cada exclusió. Si et passes del pressupost, explica què
retallaries i quina capacitat de detecció perdries.
Exercici 2: la regla personalitzada i la seva remediació
MercadoFresco té una política interna: tota instantània d'RDS de més de 90 dies ha d'estar
xifrada i no ha de ser pública, i les de més de 365 dies s'han d'esborrar llevat que portin l'etiqueta
Retencion=legal.
- a) Explica per què aquesta comprovació no es pot fer amb una sola regla gestionada, i quines regles gestionades cobreixen part del problema.
- b) Escriu la regla personalitzada (Lambda o Guard, justificant l'elecció) que avalua les instantànies.
- c) Dissenya la remediació. Decideix quina part s'automatitza i quina no, i justifica-ho amb el criteri de la lliçó.
- d) Calcula el cost afegit si MercadoFresco té 120 instantànies i la regla és periòdica cada 24 hores, enfront de per canvi de configuració.
Exercici 3: la investigació combinada
Un dilluns, la regla mercadofresco-s3-cifrado marca mercadofresco-informes-analitica com a
NO CONFORME. La remediació automàtica encara és en mode manual. Dades:
- La línia temporal mostra que el CI no conforme es va crear el diumenge a les 04:17.
- El CI anterior, del dijous, era conforme.
- La regla
mercadofresco-etiquetado-obligatoriomarca el mateix bucket com a no conforme des del diumenge a les 04:17: li falta l'etiquetaPropietario. - Hi ha tres buckets nous al compte, creats el diumenge entre les 04:10 i les 04:25, cap amb xifratge ni etiquetes.
- CloudTrail mostra 46 crides d'escriptura aquell diumenge entre les 04:05 i les 04:30, totes amb
userIdentity.type = "AssumedRole"isessionIssuer.userName = "rol-despliegue-infra".
Explica: què ha passat amb tota probabilitat; com ho confirmaries combinant Config i CloudTrail (amb comandes i consultes concretes); per què Config va detectar una cosa que CloudTrail tot sol no hauria fet saltar; quina remediació aplicaries i en quin ordre; i quin arranjament de fons proposaries perquè no torni a passar, indicant en quin mòdul del curs s'estudia.
Solucions
Solució 1
Anàlisi de l'inventari. El problema està concentrat en tres files: instàncies (620),
volums (640) i interfícies de xarxa (1.280). Són 2.540 dels 2.679 canvis mensuals: el 95 %.
Tots generats per la rotació de l'ASG i tots de configuració idèntica, perquè vénen de
lt-mercadofresco-tienda.
Configuració proposada de l'enregistrador:
| Tipus | Enregistrar? | Freqüència | Justificació |
|---|---|---|---|
AWS::S3::Bucket |
Sí | Contínua | Requisit: detecció en 15 min |
AWS::EC2::SecurityGroup |
Sí | Contínua | Requisit: detecció en 15 min |
AWS::RDS::DBInstance |
Sí | Contínua | Pocs canvis, alt valor |
AWS::IAM::Role / Policy |
Sí | Contínua | Pocs canvis, alt valor |
AWS::KMS::Key |
Sí | Contínua | 1 canvi/mes |
AWS::Logs::LogGroup |
Sí | Contínua | Requisit de retenció |
AWS::Lambda::Function |
Sí | Contínua | 20 canvis/mes, assumible |
AWS::EC2::Instance |
Sí | DIÀRIA | 620 → ~30 CI/mes |
AWS::EC2::Volume |
Sí | DIÀRIA | 640 → ~30 CI/mes |
AWS::EC2::NetworkInterface |
NO | — | 1.280 CI de valor gairebé nul |
Càlcul d'elements de configuració:
| Tipus | CI/mes | Cost |
|---|---|---|
| Buckets | 4 | 0,012 USD |
| SG | 8 | 0,024 USD |
| Instàncies (diària) | 30 | 0,090 USD |
| Volums (diària) | 30 | 0,090 USD |
| RDS | 3 | 0,009 USD |
| Rols + polítiques | 11 | 0,033 USD |
| Lambdes | 20 | 0,060 USD |
| Grups de registres | 12 | 0,036 USD |
| KMS | 1 | 0,003 USD |
| Descobriment inicial (un cop) | ~55 | 0,165 USD |
| Total CI | ~174 | ~0,52 USD |
Regles proposades:
| Regla | Activació | Avaluacions/mes | Cost |
|---|---|---|---|
s3-bucket-server-side-encryption-enabled |
Canvi | 4 + 7 inicials = 11 | 0,011 USD |
s3-bucket-public-read-prohibited |
Canvi | 11 | 0,011 USD |
restricted-ssh |
Canvi | 8 + 6 = 14 | 0,014 USD |
restricted-common-ports |
Canvi | 14 | 0,014 USD |
vpc-default-security-group-closed |
Canvi | 14 | 0,014 USD |
rds-storage-encrypted |
Canvi | 3 + 2 = 5 | 0,005 USD |
rds-multi-az-support |
Canvi | 5 | 0,005 USD |
cw-loggroup-retention-period-check |
Canvi | 12 + 9 = 21 | 0,021 USD |
encrypted-volumes |
Canvi (diària) | 30 | 0,030 USD |
required-tags |
Periòdica 24 h | 30 × 25 recursos = 750 | 0,750 USD |
iam-user-mfa-enabled |
Periòdica 24 h | 30 | 0,030 USD |
iam-root-access-key-check |
Periòdica 24 h | 30 | 0,030 USD |
cloudtrail-enabled |
Periòdica 24 h | 30 | 0,030 USD |
access-keys-rotated |
Periòdica 24 h | 30 | 0,030 USD |
kms-cmk-not-scheduled-for-deletion |
Periòdica 24 h | 30 | 0,030 USD |
| Total avaluacions | ~1.062 | ~1,03 USD |
Cost total: 0,52 + 1,03 + ~0,02 de S3 = ~1,57 USD/mes. Molt per sota dels 12 USD.
Amb el marge sobrant es pot: afegir el paquet de conformitat CIS complet (~50 regles, uns
3-4 USD més), passar required-tags a activació per canvi per a una detecció més ràpida, o incloure
AWS::EC2::NetworkInterface si alguna vegada calgués per a una investigació de xarxa.
Justificació de les exclusions:
NetworkInterface: 1.280 CI (3,84 USD) per interfícies efímeres que l'ASG crea i destrueix. La seva configuració és sempre la mateixa i ve de la plantilla de llançament. Si calgués investigar la xarxa, hi ha els VPC Flow Logs (03-01) i CloudTrail (05-03).- Instàncies i volums en mode diari: es perd la detecció immediata d'un canvi en una instància concreta. Importa? Les instàncies són bestiar, no mascotes: si una es degrada, l'ASG la reemplaça. Els canvis que importen són a la plantilla de llançament, no a la instància. El compromís és correcte.
El que es perdria retallant més: si calgués baixar d'1,57 USD, la retallada següent seria
required-tags (0,75 USD, gairebé la meitat del total). Es perdria la detecció del forat de
CentroCoste als volums, que al mòdul 11 val molt més de 0,75 USD. No es retalla.
Solució 2
a) Per què no n'hi ha prou amb una regla gestionada.
Hi ha regles gestionades que cobreixen parts:
| Regla gestionada | Què cobreix | Què li falta |
|---|---|---|
rds-snapshot-encrypted |
Instantànies xifrades | No mira l'antiguitat |
rds-snapshots-public-prohibited |
Que no siguin públiques | No mira l'antiguitat |
required-tags |
L'etiqueta Retencion |
No la relaciona amb l'edat |
El que cap no cobreix és la lògica combinada: «més de 90 dies i sense xifrar», «més de 365
dies i sense l'etiqueta Retencion=legal». Config no permet compondre regles gestionades amb
condicions entre elles. Això exigeix una regla pròpia.
b) La regla. Elecció: Lambda, no Guard.
Guard només pot mirar el que hi ha a l'element de configuració. Aquí necessitem calcular l'antiguitat respecte a la data actual, i Guard no té aritmètica de dates contra «ara». A més, convé una activació periòdica que avaluï totes les instantànies, no només les que canvien —una instantània no canvia: simplement envelleix—. Aquest és l'argument decisiu: l'incompliment apareix amb el pas del temps, no amb un canvi de configuració.
"""Regla de Config: instantanies d'RDS segons antiguitat.
Activacio PERIODICA cada 24 h: una instantania no canvia,
pero envelleix, i l'incompliment apareix pel pas del temps.
"""
import json
from datetime import datetime, timezone
import boto3
config = boto3.client("config")
rds = boto3.client("rds")
DIES_XIFRATGE = 90
DIES_ESBORRAT = 365
def edat_en_dies(data):
return (datetime.now(timezone.utc) - data).days
def avaluar_instantania(snap, etiquetes):
identificador = snap["DBSnapshotIdentifier"]
edat = edat_en_dies(snap["SnapshotCreateTime"])
if edat > DIES_ESBORRAT and etiquetes.get("Retencion") != "legal":
return ("NON_COMPLIANT",
f"{edat} dies d'antiguitat i sense Retencion=legal: s'ha d'esborrar")
if edat > DIES_XIFRATGE and not snap.get("Encrypted", False):
return ("NON_COMPLIANT",
f"{edat} dies d'antiguitat i SENSE XIFRAR")
# La comprovacio de publicitat requereix una altra crida.
atributs = rds.describe_db_snapshot_attributes(
DBSnapshotIdentifier=identificador
)["DBSnapshotAttributesResult"]["DBSnapshotAttributes"]
for atribut in atributs:
if atribut["AttributeName"] == "restore" and "all" in atribut["AttributeValues"]:
return "NON_COMPLIANT", f"La instantania es PUBLICA"
return "COMPLIANT", f"{edat} dies, xifrada i privada"
def handler(esdeveniment, context):
token = esdeveniment["resultToken"]
avaluacions = []
ara = datetime.now(timezone.utc)
paginador = rds.get_paginator("describe_db_snapshots")
for pagina in paginador.paginate(SnapshotType="manual"):
for snap in pagina["DBSnapshots"]:
etiquetes = {t["Key"]: t["Value"] for t in snap.get("TagList", [])}
estat, motiu = avaluar_instantania(snap, etiquetes)
avaluacions.append({
"ComplianceResourceType": "AWS::RDS::DBSnapshot",
"ComplianceResourceId": snap["DBSnapshotIdentifier"],
"ComplianceType": estat,
"Annotation": motiu[:256],
"OrderingTimestamp": ara,
})
# put_evaluations accepta com a maxim 100 per crida.
for i in range(0, len(avaluacions), 100):
config.put_evaluations(
Evaluations=avaluacions[i:i + 100],
ResultToken=token,
)
return {"avaluades": len(avaluacions)}Quatre detalls que fan que aquesta funció funcioni en producció i no només a l'exemple:
SnapshotType="manual": les automàtiques les gestiona RDS amb la seva pròpia retenció (02-04) i s'esborren soles. Avaluar-les generaria no conformitats impossibles de remeiar.put_evaluationsen lots de 100: és el límit de l'API. Amb 120 instantànies, una sola crida fallaria.Annotationamb l'edat concreta: qui miri la consola sabrà immediatament de què es tracta.- La comprovació de publicitat fa una crida extra per instantània. Amb 120 instantànies són 120 crides cada 24 hores: acceptable. Amb 10.000, caldria paral·lelitzar o separar en una altra regla.
c) La remediació, i aquí hi ha el criteri.
| Incompliment | Automatitzar? | Per què |
|---|---|---|
| Instantània pública | SÍ, immediat | Afegeix seguretat, és reversible, i una còpia de base de dades pública és una bretxa de dades en curs. AWSConfigRemediation-RevokeRDSDBSnapshotPublicAccess |
| Instantània sense xifrar de més de 90 dies | NO automàtic | «Xifrar» una instantània existent no és possible: cal copiar-la xifrada i esborrar l'original. És una operació amb cost, durada i risc. Es genera un tiquet |
| Instantània de més de 365 dies sense etiqueta | MAI automàtic | És un esborrament. Irreversible. Si la regla o l'etiqueta estan malament, es destrueix l'única còpia d'alguna cosa important |
Aquesta taula és exactament la regla de la lliçó: automatitza el que afegeix seguretat i és reversible; mai el que és destructiu. La instantània pública es tanca sola en minuts; l'esborrament l'aprova una persona.
Per a les dues que no s'automatitzen, la resposta correcta és notificar bé: una regla
d'EventBridge (07-03) que capturi el canvi a no conformitat i enviï a alertas-mercadofresco un
missatge que inclogui l'Annotation de l'avaluació, que és on hi ha l'explicació concreta
(«412 dies d'antiguitat i sense xifrar»). Un avís que només diu «hi ha un recurs no conforme» obliga a
entrar a la consola; un que diu quina instantània i per què es resol des del mòbil.
I una revisió trimestral al calendari de la Marta per decidir què s'esborra, amb la llista al davant.
d) Cost.
Opció periòdica cada 24 hores:
- 120 instantànies × 30 dies = 3.600 avaluacions/mes = 3,60 USD
- Invocacions de Lambda: 30/mes (una per avaluació de la regla, no per instantània) ≈ 0,00 USD
- Crides a l'API d'RDS: gratuïtes
- Total: ~3,60 USD/mes
Opció per canvi de configuració:
- Les instantànies manuals canvien poquíssim: potser 10 CI/mes.
- 10 avaluacions = 0,01 USD
- Total: ~0,01 USD/mes
Però l'opció per canvi NO SERVEIX, i aquesta és la conclusió de l'apartat. L'incompliment aquí apareix amb el pas del temps, no amb un canvi: una instantània creada avui sense xifrar és conforme, i d'aquí a 91 dies deixa de ser-ho sense que hagi canviat res en ella. Una regla per canvi no la tornaria a avaluar mai i la no conformitat no es detectaria mai.
3,60 USD al mes és el preu de detectar incompliments que depenen del temps, i
TwentyFour_Hours ja és la freqüència periòdica més espaiada que admet Config: no hi ha marge per
aquí. L'única palanca real d'estalvi seria emetre una sola avaluació agregada per regla en lloc
d'una per instantània, però llavors la consola diria «la regla no es compleix» sense dir quina de les
120 instantànies en té la culpa, que és justament la dada que cal per actuar. Es paga el detall,
i val la pena.
Solució 3
Què ha passat, amb tota probabilitat.
Les dades apunten de manera inequívoca a un desplegament automatitzat d'infraestructura el diumenge de matinada que va crear recursos sense les propietats obligatòries, i que a més va modificar un bucket existent.
Les pistes, en ordre:
- Diumenge a les 04:17, hora sense activitat humana: és un procés automàtic.
rol-despliegue-infraamb 46 crides d'escriptura en 25 minuts: és un pipeline o una execució d'infraestructura com a codi.- Tres buckets nous sense xifratge ni etiquetes, creats a la mateixa finestra.
- Un bucket existent que va passar de conforme a no conforme exactament a la mateixa hora.
El punt 4 és el més greu i el més revelador: la plantilla no només va crear recursos nous mal configurats, sinó que va redefinir un bucket que ja existia, sobreescrivint-ne el xifratge i les etiquetes amb una definició incompleta. És el patró clàssic d'una plantilla de CloudFormation o Terraform que declara un recurs que ja existia i l'«alinea» amb una especificació pobra.
Confirmació, pas a pas.
1. Veure exactament què va canviar al bucket (això és el que només Config pot donar):
aws configservice get-resource-config-history \
--resource-type AWS::S3::Bucket \
--resource-id mercadofresco-informes-analitica \
--later-time 2026-08-03T00:00:00Z \
--earlier-time 2026-07-30T00:00:00Z \
--profile mercadofresco-dev --region eu-west-1Comparant el CI del dijous amb el del diumenge es veu el diff: serverSideEncryptionConfiguration
va desaparèixer i les etiquetes es van reduir. Això és informació que CloudTrail no té: CloudTrail
registra la crida PutBucketEncryption o la seva absència, però no l'estat resultant complet del
bucket.
2. Veure qui va fer la crida concreta (això és el que només CloudTrail pot donar):
SELECT eventtime, eventname,
split_part(userIdentity.arn, '/', 3) AS sessio,
sourceipaddress, useragent,
json_extract_scalar(requestParameters, '$.bucketName') AS bucket
FROM auditoria_mercadofresco.cloudtrail_mercadofresco
WHERE anio='2026' AND mes='08' AND dia='02'
AND userIdentity.sessionContext.sessionIssuer.userName = 'rol-despliegue-infra'
ORDER BY eventtime;Es busca: el userAgent (cloudformation.amazonaws.com? Terraform/1.7?), el nom de sessió, i
si hi ha un DeleteBucketEncryption explícit o simplement un CreateBucket sobre un bucket existent.
3. Veure tots els recursos afectats alhora, amb la consulta avançada de Config:
aws configservice select-resource-config \
--expression "
SELECT resourceId, resourceName, resourceCreationTime, tags
WHERE resourceType = 'AWS::S3::Bucket'
AND resourceCreationTime > '2026-08-02T00:00:00Z'
" \
--profile mercadofresco-dev --region eu-west-14. Quadre de compliment complet, per veure si hi ha més danys dels que se sabien:
aws configservice get-compliance-details-by-config-rule \
--config-rule-name mercadofresco-etiquetado-obligatorio \
--compliance-types NON_COMPLIANT \
--profile mercadofresco-dev --region eu-west-1Per què CloudTrail tot sol no hauria fet saltar res.
Aquesta és la pregunta central de l'exercici, i hi ha tres raons:
- CloudTrail no avalua. Registra 46 crides d'un rol de desplegament un diumenge. Això és completament normal per a un pipeline programat. No hi ha res anòmal en l'esdeveniment en si.
- L'alarma de 05-03 no hauria saltat. Els filtres de mètriques que vam muntar vigilaven
DeleteBucketEncryptioniPutBucketPolicy, però des d'un rol de desplegament legítim, i probablement senseDeleteBucketEncryptionexplícit: si la plantilla simplement no declara xifratge en crear el bucket, no hi ha cap crida a registrar. L'absència d'una crida no genera un esdeveniment. - CloudTrail no coneix la política de MercadoFresco. No sap que tots els buckets han d'estar xifrats ni que calen cinc etiquetes. Config sí, perquè l'hi hem dit amb regles.
Config detecta l'estat resultant; CloudTrail detecta l'acte. Aquí l'acte era legítim i l' estat resultant no ho era. Aquest és exactament el buit que aquesta lliçó ve a cobrir.
Remediació, en ordre de risc:
| # | Acció | Mode |
|---|---|---|
| 1 | Aturar el pipeline o desactivar-ne l'execució programada | Manual, immediat |
| 2 | Restaurar el xifratge de mercadofresco-informes-analitica |
Remediació manual, verificant |
| 3 | Comprovar si es van pujar objectes sense xifrar entre el diumenge i el dilluns | Manual |
| 4 | Xifrar els tres buckets nous | Remediació manual |
| 5 | Restaurar les etiquetes del bucket afectat | Manual |
| 6 | Decidir què fer amb els tres buckets nous: havien d'existir? | Manual, amb el Luis |
| 7 | Només llavors, reactivar el pipeline amb la plantilla corregida | Manual |
El pas 3 mereix un comentari: els objectes escrits mentre el xifratge per defecte estava desactivat es van desar sense xifrar, i activar-lo ara no els xifra retroactivament. Cal reescriure'ls:
aws s3 cp s3://mercadofresco-informes-analitica/ s3://mercadofresco-informes-analitica/ \
--recursive --sse aws:kms \
--sse-kms-key-id arn:aws:kms:eu-west-1:111122223333:alias/mercadofresco-datos \
--metadata-directive REPLACE \
--profile mercadofresco-devAquest detall es passa per alt constantment i és el que converteix un incident de configuració en un incident de dades.
Els arranjaments de fons, que són la part important:
| Arranjament | Mòdul | Per què |
|---|---|---|
| Corregir la plantilla perquè declari xifratge i etiquetes obligatòries | 09-01 (CloudFormation) / 09-02 (CDK) | La causa arrel. En CDK es poden imposar valors per defecte per a tota l'organització |
Validar la plantilla abans de desplegar amb cfn-guard al pipeline |
08-02 (CodeBuild) | Detectar el problema abans que arribi a producció és sempre millor que remeiar-lo després |
Activar la remediació automàtica de mercadofresco-s3-cifrado |
Aquesta lliçó | Hauria corregit el xifratge en 8 minuts, un diumenge de matinada, sense que ningú no se n'assabentés fins al dilluns |
Política de control de serveis que denegui s3:PutObject sense xifratge |
09-04 (Organizations) | Prevenció dura: ni tan sols es pot escriure sense xifrar |
| Revisió obligatòria de canvis d'infraestructura | 08-04 (CodePipeline) | Un pas d'aprovació manual per a canvis sobre recursos existents |
La lliçó de fons, i mereix subratllar-se perquè és l'argument més fort a favor d'aquest
servei: la mateixa regla de Guard que escrius per a Config es pot executar al pipeline amb
cfn-guard abans del desplegament. Config és la xarxa de seguretat que atrapa el que se't va escapar; la
validació al pipeline és la que evita que s'escapi. Totes dues, amb la mateixa regla escrita un cop.
Aquest és el patró que MercadoFresco adopta, i que es tanca al mòdul 8.
Conclusió
MercadoFresco ja té l'última peça que li faltava. Saps què és la configuració d'un recurs
—els seus ajustos, no les seves dades— i què és un element de configuració: una fotografia completa amb els seus
relationships, la seva supplementaryConfiguration i el seu estat, que Config crea a cada canvi i que
fins i tot enregistra quan el recurs s'esborra. Coneixes la línia temporal, que respon a la pregunta
que es fa cada setmana a operacions: «això funcionava divendres; què ha canviat?».
Tens clara la diferència essencial amb la lliçó anterior: CloudTrail enregistra la crida, Config
enregistra l'estat. CloudTrail diu qui va cridar AuthorizeSecurityGroupIngress; Config diu com
va quedar el grup de seguretat, si compleix, i ho arregla. I saps que Config depèn de CloudTrail per
assabentar-se dels canvis: no competeixen, es donen suport.
Has activat l'enregistrador grabador-mercadofresco amb el seu rol de només lectura, el seu canal cap a
mercadofresco-config-historial i el seu tema d'SNS, amb les dues decisions que valen diners:
allSupported: false amb llista explícita, i recordingFrequency: DAILY per a instàncies i
volums, que és l'optimització més rendible i menys coneguda del servei. I saps que crear no és
engegar: start-configuration-recorder.
Coneixes les 29 regles gestionades que MercadoFresco activa, cadascuna lligada a alguna cosa que vam construir
en un mòdul anterior —s3-bucket-server-side-encryption-enabled per 04-02, restricted-ssh per
03-02, cloudtrail-enabled per 05-03, cw-loggroup-retention-period-check per l'incident de 610
USD de 05-01— i la diferència entre activació per canvi (minuts, però s'avalua a cada canvi) i
periòdica (fins a 24 hores, però cost fix i única opció per a comprovacions de compte).
required-tags t'ha trobat el forat que ningú no veia: els volums EBS creats per l'ASG no
hereten etiquetes, i al mòdul 11 haurien aparegut com a cost sense assignar.
Saps escriure regles pròpies: amb Lambda quan necessites cridar altres API o calcular amb
dates —retornant NOT_APPLICABLE en lloc de COMPLIANT, tractant ResourceDeleted i escrivint
una Annotation útil— i amb Guard, declaratiu, sense runtime, sense cost extra i sense manteniment,
que és el que cal fer servir per defecte quan n'hi ha prou amb mirar l'element de configuració.
I has muntat la remediació automàtica amb documents de Systems Manager, que és el que converteix
Config en una eina operativa: AWS-EnableS3BucketEncryption restaura el xifratge d'un bucket
en vuit minuts sense intervenció humana, RemoveUnrestrictedSourceIngressRules tanca un grup de
seguretat obert, i SetCloudWatchLogGroupRetention posa 30 dies a qualsevol grup de registres
nou. Amb el rol de remediació separat del de Config, amb permisos acotats per prefix i per
etiqueta, i sense AuthorizeSecurityGroupIngress: el rol pot tancar, mai obrir. I amb el
procediment innegociable de quatre fases —detecció, remediació manual, automàtica en desenvolupament,
automàtica en producció— i la regla que ho resumeix tot: automatitza el que afegeix seguretat i és
reversible; mai el que és destructiu ni el que treu disponibilitat.
Coneixes els paquets de conformitat alineats amb CIS, PCI DSS, NIST i RGPD, amb l'advertència que cal repetir sempre: desplegar el paquet de PCI DSS no et fa conforme amb PCI DSS. I el quadre de compliment t'ha donat el resultat que justifica el servei sencer: sis regles no conformes i catorze recursos, entre ells un bucket sense xifrar des del març, un port 22 obert des del maig i el grup de seguretat per defecte amb regles. Catorze problemes que feia mesos que eren allà i que no haurien disparat mai una alarma de CloudWatch ni haurien aparegut en una investigació de CloudTrail, perquè no eren esdeveniments: eren estats.
I tens les consultes avançades, gratuïtes, que inventarien el compte en segons: buckets sense
xifrar, volums sense associar que es paguen cada mes sense servir per a res, recursos sense CentroCoste.
Amb l'agregador per a la vista multicompte que arribarà a 09-04, i el repartiment clar de feina amb
GuardDuty —que detecta intrusions, no configuracions— i Security Hub, que agrega les
troballes de tots.
Tot per uns 6,40 USD al mes, enfront dels 216 USD que costaria exactament la mateixa capacitat de detecció sense les tres decisions de configuració correctes. Aquest factor de trenta- quatre és el resum de per què aquesta lliçó dedica una secció sencera al cost.
Amb això queden respostes les cinc preguntes del mòdul 4. L'avís arriba de debò, els registres estan correlacionats, la comanda de vuit segons té culpable i arranjament, sabem qui va desxifrar la còpia, i ara res no pot desactivar el xifratge d'un bucket sense que salti un avís —i es corregeixi sol en vuit minuts—.
Queda una última peça, i és diferent de tot l'anterior. Config comprova les regles que tu li has
dit. És potent i és exacte, però té un límit evident: no et pot avisar del que no se t'ha
acudit. No sap que tens tres volums EBS orfes costant diners, ni que hi ha una IP
elàstica sense associar que es factura per no fer-se servir, ni que l'asg-mercadofresco-tienda és a punt de
xocar amb una quota de servei que ningú no ha mirat mai, ni que una de les teves instàncies fa dos
mesos que està al 4 % de CPU. Ningú no ha escrit regles per a això, i ningú no les escriurà, perquè per escriure-les
caldria sospitar primer que el problema existeix.
Hi ha un servei que fa precisament aquest repàs: comparar el teu compte amb les bones pràctiques que AWS ha destil·lat de milions de clients, i dir-te el que no havies pensat a preguntar. A la lliçó 05-05, «AWS Trusted Advisor», veurem les seves cinc categories —optimització de costos, rendiment, seguretat, tolerància a errors i límits de servei—, quines comprovacions veus de debò amb el pla de suport Basic i quines no, com suplir el que falta amb el que ja saps, un recorregut comentat per un informe real de l'arquitectura de MercadoFresco, les quotes de servei i el cas concret de l'ASG que no pot passar de quatre instàncies per un límit de vCPU que ningú no havia mirat, i la rutina de revisió mensual que adopta la Marta. I amb ella tancarem el mòdul sencer.
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
