Skip to content

Commit 8f2db85

Browse files
committed
New articles
1 parent ff9ca14 commit 8f2db85

File tree

3 files changed

+299
-1
lines changed

3 files changed

+299
-1
lines changed

content/posts/2025-04-24-deno-clean-architecture.es.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: "Arquitectura limpia con Deno: estructuras escalables para proyectos open
44
author: Christian Amado
55
date: 2025-04-24 00:00:00 -0300
66
category: [Desarrollo de software]
7-
tags: [Go,GitHub Star]
7+
tags: [Deno,GitHub Star]
88
thumbnail-img: /img/posts/thumbnails/deno.png
99
cover-img: /img/posts/cover/deno.png
1010
share_img: /img/posts/shared/deno.webp
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
layout: post
3+
title: "Uso seguro de variables y secretos en GCP con Go"
4+
author: Christian Amado
5+
date: 2025-04-30 00:00:00 -0300
6+
category: [Desarrollo de software]
7+
tags: [Google,Google Cloud,GCP,Go]
8+
thumbnail-img: /img/posts/thumbnails/golang.webp
9+
cover-img: /img/posts/cover/Go-Lang.svg
10+
share_img: /img/posts/shared/golang.png
11+
---
12+
13+
Manejar secretos —como claves API, tokens y credenciales— de forma segura es esencial en cualquier aplicación moderna. **Google Cloud Platform (GCP)** ofrece una solución robusta para este desafío a través de **Secret Manager**, que permite almacenar, acceder y auditar secretos de manera segura y centralizada.
14+
15+
Este artículo muestra cómo acceder y gestionar secretos en **GCP** desde aplicaciones desarrolladas en **Go**, asegurando que tus variables sensibles estén protegidas sin necesidad de hardcodearlas o exponerlas en entornos inseguros.
16+
17+
<!--more-->
18+
19+
## ¿Por qué usar Secret Manager?
20+
21+
Secret Manager de GCP es un servicio completamente gestionado que ofrece:
22+
23+
- **Cifrado automático** con claves de Google o personalizadas (CMEK).
24+
- **Versionado de secretos** para revertir fácilmente a estados anteriores.
25+
- **Control de acceso granular** vía IAM.
26+
- **Registros de auditoría** con Cloud Audit Logs.
27+
- **Integración nativa con entornos serverless, Compute Engine y GKE**.
28+
29+
## Requisitos previos
30+
31+
Antes de comenzar, asegurate de tener:
32+
33+
- Un proyecto activo en Google Cloud.
34+
- El API de Secret Manager habilitada.
35+
- El SDK de Google Cloud (`gcloud`) configurado.
36+
- Una cuenta de servicio con permisos `Secret Manager Accessor` (`roles/secretmanager.secretAccessor`).
37+
- Go instalado (se recomienda Go 1.20+).
38+
- Módulos habilitados (`go mod init` en tu proyecto).
39+
40+
## Paso 1: Crear y almacenar un secreto en GCP
41+
42+
Desde la consola o terminal:
43+
44+
```bash
45+
gcloud secrets create DB_PASSWORD --replication-policy=automatic
46+
echo -n "super-clave-secreta" | gcloud secrets versions add DB_PASSWORD --data-file=-
47+
```
48+
49+
Esto crea el secreto `DB_PASSWORD` con una versión y lo almacena de forma segura.
50+
51+
## Paso 2: Configurar permisos de acceso
52+
53+
Otorgá acceso a la cuenta de servicio usada por tu aplicación:
54+
55+
```bash
56+
gcloud secrets add-iam-policy-binding DB_PASSWORD \
57+
--member="serviceAccount:[email protected]" \
58+
--role="roles/secretmanager.secretAccessor"
59+
```
60+
61+
## Paso 3: Instalar dependencias en Go
62+
63+
En tu archivo `go.mod`:
64+
65+
```bash
66+
go get cloud.google.com/go/secretmanager/apiv1
67+
go get google.golang.org/api/option
68+
```
69+
70+
## Paso 4: Código para acceder al secreto en Go
71+
72+
```go
73+
package main
74+
75+
import (
76+
"context"
77+
"fmt"
78+
"log"
79+
80+
secretmanager "cloud.google.com/go/secretmanager/apiv1"
81+
"google.golang.org/api/option"
82+
secretspb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
83+
)
84+
85+
func main() {
86+
ctx := context.Background()
87+
88+
client, err := secretmanager.NewClient(ctx, option.WithCredentialsFile("ruta/a/tu/clave.json"))
89+
if err != nil {
90+
log.Fatalf("Error creando cliente: %v", err)
91+
}
92+
defer client.Close()
93+
94+
accessRequest := &secretspb.AccessSecretVersionRequest{
95+
Name: "projects/ID_PROYECTO/secrets/DB_PASSWORD/versions/latest",
96+
}
97+
98+
result, err := client.AccessSecretVersion(ctx, accessRequest)
99+
if err != nil {
100+
log.Fatalf("Error accediendo al secreto: %v", err)
101+
}
102+
103+
secret := string(result.Payload.Data)
104+
fmt.Println("Secreto accedido:", secret)
105+
}
106+
```
107+
108+
> ⚠️ **Nunca imprimas el secreto en producción.** Este ejemplo es solo para demostración.
109+
110+
## Paso 5: Uso de secretos en variables de entorno
111+
112+
```go
113+
import (
114+
"os"
115+
)
116+
117+
os.Setenv("DB_PASSWORD", secret)
118+
fmt.Println(os.Getenv("DB_PASSWORD"))
119+
```
120+
121+
Esto es útil para usar librerías que esperan configuraciones vía `env`.
122+
123+
## Buenas prácticas
124+
125+
- **Nunca hardcodees secretos** en el código fuente.
126+
- **Evitá guardar secretos en archivos de configuración planos**.
127+
- **Usá versionado de secretos** para rotaciones sin downtime.
128+
- **Controlá el acceso con políticas IAM específicas** para minimizar el riesgo.
129+
- **Usá registros de auditoría** para detectar accesos indebidos.
130+
- **No loguees secretos accidentalmente.**
131+
132+
## Alternativas: acceso automático desde Cloud Run o GKE
133+
134+
Si desplegás en Cloud Run, App Engine o GKE, podés acceder a los secretos sin usar claves JSON, simplemente mediante la cuenta de servicio adjunta al entorno, lo que refuerza la seguridad y evita manejar archivos sensibles.
135+
136+
```go
137+
client, err := secretmanager.NewClient(ctx) // sin option.WithCredentialsFile
138+
```
139+
140+
Este enfoque se recomienda en producción.
141+
142+
## Conclusión
143+
144+
**Secret Manager** permite gestionar variables sensibles de forma segura, eficiente y auditada. Su integración con **Go** es directa gracias al *SDK* oficial, lo que permite eliminar configuraciones inseguras y mejorar la postura de seguridad general de cualquier aplicación backend.
145+
146+
Adoptar estas buenas prácticas desde el inicio mejora la seguridad, simplifica la gestión de configuración y garantiza que tus aplicaciones **Go** en **GCP** estén listas para producción desde el primer día.
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
layout: post
3+
title: "Mocks, cobertura y pruebas por capas en proyectos escalables"
4+
author: Christian Amado
5+
date: 2025-05-02 10:00:00 -0300
6+
category: [Desarrollo de software]
7+
tags: [Deno,GitHub Star]
8+
thumbnail-img: /img/posts/thumbnails/deno.png
9+
cover-img: /img/posts/cover/deno.png
10+
share_img: /img/posts/shared/deno.webp
11+
---
12+
13+
En el ecosistema moderno del desarrollo backend, el testing no es opcional: es esencial. En proyectos colaborativos y escalables, contar con pruebas automatizadas bien estructuradas marca la diferencia entre un código confiable y uno frágil. Deno 2 ofrece herramientas nativas poderosas para testear, pero muchas veces su uso avanzado no está del todo documentado. Este artículo muestra cómo implementar un enfoque de testing avanzado en Deno 2, incluyendo mocks manuales, cobertura de código y organización por capas.
14+
15+
<!--more-->
16+
17+
## ¿Por qué testear en Deno 2?
18+
19+
Deno 2 cuenta con un sistema de testing nativo muy sólido:
20+
- Sintaxis clara para definir y ejecutar tests.
21+
- Aislamiento automático de cada test.
22+
- Herramientas para cobertura de código (`deno coverage`).
23+
- Posibilidad de testear sin librerías externas.
24+
25+
Esto permite aplicar testing por capas y simular distintos escenarios sin introducir dependencias innecesarias.
26+
27+
## Tipos de pruebas por capa
28+
29+
### ✅ Pruebas unitarias
30+
Se enfocan en una función o clase específica, con dependencias simuladas.
31+
32+
### 🔄 Pruebas de integración
33+
Verifican cómo interactúan varios componentes entre sí, sin tocar la capa HTTP.
34+
35+
### 🌐 Pruebas end-to-end (E2E)
36+
Simulan una petición real, verificando el comportamiento de la aplicación de punta a punta.
37+
38+
## Organización recomendada de carpetas
39+
40+
```
41+
tests/
42+
├── unit/
43+
│ └── get_all_tasks_test.ts
44+
├── integration/
45+
│ └── task_repository_test.ts
46+
└── e2e/
47+
└── api_tasks_test.ts
48+
```
49+
50+
Esto permite escalar los tests de forma ordenada y mantener una separación lógica.
51+
52+
## Mocks en Deno 2 sin librerías externas
53+
54+
Deno permite crear mocks fácilmente utilizando clases o funciones anónimas. Ejemplo:
55+
56+
```ts
57+
// Mock de TaskRepository
58+
class MockTaskRepo {
59+
private tasks = [{ id: "1", title: "Test", completed: false }];
60+
61+
findAll() {
62+
return Promise.resolve(this.tasks);
63+
}
64+
}
65+
```
66+
67+
Uso en el test:
68+
```ts
69+
import { assertEquals } from "https://deno.land/[email protected]/assert/mod.ts";
70+
import { GetAllTasks } from "@app/use_cases/get_all_tasks.ts";
71+
72+
Deno.test("Devuelve tareas del repositorio mockeado", async () => {
73+
const repo = new MockTaskRepo();
74+
const useCase = new GetAllTasks(repo);
75+
const result = await useCase.execute();
76+
assertEquals(result.length, 1);
77+
});
78+
```
79+
80+
## Simulación de errores
81+
82+
También podés simular excepciones:
83+
```ts
84+
class FailingRepo {
85+
findAll() {
86+
throw new Error("DB unavailable");
87+
}
88+
}
89+
90+
Deno.test("Manejo de error en repositorio", () => {
91+
const useCase = new GetAllTasks(new FailingRepo());
92+
try {
93+
useCase.execute();
94+
} catch (e) {
95+
assertEquals(e.message, "DB unavailable");
96+
}
97+
});
98+
```
99+
100+
## Cobertura de código en Deno 2
101+
102+
### 1. Ejecutar tests con cobertura:
103+
```bash
104+
deno test --coverage=coverage/
105+
```
106+
107+
### 2. Generar informe legible:
108+
```bash
109+
deno coverage coverage/ --lcov > coverage.lcov
110+
```
111+
112+
### 3. Ver informe HTML:
113+
```bash
114+
genhtml coverage.lcov -o coverage_html
115+
```
116+
117+
Podés usar [genhtml](https://manpages.debian.org/testing/lcov/genhtml.1.en.html) desde `lcov` (requiere instalación externa).
118+
119+
## Automatización con GitHub Actions
120+
121+
Un flujo simple para ejecutar los tests y verificar la cobertura:
122+
123+
```yaml
124+
name: test
125+
on: [push, pull_request]
126+
127+
jobs:
128+
test:
129+
runs-on: ubuntu-latest
130+
steps:
131+
- uses: actions/checkout@v3
132+
- name: Setup Deno
133+
uses: denoland/setup-deno@v1
134+
with:
135+
deno-version: v2.x
136+
- name: Run Tests
137+
run: deno test --coverage=coverage/
138+
```
139+
140+
También podés subir la cobertura a [coveralls.io](https://coveralls.io/) o [codecov.io](https://about.codecov.io/) si querés seguimiento continuo.
141+
142+
## Buenas prácticas
143+
144+
- ✅ Nombrar tests descriptivamente.
145+
- ✅ Mantener las dependencias mínimas.
146+
- ✅ Testear cada capa por separado.
147+
- ✅ Usar import maps para simplificar imports.
148+
- ✅ Evitar testear implementaciones internas.
149+
150+
## Conclusión
151+
152+
Con **Deno 2**, tenés todo lo necesario para aplicar pruebas por capas, cobertura de código y mocks sin dependencias externas. Adoptar estas prácticas no solo mejora la calidad de tu software, sino que también facilita la colaboración en proyectos open source.

0 commit comments

Comments
 (0)