Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Secrets Management — Tajne Depesze Imperium

W Imperium Rzymskim najważniejsze informacje — plany bitew, lokalizacje skarbców, hasła legionów — były przekazywane zaszyfrowanymi depeszami. Tylko uprawnieni dowódcy mogli je odczytać. W aplikacjach produkcyjnych, zarządzanie sekretami (secrets management) pełni identyczną rolę — chroni hasła, klucze API i certyfikaty przed nieautoryzowanym dostępem.

Dlaczego NIE .env na produkcji?

Wielu programistów przechowuje sekrety w plikach

.env
— na development to akceptowalne, ale na produkcji to poważne zagrożenie:

1// Problemy z plikami .env na produkcji
2const envProblems = {
3  wyciek: 'Plik .env przypadkowo commitowany do repozytorium',
4  brakRotacji: 'Ręczna zmiana haseł na każdym serwerze',
5  brakAudytu: 'Nie wiadomo, kto i kiedy miał dostęp do sekretów',
6  brakSzyfrowania: 'Sekrety zapisane jako plain text na dysku',
7  skalowanie: 'Kopiowanie .env na każdy nowy serwer',
8};
9
10// GitHub Leaked Secrets (2023):
11// > 12 milionów sekretów wyciekło z publicznych repozytoriów

HashiCorp Vault — Skarbiec Imperium

HashiCorp Vault to najpopularniejsze narzędzie do zarządzania sekretami. Działa jak cesarskie skarbce (aerarium) — centralnie przechowuje i kontroluje dostęp do sekretów:

1// Jak Vault zarządza sekretami
2interface VaultConcepts {
3  engine: 'Secret Engine — backend przechowywania (KV, Database, PKI)';
4  policy: 'Policy — reguły dostępu (kto co może odczytać)';
5  token: 'Token — klucz autoryzacji (jak pieczęć cesarza)';
6  lease: 'Lease — czas życia sekretu (automatyczna rotacja)';
7  audit: 'Audit Log — pełny rejestr dostępów';
8}
9
10// Przykład użycia Vault API
11// vault kv put secret/roman-api DATABASE=mongodb://... JWT_SECRET=...
12// vault kv get secret/roman-api

Integracja Vault z NestJS

1// config/vault.config.ts
2import { registerAs } from '@nestjs/config';
3import Vault from 'node-vault';
4
5const vault = Vault({
6  endpoint: process.env.VAULT_ADDR || 'http://127.0.0.1:8200',
7  token: process.env.VAULT_TOKEN,
8});
9
10export default registerAs('secrets', async () => {
11  const result = await vault.read('secret/data/roman-api');
12  return {
13    database: result.data.data.DATABASE,
14    jwtSecret: result.data.data.JWT_SECRET,
15    redisPassword: result.data.data.REDIS_PASSWORD,
16  };
17});
18
19// app.module.ts — ładowanie asynchroniczne
20@Module({
21  imports: [
22    ConfigModule.forRoot({
23      isGlobal: true,
24      load: [vaultConfig],
25    }),
26  ],
27})
28export class AppModule {}

AWS Secrets Manager

Dla aplikacji hostowanych na AWS, Secrets Manager zapewnia natywną integrację:

1// config/aws-secrets.ts
2import {
3  SecretsManagerClient,
4  GetSecretValueCommand,
5} from '@aws-sdk/client-secrets-manager';
6
7const client = new SecretsManagerClient({ region: 'eu-central-1' });
8
9export async function getSecrets(): Promise<Record<string, string>> {
10  const command = new GetSecretValueCommand({
11    SecretId: 'roman-api/production',
12  });
13
14  const response = await client.send(command);
15  return JSON.parse(response.SecretString);
16}
17
18// Użycie w NestJS
19export default registerAs('aws', async () => {
20  const secrets = await getSecrets();
21  return {
22    database: secrets.DATABASE,
23    jwtSecret: secrets.JWT_SECRET,
24  };
25});

Kubernetes Secrets

W Kubernetes sekrety przechowujemy jako obiekty Secret, zakodowane w base64:

1# k8s/secret.yaml
2apiVersion: v1
3kind: Secret
4metadata:
5  name: roman-api-secrets
6  namespace: production
7type: Opaque
8data:
9  DATABASE: bW9uZ29kYjovL2ltcGVyYXRvcjpyb21hQG1vbmdvZGI6MjcwMTcvaW1wZXJpdW0=
10  JWT_SECRET: c3VwZXItc2VjcmV0LWtleS1taW4tMTYtY2hhcnM=

Sealed Secrets — Bezpieczne commitowanie

Sealed Secrets pozwalają bezpiecznie przechowywać sekrety w repozytorium Git — są zaszyfrowane kluczem publicznym klastra:

1# Instalacja kubeseal
2brew install kubeseal
3
4# Szyfrowanie sekretów
5kubeseal --format yaml < secret.yaml > sealed-secret.yaml
6
7# Tylko klaster może odszyfrować sealed-secret.yaml
8# Można bezpiecznie commitować do repozytorium

Rotacja sekretów

Regularna zmiana sekretów minimalizuje ryzyko wycieku:

1// Strategia rotacji sekretów
2interface RotationStrategy {
3  secret: string;
4  interval: string;
5  method: string;
6}
7
8const rotationPolicies: RotationStrategy[] = [
9  {
10    secret: 'DATABASE_PASSWORD',
11    interval: 'Co 90 dni',
12    method: 'Vault dynamic secrets — automatyczna rotacja',
13  },
14  {
15    secret: 'JWT_SECRET',
16    interval: 'Co 30 dni',
17    method: 'Vault KV v2 — wersjonowanie + graceful rotation',
18  },
19  {
20    secret: 'API_KEYS',
21    interval: 'Co 60 dni',
22    method: 'AWS Secrets Manager — automatyczna Lambda rotacji',
23  },
24];

NestJS ConfigModule z zewnętrznym providerem

1// config/secrets.provider.ts
2import { ConfigModuleOptions } from '@nestjs/config';
3
4export const secretsConfig: ConfigModuleOptions = {
5  isGlobal: true,
6  load: [
7    // Priorytet 1: Vault (produkcja)
8    async () => {
9      if (process.env.VAULT_ADDR) {
10        return loadFromVault();
11      }
12      return {};
13    },
14    // Priorytet 2: AWS Secrets Manager
15    async () => {
16      if (process.env.AWS_REGION) {
17        return loadFromAWS();
18      }
19      return {};
20    },
21    // Priorytet 3: Zmienne środowiskowe (fallback)
22    () => ({
23      database: process.env.DATABASE,
24      jwtSecret: process.env.JWT_SECRET,
25    }),
26  ],
27};
28
29// app.module.ts
30@Module({
31  imports: [ConfigModule.forRoot(secretsConfig)],
32})
33export class AppModule {}

Zarządzanie sekretami to sztuka ochrony tajnych depesz Imperium. Nigdy nie zostawiaj sekretów w plikach .env na produkcji — używaj dedykowanych narzędzi: Vault, AWS Secrets Manager lub Kubernetes Secrets.

Vai a CodeWorlds