Microservice Anda berbagi VPC, sehingga mereka saling mempercayai. Kepercayaan itu adalah ambient authority: izin untuk memanggil service diberikan bukan oleh bukti kriptografis, melainkan oleh topologi jaringan. Penyerang yang menembus perimeter mewarisi semuanya.
Service benar-benar dapat mengautentikasi tanpa ambient authority. Pertanyaan yang lebih sulit adalah mengapa platform Anda membuatnya terasa seperti pengkhianatan.
Seperti apa ambient authority di produksi
Sebagian besar “autentikasi” antar-service sebenarnya hanyalah segmentasi jaringan. Service berada di subnet privat, di belakang API gateway, atau di dalam cluster Kubernetes dengan service mesh. Asumsinya sederhana: jika permintaan berasal dari IP internal, maka itu sah.
Model ini runtuh ketika perimeter runtuh. Pod yang terkompromi, pergerakan lateral setelah kebocoran kredensial, atau injeksi supply chain menempatkan penyerang di dalam zona kepercayaan. Pada titik itu, setiap service terjangkau dan sebagian besar tidak akan meminta bukti identitas. Penyerang tidak perlu mencuri lebih banyak kredensial. Mereka hanya mewarisi ambient authority dari jaringan.
Autentikasi yang sebenarnya antar-service berarti setiap pemanggil membuktikan siapa dirinya, dan setiap yang dipanggil memverifikasi bukti tersebut. Jaringan hanyalah transport. Jaringan tidak boleh menjadi kredensial.
Cara kerja autentikasi service berbasis capability
Ada dua pendekatan praktis: identitas kriptografis (setiap service memiliki nama yang dapat dibuktikan) dan capability token (setiap permintaan membawa otorisasi scoped yang tidak dapat dipalsukan).
Identitas kriptografis dengan mTLS
Dalam mutual TLS, baik client maupun server menyajikan sertifikat X.509. Server memverifikasi sertifikat client sebelum menangani permintaan. Client memverifikasi sertifikat server sebelum mengirim data. Tidak ada pihak yang mempercayai pihak lain karena alamat IP.
Tantangan infrastruktur adalah distribusi sertifikat. SPIFFE dan SPIRE menyelesaikan ini dengan memberikan setiap workload identitas kriptografis yang diturunkan dari propertinya, bukan dari lokasinya. Pod yang menjalankan payments-api mendapatkan SPIFFE ID seperti spiffe://prod.example.com/payments-api. Sertifikatnya berumur pendek dan dirotasi secara otomatis.
Berikut tampilannya di Go:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"net/http"
"os"
)
// loadClientTLS returns a config that verifies the server AND presents a client cert.
func loadClientTLS(caCert, clientCert, clientKey []byte) *tls.Config {
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caCert)
cert, err := tls.X509KeyPair(clientCert, clientKey)
if err != nil {
log.Fatalf("failed to load client cert: %v", err)
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: pool,
// Do not skip verification based on IP or DNS name alone.
InsecureSkipVerify: false,
}
}
func main() {
caCert, _ := os.ReadFile("ca.crt")
clientCert, _ := os.ReadFile("service.crt")
clientKey, _ := os.ReadFile("service.key")
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: loadClientTLS(caCert, clientCert, clientKey),
},
}
resp, err := client.Get("https://orders-api.internal:8443/orders")
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Status)
}
Baris kritisnya adalah InsecureSkipVerify: false. Tanpa itu, Anda kembali ke ambient trust. Dengan itu, client menolak untuk terhubung kecuali server menyajikan sertifikat yang valid yang ditandatangani oleh CA. Server melakukan hal yang sama untuk client.
Capability token untuk otorisasi scoped
Sertifikat membuktikan identitas. Capabilities membuktikan otorisasi. Di banyak sistem, Anda menginginkan keduanya: buktikan siapa Anda, lalu buktikan bahwa Anda diizinkan melakukan hal spesifik ini.
Capability token mengikat identitas, sebuah action, dan sebuah resource menjadi package yang tidak dapat dipalsukan. Service mencetaknya. Service memverifikasinya. Tidak ada penyimpanan sesi sentral yang harus di-query.
import hmac
import hashlib
import secrets
import time
SECRET = secrets.token_bytes(32)
def mint_service_capability(
caller_id: str,
service: str,
action: str,
resource: str,
ttl_seconds: int = 300
) -> str:
"""Mint a time-bound capability for a specific service action."""
expires = int(time.time()) + ttl_seconds
payload = f"{caller_id}:{service}:{action}:{resource}:{expires}"
sig = hmac.new(SECRET, payload.encode(), hashlib.sha256).hexdigest()[:24]
return f"{payload}:{sig}"
def verify_service_capability(
token: str,
expected_service: str,
expected_action: str,
expected_resource: str
) -> bool:
"""Verify a capability token is unexpired and correctly scoped."""
try:
caller_id, svc, action, resource, expires, sig = token.rsplit(":", 5)
except ValueError:
return False
if int(expires) < time.time():
return False
if svc != expected_service or action != expected_action or resource != expected_resource:
return False
payload = f"{caller_id}:{svc}:{action}:{resource}:{expires}"
expected_sig = hmac.new(SECRET, payload.encode(), hashlib.sha256).hexdigest()[:24]
return hmac.compare_digest(sig, expected_sig)
# Service A requests a capability to call Service B.
token = mint_service_capability("payments-api", "orders-api", "read", "order-123")
# Service B verifies the capability before handling the request.
if not verify_service_capability(token, "orders-api", "read", "order-123"):
raise PermissionError("Invalid or expired capability")
Tokennya self-contained dan berumur pendek. Service B tidak perlu memanggil authorization server. Ia hanya memeriksa HMAC dan masa berlakunya. Scopenya eksplisit: token ini hanya valid untuk membaca order-123 dari orders-api.
Mengapa ini lebih sulit dari yang seharusnya
Teknologinya sudah ada. Kesulitannya adalah operasional.
Bootstrapping trust adalah masalah pertama. Jika setiap service membutuhkan sertifikat, sesuatu harus menerbitkan sertifikat tersebut. Sesuatu itu, certificate authority atau server SPIRE, menjadi target baru. Anda belum menghilangkan kepercayaan. Anda memusatkannya.
Ada juga masalah revocation. Jika sebuah service terkompromi, bagaimana Anda membatalkan identitasnya? Sertifikat mTLS bisa berumur pendek, yang membantu, tetapi mencabut sertifikat tertentu masih memerlukan distribusi certificate revocation list atau penggunaan OCSP. Capability token kedaluwarsa dengan cepat, yang membatasi kerusakan, tetapi kunci signing yang dicuri memungkinkan penyerang mencetak token tanpa batas.
Performa adalah masalah lain. TLS handshake menambah latensi. Di service mesh dengan sidecar, overheadnya biasanya dapat diterima (beberapa milidetik), tetapi di jalur throughput tinggi, milidetik-milidetik itu terakumulasi. Capability token menghindari round trip ke auth server, tetapi verifikasi HMAC tidak gratis dalam skala besar.
Di mana ambient authority masih masuk akal
Tidak setiap panggilan internal membutuhkan bukti kriptografis. Cron job yang berjalan di dalam container yang sama dengan client database tidak memerlukan mTLS untuk berbicara ke localhost. Health check antara load balancer dan node tidak membutuhkan capability token.
Tujuannya bukan ambient authority nol. Tujuannya adalah mengetahui di mana ambient authority Anda berada dan apakah blast radius-nya dapat diterima. VPC bersama dengan 200 service dan tanpa autentikasi internal adalah blast radius yang besar dan tak terlihat. Socket Unix lokal dengan izin file 0600 adalah blast radius yang kecil dan eksplisit.
Cara mulai menghilangkan ambient authority dari panggilan service
Anda tidak membutuhkan service mesh di hari pertama. Mulailah dari service yang menyentuh data sensitif atau berada di trust boundaries.
Pertama, identifikasi wakil Anda. Service mana yang memiliki hak istimewa yang tidak dimiliki oleh yang lain? API internal mana yang akan berbahaya jika dipanggil oleh service yang salah? Itulah kandidat Anda.
Kedua, tambahkan mTLS ke lapisan API. Jika Anda menggunakan reverse proxy seperti Envoy atau NGINX, Anda dapat melakukan terminasi mTLS di sana tanpa mengubah kode aplikasi. Proxy meneruskan header dengan identitas client yang terverifikasi ke upstream. Upstream memeriksa header tersebut.
Ketiga, scope token Anda. Jika Anda sudah menggunakan JWT untuk autentikasi service, berhenti memasukkan role: service ke dalam payload. Masukkan allowed_services: ["orders-api"] dan allowed_resources: ["order:*"]. Jadikan otorisasi seterinci operasinya.
Pertanyaan yang sering diajukan tentang autentikasi service tanpa ambient authority
Apakah mTLS sudah cukup, atau apakah saya juga membutuhkan capabilities?
mTLS membuktikan identitas. Capabilities membuktikan otorisasi. Keduanya menyelesaikan masalah yang berbeda. Service dengan sertifikat yang valid seharusnya tetap tidak diizinkan menghapus data sewenang-wenang. Gunakan mTLS untuk transport security dan identitas, capabilities untuk access control.
Bagaimana dengan service mesh seperti Istio atau Linkerd?
Service mesh mengotomatiskan mTLS dan identitas antar-pod. Mereka adalah cara praktis untuk menghilangkan ambient authority tanpa menulis ulang setiap service. Mesh menangani certificate rotation, identity attestation, dan encryption lalu lintas. Komprominya adalah kompleksitas dan control plane baru yang harus diamankan.
Apakah ini berfungsi untuk serverless function?
Ya, tetapi lebih sulit. Serverless function bersifat ephemeral, sehingga certificate rotation dan identity attestation perlu terjadi pada saat invocation. Cloud provider menawarkan workload identity untuk ini (AWS IAM Roles for Service Accounts, GCP Workload Identity). Ini bersifat capability-like: function menerima token yang scoped sesuai dengan apa yang diizinkan untuk dilakukannya, bukan kredensial menyeluruh.
Apa perbedaan antara service account dan capability?
Service account adalah identitas yang secara default membawa ambient authority. Jika Service A berjalan sebagai payments-sa, biasanya ia dapat melakukan apa pun yang diizinkan untuk payments-sa. Capability di-scoped ke action spesifik pada resource spesifik. Bahkan jika capability dicuri, ia tidak dapat direplay ke target yang berbeda.
Mulailah dari perimeter yang sudah Anda miliki
VPC Anda tidak pernah menjadi security boundary. Ia adalah network boundary yang kita pura-pura jadikan security boundary. Menghilangkan ambient authority berarti memperlakukan setiap panggilan service seolah-olah melintasi batas itu. Identitas kriptografis dan capability scoped adalah alatnya. Bagian yang sulit adalah mengakui bahwa model lama adalah kemudahan yang dikemas sebagai keamanan.
Pilih satu API internal. Tambahkan verifikasi client certificate. Amati apa yang rusak. Sebagian besar waktu, hal yang rusak adalah asumsi yang tidak Anda ketahui sedang dibuat oleh kode Anda.