tutorial

  1. Studi Kasus: Mengamankan API gRPC Internal

Studi Kasus: Mengamankan API gRPC Internal

Dalam era modern pengembangan perangkat lunak, API gRPC semakin populer berkat performa, efisiensi serialisasi data, serta dukungan multi bahasa. gRPC banyak digunakan untuk service-to-service communication dalam arsitektur microservices, baik pada aplikasi cloud-native maupun enterprise. Namun, mengamankan API gRPC, terutama untuk konsumsi internal, sering kali dianggap remeh. Banyak tim development yang berasumsi bahwa API internal aman dari ancaman eksternal karena berada di dalam trusted network. Nyatanya, ada beragam skenario yang dapat mengekspos API internal pada risiko serius.

Artikel ini akan membahas studi kasus penerapan keamanan pada API gRPC internal. Kita akan mengeksplorasi ancaman utama, strategi mitigasinya, serta contoh kode dan arsitektur real-world yang bisa langsung diadopsi untuk mengamankan ekosistem gRPC-mu.


Ancaman pada API Internal

Banyak insiden keamanan besar dalam dua dekade terakhir karena kepercayaan berlebihan pada internal perimeter. Berikut ancaman umum pada API internal:

AncamanPenjelasan
Lateral MovementPenyerang yang berhasil masuk ke salah satu service/VM dapat berpindah ke service lain.
Data LeakageTanpa enkripsi, data sensitif dapat di-sniff di jaringan internal.
Unauthorized AccessTidak ada otentikasi/authorization sehingga service manapun bisa mengakses API internal.
Privilege EscalationService dengan hak akses terlalu luas bisa digunakan sebagai pintu masuk penyerang.
Service ImpersonationPenyerang menyamar sebagai service internal menggunakan custom client.

Studi Kasus: Payroll Service

Mari asumsikan sebuah arsitektur microservices sederhana di internal perusahaan fintech. Salah satu service penting adalah PayrollService, bertugas memproses gaji karyawan. Service ini hanya boleh diakses oleh HRService dan FinanceService.

Diagram Arsitektur

flowchart LR
    subgraph Internal Network
        HRService
        FinanceService
        PayrollService
    end
    HRService -- gRPC call --> PayrollService
    FinanceService -- gRPC call --> PayrollService

1. Mengaktifkan TLS pada gRPC

Secara default, gRPC menggunakan HTTP/2 tanpa harus TLS aktif (plaintext), namun ini rawan sniffing di internal LAN. Wajib hukumnya mengaktifkan TLS pada semua komunikasi gRPC, bahkan di internal.

Contoh Implementasi TLS di Go

Generate certificate:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=payroll.internal"

PayrollServer.go

import (
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

func main() {
    creds, err := credentials.NewServerTLSFromFile("cert.pem", "key.pem")
    if err != nil { log.Fatalf("failed to load cert: %v", err) }

    grpcServer := grpc.NewServer(grpc.Creds(creds))
    // register your service implementation...
}

Client dengan TLS:

conn, err := grpc.Dial(
    "payroll.internal:50051",
    grpc.WithTransportCredentials(credentials.NewClientTLSFromFile("cert.pem", "")),
)

Jangan pernah deploy service gRPC, bahkan di internal, tanpa TLS!


2. Service Authentication dan Mutual TLS (mTLS)

TLS melindungi data in-transit, namun tidak memastikan siapa klien atau server. Dengan mutual TLS, kedua pihak harus memperlihatkan digital certificate valid yang diterbitkan CA terpercaya.

Implementasi mTLS: PayrollService hanya menerima permintaan dari service yang sudah di-whitelist.

Generate CA, server dan client certificate

# Generate CA
openssl genrsa -out ca.key 4096
openssl req -x509 -new -key ca.key -sha256 -out ca.crt -subj "/CN=companyCA"

# Server key dan CSR
openssl genrsa -out payroll.key 4096
openssl req -new -key payroll.key -out payroll.csr -subj "/CN=payroll.internal"
openssl x509 -req -in payroll.csr -CA ca.crt -CAkey ca.key -out payroll.crt -CAcreateserial

# Client (misal HRService)
openssl genrsa -out hr.key 4096
openssl req -new -key hr.key -out hr.csr -subj "/CN=hr.internal"
openssl x509 -req -in hr.csr -CA ca.crt -CAkey ca.key -out hr.crt -CAcreateserial

Server (Go):

creds, _ := credentials.NewTLS(&tls.Config{
    ClientAuth: tls.RequireAndVerifyClientCert,
    Certificates: []tls.Certificate{serverCert},
    ClientCAs: caCertPool,  // berisi ca.crt
})
grpcServer := grpc.NewServer(grpc.Creds(creds))

Client (Go):

creds, _ := credentials.NewTLS(&tls.Config{
    Certificates: []tls.Certificate{clientCert}, // hr.crt & hr.key
    RootCAs: caCertPool, // ca.crt
})
conn, _ := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds))

Dengan skema ini, payroll service yakin yang terkoneksi adalah client terpercaya. Bila ada service lain mencoba connect tanpa sertifikat CA, request akan otomatis ditolak.


3. Authorization Layer: Membatasi Service yang Boleh Akses

Meskipun service sudah terautentikasi via mTLS, perlu juga authorization agar service hanya mengakses resource yang berhak.

Kita dapat menerapkan interceptors pada server untuk memeriksa CN (Common Name) dari sertifikat client.

Contoh Interceptor di Go:

import (
    "google.golang.org/grpc"
    "google.golang.org/grpc/peer"
)

func authorizeInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    p, ok := peer.FromContext(ctx)
    if !ok { return nil, status.Errorf(codes.PermissionDenied, "No peer found") }

    tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo)
    if !ok { return nil, status.Errorf(codes.PermissionDenied, "No TLS auth info") }

    cn := tlsInfo.State.PeerCertificates[0].Subject.CommonName
    if cn != "hr.internal" && cn != "finance.internal" {
        return nil, status.Errorf(codes.PermissionDenied, "Unauthorized service: %s", cn)
    }

    return handler(ctx, req)
}

grpcServer := grpc.NewServer(grpc.Creds(creds), grpc.UnaryInterceptor(authorizeInterceptor))

4. Audit dan Rate Limit

Kombinasi audit log dan rate limit dapat membatasi peluang abuse, terutama pada API payroll yang sangat sensitif.

  • Implementasi rate limiter sisi server misal dengan ratelimit library.
  • Simpan audit log setiap request beserta client CN agar traceable jika terjadi insiden.

5. Summary Best Practices

PraktikRekomendasi
Transport securitySelalu gunakan TLS, meski di “trusted” network
Service identityTerapkan mTLS dan PKI internal
AuthorizationValidasi CN di setiap request, whitelist service tertentu
Rate LimitBatasi frekuensi call ke API sensitif
Audit LogCatat semua call beserta identitas ke dalam log terproteksi
Cert managementOtomatiskan rotasi dan distribusi certificate, misal via cert-manager

Flow Data Protection PayrollService

sequenceDiagram
    participant HR as HRService (Client)
    participant PS as PayrollService (Server)
    Note left of HR: Hold mTLS Cert (CN=hr.internal)
    Note right of PS: Hold mTLS Cert (CN=payroll.internal)

    HR->>PS: Initiate gRPC TLS handshake
    HR-->>PS: Present client cert
    PS-->>HR: Present server cert
    PS->>PS: Verify client CN == Whitelist
    HR->>PS: PayrollRequest (berhasil jika mTLS & CN OK)
    PS-->>HR: PayrollResponse

    Note over HR,PS: Semua data terenkripsi & terotorisasi end-to-end

Kesimpulan

Meskipun gRPC biasanya diterapkan pada internal service, menganggap API internal aman bagaikan menganggap rumah tanpa pintu cukup karena berada di lingkungan “aman”. Nyatanya, ancaman siber berkembang; peluang lateral movement, sniffing, hingga eksfiltrasi data bisa terjadi kapan saja. Penerapan TLS, mTLS, authorization per service, serta audit log sudah menjadi minimum viable security pada ekosistem gRPC internal.

Mulailah dengan mengaktifkan TLS hari ini. Lanjutkan ke mTLS dan selanjutnya, otomasikan deployment sertifikat via proper secret management. Budayakan zero trust – waspadai serangan dari dalam dan luar perimeter. Saat insiden terjadi, audit log adalah penyelamat. Semoga dengan studi kasus PayrollService ini, Anda lebih siap membangun gRPC internal yang secure by design.


Referensi:

comments powered by Disqus