TDCTF Academy Logo TDCTF ACADEMY

9.3.3 Secret Management

Secret Management adalah praktik penyimpanan, distribusi, rotasi, dan audit kredensial sensitif - termasuk API key, database password, SSH key, token OAuth, dan certificate - secara aman. Tanpa secret management yang baik, organisasi cloud sangat rentan terhadap kebocoran kredensial.

Masalah Hardcoded Credentials di Cloud

Hardcoded credentials masih menjadi penyebab utama data breach di cloud. Berikut pola yang sering ditemukan:

# ❌ BURUK: Hardcoded credentials di source code
db_password = "P@ssw0rd123!"
aws_access_key = "AKIAIOSFODNN7EXAMPLE"
aws_secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Risiko hardcoded credentials:

  • Source code terupload ke GitHub publik → credential leak
  • Container image menyimpan secret → siapa pun yang pull image bisa melihatnya
  • Environment variable di CI/CD pipeline → terekspos di log build
  • Tidak ada audit trail → tidak tahu siapa yang menggunakan secret kapan

Deteksi Hardcoded Secrets di Codebase

TruffleHog - tools untuk menemukan secrets di git history:

# Scan repository git
trufflehog git https://github.com/perusahaan/repo-produk.git --json

# Scan direktori lokal
trufflehog filesystem /home/user/project --json

GitLeaks - alternatif open-source:

# Deteksi secrets sebelum commit (pre-commit hook)
gitleaks detect --source . --verbose

# Scan branch spesifik
gitleaks detect --source . --branch main --report-path gitleaks-report.json

AWS Secrets Manager - deteksi dengan AWS Config:

# Managed rule untuk deteksi hardcoded credentials
aws configservice put-config-rule \
--config-rule '{"ConfigRuleName":"secretsmanager-secret-rotation-enabled","Source":{"Owner":"AWS","SourceIdentifier":"SECRETSMANAGER_SECRET_ROTATION_ENABLED"}}'

AWS Secrets Manager vs Parameter Store

AWS menawarkan dua layanan manajemen secret: Secrets Manager (premium) dan Parameter Store (gratis).

Fitur Secrets Manager Parameter Store (Standard)
Harga $0.40 per secret/bulan + API calls Gratis (parameter)
Max secret size 64 KB 4 KB (Standard), 8 KB (Advanced)
Auto-rotation ✅ Ya (built-in untuk RDS, Redshift, DocumentDB) ❌ Tidak otomatis
Encryption ✅ AWS KMS (wajib) ✅ Opsional (SecureString dengan KMS)
Cross-account ✅ Ya (via resource policy) ✅ Ya (Advanced tier)
CloudFormation ✅ Ya ✅ Ya
Versioning ✅ Otomatis ✅ Otomatis

AWS Secrets Manager - Implementasi

# Membuat secret untuk database RDS
aws secretsmanager create-secret \
--name prod/mysql/main-db \
--description "Main database credentials for production" \
--secret-string '{"username":"dbadmin","password":"P@ssw0rd!2024","host":"prod-db.abc123.ap-southeast-1.rds.amazonaws.com","port":3306,"dbname":"app_prod"}' \
--kms-key-id alias/secrets-key \
--tags Key=Environment,Value=Production Key=Owner,Value=DevOps

# Mengaktifkan auto-rotation (setiap 30 hari)
aws secretsmanager rotate-secret \
--secret-id prod/mysql/main-db \
--rotation-rules AutomaticallyAfterDays=30

# Mengambil secret di aplikasi (Lambda, EC2, ECS)
aws secretsmanager get-secret-value \
--secret-id prod/mysql/main-db \
--query SecretString \
--output text

AWS Systems Manager Parameter Store

# Menyimpan parameter sebagai SecureString (terenkripsi)
aws ssm put-parameter \
--name /prod/app/database/url \
--value "postgresql://app:password@pg-prod:5432/app" \
--type SecureString \
--key-id alias/ssm-key \
--tags Key=Environment,Value=Production

# Mengambil parameter
aws ssm get-parameter \
--name /prod/app/database/url \
--with-decryption \
--query Parameter.Value \
--output text

Kapan menggunakan apa:

  • Secrets Manager: Auto-rotation untuk RDS, secret >4KB, cross-account
  • Parameter Store (Advanced): Config aplikasi, license key, secret kecil tanpa rotation
  • Parameter Store (Standard): Konfigurasi non-sensitif, environment variables

Azure Key Vault

Azure Key Vault menyimpan secrets, keys, dan certificates dalam satu layanan terpadu:

# Membuat Key Vault
az keyvault create \
--name "kv-perusahaan-prod" \
--resource-group rg-prod \
--location southeastasia \
--sku premium \
--enable-purge-protection \
--enable-rbac-authorization

# Menambahkan secret
az keyvault secret set \
--vault-name "kv-perusahaan-prod" \
--name "db-connection-string" \
--value "Server=prod-db.database.windows.net;Database=app;User Id=admin;Password=P@ssw0rd;"

# Mengaktifkan soft-delete dan purge protection
az keyvault update \
--name "kv-perusahaan-prod" \
--enable-soft-delete true \
--soft-delete-retention-days 90 \
--enable-purge-protection true

# Mengaktifkan diagnostic logging
az monitor diagnostic-settings create \
--name "kv-audit-logs" \
--resource "/subscriptions/xxx/resourceGroups/rg-prod/providers/Microsoft.KeyVault/vaults/kv-perusahaan-prod" \
--workspace "/subscriptions/xxx/resourceGroups/rg-monitoring/providers/Microsoft.OperationalInsights/workspaces/log-analytics-prod" \
--logs '[{"category":"AuditEvent","enabled":true}]'

GCP Secret Manager

# Membuat secret
gcloud secrets create db-credentials \
--replication-policy="automatic" \
--labels="environment=production,team=backend"

# Menambahkan versi secret
echo -n '{"username":"admin","password":"supersecret"}' | \
gcloud secrets versions add db-credentials --data-file=-

# Memberi akses ke service account
gcloud secrets add-iam-policy-binding db-credentials \
--member="serviceAccount:[email protected]" \
--role="roles/secretmanager.secretAccessor"

# Mengakses secret dari aplikasi (Python)
cat << 'PYEOF'
# from google.cloud import secretmanager
# client = secretmanager.SecretManagerServiceClient()
# response = client.access_secret_version(request={"name": "projects/project/secrets/db-credentials/versions/latest"})
# payload = response.payload.data.decode("UTF-8")
PYEOF

Rotasi Otomatis

AWS Secrets Manager - Rotasi dengan Lambda

# Lambda function untuk rotasi secret RDS
import json
import boto3
import pymysql

def lambda_handler(event, context):
secret_arn = event['SecretId']
token = event['ClientRequestToken']
step = event['Step']

if step == 'createSecret':
# Generate password baru
new_password = generate_random_password()
# Simpan pending secret
secrets_manager = boto3.client('secretsmanager')
secrets_manager.put_secret_value(
SecretId=secret_arn,
ClientRequestToken=token,
SecretString=json.dumps({
'username': 'dbadmin',
'password': new_password,
'host': 'prod-db.amazonaws.com'
})
)

elif step == 'setSecret':
# Update password di database
connection = pymysql.connect(...)
cursor = connection.cursor()
cursor.execute(f"ALTER USER 'dbadmin'@'%' IDENTIFIED BY '{new_password}'")

elif step == 'testSecret':
# Verifikasi password baru
connection = pymysql.connect(host=..., user='dbadmin', password=new_password)

elif step == 'finishSecret':
# Tandai secret sebagai aktif
secrets_manager = boto3.client('secretsmanager')
secrets_manager.update_secret_version_stage(
SecretId=secret_arn,
VersionStage='AWSCURRENT',
RemoveFromVersionId='AWSPENDING',
MoveToVersionId=token
)

return {'status': 'success'}

Encryption at Rest

Semua secret management service menggunakan enclryption at rest secara default dengan Customer Master Key (CMK):

# AWS KMS - key untuk secret
aws kms create-key \
--description "Master key for Secrets Manager" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS

aws kms create-alias \
--alias-name alias/secrets-manager-key \
--target-key-id arn:aws:kms:ap-southeast-1:123456789012:key/abc123

# Membuat grant untuk service lain
aws kms create-grant \
--key-id alias/secrets-manager-key \
--grantee-principal arn:aws:iam::123456789012:role/ecs-task-role \
--operations Decrypt

Key hierarchy: Data key → Customer Master Key → HSM Root Key.

Access Policies untuk Secrets

AWS Resource Policy

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/backend-prod"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"secretsmanager:VersionStage": "AWSCURRENT"
}
}
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "secretsmanager:DeleteSecret",
"Resource": "*"
}
]
}

Audit Logging

Semua akses ke secret management tercatat di CloudTrail (AWS), Azure Monitor (Azure), atau Cloud Audit Logs (GCP):

# Query CloudTrail untuk akses secret
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue \
--start-time "2024-01-01T00:00:00Z" \
--end-time "2024-12-31T23:59:59Z"

Integration dengan CI/CD, Container, dan Serverless

CI/CD - GitHub Actions dengan OpenID Connect (OIDC)

name: Deploy with Secrets
on:
push:
branches: [main]

permissions:
id-token: write
contents: read

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-role
aws-region: ap-southeast-1

- name: Get Database Secret
run: |
SECRET=\`aws secretsmanager get-secret-value --secret-id prod/mysql/main-db --query SecretString --output text\`
echo "DB_HOST=\$(echo \$SECRET | jq -r '.host')" >> \$GITHUB_ENV

- name: Deploy Application
run: ./deploy.sh

Container - external-secrets-operator

external-secrets-operator adalah Kubernetes operator yang menyinkronkan secret dari cloud ke K8s Secret:

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secrets-store
spec:
provider:
aws:
service: SecretsManager
region: ap-southeast-1
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: "1h"
secretStoreRef:
name: aws-secrets-store
kind: SecretStore
target:
name: db-credentials
data:
- secretKey: username
remoteRef:
key: prod/mysql/main-db
property: username
- secretKey: password
remoteRef:
key: prod/mysql/main-db
property: password

Serverless - Lambda dengan Environment Variable dari Secrets Manager

# CloudFormation untuk Lambda + Secrets
MyLambda:
Type: AWS::Serverless::Function
Properties:
Policies:
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action: secretsmanager:GetSecretValue
Resource: !Ref DatabaseSecret
Environment:
Variables:
DB_SECRET_ARN: !Ref DatabaseSecret

Tools Pendukung

HashiCorp Vault

Vault adalah secret management tool open-source yang berjalan di mana saja (multi-cloud, on-premise):

# Vault CLI - menulis secret
vault kv put secret/database/prod username=dbadmin password=P@ssw0rd

# Membaca secret
vault kv get secret/database/prod

# Dynamic secrets - database credentials yang auto-rotate
vault read database/creds/readonly

SOPS (Secrets OPerationS)

SOPS adalah tool enkripsi file yang mendukung AWS KMS, GCP KMS, Azure Key Vault, dan PGP:

# Enkripsi file konfigurasi dengan KMS
sops -e -k arn:aws:kms:ap-southeast-1:123456789012:key/abc123 config.yaml > config.enc.yaml

# Dekripsi
sops -d config.enc.yaml

# Edit langsung
sops config.enc.yaml

Format file yang didukung SOPS: YAML, JSON, ENV, INI, dan binary.

external-secrets-operator (sudah dibahas di atas)

Verifikasi

# Cek rotasi secret
aws secretsmanager describe-secret --secret-id prod/mysql/main-db --query RotationRules

# Audit akses secret
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue --max-results 10

# Cek hardcoded secrets di codebase
trufflehog git https://github.com/perusahaan/repo.git

Referensi

PADA HALAMAN INI