Hem protegit la vora amb cura: xarxa segmentada, balancejador, memòria cau, permisos mínims i un WAF calibrat amb paciència. I mentrestant, la contrasenya de l'usuari app_catalogo de la base de dades alpinashop-pedidos continua exactament on la vam deixar a 02-01: en una variable d'entorn definida dins de l'startup-script de la plantilla d'instància del MIG.
Val la pena enumerar per què això és deute de seguretat, i no una simple falta d'elegància:
- És llegible per qualsevol amb
compute.instances.get. Les metadades d'una instància, inclòs l'script d'arrencada, es llegeixen amb ungcloud compute instances describe. El Dani, que només té rol de lectura en producció, pot veure la contrasenya de producció. - És a l'historial de Git, perquè la plantilla es genera des d'un script versionat. Esborrar-la del fitxer no l'esborra del repositori.
- No es pot rotar sense tornar a desplegar. Canviar la contrasenya exigeix una plantilla nova i una actualització progressiva del MIG. A la pràctica, això significa que no es rota mai.
- Està duplicada. A la plantilla, al
.envdel portàtil del Dani, a l'entorn de desenvolupament, probablement en un missatge de xat de fa vuit mesos. - No deixa rastre. No hi ha manera de saber qui l'ha llegit ni quan.
Aquesta lliçó resol aquest problema i respon a més la pregunta que ve just al darrere: si Google guarda les meves dades, qui les xifra i amb quina clau? Veuràs Secret Manager per als secrets de l'aplicació i Cloud KMS per al material criptogràfic, i entendràs quan té sentit assumir la responsabilitat de gestionar les teves pròpies claus i quan és una complicació que no compra seguretat real.
Avís. Xifratge i gestió de secrets toquen directament obligacions normatives: RGPD, PCI DSS si es processen pagaments, i requisits sectorials de residència de les dades. El que segueix és un model docent tècnicament correcte, però qualsevol disseny destinat a producció amb dades personals o de pagament l'ha de revisar un professional de seguretat i compliment normatiu abans de desplegar-se. Una fallada aquí no es mesura en minuts de caiguda.
Contingut
- El problema concret: la contrasenya d'
app_catalogo - Secret Manager: model de secrets i versions
- Crear els secrets d'AlpinaShop
- Accedir-hi des de l'aplicació Flask
- Permisos per secret: el mínim privilegi aplicat
- Rotació: desactivar en lloc de destruir
- Replicació automàtica davant de regional: residència de les dades
- Integració amb Cloud Run, GKE i Cloud Build
- Xifratge a Google Cloud: què passa per defecte
- La jerarquia de claus: DEK i KEK
- Google-managed, CMEK i CSEK: taula de decisió
- Cloud KMS: clauer, claus i rotació
- HSM i External Key Manager
- Aplicar CMEK al bucket i a Cloud SQL
- Xifratge en trànsit
- Què NO fer mai
- El problema concret: la contrasenya d'
app_catalogo
app_catalogoAixí està avui la plantilla del MIG, i així no ha de quedar-se:
# ANTIPATRO: la contrasenya a les metadades de la instancia
gcloud compute instance-templates create tpl-catalogo-v3 \
--metadata=startup-script='#!/bin/bash
export DB_PASSWORD="Tr3kking!2026" # <-- visible per a tothom
gunicorn --bind 0.0.0.0:8080 app:app'Comprova tu mateix com n'està d'exposada:
gcloud compute instances describe alpinashop-web-1 --zone=europe-west1-b \
--format="value(metadata.items[startup-script])"Aquesta comanda només necessita compute.instances.get, un permís que forma part de roles/compute.viewer i que hem concedit al grup gcp-desarrollo@ en producció (03-04). És a dir: el nostre propi disseny de permisos, curosament construït, se salta completament per culpa d'on està desada la contrasenya.
La destinació és aquesta, i la resta de la lliçó explica cada peça:
flowchart LR
APP["Aplicació Flask al MIG<br/>identitat: sa-catalogo-web"]
SM["Secret Manager<br/>db-password-catalogo"]
KMS["Cloud KMS<br/>xifra el secret en repòs"]
SQL[("Cloud SQL<br/>alpinashop-pedidos")]
AUD["Registres d'auditoria<br/>qui hi ha accedit i quan"]
APP -->|"1. accessSecretVersion<br/>amb la seva identitat"| SM
SM -->|2. desxifra| KMS
SM -->|3. retorna el valor| APP
APP -->|4. connecta| SQL
SM -.->|registra cada accés| AUD
- Secret Manager: model de secrets i versions
Secret Manager guarda cadenes o binaris petits —contrasenyes, claus d'API, certificats, tokens— amb control d'accés per IAM, xifratge en repòs, versionatge i auditoria.
El model té dos nivells, i confondre'ls és la font de gairebé tots els errors:
| Nivell | Què és | Conté |
|---|---|---|
| Secret | El contenidor amb nom i la seva política IAM | Metadades, etiquetes, política de replicació, cap valor |
| Versió | Un valor concret, immutable, numerat des d'1 | La dada real |
Propietats que es deriven d'aquest model:
- Les versions són immutables. No s'"actualitza" un secret: s'afegeix una versió nova. La 1 continua existint.
latestés un àlies mòbil que apunta sempre a la versió habilitada més recent.- Una versió pot estar en tres estats: habilitada (es pot llegir), deshabilitada (existeix però l'accés falla, i és reversible) i destruïda (el material s'esborra de forma irreversible; només en queden les metadades).
- Els permisos es donen sobre el secret, no sobre la versió.
- Crear els secrets d'AlpinaShop
gcloud config set project alpinashop-prod
gcloud services enable secretmanager.googleapis.com
# 1) Contrasenya de la base de dades
gcloud secrets create db-password-catalogo \
--replication-policy=automatic \
--labels=entorno=produccion,equipo=plataforma,aplicacion=catalogo,centro-coste=tienda
# 2) Afegir la primera versio SENSE que quedi a l'historial del shell.
# El guio final significa "llegir de l'entrada estandard".
printf '%s' 'Tr3kking!2026' | gcloud secrets versions add db-password-catalogo --data-file=-
# 3) Clau de la passarel·la de pagament
gcloud secrets create api-key-pasarela-pago \
--replication-policy=automatic \
--labels=entorno=produccion,equipo=plataforma,aplicacion=pagos,centro-coste=tienda
printf '%s' 'sk_live_9f2c...' | gcloud secrets versions add api-key-pasarela-pago --data-file=-Detalls que importen d'aquestes comandes:
--data-file=-ambprintfi sense salt de línia final. Si fas servirecho, afegeixes un\nal valor i la contrasenya que llegeix l'aplicació no és la que et penses. És una fallada clàssica que costa mitja tarda de depuració. Si el secret és en un fitxer,--data-file=fitxeri esborra el fitxer després ambshred -u.- No passis mai el valor per la línia de comandes. Existeix
--data-file, però no un--data: és deliberat. Un valor a la línia de comandes queda a~/.bash_historyi a la llista de processos. - Etiqueta els secrets amb el mateix conveni que la resta de recursos (
entorno,equipo,centro-coste,aplicacion). Serveix per a l'inventari i per a la revisió periòdica.
Operacions habituals:
gcloud secrets list --format="table(name, createTime, labels.aplicacion)"
gcloud secrets versions list db-password-catalogo \
--format="table(name, state, createTime)"
# Llegir el valor (aixo queda registrat a auditoria)
gcloud secrets versions access latest --secret=db-password-catalogo
- Accedir-hi des de l'aplicació Flask
L'aplicació s'autentica amb la identitat de la VM —el compte de servei sa-catalogo-web— sense cap credencial al codi. És el patró que ja vas fer servir amb Cloud Storage a 02-02, aplicat ara als secrets.
# secretos.py — acces a Secret Manager amb memoria cau en memoria
import os
from functools import lru_cache
from google.cloud import secretmanager
PROJECTE = os.environ.get("GOOGLE_CLOUD_PROJECT", "alpinashop-prod")
# El client es car de crear: un per proces.
_client = secretmanager.SecretManagerServiceClient()
@lru_cache(maxsize=32)
def llegir_secret(nom: str, versio: str = "latest") -> str:
"""Retorna el valor d'un secret.
lru_cache evita anar a l'API a cada peticio HTTP: sense ella,
una botiga amb 500 req/s faria 500 crides per segon a
Secret Manager. Aixo es lent, car i a mes topa amb la quota.
El preu de la memoria cau es que un canvi de secret no es veu fins
que es reinicia el proces. Es un compromis ACCEPTABLE i cal
prendre'l conscientment: la rotacio s'acompanya d'un reinici
progressiu del MIG.
"""
ruta = f"projects/{PROJECTE}/secrets/{nom}/versions/{versio}"
resposta = _client.access_secret_version(request={"name": ruta})
return resposta.payload.data.decode("UTF-8")# app.py — construccio de la cadena de connexio a l'arrencada
from secretos import llegir_secret
def crear_pool_connexions():
password = llegir_secret("db-password-catalogo")
return crear_pool(
usuari="app_catalogo",
password=password,
host="10.10.1.5", # IP privada, 03-01
base_dades="tienda",
)Tres decisions de disseny explícites en aquest codi:
- Es llegeix a l'arrencada, no a cada petició. El cost i la latència d'una crida per petició són inacceptables.
- Es fa servir
latest, cosa que fa que un reinici reculli automàticament la versió nova després d'una rotació. L'alternativa —fixar la versió3— és més determinista però obliga a desplegar codi per rotar. Per a AlpinaShop,latestés l'elecció correcta; en un sistema on un secret equivocat sigui catastròfic, la versió fixa té el seu argument. - El valor no es registra mai. Ni en un
print, ni en un registre de depuració, ni en un missatge d'excepció. Si el valor arriba a Cloud Logging (06-06), l'has tornat a exposar, ara en un lloc que a més es conserva i s'exporta.
- Permisos per secret: el mínim privilegi aplicat
Aquí s'aplica de forma directa el que has après a 03-04. Els rols rellevants:
| Rol | Permet | Per a qui |
|---|---|---|
roles/secretmanager.secretAccessor |
Llegir el valor de les versions | L'aplicació. Res més |
roles/secretmanager.viewer |
Veure que el secret existeix i les seves metadades, sense llegir-lo | Auditoria, inventari |
roles/secretmanager.secretVersionAdder |
Afegir versions noves, sense poder llegir-les | El procés de rotació |
roles/secretmanager.secretVersionManager |
Habilitar, deshabilitar i destruir versions | Operació |
roles/secretmanager.admin |
Tot, inclòs crear i esborrar secrets | Només gcp-infra@, i amb moderació |
SA_WEB="[email protected]"
# L'aplicacio nomes pot LLEGIR, i nomes AQUEST secret
gcloud secrets add-iam-policy-binding db-password-catalogo \
--member="serviceAccount:$SA_WEB" \
--role="roles/secretmanager.secretAccessor"
gcloud secrets add-iam-policy-binding api-key-pasarela-pago \
--member="serviceAccount:$SA_WEB" \
--role="roles/secretmanager.secretAccessor"
# Auditoria: veu que existeixen, no els llegeix
gcloud secrets add-iam-policy-binding db-password-catalogo \
--member="group:[email protected]" \
--role="roles/secretmanager.viewer"
# Verificar qui pot llegir cada secret
gcloud secrets get-iam-policy db-password-catalogo --format=yamlLa regla que no s'ha de trencar: els permisos es concedeixen a nivell de secret, mai de projecte. Un roles/secretmanager.secretAccessor sobre alpinashop-prod donaria accés a tots els secrets presents i futurs, inclosa la clau de la passarel·la de pagament que es creï el mes que ve. És exactament el mateix raonament que vam aplicar amb el bucket i amb les condicions d'IAM.
Un detall que sorprèn i que convé saber: l'accés a un secret queda registrat als registres d'auditoria d'accés a dades, però aquests registres s'han d'activar explícitament perquè no vénen habilitats per defecte. Sense ells no sabràs qui va llegir què. La configuració dels registres d'auditoria es tracta a 07-07; per a un secret de producció, activa'ls.
- Rotació: desactivar en lloc de destruir
Rotar és substituir el valor per un altre de nou. El procediment correcte té un pas que gairebé tothom se salta, i és el que evita el tall de servei.
# PAS 1 — Crear la credencial nova al sistema de desti,
# convivint amb la vella
gcloud sql users set-password app_catalogo \
--instance=alpinashop-pedidos --password="$NUEVA"
# PAS 2 — Afegir la versio nova al secret (la vella continua viva)
printf '%s' "$NUEVA" | gcloud secrets versions add db-password-catalogo --data-file=-
# PAS 3 — Desplegar: reinici progressiu del MIG perque els processos
# rellegeixin 'latest'. Sense tall, gracies al drenatge de connexions (03-02).
gcloud compute instance-groups managed rolling-action restart alpinashop-web-mig \
--region=europe-west1 --max-unavailable=1
# PAS 4 — Verificar que ningu no fa servir ja la versio anterior, i DESACTIVAR-LA
gcloud secrets versions disable 1 --secret=db-password-catalogo
# PAS 5 — Nomes despres d'un periode de gracia (dies), destruir
gcloud secrets versions destroy 1 --secret=db-password-catalogoEl pas 4 és la clau de tota la lliçó en matèria d'operació. disable és reversible: si alguna cosa es trenca, un gcloud secrets versions enable 1 retorna el servei en segons. destroy és irreversible. La regla: deshabilitar sempre primer, destruir molt després, i mai les dues coses el mateix dia.
Secret Manager pot a més recordar-te que toca rotar:
gcloud secrets update db-password-catalogo \
--next-rotation-time="2026-11-01T03:00:00Z" \
--rotation-period="90d" \
--add-topics="projects/alpinashop-prod/topics/rotacion-secretos"Aquí hi ha un matís que es malinterpreta molt sovint: Secret Manager no rota res. Publica un missatge en un tema de Pub/Sub quan arriba la data. Qui rota és el teu automatisme —una Cloud Function subscrita a aquest tema (06-03) que genera la contrasenya, l'aplica a Cloud SQL, afegeix la versió i llança el reinici del MIG—. La rotació completament automàtica és un projecte en si mateix; el recordatori amb Pub/Sub i un procediment escrit és el mínim exigible.
També es pot posar caducitat a un secret, útil per a credencials temporals:
- Replicació automàtica davant de regional: residència de les dades
En crear un secret es tria on s'emmagatzema, i la decisió és irreversible.
| Política | On viu | Avantatges | Quan |
|---|---|---|---|
automatic |
Google decideix, replicat globalment | Màxima disponibilitat, sense decisions | Per defecte, tret de requisit contrari |
user-managed |
A les regions que tu indiquis | Compleix requisits de residència | Quan la dada no pot sortir d'una zona geogràfica |
# Secret restringit a Europa, amb dues regions per tolerar la fallada d'una
gcloud secrets create api-key-pasarela-pago-eu \
--replication-policy=user-managed \
--locations=europe-west1,europe-west4Existeix a més la variant de secrets regionals, creats amb --location=europe-west1, que viuen íntegrament al pla de control regional i ofereixen l'aïllament més estricte. S'hi accedeix amb un punt final regional (secretmanager.europe-west1.rep.googleapis.com), cosa que cal tenir en compte al codi.
Per a AlpinaShop, la facturació i la clientela de la qual són europees, l'elecció raonable és user-managed amb regions europees per als secrets lligats a dades personals o de pagament, i automatic per a la resta. Quina de les dues exigeix el marc normatiu aplicable és una pregunta per al responsable de compliment normatiu, no per a l'equip de plataforma.
- Integració amb Cloud Run, GKE i Cloud Build
Fora de les VM, la integració és encara més neta: la plataforma injecta el secret i el teu codi ni tan sols crida l'API.
Cloud Run (que serà la destinació del catàleg segons DA-001, a 07-02) ofereix les dues formes:
# Com a variable d'entorn: comode
gcloud run deploy catalogo \
--image=europe-west1-docker.pkg.dev/alpinashop-prod/alpinashop/catalogo:1.4.0 \
--region=europe-west1 \
--service-account=sa-catalogo-web@alpinashop-prod.iam.gserviceaccount.com \
--set-secrets=DB_PASSWORD=db-password-catalogo:latest
# Com a fitxer muntat: mes segur
gcloud run deploy catalogo \
--image=europe-west1-docker.pkg.dev/alpinashop-prod/alpinashop/catalogo:1.4.0 \
--region=europe-west1 \
--service-account=sa-catalogo-web@alpinashop-prod.iam.gserviceaccount.com \
--set-secrets=/secretos/db-password=db-password-catalogo:latest| Variable d'entorn | Fitxer muntat | |
|---|---|---|
| Comoditat | Alta: os.environ["DB_PASSWORD"] |
Requereix llegir un fitxer |
| Visibilitat accidental | Alta: apareix en bolcats d'entorn, en traces d'excepció de molts frameworks i en eines de depuració | Baixa |
| Actualització sense tornar a desplegar | No, amb :latest es fixa en desplegar |
Sí: fent servir :latest, el fitxer s'actualitza |
| Recomanació | Acceptable per a secrets poc crítics | Preferible per a contrasenyes i claus de pagament |
GKE Autopilot (el clúster alpinashop-cluster, namespace tienda) fa servir el complement de Secret Manager amb el controlador CSI, que munta el secret com a volum:
# secret-provider.yaml — el secret es munta, no es copia a un Secret de Kubernetes
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: alpinashop-secretos
namespace: tienda
spec:
provider: gcp
parameters:
secrets: |
- resourceName: "projects/alpinashop-prod/secrets/db-password-catalogo/versions/latest"
path: "db-password"# Al Deployment: es munta com a fitxer a /var/secretos/db-password
volumes:
- name: secretos
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "alpinashop-secretos"Això tanca per fi l'advertiment que vam deixar a 02-05: un Secret de Kubernetes està codificat en base64, que no és xifratge. Qualsevol amb permís de lectura al namespace el descodifica en un segon. Amb el controlador CSI, el valor no existeix com a objecte de Kubernetes: el porta Secret Manager, autenticat amb Workload Identity, i només apareix al sistema de fitxers del pod.
Cloud Build (06-01) permet fer servir secrets al pipeline sense escriure'ls al fitxer de configuració:
# cloudbuild.yaml
availableSecrets:
secretManager:
- versionName: projects/alpinashop-prod/secrets/api-key-pasarela-pago/versions/latest
env: 'API_KEY_PAGO'
steps:
- name: python:3.12
entrypoint: bash
secretEnv: ['API_KEY_PAGO']
args:
- -c
- |
# Disponible com a $$API_KEY_PAGO. NO l'imprimeixis MAI:
# els registres de Cloud Build son llegibles per tot l'equip.
pytest tests/integracion
- Xifratge a Google Cloud: què passa per defecte
Canviem de tema, del secret d'aplicació al xifratge de les dades.
El primer, per treure ansietat innecessària: totes les dades en repòs de Google Cloud estan xifrades per defecte, sempre, sense que facis res i sense cost addicional. Cloud Storage, discos persistents, Cloud SQL, BigQuery, Firestore: tot. No hi ha una casella d'"activar xifratge" perquè no hi ha manera de desactivar-lo.
Per tant, la pregunta correcta no és "estan xifrades les meves dades?" sinó "qui controla la clau?". I aquesta pregunta rarament la respon la seguretat tècnica: la respon el compliment normatiu, el sector i, de vegades, el contracte amb un client gran.
- La jerarquia de claus: DEK i KEK
Entendre això explica de cop per què CMEK és barat d'activar i per què rotar una clau no reescriu petabytes.
flowchart TD
D["Les teves dades<br/>trossejades en fragments"]
DEK["DEK — Data Encryption Key<br/>una per fragment, AES-256"]
KEK["KEK — Key Encryption Key<br/>viu a Cloud KMS, no en surt mai"]
ROOT["Magatzem arrel de claus de Google<br/>o la teva clau CMEK"]
D -->|xifrat amb| DEK
DEK -->|"embolcallada (wrapped) per"| KEK
KEK -->|protegida per| ROOT
El mecanisme, pas a pas:
- Les dades es trossegen en fragments i cada fragment es xifra amb una DEK pròpia i diferent.
- La DEK no es desa en clar: es xifra ("embolcalla") amb una KEK i s'emmagatzema embolcallada juntament amb el fragment.
- La KEK viu a Cloud KMS i no en surt mai. Per desxifrar, el servei envia la DEK embolcallada a KMS, que la desembolcalla i la retorna; la DEK en clar viu en memòria el mínim imprescindible.
Conseqüències que responen preguntes molt freqüents:
- Rotar la KEK és instantani i no reescriu ni un byte de dades. Només canvia la clau amb la qual s'embolcallen les DEK noves; les antigues se segueixen desembolcallant amb la versió antiga, que es conserva.
- Revocar l'accés a la KEK inutilitza les dades immediatament. Sense KEK no hi ha DEK, i sense DEK no hi ha dades. Això és alhora la garantia més potent de CMEK i el seu perill operatiu més gran.
- CMEK és substituir la KEK, no xifrar tu les dades. Per això activar-lo té un cost computacional menyspreable.
- Google-managed, CMEK i CSEK: taula de decisió
| Google-managed (per defecte) | CMEK (claus gestionades pel client) | CSEK (claus proporcionades pel client) | |
|---|---|---|---|
| Qui crea la clau | Tu, a Cloud KMS | Tu, fora de Google | |
| On viu | Infraestructura de Google | Cloud KMS, al teu projecte | Enlloc de Google: l'envies a cada petició |
| La pots rotar | No la veus | Sí, manual o automàtica | Tu t'ho munteges |
| La pots revocar | No | Sí: inutilitza les dades a l'instant | Deixant d'enviar-la |
| Auditoria d'ús de la clau | No | Sí, cada operació als registres | No |
| Si la perds | No aplica | Es pot recuperar mentre estigui programada per a destrucció | Les dades es perden per sempre |
| Serveis compatibles | Tots | La majoria dels importants | Només Cloud Storage i discos de Compute Engine |
| Cost | 0 | Cost de KMS: baix | 0, però altíssim cost operatiu |
| Complexitat | Cap | Mitjana | Alta |
Com decidir, sense misticisme:
- Google-managed cobreix bé la immensa majoria dels casos. Si ningú no t'ha demanat el contrari, això és el correcte i no és "menys segur".
- CMEK quan necessites una d'aquestes tres coses: poder revocar l'accés a les dades de forma unilateral, auditar cada ús de la clau, o complir un requisit normatiu o contractual que ho exigeixi explícitament. Afegeix un mode de fallada nou —si la clau no està disponible, el servei no arrenca— i això cal assumir-ho conscientment.
- CSEK és gairebé sempre la resposta equivocada. Assumeixes la custòdia, la rotació i la disponibilitat de la clau, i un error significa pèrdua definitiva de dades. Existeix per a requisits molt concrets on la clau no pot residir al núvol sota cap circumstància.
Per a AlpinaShop, la decisió raonada: CMEK a alpinashop-catalogo i a la base de dades de comandes, perquè contenen dades de clients i l'empresa vol poder demostrar control de la clau davant d'una auditoria; Google-managed a alpinashop-dev, on no hi ha dades reals i afegir un mode de fallada no compensa.
- Cloud KMS: clauer, claus i rotació
La jerarquia de KMS és: projecte → ubicació → clauer (keyring) → clau → versions de clau.
gcloud services enable cloudkms.googleapis.com
# El clauer agrupa claus i NO ES POT ESBORRAR. Tria be el nom i la ubicacio.
gcloud kms keyrings create alpinashop-keyring --location=europe-west1
# Clau simetrica amb rotacio automatica cada 90 dies
gcloud kms keys create clave-catalogo \
--location=europe-west1 \
--keyring=alpinashop-keyring \
--purpose=encryption \
--rotation-period=90d \
--next-rotation-time=2026-11-01T03:00:00Z \
--protection-level=software
gcloud kms keys create clave-pedidos \
--location=europe-west1 \
--keyring=alpinashop-keyring \
--purpose=encryption \
--rotation-period=90d \
--next-rotation-time=2026-11-01T03:00:00Z
gcloud kms keys versions list --key=clave-catalogo \
--keyring=alpinashop-keyring --location=europe-west1Quatre coses que cal saber de KMS i que no són evidents:
- La ubicació de la clau ha de ser compatible amb la del recurs. Una clau a
europe-west1per a un bucket aeurope-west1: correcte. Per a un bucket multiregióEUcal una clau a la ubicacióeurope. Si no coincideixen, l'operació falla amb un error poc clar. - Els clauers i les claus no es poden esborrar. Mai. Només se'n destrueixen les versions. Això és deliberat: evita que un esborrat accidental deixi dades irrecuperables. Conseqüència pràctica: pensa la nomenclatura abans de crear, perquè viurà per sempre.
- Destruir una versió de clau té un període de gràcia, 30 dies per defecte, durant el qual es pot restaurar. És la xarxa de seguretat que impedeix que un error es converteixi en una catàstrofe.
- La rotació automàtica no torna a xifrar res. Crea una versió nova que passa a ser la primària per a les operacions futures. Les versions antigues es conserven habilitades per poder desxifrar el que ja està xifrat.
Permisos, un altre cop amb criteri de mínim privilegi:
| Rol | Permet |
|---|---|
roles/cloudkms.cryptoKeyEncrypterDecrypter |
Xifrar i desxifrar amb la clau. És el que necessiten els agents de servei |
roles/cloudkms.cryptoKeyEncrypter |
Només xifrar |
roles/cloudkms.viewer |
Veure metadades, sense fer-la servir |
roles/cloudkms.admin |
Gestionar claus. Mai a qui també accedeix a les dades |
Aquesta última línia és separació de funcions aplicada al xifratge: qui administra les claus no ha de ser qui accedeix a les dades xifrades, perquè en aquest cas el xifratge no protegeix de res davant d'aquesta persona.
KMS serveix a més per xifrar dades petites directament:
echo -n "dada sensible" | gcloud kms encrypt \
--location=europe-west1 --keyring=alpinashop-keyring --key=clave-catalogo \
--plaintext-file=- --ciphertext-file=cifrado.bin
gcloud kms decrypt \
--location=europe-west1 --keyring=alpinashop-keyring --key=clave-catalogo \
--ciphertext-file=cifrado.bin --plaintext-file=-Encara que per a contrasenyes i claus d'API, Secret Manager és l'eina adequada, no KMS. KMS és per a claus; Secret Manager és per a secrets. Internament, Secret Manager ja fa servir KMS.
- HSM i External Key Manager
El nivell de protecció determina on viu físicament el material de la clau:
| Nivell | On resideix la clau | Certificació | Cost relatiu | Quan |
|---|---|---|---|---|
SOFTWARE |
A la infraestructura de Google | — | Base | Per defecte |
HSM |
Mòdul de maquinari dedicat | FIPS 140-2 nivell 3 | ~10-40× per versió de clau | Requisit normatiu explícit |
EXTERNAL |
Fora de Google, al teu proveïdor d'EKM | Segons el proveïdor | Alt + cost del proveïdor | Sobirania de les dades, requisit contractual |
gcloud kms keys create clave-pagos-hsm \
--location=europe-west1 --keyring=alpinashop-keyring \
--purpose=encryption --protection-level=hsmExternal Key Manager (EKM) és el cas extrem: la clau viu en un gestor extern (Thales, Fortanix, Equinix i similars) i Google crida aquest sistema per a cada operació criptogràfica. Si talles l'accés, Google no pot desxifrar les teves dades, ni tan sols si volgués. És la resposta tècnica a "vull poder demostrar que ni el proveïdor de núvol pot llegir les meves dades".
El preu d'aquesta garantia és alt i cal dir-ho clar: afegeixes una dependència externa al camí crític d'accés a les teves dades. Si l'EKM no respon, els teus serveis no arrenquen. Per a una pime com AlpinaShop, SOFTWARE amb CMEK és l'elecció proporcionada; HSM només si la passarel·la de pagament o una auditoria PCI ho exigeixen per escrit.
- Aplicar CMEK al bucket i a Cloud SQL
Aquí apareix el concepte que més gent encalla: l'agent de servei. Quan Cloud Storage xifra un objecte amb la teva clau, qui crida KMS no ets tu: és un compte de servei intern del servei, gestionat per Google, que ha de tenir permís sobre la teva clau.
Bucket alpinashop-catalogo:
PROYECTO_NUM=$(gcloud projects describe alpinashop-prod --format="value(projectNumber)")
CLAVE="projects/alpinashop-prod/locations/europe-west1/keyRings/alpinashop-keyring/cryptoKeys/clave-catalogo"
# 1) Obtenir l'agent de servei de Cloud Storage del projecte
AGENTE_GCS=$(gcloud storage service-agent --project=alpinashop-prod)
echo "$AGENTE_GCS" # service-<NUM>@gs-project-accounts.iam.gserviceaccount.com
# 2) Donar-li permis sobre la clau (i NOMES sobre aquesta clau)
gcloud kms keys add-iam-policy-binding clave-catalogo \
--location=europe-west1 --keyring=alpinashop-keyring \
--member="serviceAccount:$AGENTE_GCS" \
--role="roles/cloudkms.cryptoKeyEncrypterDecrypter"
# 3) Establir la clau per defecte del bucket
gcloud storage buckets update gs://alpinashop-catalogo \
--default-encryption-key="$CLAVE"
gcloud storage buckets describe gs://alpinashop-catalogo \
--format="value(default_kms_key)"Un matís essencial: això només afecta els objectes nous. Els 60 GB ja pujats continuen xifrats amb la clau de Google. Per migrar-los cal reescriure'ls:
# Reescriu els objectes existents amb la clau nova.
# En 60 GB aixo triga i genera operacions de classe A: fes-ho per lots i fora d'hora punta.
gcloud storage objects update "gs://alpinashop-catalogo/productos/**" \
--encryption-key="$CLAVE"Cloud SQL alpinashop-pedidos: aquí hi ha una restricció que canvia el pla de treball i que convé saber abans de prometre res.
CMEK a Cloud SQL només es pot establir en crear la instància. No es pot afegir a una instància existent. Migrar
alpinashop-pedidosa CMEK significa crear una instància nova i migrar les dades, amb la finestra de manteniment que això implica.
AGENTE_SQL="service-${PROYECTO_NUM}@gcp-sa-cloud-sql.iam.gserviceaccount.com"
gcloud kms keys add-iam-policy-binding clave-pedidos \
--location=europe-west1 --keyring=alpinashop-keyring \
--member="serviceAccount:$AGENTE_SQL" \
--role="roles/cloudkms.cryptoKeyEncrypterDecrypter"
# Instancia NOVA amb CMEK des del primer moment
gcloud sql instances create alpinashop-pedidos-cmek \
--database-version=POSTGRES_16 \
--region=europe-west1 \
--availability-type=REGIONAL \
--disk-encryption-key="projects/alpinashop-prod/locations/europe-west1/keyRings/alpinashop-keyring/cryptoKeys/clave-pedidos"La migració es faria amb les eines de 02-03: còpia, restauració a la instància nova, sincronització i canvi de la cadena de connexió. La decisió d'AlpinaShop és fer-ho fora de la campanya de tardor, no abans.
I l'avís operatiu que tanca l'apartat, perquè és el risc real de CMEK:
Si deshabilites o destrueixes la versió de la clau, el bucket deixa de servir objectes i la base de dades deixa d'arrencar, de forma immediata. No és un avís teòric: és exactament el comportament dissenyat. Abans de tocar una clau en producció, comprova amb
gcloud logging readquè l'està fent servir, i tingues un procediment escrit de recuperació.
- Xifratge en trànsit
Menys configurable, però convé conèixer el mapa complet:
| Trajecte | Com es xifra | Configures alguna cosa? |
|---|---|---|
| Client → balancejador | TLS amb el teu certificat | Sí: certificats i política SSL, a 03-07 |
| Balancejador → backend | TLS o xarxa privada de Google | Opcional: HTTPS cap al backend |
| Entre serveis de Google | ALTS, protocol propi d'autenticació i xifratge | No |
| Entre centres de dades de Google | Xifratge a nivell d'enllaç i d'aplicació | No |
| Aplicació → Cloud SQL | TLS, i amb l'Auth Proxy a més autenticació IAM (02-03) | Sí: fes servir l'Auth Proxy |
| Aplicació → APIs de Google | TLS 1.2 o superior | No |
El punt que sí que depèn de tu és el primer, i és el tema de la lliçó següent. El segon també mereix una decisió: el trànsit entre el balancejador i el MIG viatja per la xarxa privada de Google dins d'alpinashop-vpc, cosa que és raonable, però per a dades de pagament la pràctica recomanada és xifrar també aquest tram configurant el servei de backend amb protocol HTTPS.
- Què NO fer mai
Una llista curta, sense matisos, perquè cada punt ha causat una bretxa real en alguna empresa:
- Secrets a Git. Ni en un
.env, ni en unconfig.py, ni en unterraform.tfvars, ni en un fitxer de proves. Esborrar-los no n'hi ha prou: queden a l'historial. Si passa, cal rotar la credencial, no només reescriure l'historial. Fes servirgit-secretso l'escaneig de secrets de la teva plataforma per impedir-ho d'entrada. - Secrets en imatges de contenidor. Un
ENV DB_PASSWORD=...o un fitxer copiat alDockerfilequeden a la capa de la imatge i són llegibles per qualsevol que la descarregui d'europe-west1-docker.pkg.dev/alpinashop-prod/alpinashop/catalogo. - Secrets a metadades o variables d'instància. El problema amb què va començar aquesta lliçó.
- Secrets als registres. Una excepció que imprimeix la cadena de connexió completa deixa la contrasenya a Cloud Logging, on es conserva i de vegades s'exporta a BigQuery.
- Secrets en Secrets de Kubernetes sense xifratge addicional. Base64 no és xifratge.
- Secrets per xat o correu. Queden indexats i sincronitzats en dispositius que no controles.
- La mateixa contrasenya en desenvolupament i en producció. L'entorn de desenvolupament té permisos més laxos per disseny; comprometre'l no ha de comprometre producció.
- Claus JSON de comptes de servei descarregades (03-04). Són secrets que no caduquen.
Errors habituals i consells
- Fer servir
echoen lloc deprintfen crear una versió. Afegeix un salt de línia al valor i l'autenticació falla amb un missatge que no ajuda. - Concedir
secretAccessora nivell de projecte. Dona accés a tots els secrets, inclosos els futurs. Sempre a nivell de secret. - Llegir el secret a cada petició HTTP. Latència, cost i quota. Desa'l en memòria cau al procés i accepta conscientment que la rotació exigeix reiniciar.
- Destruir una versió sense haver-la deshabilitat abans.
disableés reversible;destroyno. Mai les dues coses el mateix dia. - Creure que Secret Manager rota els secrets. Només avisa per Pub/Sub. La rotació la programes tu.
- Triar la política de replicació sense pensar. És irreversible i pot tenir implicacions de residència de les dades.
- Registrar el valor del secret. Un
printde depuració el porta a Cloud Logging, que es conserva i s'exporta. - Oblidar l'agent de servei en activar CMEK. L'error és un permís denegat sobre la clau, no sobre el bucket, i despista molt.
- Esperar que CMEK xifri el que ja existeix. Només s'aplica a les dades noves; l'anterior s'ha de reescriure.
- Prometre CMEK en una instància de Cloud SQL existent. Només es pot en crear-la; implica migració.
- Desactivar una versió de clau en producció "per provar". El bucket deixa de servir i la base de dades deixa d'arrencar a l'instant.
- Confondre KMS amb Secret Manager. KMS gestiona claus; Secret Manager gestiona secrets. Per a una contrasenya, Secret Manager.
- Posar claus en HSM per precaució. Costa bastant més per versió de clau i només aporta si hi ha un requisit normatiu concret.
- Consell: separa qui administra les claus de qui accedeix a les dades. Sense aquesta separació, el xifratge no protegeix de ningú rellevant.
- Consell: anomena els secrets per la seva funció, no pel seu valor.
db-password-catalogo, nopassword-prod-2026.
Exercicis
Exercici 1 — Treure la contrasenya de la plantilla del MIG
Escriu el pla complet per eliminar la contrasenya de l'startup-script de tpl-catalogo-v3 sense tallar el servei: comandes, canvis al codi, permisos, ordre de les operacions i verificació. Inclou què fer amb la contrasenya actual, que fa vuit mesos que està exposada a les metadades i a l'historial de Git.
Exercici 2 — Decidir el model de xifratge
Per a cada conjunt de dades d'AlpinaShop, decideix entre Google-managed, CMEK o CSEK, i justifica-ho en dues línies:
- Els 60 GB d'imatges de producte a
alpinashop-catalogo. - La base de dades
alpinashop-pedidos, amb noms, adreces i últims quatre dígits de targeta. - Les exportacions CSV per a la Lucía a
gs://alpinashop-catalogo/exportaciones/. - Els discos de les instàncies del MIG, que només contenen el codi de l'aplicació.
- Una còpia dels contractes signats amb proveïdors, que per contracte "no pot ser accessible pel proveïdor de núvol".
Exercici 3 — Un incident de secret exposat
Un dilluns al matí, l'escaneig de secrets del repositori avisa: la clau sk_live_... de la passarel·la de pagament és en un commit de fa tres setmanes, en un fitxer de proves d'integració. El repositori és privat, amb accés per a les sis persones de l'equip tècnic i dos col·laboradors externs.
Escriu el pla de resposta ordenat per prioritat, i les mesures perquè no torni a passar.
Solucions
Solució 1
Ordre d'operacions, sense tall de servei:
# PAS 0 — La contrasenya actual esta compromesa. Es ROTA, no es reutilitza.
NUEVA=$(openssl rand -base64 32)
gcloud sql users set-password app_catalogo \
--instance=alpinashop-pedidos --password="$NUEVA"
# PAS 1 — Crear el secret amb el valor NOU
gcloud secrets create db-password-catalogo \
--replication-policy=user-managed --locations=europe-west1,europe-west4 \
--labels=entorno=produccion,equipo=plataforma,aplicacion=catalogo
printf '%s' "$NUEVA" | gcloud secrets versions add db-password-catalogo --data-file=-
unset NUEVA
# PAS 2 — Permis, nomes a la identitat de l'aplicacio i nomes sobre aquest secret
gcloud secrets add-iam-policy-binding db-password-catalogo \
--member="serviceAccount:[email protected]" \
--role="roles/secretmanager.secretAccessor"PAS 3 — Canvi al codi: l'aplicació passa a fer servir el mòdul secretos.py de l'apartat 4 i deixa de llegir os.environ["DB_PASSWORD"]. És important que l'arrencada falli de forma sorollosa si no pot llegir el secret, en lloc de continuar amb un valor buit.
# PAS 4 — Plantilla nova, SENSE contrasenya i amb el compte de servei correcte
gcloud compute instance-templates create tpl-catalogo-v4 \
--service-account=sa-catalogo-web@alpinashop-prod.iam.gserviceaccount.com \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--metadata-from-file=startup-script=startup-sin-secretos.sh \
--tags=web-catalogo
# PAS 5 — Actualitzacio progressiva, sense tall (02-01 i 03-02)
gcloud compute instance-groups managed rolling-action start-update alpinashop-web-mig \
--region=europe-west1 \
--version=template=tpl-catalogo-v4 \
--max-surge=2 --max-unavailable=0
# PAS 6 — Verificar i netejar
gcloud compute instances describe alpinashop-web-1 --zone=europe-west1-b \
--format="value(metadata.items[startup-script])" | grep -i password || echo "Net"
gcloud compute instance-templates delete tpl-catalogo-v3 --quietQuè fer amb la contrasenya vella. Va estar vuit mesos llegible per a qualsevol amb compute.viewer i va quedar a l'historial de Git. Es considera compromesa: rotar-la és obligatori i és el pas 0, no l'últim. Reescriure l'historial de Git és recomanable però secundari; el que anul·la el risc és que el valor ja no serveixi per a res. Addicionalment, convé revisar els registres d'accés a Cloud SQL del període per si hi hagués connexions des d'orígens inesperats.
Solució 2
- Imatges de producte → Google-managed, o CMEK si es busca coherència. No són dades personals ni confidencials: són fotos d'un catàleg públic. Google-managed és suficient. En el cas d'AlpinaShop es va aplicar CMEK per homogeneïtat de política i per poder demostrar control davant d'una auditoria, cosa que és un argument vàlid sempre que s'assumeixi el mode de fallada afegit.
alpinashop-pedidos→ CMEK, sens dubte. Conté dades personals subjectes a l'RGPD i fragments de dades de targeta. Aquí la capacitat de revocar i d'auditar l'ús de la clau és exactament el que es demana en una auditoria. Amb la salvetat operativa coneguda: exigeix crear una instància nova i migrar.- Exportacions CSV → CMEK, la mateixa clau que les comandes. Són un extracte de les mateixes dades personals. Seria incoherent protegir l'origen i no la còpia; de fet, les exportacions solen ser el punt més feble de la cadena.
- Discos del MIG → Google-managed. Només contenen codi, que a més és a Artifact Registry i a Git. CMEK aquí només afegiria un mode de fallada —si la clau falla, les instàncies no arrenquen— sense protegir res que no sigui ja públic internament.
- Contractes amb la clàusula d'inaccessibilitat → EKM (
EXTERNAL), o replantejar el requisit. És exactament el cas per al qual existeix External Key Manager: la clau viu fora de Google i sense ella Google no pot desxifrar. CSEK seria tècnicament possible a Cloud Storage, però la custòdia manual de la clau és massa fràgil per a un requisit contractual. L'alternativa honesta és discutir amb el proveïdor si el requisit se satisfà amb CMEK més registres d'accés, que és bastant més operable.
Solució 3
Prioritat 1 — Invalidar la credencial (minuts, no hores).
# 1) Al panell de la passarel·la de pagament: revocar sk_live_... ARA.
# Mentre existeixi, el repositori, les seves copies i els portatils de vuit
# persones la contenen. Reescriure l'historial NO la invalida.
# 2) Generar la clau nova i desar-la on ha de ser
printf '%s' "$CLAVE_NUEVA" | \
gcloud secrets versions add api-key-pasarela-pago --data-file=-
# 3) Reinici progressiu perque els processos rellegeixin 'latest'
gcloud compute instance-groups managed rolling-action restart alpinashop-web-mig \
--region=europe-west1 --max-unavailable=1Prioritat 2 — Avaluar l'impacte. Revisar al panell de la passarel·la les operacions de les últimes tres setmanes buscant cobraments, reemborsaments o consultes des d'orígens no habituals. Si hi va haver ús indegut, hi ha obligacions de notificació que depenen del marc aplicable: això ho decideix el responsable de compliment normatiu, no l'equip tècnic.
Prioritat 3 — Netejar. Eliminar el secret de l'historial de Git (git filter-repo o equivalent), forçar l'actualització de totes les còpies de l'equip i comprovar que no ha quedat en artefactes derivats: imatges de contenidor a Artifact Registry, registres de Cloud Build, exportacions de registres.
Prioritat 4 — Que no torni a passar.
| Mesura | Com |
|---|---|
| Escaneig previ al commit | git-secrets o gitleaks com a hook, més l'escaneig de secrets del proveïdor del repositori |
| Escaneig al pipeline | Un pas de Cloud Build que falla si detecta patrons de credencial (06-01) |
| Secrets a les proves | Les proves d'integració llegeixen de Secret Manager amb una credencial de proves, mai sk_live_ |
| Claus separades per entorn | La passarel·la ofereix claus de prova i de producció; en desenvolupament no hi ha d'haver una de producció |
| Revisió d'accessos | Reavaluar si els dos col·laboradors externs necessiten accés al repositori complet |
| Rotació periòdica | --rotation-period=90d amb avís per Pub/Sub, perquè rotar sigui rutina i no una emergència |
| Formació | El fitxer de proves es va pujar sense mala intenció. La mesura més eficaç sol ser explicar a l'equip per què importa |
Conclusió
La contrasenya d'app_catalogo ha sortit de l'startup-script. Saps per què aquell lloc era inacceptable —llegible amb compute.viewer, present a l'historial de Git, no rotable sense desplegar, duplicada per tot arreu i sense cap traçabilitat— i has construït l'alternativa completa: els secrets db-password-catalogo i api-key-pasarela-pago a Secret Manager, amb el seu model de secret contenidor i versions immutables, l'àlies latest, i els tres estats d'una versió.
Domines l'accés des de l'aplicació Flask amb la identitat sa-catalogo-web i sense ni una sola credencial al codi, amb memòria cau en memòria i la consciència del que aquesta memòria cau implica per a la rotació. Has concedit roles/secretmanager.secretAccessor a nivell de secret i mai de projecte, i saps que el registre de qui llegeix cada secret existeix però s'ha d'activar. Coneixes el procediment de rotació en cinc passos, amb la regla que evita les catàstrofes: deshabilitar sempre abans de destruir, i mai el mateix dia; i saps que Secret Manager no rota res, només avisa per Pub/Sub i l'automatització l'escrius tu. Has triat entre replicació automàtica i regional entenent que és irreversible i que la residència de les dades és una pregunta de compliment normatiu. I has vist les integracions que fan això encara més net: Cloud Run amb --set-secrets, amb fitxer muntat millor que variable d'entorn; el controlador CSI a GKE, que tanca l'advertiment de 02-05 sobre el base64 dels Secrets de Kubernetes; i availableSecrets a Cloud Build.
En xifratge, has entès el primer que cal entendre: tot està xifrat en repòs per defecte, així que la pregunta real és qui controla la clau. Coneixes la jerarquia DEK/KEK, que explica per què rotar és instantani, per què revocar inutilitza les dades a l'instant i per què CMEK és substituir la KEK i no xifrar tu res. Tens la taula de decisió entre Google-managed, CMEK i CSEK, amb criteris i no amb dogmes: CMEK quan necessitis revocar, auditar o complir; CSEK gairebé mai. Has creat el clauer alpinashop-keyring i les claus clave-catalogo i clave-pedidos amb rotació a 90 dies, sabent que clauers i claus no s'esborren mai i que la ubicació ha de ser compatible amb la del recurs. Has aplicat CMEK al bucket concedint permís a l'agent de servei —el pas que tothom oblida—, has descobert que només afecta els objectes nous, i has après la restricció que canvia els plans: CMEK a Cloud SQL només es pot establir en crear la instància. I tens clars els nivells HSM i EXTERNAL, amb el preu real de la sobirania: una dependència externa al camí crític de les teves dades.
Només falta un trajecte per protegir, i és el més visible de tots: el que va del navegador del client a alpinashop-lb-ip. Avui AlpinaShop se serveix per una adreça IP numèrica i sense certificat; ningú no compra una motxilla de 200 euros en un lloc amb un cadenat ratllat. A la lliçó següent, 03-07, Cloud DNS, certificats TLS i publicació segura de serveis, tanquem el mòdul: crearem la zona pública d'alpinashop.example, apuntarem el domini a la IP global, aprovisionarem un certificat gestionat per Google —amb els seus requisits de DNS i aquesta espera a PROVISIONING que desespera tothom—, ajustarem la política SSL i les capçaleres de seguretat de l'aplicació, i repassarem amb una llista de comprovació tot el que hem construït al mòdul 3.
Curs de Google Cloud Platform (GCP)
Mòdul 1: Introducció a Google Cloud Platform
- Què és Google Cloud Platform?
- Configuració del teu compte de GCP
- Descripció general de la consola de GCP
- Projectes, jerarquia de recursos i facturació
- Regions, zones i model de responsabilitat compartida
- Cloud Shell i la CLI de gcloud
Mòdul 2: Serveis principals de GCP
- Compute Engine: màquines virtuals a Google Cloud
- Cloud Storage: emmagatzematge d'objectes
- Cloud SQL: bases de dades relacionals gestionades
- App Engine: plataforma com a servei
- Google Kubernetes Engine (GKE)
- Bases de dades NoSQL: Firestore, Bigtable i Spanner
- Com triar el servei de còmput adequat
Mòdul 3: Xarxes i seguretat
- Xarxes VPC
- Balanceig de càrrega al núvol
- Cloud CDN
- Gestió d'identitat i accés (IAM)
- Cloud Armor
- Secrets i xifratge: Secret Manager i Cloud KMS
- Cloud DNS, certificats TLS i publicació segura de serveis
Mòdul 4: Dades i anàlisi
- BigQuery: el magatzem de dades analític
- Cloud Dataflow: processament de dades per lots i en temps real
- Cloud Dataproc: Spark i Hadoop gestionats
- Cloud Pub/Sub: missatgeria asíncrona
- Cloud Data Fusion: integració de dades sense codi
- Orquestració de pipelines amb Cloud Composer i Workflows
- Govern de les dades i taulers amb Dataplex i Looker Studio
Mòdul 5: Aprenentatge automàtic i IA
- Vertex AI: la plataforma d'aprenentatge automàtic de GCP
- AutoML: models a mida sense escriure codi
- TensorFlow a GCP: entrenament i servei de models
- API de llenguatge natural
- API de visió
- IA generativa a Vertex AI: models Gemini i incrustacions
- MLOps: del model al producte amb Vertex AI Pipelines
Mòdul 6: DevOps i monitoratge
- Cloud Build: integració contínua a GCP
- Cloud Source Repositories i gestió del codi font
- Cloud Functions: funcions sense servidor
- Cloud Monitoring (abans Stackdriver): mètriques, taulers i alertes
- Cloud Deployment Manager i infraestructura com a codi nativa
- Cloud Logging i Cloud Trace: registres, traces i diagnòstic
- Terraform a GCP: infraestructura com a codi a la pràctica
Mòdul 7: Temes avançats de GCP
- Híbrid i multinúvol amb Anthos
- Computació sense servidor amb Cloud Run
- Xarxes avançades: VPC compartida, aparellament i connectivitat híbrida
- Bones pràctiques de seguretat
- Gestió i optimització de costos
- Fiabilitat: SLO, alta disponibilitat i recuperació de desastres
- Govern a escala: organització, polítiques i auditoria
