Halaman ini menjelaskan cara mengamankan aplikasi dengan header IAP yang ditandatangani. Jika dikonfigurasi, Identity-Aware Proxy (IAP) akan menggunakan JSON Web Token (JWT) untuk memastikan bahwa permintaan ke aplikasi Anda diotorisasi. Cara ini melindungi aplikasi Anda dari jenis risiko berikut:
- IAP dinonaktifkan secara tidak sengaja;
- {i>Firewall<i} yang salah dikonfigurasi;
- Akses dari dalam project.
Untuk mengamankan aplikasi dengan benar, Anda harus menggunakan header bertanda tangan untuk semua jenis aplikasi.
Atau, jika Anda memiliki aplikasi lingkungan standar App Engine, Users API dapat digunakan.
Perlu diperhatikan bahwa health check Compute Engine dan GKE tidak menyertakan header JWT, dan IAP tidak menangani health check. Jika health check Anda menampilkan error akses, pastikan Anda mengonfigurasinya dengan benar di Konsol Google Cloud dan validasi header JWT Anda mengizinkan jalur health check. Untuk mengetahui informasi selengkapnya, lihat Membuat pengecualian health check.
Sebelum memulai
Untuk mengamankan aplikasi dengan header yang ditandatangani, Anda akan memerlukan hal berikut:
- Aplikasi yang Anda inginkan untuk terhubung dengan pengguna.
- Library JWT pihak ketiga untuk bahasa Anda yang mendukung
algoritma
ES256
.
Mengamankan aplikasi Anda dengan header IAP
Untuk mengamankan aplikasi Anda dengan JWT IAP, verifikasi header,
payload, dan tanda tangan JWT. JWT berada di x-goog-iap-jwt-assertion
header permintaan HTTP. Jika penyerang mengabaikan IAP, mereka
dapat memalsukan header identitas tanpa tanda tangan IAP,
x-goog-authenticated-user-{email,id}
. IAP JWT menyediakan
alternatif yang lebih aman.
Header bertanda tangan memberikan keamanan sekunder jika seseorang mengabaikan
IAP. Perlu diperhatikan bahwa jika diaktifkan, IAP
akan menghapus header x-goog-*
yang disediakan oleh klien saat permintaan melewati
infrastruktur penyaluran IAP.
Memverifikasi header JWT
Verifikasi bahwa header JWT sesuai dengan batasan berikut:
Klaim Header JWT | ||
---|---|---|
alg |
Algoritma | ES256 |
kid |
ID Kunci |
Harus sesuai dengan salah satu kunci publik yang tercantum dalam file kunci IAP, yang tersedia dalam dua format berbeda: https://www.gstatic.com/iap/verify/public_key dan https://www.gstatic.com/iap/verify/public_key-jwk
|
Pastikan JWT ditandatangani oleh kunci pribadi yang sesuai dengan
klaim kid
token. Untuk melakukannya, pertama-tama ambil kunci publik dari salah satu dari dua tempat:
https://www.gstatic.com/iap/verify/public_key
. URL ini berisi kamus JSON yang memetakan klaimkid
ke nilai kunci publik.https://www.gstatic.com/iap/verify/public_key-jwk
. URL ini berisi kunci publik IAP dalam format JWK.
Setelah Anda memiliki kunci publik, gunakan library JWT untuk memverifikasi tanda tangan.
Memverifikasi payload JWT
Verifikasi bahwa payload JWT sesuai dengan batasan berikut:
Klaim Payload JWT | ||
---|---|---|
exp |
Waktu habis masa berlaku | Harus di masa depan. Waktu diukur dalam hitungan detik sejak epoch UNIX. Tunggu 30 detik agar lebih miring. Masa aktif maksimum token adalah 10 menit + 2 * kemiringan. |
iat |
Waktu penerbitan | Harus di masa lalu. Waktu diukur dalam hitungan detik sejak epoch UNIX. Tunggu 30 detik agar lebih miring. |
aud |
Audience |
Harus berupa string dengan nilai berikut:
|
iss |
Penerbit |
Harus berupa https://cloud.google.com/iap .
|
hd |
Domain akun |
Jika akun termasuk dalam domain yang dihosting, klaim hd akan diberikan untuk membedakan domain yang terkait dengan akun tersebut.
|
google |
klaim Google |
Jika satu atau beberapa tingkat akses
diterapkan pada permintaan, namanya akan disimpan dalam objek JSON
klaim google , pada kunci access_levels , sebagai array
string.
Saat Anda menentukan kebijakan perangkat dan Organisasi memiliki akses ke data perangkat, |
Anda bisa mendapatkan nilai untuk string aud
yang disebutkan di atas dengan mengakses Konsol Google Cloud, atau Anda dapat menggunakan alat command line gcloud.
Untuk mendapatkan nilai string aud
dari Konsol Google Cloud, buka
setelan Identity-Aware Proxy
untuk project Anda, klik More di samping resource Load Balancer, lalu pilih
Signed Header JWT Audience. Dialog Signed Header JWT
yang muncul menampilkan klaim aud
untuk resource yang dipilih.
Jika ingin menggunakan alat command line gcloud gcloud CLI untuk mendapatkan nilai string aud
, Anda harus mengetahui project ID. Anda dapat menemukan project ID di kartu Project info Google Cloud Console, lalu menjalankan perintah yang ditentukan di bawah untuk setiap nilai.
Nomor project
Untuk mendapatkan nomor project Anda menggunakan alat command line gcloud, jalankan perintah berikut:
gcloud projects describe PROJECT_ID
Perintah tersebut akan menampilkan output seperti berikut:
createTime: '2016-10-13T16:44:28.170Z' lifecycleState: ACTIVE name: project_name parent: id: '433637338589' type: organization projectId: PROJECT_ID projectNumber: 'PROJECT_NUMBER'
ID Layanan
Untuk mendapatkan ID layanan menggunakan alat command line gcloud, jalankan perintah berikut:
gcloud compute backend-services describe SERVICE_NAME --project=PROJECT_ID --global
Perintah tersebut akan menampilkan output seperti berikut:
affinityCookieTtlSec: 0 backends: - balancingMode: UTILIZATION capacityScaler: 1.0 group: https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/instanceGroups/my-group connectionDraining: drainingTimeoutSec: 0 creationTimestamp: '2017-04-03T14:01:35.687-07:00' description: '' enableCDN: false fingerprint: zaOnO4k56Cw= healthChecks: - https://www.googleapis.com/compute/v1/projects/project_name/global/httpsHealthChecks/my-hc id: 'SERVICE_ID' kind: compute#backendService loadBalancingScheme: EXTERNAL name: my-service port: 8443 portName: https protocol: HTTPS selfLink: https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/my-service sessionAffinity: NONE timeoutSec: 3610
Mengambil identitas pengguna
Jika semua verifikasi di atas berhasil, ambil identitas pengguna. Payload token ID berisi informasi pengguna berikut:
Identitas Pengguna Payload Token ID | ||
---|---|---|
sub |
Subjek |
ID yang unik dan stabil untuk pengguna. Gunakan nilai ini, bukan
header x-goog-authenticated-user-id .
|
email |
Email pengguna | Alamat email pengguna.
|
Berikut ini beberapa kode contoh untuk mengamankan aplikasi dengan header IAP yang ditandatangani:
C#
Go
Java
Node.js
PHP
Python
Ruby
Menguji kode validasi Anda
Jika Anda membuka aplikasi menggunakan parameter kueri secure_token_test
, IAP akan menyertakan JWT yang tidak valid. Gunakan ini untuk memastikan logika validasi JWT Anda menangani semua berbagai kasus kegagalan, dan untuk melihat perilaku aplikasi saat menerima JWT yang tidak valid.
Membuat pengecualian health check
Seperti yang disebutkan sebelumnya, health check Compute Engine dan GKE tidak menggunakan header JWT dan IAP tidak menangani health check. Anda harus mengonfigurasi health check dan aplikasi untuk mengizinkan akses health check.
Mengonfigurasi health check
Jika Anda belum menetapkan jalur untuk health check, gunakan Konsol Google Cloud untuk menetapkan jalur tidak sensitif untuk health check. Pastikan jalur ini tidak digunakan bersama oleh resource lain.
- Buka halaman Health check di konsol Google Cloud.
Buka halaman Health check - Klik health check yang Anda gunakan untuk aplikasi, lalu klik Edit.
- Di bagian Jalur permintaan, tambahkan nama jalur yang tidak sensitif. Kolom ini menentukan
jalur URL yang digunakan Google Cloud saat mengirim permintaan health check.
Jika dihapus, permintaan health check akan dikirimkan ke
/
. - Klik Save.
Mengonfigurasi validasi JWT
Dalam kode yang memanggil rutinitas validasi JWT, tambahkan kondisi untuk menampilkan status HTTP 200 untuk jalur permintaan health check Anda. Contoh:
if HttpRequest.path_info = '/HEALTH_CHECK_REQUEST_PATH' return HttpResponse(status=200) else VALIDATION_FUNCTION
JWT untuk identitas eksternal
Jika Anda menggunakan IAP dengan identitas eksternal, IAP akan tetap mengeluarkan JWT bertanda tangan pada setiap permintaan terautentikasi, seperti yang dilakukan dengan identitas Google. Namun, ada beberapa perbedaan.
Informasi penyedia
Saat menggunakan identitas eksternal, payload JWT akan berisi klaim yang bernama gcip
. Klaim ini berisi informasi tentang pengguna, seperti URL
email dan foto, serta atribut khusus penyedia lainnya.
Berikut ini adalah contoh JWT untuk pengguna yang masuk dengan Facebook:
"gcip": '{
"auth_time": 1553219869,
"email": "facebook_user@gmail.com",
"email_verified": false,
"firebase": {
"identities": {
"email": [
"facebook_user@gmail.com"
],
"facebook.com": [
"1234567890"
]
},
"sign_in_provider": "facebook.com",
},
"name": "Facebook User",
"picture: "https://graph.facebook.com/1234567890/picture",
"sub": "gZG0yELPypZElTmAT9I55prjHg63"
}',
Kolom email
dan sub
Jika pengguna diautentikasi oleh Identity Platform, kolom email
dan sub
pada JWT akan diawali dengan penerbit token Identity Platform dan ID tenant yang digunakan (jika ada). Contoh:
"email": "securetoken.google.com/PROJECT-ID/TENANT-ID:demo_user@gmail.com", "sub": "securetoken.google.com/PROJECT-ID/TENANT-ID:gZG0yELPypZElTmAT9I55prjHg63"
Mengontrol akses dengan sign_in_attributes
IAM tidak didukung untuk digunakan dengan identitas eksternal, tetapi
Anda dapat menggunakan klaim yang disematkan di kolom sign_in_attributes
untuk mengontrol
akses. Misalnya, pertimbangkan pengguna yang login menggunakan penyedia SAML:
{
"aud": "/projects/project_number/apps/my_project_id",
"gcip": '{
"auth_time": 1553219869,
"email": "demo_user@gmail.com",
"email_verified": true,
"firebase": {
"identities": {
"email": [
"demo_user@gmail.com"
],
"saml.myProvider": [
"demo_user@gmail.com"
]
},
"sign_in_attributes": {
"firstname": "John",
"group": "test group",
"role": "admin",
"lastname": "Doe"
},
"sign_in_provider": "saml.myProvider",
"tenant": "my_tenant_id"
},
"sub": "gZG0yELPypZElTmAT9I55prjHg63"
}',
"email": "securetoken.google.com/my_project_id/my_tenant_id:demo_user@gmail.com",
"exp": 1553220470,
"iat": 1553219870,
"iss": "https://cloud.google.com/iap",
"sub": "securetoken.google.com/my_project_id/my_tenant_id:gZG0yELPypZElTmAT9I55prjHg63"
}
Anda dapat menambahkan logika ke aplikasi yang mirip dengan kode di bawah ini untuk membatasi akses bagi pengguna dengan peran yang valid:
const gcipClaims = JSON.parse(decodedIapJwtClaims.gcip);
if (gcipClaims &&
gcipClaims.firebase &&
gcipClaims.firebase.sign_in_attributes &&
gcipClaims.firebase.sign_in_attribute.role === 'admin') {
// Allow access to admin restricted resource.
} else {
// Block access.
}
Atribut pengguna tambahan dari penyedia SAML dan OIDC Identity Platform dapat diakses menggunakan klaim bertingkat gcipClaims.gcip.firebase.sign_in_attributes
.
Batasan ukuran klaim IdP
Setelah pengguna login dengan Identity Platform, atribut pengguna tambahan akan diterapkan ke payload token ID Platform Identitas stateless yang akan diteruskan dengan aman ke IAP. Kemudian, IAP akan mengeluarkan cookie buram statelessnya sendiri yang juga berisi klaim yang sama. IAP akan menghasilkan header JWT yang ditandatangani berdasarkan konten cookie.
Akibatnya, jika sebuah sesi dimulai dengan sejumlah besar klaim, sesi tersebut mungkin melebihi ukuran cookie maksimum yang diizinkan, yaitu biasanya ~4 KB di sebagian besar browser. Hal ini akan menyebabkan operasi login gagal.
Anda harus memastikan bahwa hanya klaim yang diperlukan yang disebarkan di atribut SAML IdP atau OIDC. Opsi lainnya adalah menggunakan fungsi pemblokiran untuk memfilter klaim yang tidak diperlukan untuk pemeriksaan otorisasi.
const gcipCloudFunctions = require('gcip-cloud-functions');
const authFunctions = new gcipCloudFunctions.Auth().functions();
// This function runs before any sign-in operation.
exports.beforeSignIn = authFunctions.beforeSignInHandler((user, context) => {
if (context.credential &&
context.credential.providerId === 'saml.my-provider') {
// Get the original claims.
const claims = context.credential.claims;
// Define this function to filter out the unnecessary claims.
claims.groups = keepNeededClaims(claims.groups);
// Return only the needed claims. The claims will be propagated to the token
// payload.
return {
sessionClaims: claims,
};
}
});