Men-deploy ke Cloud Run dengan Aman

1. Ringkasan

Anda akan mengubah langkah-langkah default untuk men-deploy layanan ke Cloud Run guna meningkatkan keamanan, lalu melihat cara mengakses aplikasi yang di-deploy dengan aman. Aplikasi ini adalah "layanan pendaftaran partner" dari aplikasi Cymbal Eats, yang digunakan oleh perusahaan yang bekerja sama dengan Cymbal Eats untuk memproses pesanan makanan.

Yang akan Anda pelajari

Dengan melakukan beberapa perubahan kecil pada langkah default minimal untuk men-deploy aplikasi ke Cloud Run, Anda dapat meningkatkan keamanannya secara signifikan. Anda akan mengambil aplikasi dan petunjuk deployment yang ada, lalu mengubah langkah-langkah deployment untuk meningkatkan keamanan aplikasi yang di-deploy.

Kemudian, Anda akan melihat cara memberikan otorisasi akses ke aplikasi dan membuat permintaan yang diotorisasi.

Ini bukan gambaran lengkap tentang keamanan deployment aplikasi, tetapi merupakan gambaran tentang perubahan yang dapat Anda lakukan pada semua deployment aplikasi mendatang yang akan meningkatkan keamanannya dengan sedikit upaya.

2. Penyiapan dan Persyaratan

Penyiapan lingkungan mandiri

  1. Login ke Google Cloud Console dan buat project baru atau gunakan kembali project yang sudah ada. Jika belum memiliki akun Gmail atau Google Workspace, Anda harus membuatnya.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Project name adalah nama tampilan untuk peserta project ini. String ini adalah string karakter yang tidak digunakan oleh Google API. Anda dapat memperbaruinya kapan saja.
  • Project ID bersifat unik di semua project Google Cloud dan tidak dapat diubah (tidak dapat diubah setelah ditetapkan). Cloud Console otomatis membuat string unik; biasanya Anda tidak mementingkan kata-katanya. Di sebagian besar codelab, Anda harus merujuk Project ID-nya (umumnya diidentifikasi sebagai PROJECT_ID). Jika tidak suka dengan ID yang dibuat, Anda dapat membuat ID acak lainnya. Atau, Anda dapat mencobanya sendiri dan melihat apakah ID tersebut tersedia. ID tidak dapat diubah setelah langkah ini dan akan tetap ada selama durasi project.
  • Sebagai informasi, ada nilai ketiga, Project Number, yang digunakan oleh beberapa API. Pelajari lebih lanjut ketiga nilai ini di dokumentasi.
  1. Selanjutnya, Anda harus mengaktifkan penagihan di Konsol Cloud untuk menggunakan resource/API Cloud. Menjalankan operasi dalam codelab ini seharusnya tidak memerlukan banyak biaya, bahkan mungkin tidak sama sekali. Guna mematikan resource agar tidak menimbulkan penagihan di luar tutorial ini, Anda dapat menghapus resource yang dibuat atau menghapus seluruh project. Pengguna baru Google Cloud memenuhi syarat untuk mengikuti program Uji Coba Gratis senilai $300 USD.

Mengaktifkan Cloud Shell

  1. Dari Cloud Console, klik Aktifkan Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jika belum pernah memulai Cloud Shell, Anda akan melihat layar perantara (di paruh bawah) yang menjelaskan apa itu Cloud Shell. Jika memang demikian, klik Lanjutkan (dan Anda tidak akan pernah melihatnya lagi). Berikut tampilan layar sekali-tampil tersebut:

9c92662c6a846a5c.png

Perlu waktu beberapa saat untuk penyediaan dan terhubung ke Cloud Shell.

9f0e51b578fecce5.png

Virtual machine ini berisi semua alat pengembangan yang Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Sebagian besar pekerjaan Anda dalam codelab ini dapat dilakukan hanya dengan browser atau Chromebook.

Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke project ID Anda.

  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa Anda telah diautentikasi:
gcloud auth list

Output perintah

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda:
gcloud config list project

Output perintah

[core]
project = <PROJECT_ID>

Jika tidak, Anda dapat menyetelnya dengan perintah ini:

gcloud config set project <PROJECT_ID>

Output perintah

Updated property [core/project].

Penyiapan Lingkungan

Anda akan menjalankan perintah di command line Cloud Shell untuk lab ini. Anda biasanya dapat menyalin perintah dan menempelkannya apa adanya, meskipun dalam beberapa kasus Anda perlu mengubah nilai placeholder menjadi nilai yang benar.

  1. Tetapkan variabel lingkungan ke Project ID untuk digunakan dalam perintah selanjutnya:
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export SERVICE_NAME=partner-registration-service
  1. Aktifkan API layanan Cloud Run yang akan menjalankan aplikasi Anda, Firestore API yang akan menyediakan penyimpanan data NoSQL, Cloud Build API yang akan digunakan oleh perintah deployment, dan Artifact Registry yang akan digunakan untuk menyimpan penampung aplikasi saat di-build:
gcloud services enable \
  run.googleapis.com \
  firestore.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com
  1. Lakukan inisialisasi database Firestore dalam mode Native. Perintah tersebut menggunakan App Engine API, sehingga harus diaktifkan terlebih dahulu.

Perintah ini harus menentukan region untuk App Engine, yang tidak akan kita gunakan, tetapi harus dibuat karena alasan historis, dan region untuk database. Kita akan menggunakan us-central untuk App Engine, dan nam5 untuk database. nam5 adalah lokasi multi-region Amerika Serikat. Lokasi multi-region memaksimalkan ketersediaan dan ketahanan database.

gcloud services enable appengine.googleapis.com

gcloud app create --region=us-central
gcloud firestore databases create --region=nam5
  1. Clone repositori aplikasi contoh dan buka direktori
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git

cd cymbal-eats/partner-registration-service

3. Meninjau README

Buka editor dan lihat file yang menyusun aplikasi. Lihat README.md, yang menjelaskan langkah-langkah yang diperlukan untuk men-deploy aplikasi ini. Beberapa langkah ini mungkin melibatkan keputusan keamanan implisit atau eksplisit yang perlu dipertimbangkan. Anda akan mengubah beberapa pilihan ini untuk meningkatkan keamanan aplikasi yang di-deploy, seperti yang dijelaskan di sini:

Langkah 3 - Jalankan npm install

Penting untuk mengetahui asal dan integritas software pihak ketiga yang digunakan dalam aplikasi. Mengelola Keamanan Supply Chain Software relevan untuk mem-build software apa pun, bukan hanya aplikasi yang di-deploy ke Cloud Run. Lab ini berfokus pada deployment, sehingga tidak membahas area ini, tetapi Anda dapat meneliti topik ini secara terpisah.

Langkah 4 dan 5 - Edit dan jalankan deploy.sh

Langkah-langkah ini men-deploy aplikasi ke Cloud Run dengan membiarkan sebagian besar opsi tetap menggunakan setelan default. Anda akan mengubah langkah ini untuk membuat deployment lebih aman dengan dua cara utama:

  1. Jangan izinkan akses yang tidak diautentikasi. Anda dapat mengizinkannya untuk mencoba berbagai hal selama eksplorasi, tetapi ini adalah layanan web untuk digunakan oleh partner komersial, dan harus selalu mengautentikasi penggunanya.
  2. Tentukan bahwa aplikasi harus menggunakan akun layanan khusus yang disesuaikan hanya dengan hak istimewa yang diperlukan, bukan akun layanan default yang kemungkinan akan memiliki lebih banyak akses API dan resource daripada yang diperlukan. Hal ini dikenal sebagai prinsip hak istimewa terendah, dan merupakan konsep dasar keamanan aplikasi.

Langkah 6 hingga 11 - Buat contoh permintaan web untuk memverifikasi perilaku yang benar

Karena deployment aplikasi kini memerlukan autentikasi, permintaan ini kini harus menyertakan bukti identitas pemohon. Daripada mengubah file ini, Anda akan membuat permintaan langsung dari command line.

4. Men-deploy layanan dengan aman

Ada dua perubahan yang diidentifikasi sebagai diperlukan dalam skrip deploy.sh: tidak mengizinkan akses yang tidak diautentikasi, dan menggunakan akun layanan khusus dengan hak istimewa minimal.

Anda akan membuat akun layanan baru terlebih dahulu, lalu mengedit skrip deploy.sh untuk mereferensikan akun layanan tersebut dan melarang akses yang tidak diautentikasi, lalu men-deploy layanan dengan menjalankan skrip yang diubah sebelum kita dapat menjalankan skrip deploy.sh yang diubah.

Membuat akun layanan dan memberinya akses yang diperlukan ke Firestore/Datastore

gcloud iam service-accounts create partner-sa

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:partner-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role=roles/datastore.user

Edit deploy.sh

Ubah file deploy.sh untuk melarang akses yang tidak diautentikasi(–no-allow-unauthenticated), dan untuk menentukan akun layanan baru(–service-account) untuk aplikasi yang di-deploy. Perbaiki GOOGLE_PROJECT_ID menjadi ID project Anda sendiri.

Anda akan menghapus dua baris pertama, dan mengubah tiga baris lainnya seperti yang ditunjukkan di bawah.

gcloud run deploy $SERVICE_NAME \
  --source . \
  --platform managed \
  --region ${REGION} \
  --no-allow-unauthenticated \
  --project=$PROJECT_ID \
  --service-account=partner-sa@${PROJECT_ID}.iam.gserviceaccount.com

Men-deploy layanan

Dari command line, jalankan skrip deploy.sh:

./deploy.sh

Setelah deployment selesai, baris terakhir output perintah akan menampilkan URL Layanan aplikasi baru. Simpan URL dalam variabel lingkungan:

export SERVICE_URL=<URL from last line of command output>

Sekarang, coba ambil pesanan dari aplikasi menggunakan alat curl:

curl -i -X GET $SERVICE_URL/partners

Flag -i untuk perintah curl memberi tahu perintah untuk menyertakan header respons dalam output. Baris pertama output harus berupa:

HTTP/2 403

Aplikasi di-deploy dengan opsi untuk melarang permintaan yang tidak diautentikasi. Perintah curl ini tidak berisi informasi autentikasi, sehingga ditolak oleh Cloud Run. Aplikasi yang di-deploy sebenarnya bahkan tidak menjalankan atau menerima data apa pun dari permintaan ini.

5. Membuat Permintaan yang Diautentikasi

Aplikasi yang di-deploy dipanggil dengan membuat permintaan web, yang sekarang harus diautentikasi agar Cloud Run mengizinkannya. Permintaan web diautentikasi dengan menyertakan header Authorization dalam bentuk:

Authorization: Bearer identity-token

Token identitas adalah string berjangka pendek yang ditandatangani secara kriptografis dan dienkode yang dikeluarkan oleh penyedia autentikasi tepercaya. Dalam hal ini, token identitas yang valid dan belum habis masa berlakunya yang diterbitkan Google diperlukan.

Membuat permintaan sebagai akun pengguna Anda

Alat Google Cloud CLI dapat memberikan token untuk pengguna yang diautentikasi secara default. Jalankan perintah ini untuk mendapatkan token identitas untuk akun Anda sendiri dan menyimpannya di variabel lingkungan ID_TOKEN:

export ID_TOKEN=$(gcloud auth print-identity-token)

Secara default, token identitas yang dikeluarkan Google berlaku selama satu jam. Jalankan perintah curl berikut untuk membuat permintaan yang ditolak sebelumnya karena tidak diotorisasi. Perintah ini akan menyertakan header yang diperlukan:

curl -i -X GET $SERVICE_URL/partners \
  -H "Authorization: Bearer $ID_TOKEN"

Output perintah harus diawali dengan HTTP/2 200, yang menunjukkan bahwa permintaan dapat diterima dan dihormati. (Jika Anda menunggu satu jam dan mencoba permintaan ini lagi, permintaan akan gagal karena masa berlaku token akan habis.) Isi respons berada di akhir output, setelah baris kosong:

{"status":"success","data":[]}

Belum ada partner.

Daftarkan partner menggunakan contoh data JSON di direktori dengan dua perintah curl:

curl -X POST \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d "@example-partner.json" \
  $SERVICE_URL/partner

dan

curl -X POST \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d "@example-partner2.json" \
  $SERVICE_URL/partner

Ulangi permintaan GET sebelumnya untuk melihat semua partner terdaftar sekarang:

curl -i -X GET $SERVICE_URL/partners \
  -H "Authorization: Bearer $ID_TOKEN"

Anda akan melihat data JSON dengan konten yang jauh lebih banyak, yang memberikan informasi tentang dua partner terdaftar.

Membuat permintaan sebagai akun yang tidak sah

Permintaan yang diautentikasi yang dibuat pada langkah terakhir berhasil tidak hanya karena diautentikasi, tetapi juga karena pengguna yang diautentikasi (akun Anda) diberi otorisasi. Artinya, akun memiliki izin untuk memanggil aplikasi. Tidak semua akun yang diautentikasi akan diberi otorisasi untuk melakukannya.

Akun default yang digunakan dalam permintaan sebelumnya diberi otorisasi karena akun tersebut adalah akun yang membuat project yang berisi aplikasi, dan secara default akun tersebut memberinya izin untuk memanggil aplikasi Cloud Run apa pun di akun. Izin tersebut dapat dicabut jika diperlukan, yang akan diinginkan dalam aplikasi produksi. Alih-alih melakukannya sekarang, Anda akan membuat akun layanan baru tanpa hak istimewa atau peran yang ditetapkan dan menggunakannya untuk mencoba mengakses aplikasi yang di-deploy.

  1. Buat akun layanan bernama tester.
gcloud iam service-accounts create tester
  1. Anda akan mendapatkan token identitas untuk akun baru ini dengan cara yang sama seperti yang Anda dapatkan untuk akun default sebelumnya. Namun, hal ini mengharuskan akun default Anda memiliki izin untuk meniru identitas akun layanan. Berikan izin ini ke akun Anda.
export USER_EMAIL=$(gcloud config list account --format "value(core.account)")

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="user:$USER_EMAIL" \
  --role=roles/iam.serviceAccountTokenCreator
  1. Sekarang, jalankan perintah berikut untuk menyimpan token identitas untuk akun baru ini di variabel lingkungan TEST_IDENTITY. Jika perintah menampilkan pesan error, tunggu satu atau dua menit, lalu coba lagi.
export TEST_TOKEN=$( \
  gcloud auth print-identity-token \
    --impersonate-service-account \
    "tester@$PROJECT_ID.iam.gserviceaccount.com" \
)
  1. Buat permintaan web yang diautentikasi seperti sebelumnya, tetapi menggunakan token identitas ini:
curl -i -X GET $SERVICE_URL/partners \
  -H "Authorization: Bearer $TEST_TOKEN"

Output perintah akan kembali dimulai dengan HTTP/2 403 karena permintaan, meskipun diautentikasi, tidak diotorisasi. Akun layanan baru tidak memiliki izin untuk memanggil aplikasi ini.

Mengizinkan akun

Akun pengguna atau akun layanan harus memiliki peran Cloud Run Invoker di layanan Cloud Run agar dapat membuat permintaan ke layanan tersebut. Berikan peran tersebut kepada akun layanan penguji dengan perintah:

export REGION=us-central1
gcloud run services add-iam-policy-binding ${SERVICE_NAME} \
  --member="serviceAccount:tester@$PROJECT_ID.iam.gserviceaccount.com" \
  --role=roles/run.invoker \
  --region=${REGION}

Setelah menunggu satu atau dua menit agar peran baru diperbarui, ulangi permintaan yang diautentikasi. Simpan TEST_TOKEN baru jika sudah satu jam atau lebih sejak pertama kali disimpan.

curl -i -X GET $SERVICE_URL/partners \
  -H "Authorization: Bearer $TEST_TOKEN"

Output perintah kini dimulai dengan HTTP/1.1 200 OK dan baris terakhir berisi respons JSON. Permintaan ini diterima oleh Cloud Run dan diproses oleh aplikasi.

6. Mengautentikasi program versus mengautentikasi pengguna

Permintaan yang diautentikasi yang telah Anda buat hingga saat ini telah menggunakan alat command line curl. Ada alat dan bahasa pemrograman lain yang dapat digunakan sebagai gantinya. Namun, permintaan Cloud Run yang diautentikasi tidak dapat dibuat menggunakan browser web dengan halaman web biasa. Jika pengguna mengklik link atau mengklik tombol untuk mengirimkan formulir di halaman web, browser tidak akan menambahkan header Authorization yang diperlukan oleh Cloud Run untuk permintaan yang diautentikasi.

Mekanisme autentikasi bawaan Cloud Run ditujukan untuk digunakan oleh program, bukan oleh pengguna akhir.

Catatan:

Cloud Run dapat menghosting aplikasi web yang ditampilkan kepada pengguna, tetapi aplikasi semacam itu harus menyetel Cloud Run untuk mengizinkan permintaan yang tidak diautentikasi dari browser web pengguna. Jika aplikasi memerlukan autentikasi pengguna, aplikasi harus menanganinya, bukan meminta Cloud Run untuk melakukannya. Aplikasi dapat melakukannya dengan cara yang sama seperti aplikasi web di luar Cloud Run. Cara melakukannya berada di luar cakupan codelab ini.

Anda mungkin telah memperhatikan bahwa respons terhadap contoh permintaan hingga saat ini adalah objek JSON, bukan halaman web. Hal ini karena layanan pendaftaran partner ini ditujukan untuk digunakan oleh program, dan JSON adalah bentuk yang mudah digunakan oleh program. Selanjutnya, Anda akan menulis dan menjalankan program untuk menggunakan dan memanfaatkan data ini.

Permintaan terautentikasi dari program Python

Program dapat membuat permintaan diautentikasi dari aplikasi Cloud Run yang aman melalui permintaan web HTTP standar, tetapi menyertakan header Authorization. Satu-satunya tantangan baru untuk program tersebut adalah mendapatkan token identitas yang valid dan belum habis masa berlakunya untuk ditempatkan di header tersebut. Token tersebut akan divalidasi oleh Cloud Run menggunakan Google Cloud Identity and Access Management (IAM), sehingga token harus diterbitkan dan ditandatangani oleh otoritas yang diakui oleh IAM. Ada library klien yang tersedia dalam banyak bahasa yang dapat digunakan program untuk meminta token tersebut diterbitkan. Library klien yang akan digunakan contoh ini adalah google.auth Python. Ada beberapa library Python untuk membuat permintaan web secara umum; contoh ini menggunakan modul requests yang populer.

Langkah pertama adalah menginstal dua library klien:

pip install google-auth
pip install requests

Kode Python untuk meminta token identitas bagi pengguna default adalah:

credentials, _ = google.auth.default()
credentials.refresh(google.auth.transport.requests.Request())
identity_token = credentials.id_token

Jika Anda menggunakan shell perintah seperti Cloud Shell atau shell terminal standar di komputer Anda sendiri, pengguna default adalah pengguna yang telah diautentikasi di dalam shell tersebut. Di Cloud Shell, pengguna yang login ke Google biasanya akan menggunakan akun tersebut. Dalam kasus lain, ini adalah pengguna apa pun yang diautentikasi dengan gcloud auth login atau perintah gcloud lainnya. Jika pengguna belum pernah login, tidak akan ada pengguna default dan kode ini akan gagal.

Untuk program yang membuat permintaan dari program lain, Anda biasanya tidak ingin menggunakan identitas seseorang, tetapi identitas program yang meminta. Di sinilah akun layanan berfungsi. Anda men-deploy layanan Cloud Run dengan akun layanan khusus yang memberikan identitas yang digunakan saat membuat permintaan API, seperti ke Cloud Firestore. Saat program berjalan di platform Google Cloud, library klien akan otomatis menggunakan akun layanan yang ditetapkan sebagai identitas default-nya, sehingga kode program yang sama berfungsi dalam kedua situasi tersebut.

Kode Python untuk membuat permintaan dengan header Otorisasi yang ditambahkan adalah:

auth_header = {"Authorization": "Bearer " + identity_token}
response = requests.get(url, headers=auth_header)

Program Python lengkap berikut akan membuat permintaan yang diautentikasi ke layanan Cloud Run untuk mengambil semua partner terdaftar, lalu mencetak nama dan ID yang ditetapkan. Salin dan jalankan perintah di bawah untuk menyimpan kode ini ke file print_partners.py.

cat > ./print_partners.py << EOF
def print_partners():
    import google.auth
    import google.auth.transport.requests
    import requests

    credentials, _ = google.auth.default()
    credentials.refresh(google.auth.transport.requests.Request())
    identity_token = credentials.id_token

    auth_header = {"Authorization": "Bearer " + identity_token}
    response = requests.get("${SERVICE_URL}/partners", headers=auth_header)

    parsed_response = response.json()
    partners = parsed_response["data"]

    for partner in partners:
        print(f"{partner['partnerId']}: {partner['name']}")


print_partners()
EOF

Anda akan menjalankan program ini dengan perintah shell. Anda harus melakukan autentikasi sebagai pengguna default terlebih dahulu, sehingga program dapat menggunakan kredensial tersebut. Jalankan perintah gcloud auth di bawah ini:

gcloud auth application-default login

Ikuti petunjuk untuk menyelesaikan login. Kemudian, jalankan program dari command line:

python print_partners.py

Outputnya akan terlihat seperti berikut:

10102: Zippy food delivery
67292: Foodful

Permintaan program mencapai layanan Cloud Run karena diautentikasi dengan identitas Anda, dan Anda adalah pemilik project ini sehingga diberi otorisasi untuk menjalankannya secara default. Program ini biasanya berjalan dengan identitas akun layanan. Saat dijalankan di sebagian besar produk Google Cloud, seperti Cloud Run atau App Engine, identitas defaultnya adalah akun layanan dan akan digunakan, bukan akun pribadi.

7. Selamat!

Selamat, Anda telah menyelesaikan codelab!

Langkah berikutnya:

Jelajahi codelab Cymbal Eats lainnya:

Pembersihan

Agar tidak dikenai biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

Menghapus project

Cara termudah untuk menghilangkan penagihan adalah dengan menghapus project yang Anda buat untuk tutorial.