Mengelola Secret dan Environment Variable di AWS dengan Parameter Store dan Secrets Manager

Lhuqita Fazry
Cloud Computing AWS Parameter Store Secrets Manager Cloud Security
Mengelola Secret dan Environment Variable di AWS dengan Parameter Store dan Secrets Manager

Why Environment Variables Alone Are Not Enough for Sensitive Data

Banyak developer memulai dengan menyimpan konfigurasi aplikasi di file .env atau OS-level environment variables. Pendekatan ini cukup untuk development lokal, tetapi ketika aplikasi beranjak ke production, keterbatasannya mulai terlihat. File .env bersifat statis, sering disimpan dalam bentuk plaintext, dan sangat rentan bocor ke source control atau tercetak di CI/CD logs. Kita tidak bisa mengandalkan mekanisme sederhana ini untuk melindungi database password, API keys, atau token autentikasi.

Permasalahan utamanya adalah sensitive data dan regular configuration membutuhkan perlakuan yang berbeda. Nilai konfigurasi seperti URL endpoint atau timeout bisa disimpan dengan tingkat keamanan yang lebih rendah. Tetapi credential seperti koneksi database dan kunci API memerlukan enkripsi, audit trail, dan kemampuan rotasi otomatis. AWS menyediakan dua layanan komplementer untuk kebutuhan ini: Systems Manager Parameter Store untuk konfigurasi hierarkis, dan Secrets Manager untuk secret yang memerlukan rotasi otomatis.

Dalam artikel ini, kita akan membangun sistem centralized secret store yang terenkripsi dan dapat diakses dari berbagai resource AWS dengan IAM boundaries yang tepat. Tujuannya adalah menghilangkan praktik menyimpan credential di file konfigurasi atau source code, dan menggantinya dengan mekanisme yang aman, teraudit, dan mudah dikelola.

Comparing AWS Systems Manager Parameter Store dan Secrets Manager

AWS menawarkan dua pendekatan yang berbeda untuk menyimpan data sensitif. Parameter Store adalah solusi gratis yang mendukung penyimpanan parameter dalam bentuk plaintext maupun SecureString (terenkripsi dengan KMS). Parameter Store menggunakan hierarki path seperti /production/db/host atau /staging/api/key, yang memudahkan pengelolaan konfigurasi multi-environment. Setiap parameter dibatasi hingga 8 KB, dan layanan ini tidak mendukung rotasi otomatis.

Secrets Manager di sisi lain adalah layanan berbayar dengan biaya $0.40 per secret per bulan ditambah biaya rotasi. Secrets Manager mendukung ukuran secret hingga 64 KB, memiliki fitur cross-region replication, dan menyediakan integrasi bawaan dengan RDS, Redshift, serta DocumentDB. Fitur unggulannya adalah automatic rotation menggunakan Lambda yang memungkinkan secret berubah secara periodik tanpa campur tangan manual.

Bagaimana cara memilih di antara keduanya? Gunakan Parameter Store untuk non-sensitive configuration dan nilai terenkripsi berukuran kecil yang tidak memerlukan rotasi. Gunakan Secrets Manager untuk credential yang harus berotasi secara berkala atau yang ukurannya melebihi 8 KB. Kedua layanan ini memiliki prasyarat IAM yang sama: tanpa izin eksplisit ssm:GetParameter atau secretsmanager:GetSecretValue, akses akan ditolak secara default.

Arsitektur siklus hidup secret menunjukkan titik keputusan antara Parameter Store dan Secrets Manager

Gambar: Diagram arsitektur yang membandingkan siklus hidup secret di AWS, menunjukkan kapan harus menggunakan Parameter Store versus Secrets Manager berdasarkan kebutuhan rotasi, enkripsi, dan tipe data — Sumber: [AWS Certification Handbook](https://www.awscertificationhandbook.com/guides/aws-ssm-vs-secrets-manager/)

Berikut adalah contoh penggunaan AWS CLI untuk membuat dan membaca parameter serta secret:

bashbash
# Membuat parameter SecureString di Parameter Store
aws ssm put-parameter \
  --name "/production/db/host" \
  --value "db.production.internal" \
  --type SecureString \
  --key-id alias/aws/ssm

# Membaca parameter dengan dekripsi
aws ssm get-parameter \
  --name "/production/db/host" \
  --with-decryption

# Membuat secret di Secrets Manager
aws secretsmanager create-secret \
  --name "production/db-password" \
  --secret-string "P@ssw0rd123!"

# Membaca secret dari Secrets Manager
aws secretsmanager get-secret-value \
  --secret-id "production/db-password"

Output:

> ⚠️ Note: Perintah-perintah AWS CLI di atas memerlukan AWS CLI yang terinstall dan kredensial AWS yang valid untuk dapat dieksekusi. Pada environment ini, AWS CLI tidak tersedia sehingga perintah tidak dapat dijalankan. Untuk menjalankannya di lingkungan lokal, pastikan AWS CLI telah dikonfigurasi dengan aws configure.

Setiap perintah di atas mengembalikan response JSON dari AWS API yang berisi metadata dan nilai yang tersimpan. Perhatikan penggunaan flag --with-decryption pada get-parameter — tanpa flag ini, AWS hanya mengembalikan nilai terenkripsi yang tidak bisa kita baca.

Retrieving Secrets dari Node.js Application Menggunakan AWS SDK v3

Setelah secret tersimpan di AWS, langkah berikutnya adalah mengambilnya dari aplikasi. Kita akan menggunakan AWS SDK v3 untuk JavaScript yang menyediakan modular package sehingga kita hanya menginstal client yang diperlukan.

Ada dua strategi pengambilan secret yang umum digunakan. Cold-start fetch mengambil semua secret saat aplikasi boot dan menyimpannya di cache in-memory — pendekatan ini cepat untuk request berikutnya tetapi menambah latency saat startup. On-demand fetch mengambil secret setiap kali dibutuhkan, yang lebih hemat biaya untuk secret yang jarang diakses tetapi menambah latency pada setiap request. Kombinasi keduanya dengan cache TTL (Time-to-Live) biasanya merupakan pilihan terbaik.

Mari kita implementasikan sebuah SecretsService yang menangani pengambilan dan caching secret:

typescripttypescript
import {
  SSMClient,
  GetParameterCommand,
} from "@aws-sdk/client-ssm";
import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from "@aws-sdk/client-secrets-manager";

interface SecretsCache {
  [key: string]: {
    value: string;
    expiresAt: number;
  };
}

export class SecretsService {
  private ssmClient: SSMClient;
  private secretsClient: SecretsManagerClient;
  private cache: SecretsCache = {};
  private readonly ttlMs = 5 * 60 * 1000; // 5 menit

  constructor(region: string) {
    this.ssmClient = new SSMClient({ region });
    this.secretsClient = new SecretsManagerClient({ region });
  }

  async getParameter(name: string): Promise<string> {
    const cached = this.cache[name];
    if (cached && Date.now() < cached.expiresAt) {
      return cached.value;
    }

    const command = new GetParameterCommand({
      Name: name,
      WithDecryption: true,
    });

    try {
      const response = await this.ssmClient.send(command);
      const value = response.Parameter?.Value || "";

      this.cache[name] = {
        value,
        expiresAt: Date.now() + this.ttlMs,
      };

      console.log(`DB_PASSWORD: ****`); // jangan log nilai asli!
      return value;
    } catch (error) {
      console.warn("Gagal mengambil parameter, fallback ke env local");
      return process.env[name] || "";
    }
  }
}

Output:

> ⚠️ Note: Kode TypeScript di atas memerlukan package @aws-sdk/client-ssm dan @aws-sdk/client-secrets-manager dari AWS SDK v3. Untuk menjalankannya, instal dependencies terlebih dahulu dengan perintah: > ``bash > npm install @aws-sdk/client-ssm @aws-sdk/client-secrets-manager > ` > Kemudian kompilasi dan jalankan menggunakan ts-node` atau setelah transpilasi ke JavaScript.

Perhatikan bagaimana kita menangani error dengan fallback ke environment variables lokal ketika AWS tidak dapat dijangkau — ini sangat berguna untuk development lokal. Cache dengan TTL 5 menit memastikan kita tidak memanggil AWS API pada setiap request, mengurangi biaya dan latency. Yang paling penting: kita tidak pernah mencatat (log) nilai secret asli, bahkan dalam error messages sekalipun.

Configuring IAM Policies dan Enabling Secret Rotation

Mengelola hak akses adalah aspek kritis dalam secret management. Prinsip least-privilege harus diterapkan: setiap resource hanya mendapatkan izin minimal yang diperlukan. Untuk EC2 instance atau Lambda function yang perlu mengakses Parameter Store dan Secrets Manager, kita perlu merancang IAM policy yang spesifik.

Berikut adalah contoh IAM policy document yang memberikan akses read-only ke parameter dan secret tertentu:

jsonjson
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ssm:GetParameter",
      "Resource": "arn:aws:ssm:us-east-1:123456789012:parameter/production/*"
    },
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:production/*"
    },
    {
      "Effect": "Deny",
      "Action": [
        "ssm:PutParameter",
        "ssm:DeleteParameter",
        "secretsmanager:PutSecretValue",
        "secretsmanager:DeleteSecret"
      ],
      "Resource": "*"
    }
  ]
}

Policy ini membatasi akses hanya ke path /production/* untuk Parameter Store dan secret dengan prefix production/ di Secrets Manager. Tindakan write seperti PutParameter dan DeleteSecret secara eksplisit ditolak.

Arsitektur hybrid menggunakan Secrets Manager untuk kredensial dan Parameter Store untuk konfigurasi di lingkungan multi-account

Gambar: Arsitektur hybrid yang merekomendasikan penggunaan Secrets Manager untuk kredensial database dan API keys yang memerlukan rotasi, serta Parameter Store untuk konfigurasi aplikasi dan feature flags — Sumber: [AWS Certification Handbook](https://www.awscertificationhandbook.com/guides/aws-ssm-vs-secrets-manager/)

Untuk rotasi otomatis di Secrets Manager, mekanismenya bekerja seperti ini: sebuah Lambda function dipicu oleh scheduler CloudWatch Events untuk menghasilkan password baru, kemudian memperbarui nilai secret sekaligus meng-update target service seperti RDS. Semua akses ke secret tercatat di AWS CloudTrail, sehingga kita bisa mendeteksi anomali seperti panggilan GetSecretValue dari IP address atau IAM principal yang tidak dikenal.

Avoiding Common Pitfalls dalam Production

Setelah menerapkan solusi secret management, ada beberapa jebakan yang sering ditemui di production. Pertama, rotasi manual sangat rentan terhadap human error — selalu aktifkan automatic rotation untuk Secrets Manager yang digunakan di production. Kedua, hindari hardcoding parameter names di dalam kode aplikasi. Gunakan environment-specific path prefixes seperti /dev/, /staging/, dan /prod/ agar deployment ke environment berbeda tidak memerlukan perubahan kode.

Ketiga, memanggil API untuk mengambil secret pada setiap request akan menambah latency dan biaya yang tidak perlu. Strategi yang lebih baik adalah melakukan batch fetch saat startup dan menyimpan nilai tersebut di cache in-memory dengan TTL yang sesuai. Keempat, jangan lupa mengaktifkan enkripsi KMS pada parameter SecureString. Tanpa enkripsi, data tetap bisa dibaca oleh siapapun yang memiliki izin ssm:GetParameter.

Terakhir, dan ini yang paling sering dilanggar: jangan pernah mengirim nilai secret mentah ke console.log, logging frameworks, atau error tracking tools. Sekali secret tercetak di log, nilai secret tersebut akan tersimpan selamanya di sistem logging dan menjadi surface serangan yang serius. Gunakan masking atau redaction sebelum mencatat informasi yang berhubungan dengan secret.

Mengelola secret dan environment variable di AWS bukanlah tugas yang rumit jika kita menggunakan tools yang tepat. Parameter Store dan Secrets Manager memberikan lapisan keamanan tambahan yang sangat dibutuhkan aplikasi modern. Kuasai AWS secret management end-to-end, dari IAM policies hingga enkripsi dan rotasi, dalam Cloud Architecture Bootcamp di Rumah Coding. Dapatkan panduan langsung untuk menerapkan praktik terbaik dalam production environment.

Artikel Terkait