Mengakses secret yang disimpan di luar cluster GKE menggunakan library klien


Tutorial ini menunjukkan cara menyimpan data sensitif yang digunakan oleh cluster Google Kubernetes Engine (GKE) di Secret Manager, dan cara mengakses data dari Pod dengan lebih aman menggunakan Workload Identity Federation for GKE dan library klien Google Cloud. Tutorial ini ditujukan untuk administrator keamanan yang ingin memindahkan data sensitif dari penyimpanan dalam cluster.

Menyimpan data sensitif di luar penyimpanan cluster akan mengurangi risiko akses tidak sah ke data jika terjadi serangan. Dengan menggunakan Workload Identity Federation for GKE, Anda dapat mengakses data untuk menghindari risiko yang terkait dengan pengelolaan kunci akun layanan yang berumur panjang. Selain itu, Anda dapat mengontrol akses ke secret menggunakan Identity and Access Management (IAM), bukan aturan RBAC dalam cluster. Anda dapat menggunakan penyedia penyimpanan secret eksternal apa pun, seperti Secret Manager atau HashiCorp Vault.

Tutorial ini menggunakan cluster GKE Autopilot. Untuk menjalankan langkah-langkah menggunakan GKE Standard, Anda harus mengaktifkan Workload Identity Federation for GKE secara manual.

Anda dapat menggunakan Workload Identity Federation for GKE untuk mengakses Google Cloud API apa pun dari workload GKE tanpa harus menggunakan pendekatan yang kurang aman seperti file kunci akun layanan statis. Tutorial ini menggunakan Secret Manager sebagai contoh, tetapi Anda dapat menggunakan langkah yang sama untuk mengakses Google Cloud API lainnya. Untuk mempelajari lebih lanjut, lihat Workload Identity Federation untuk GKE.

Tujuan

  • Membuat secret di Google Cloud Secret Manager.
  • Membuat dan mengonfigurasi akun layanan IAM untuk mengakses secret.
  • Membuat cluster GKE Autopilot, namespace Kubernetes, dan Akun Layanan Kubernetes.
  • Menggunakan aplikasi pengujian untuk memverifikasi akses akun layanan.
  • Menjalankan aplikasi contoh yang mengakses secret menggunakan Secret Manager API.

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. Menginstal Google Cloud CLI.
  3. Untuk initialize gcloud CLI, jalankan perintah berikut:

    gcloud init
  4. Buat atau pilih project Google Cloud.

    • Membuat project Google Cloud:

      gcloud projects create PROJECT_ID

      Ganti PROJECT_ID dengan nama untuk project Google Cloud yang Anda buat.

    • Pilih project Google Cloud yang Anda buat:

      gcloud config set project PROJECT_ID

      Ganti PROJECT_ID dengan nama project Google Cloud Anda.

  5. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  6. Aktifkan API Kubernetes Engine and Secret Manager:

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  7. Menginstal Google Cloud CLI.
  8. Untuk initialize gcloud CLI, jalankan perintah berikut:

    gcloud init
  9. Buat atau pilih project Google Cloud.

    • Membuat project Google Cloud:

      gcloud projects create PROJECT_ID

      Ganti PROJECT_ID dengan nama untuk project Google Cloud yang Anda buat.

    • Pilih project Google Cloud yang Anda buat:

      gcloud config set project PROJECT_ID

      Ganti PROJECT_ID dengan nama project Google Cloud Anda.

  10. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  11. Aktifkan API Kubernetes Engine and Secret Manager:

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  12. Berikan peran ke Akun Google Anda. Jalankan perintah berikut satu kali untuk setiap peran IAM berikut: roles/secretmanager.admin, roles/container.clusterAdmin, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
    • Ganti PROJECT_ID dengan project ID Anda.
    • Ganti EMAIL_ADDRESS dengan alamat email Anda.
    • Ganti ROLE dengan setiap peran individual.

Menyiapkan lingkungan

Clone repositori GitHub yang berisi file contoh untuk tutorial ini:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd ~/kubernetes-engine-samples/security/wi-secrets

Membuat secret di Secret Manager

  1. Contoh berikut menampilkan data yang akan Anda gunakan untuk membuat secret:

    key=my-api-key
  2. Buat secret untuk menyimpan data sampel:

    gcloud secrets create bq-readonly-key \
        --data-file=manifests/bq-readonly-key \
        --ttl=3600s
    

    Perintah ini akan melakukan hal berikut:

    • Membuat secret Secret Manager baru dengan kunci contoh di region Google Cloud us-central1.
    • Menetapkan masa berlaku secret agar berakhir satu jam setelah Anda menjalankan perintah.

Mengonfigurasi akun layanan IAM

  1. Buat dua akun layanan IAM baru untuk akses hanya baca dan akses baca-tulis:

    gcloud iam service-accounts create readonly-secrets --display-name="Read secrets"
    gcloud iam service-accounts create readwrite-secrets --display-name="Read write secrets"
    
  2. Beri akun layanan IAM readonly-secrets akses hanya baca ke secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=serviceAccount:readonly-secrets@PROJECT_ID.iam.gserviceaccount.com \
        --role='roles/secretmanager.secretAccessor'
    
  3. Beri akun layanan IAM readwrite-secrets akses baca-tulis ke secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=serviceAccount:readwrite-secrets@PROJECT_ID.iam.gserviceaccount.com \
        --role='roles/secretmanager.secretAccessor'
    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=serviceAccount:readwrite-secrets@PROJECT_ID.iam.gserviceaccount.com \
        --role='roles/secretmanager.secretVersionAdder'
    

Membuat resource cluster dan Kubernetes

Buat cluster GKE, namespace Kubernetes, dan akun layanan Kubernetes. Anda membuat dua namespace, satu untuk akses hanya baca dan satu untuk akses baca-tulis ke secret. Anda juga akan membuat akun layanan Kubernetes di setiap namespace untuk digunakan dengan Workload Identity Federation for GKE.

  1. Buat cluster GKE Autopilot:

    gcloud container clusters create-auto secret-cluster \
        --region=us-central1
    

    Mungkin perlu waktu sekitar lima menit untuk men-deploy cluster. Cluster Autopilot selalu mengaktifkan Workload Identity Federation for GKE. Jika ingin menggunakan cluster GKE Standard, Anda harus mengaktifkan Workload Identity Federation untuk GKE secara manual sebelum melanjutkan.

  2. Buat namespace readonly-ns dan namespace admin-ns:

    kubectl create namespace readonly-ns
    kubectl create namespace admin-ns
    
  3. Buat akun layanan Kubernetes readonly-sa dan akun layanan Kubernetes admin-sa:

    kubectl create serviceaccount readonly-sa --namespace=readonly-ns
    kubectl create serviceaccount admin-sa --namespace=admin-ns
    
  4. Ikat akun layanan IAM ke akun layanan Kubernetes:

    gcloud iam service-accounts add-iam-policy-binding readonly-secrets@PROJECT_ID.iam.gserviceaccount.com \
        --member=serviceAccount:PROJECT_ID.svc.id.goog[readonly-ns/readonly-sa] \
        --role='roles/iam.workloadIdentityUser'
    gcloud iam service-accounts add-iam-policy-binding readwrite-secrets@PROJECT_ID.iam.gserviceaccount.com \
        --member=serviceAccount:PROJECT_ID.svc.id.goog[admin-ns/admin-sa] \
        --role='roles/iam.workloadIdentityUser'
    
  5. Anotasikan akun layanan Kubernetes dengan nama akun layanan IAM yang diikat:

    kubectl annotate serviceaccount readonly-sa \
        --namespace=readonly-ns \
        iam.gke.io/gcp-service-account=readonly-secrets@PROJECT_ID.iam.gserviceaccount.com
    kubectl annotate serviceaccount admin-sa \
        --namespace=admin-ns \
        iam.gke.io/gcp-service-account=readwrite-secrets@PROJECT_ID.iam.gserviceaccount.com
    

Sekarang Anda memiliki cluster yang dikonfigurasi untuk mengakses secret dari Pod menggunakan Workload Identity Federation for GKE.

Memverifikasi akses secret

Deploy Pod pengujian di setiap namespace untuk memverifikasi akses hanya baca dan baca-tulis.

  1. Tinjau manifes Pod hanya baca:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: readonly-test
      namespace: readonly-ns
    spec:
      containers:
      - image: google/cloud-sdk:slim
        name: workload-identity-test
        command: ["sleep","infinity"]
        resources:
          requests:
            cpu: "150m"
            memory: "150Mi"
      serviceAccountName: readonly-sa

    Pod ini menggunakan akun layanan readonly-sa di namespace readonly-ns.

  2. Tinjau manifes Pod baca-tulis:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: admin-test
      namespace: admin-ns
    spec:
      containers:
      - image: google/cloud-sdk:slim
        name: workload-identity-test
        command: ["sleep","infinity"]
        resources:
          requests:
            cpu: "150m"
            memory: "150Mi"
      serviceAccountName: admin-sa

    Pod ini menggunakan akun layanan admin-sa di namespace admin-ns.

  3. Deploy Pod pengujian:

    kubectl apply -f manifests/admin-pod.yaml
    kubectl apply -f manifests/readonly-pod.yaml
    

    Mungkin perlu waktu beberapa menit untuk Pod mulai berjalan. Untuk memantau progres, jalankan perintah berikut:

    watch kubectl get pods -n readonly-ns
    

    Saat status Pod berubah menjadi RUNNING, tekan Ctrl+C untuk kembali ke command line.

Menguji akses hanya baca

  1. Buka shell di Pod readonly-test:

    kubectl exec -it readonly-test --namespace=readonly-ns -- /bin/bash
    
  2. Coba baca secret-nya:

    gcloud secrets versions access 1 --secret=bq-readonly-key
    

    Outputnya adalah key=my-api-key.

  3. Coba tulis data baru ke secret:

    printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
    

    Outputnya mirip dengan hal berikut ini:

    ERROR: (gcloud.secrets.versions.add) PERMISSION_DENIED: Permission 'secretmanager.versions.add' denied for resource 'projects/PROJECT_ID/secrets/bq-readonly-key' (or it may not exist).
    

    Pod yang menggunakan akun layanan hanya baca hanya dapat membaca secret, dan tidak dapat menulis data baru.

  4. Keluar dari Pod:

    exit
    

Menguji akses baca-tulis

  1. Buka shell di Pod admin-test:

    kubectl exec -it admin-test --namespace=admin-ns -- /bin/bash
    
  2. Coba baca secret-nya:

    gcloud secrets versions access 1 --secret=bq-readonly-key
    

    Outputnya adalah key=my-api-key.

  3. Coba tulis data baru ke secret:

    printf "my-second-api-key" | gcloud secrets versions add bq-readonly-key --data-file=-
    

    Outputnya mirip dengan hal berikut ini:

    Created version [2] of the secret [bq-readonly-key].
    
  4. Baca versi secret baru:

    gcloud secrets versions access 2 --secret=bq-readonly-key
    

    Outputnya adalah my-second-api-key.

  5. Keluar dari Pod:

    exit
    

Pod hanya mendapatkan tingkat akses yang Anda berikan ke akun layanan IAM yang terikat dengan akun layanan Kubernetes yang digunakan dalam manifes Pod. Setiap Pod yang menggunakan akun Kubernetes admin-sa di namespace admin-ns dapat menulis versi baru secret, tetapi semua Pod dalam namespace readonly-ns yang menggunakan akun layanan Kubernetes readonly-sa hanya dapat membaca secret.

Mengakses secret dari kode Anda

Di bagian ini, Anda akan melakukan hal berikut:

  1. Men-deploy aplikasi contoh yang membaca secret Anda di Secret Manager menggunakan library klien.

  2. Memastikan aplikasi dapat mengakses secret Anda.

Anda harus mengakses secret Secret Manager dari kode aplikasi jika memungkinkan, menggunakan Secret Manager API.

  1. Meninjau kode sumber aplikasi contoh:

    // Copyright 2022 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    package main
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"os"
    
    	secretmanager "cloud.google.com/go/secretmanager/apiv1"
    	secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
    )
    
    func main() {
    
            // Get environment variables from Pod spec.
            projectID := os.Getenv("PROJECT_ID")
            secretId := os.Getenv("SECRET_ID")
            secretVersion := os.Getenv("SECRET_VERSION")
    
            // Create the Secret Manager client.
            ctx := context.Background()
            client, err := secretmanager.NewClient(ctx)
            if err != nil {
                    log.Fatalf("failed to setup client: %v", err)
            }
            defer client.Close()
    
            // Create the request to access the secret.
            accessSecretReq := &secretmanagerpb.AccessSecretVersionRequest{
                    Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", projectID, secretId, secretVersion),
            }
    
            secret, err := client.AccessSecretVersion(ctx, accessSecretReq)
            if err != nil {
                    log.Fatalf("failed to access secret: %v", err)
            }
    
            // Print the secret payload.
            //
            // WARNING: Do not print the secret in a production environment - this
            // snippet is showing how to access the secret material.
            log.Printf("Welcome to the key store, here's your key:\nKey: %s", secret.Payload.Data)
    }
    

    Aplikasi ini memanggil Secret Manager API untuk mencoba dan membaca secret tersebut.

  2. Tinjau manifes Pod aplikasi contoh:

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: readonly-secret-test
      namespace: readonly-ns
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/wi-secret-store:latest
        name: secret-app
        env:
          - name: PROJECT_ID
            value: "YOUR_PROJECT_ID"
          - name: SECRET_ID
            value: "bq-readonly-key"
          - name: SECRET_VERSION
            value: "latest"
        resources:
          requests:
            cpu: "125m"
            memory: "64Mi"
      serviceAccountName: readonly-sa

    Manifes ini melakukan hal berikut:

    • Membuat Pod di namespace readonly-ns yang menggunakan akun layanan readonly-sa.
    • Mengambil aplikasi contoh dari registry image Google. Aplikasi ini memanggil Secret Manager API menggunakan library klien Google Cloud. Anda dapat melihat kode aplikasi di /main.go pada repositori.
    • Menetapkan variabel lingkungan untuk digunakan oleh aplikasi contoh.
  3. Ganti variabel lingkungan dalam aplikasi contoh:

    sed -i "s/YOUR_PROJECT_ID/PROJECT_ID/g" "manifests/secret-app.yaml"
    
  4. Deploy aplikasi contoh:

    kubectl apply -f manifests/secret-app.yaml
    

    Mungkin perlu waktu beberapa menit untuk Pod mulai bekerja. Jika Pod memerlukan node baru di cluster, Anda mungkin melihat peristiwa jenis CrashLoopBackOff saat GKE menyediakan node. Error akan berhenti saat node berhasil disediakan.

  5. Verifikasi akses secret:

    kubectl logs readonly-secret-test -n readonly-ns
    

    Outputnya adalah my-second-api-key. Jika output kosong, Pod mungkin belum berjalan. Tunggu beberapa menit dan coba lagi.

Pendekatan alternatif

Jika Anda perlu memasang data sensitif ke Pod, gunakan add-on Secret Manager untuk GKE (Pratinjau). Add-on ini men-deploy dan mengelola penyedia Google Cloud Secret Manager untuk driver CSI Kubernetes Secret Store di cluster GKE Anda. Untuk mengetahui petunjuknya, lihat Menggunakan add-on Secret Manager dengan GKE.

Menyediakan secret sebagai volume yang terpasang memiliki risiko berikut:

  1. Volume yang terpasang rentan terhadap serangan traversal direktori.
  2. Variabel lingkungan dapat disusupi karena kesalahan konfigurasi seperti membuka endpoint debug.

Jika memungkinkan, sebaiknya Anda mengakses secret secara terprogram melalui Secret Manager API. Untuk mendapatkan petunjuk, gunakan aplikasi contoh dalam tutorial ini atau lihat library klien Secret Manager.

Pembersihan

Agar tidak perlu membayar 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 resource satu per satu

  1. Hapus kluster:

    gcloud container clusters delete secret-cluster \
        --region=us-central1
    
  2. Hapus akun layanan IAM:

    gcloud iam service-accounts delete readonly-secrets@PROJECT_ID.iam.gserviceaccount.com
    gcloud iam service-accounts delete readwrite-secrets@PROJECT_ID.iam.gserviceaccount.com
    
  3. Opsional: Hapus secret di Secret Manager:

    gcloud secrets delete bq-readonly-key
    

    Jika Anda tidak melakukan langkah ini, secret akan otomatis berakhir karena Anda menetapkan flag --ttl selama pembuatan.

Menghapus project

    Menghapus project Google Cloud:

    gcloud projects delete PROJECT_ID

Langkah selanjutnya