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 dengan lebih aman dari Pod menggunakan Workload Identity Federation untuk 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 untuk GKE untuk mengakses data, Anda dapat menghindari risiko yang terkait dengan pengelolaan kunci akun layanan yang aktif untuk jangka waktu lama, dan memungkinkan Anda mengontrol akses ke secret Anda 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 melakukan langkah-langkah menggunakan GKE Standard, Anda harus mengaktifkan Workload Identity Federation untuk GKE secara manual.

Anda dapat menggunakan Workload Identity Federation untuk GKE guna mengakses Google Cloud API 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-langkah yang sama untuk mengakses Google Cloud API lainnya. Untuk mempelajari lebih lanjut, lihat Workload Identity Federation for GKE.

Tujuan

  • Membuat secret di Google Cloud Secret Manager.
  • Membuat cluster GKE Autopilot, namespace Kubernetes, dan akun layanan Kubernetes.
  • Buat kebijakan izin IAM untuk memberikan akses ke akun layanan Kubernetes Anda di secret.
  • 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. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.
  3. To initialize the gcloud CLI, run the following command:

    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. Make sure that billing is enabled for your Google Cloud project.

  6. Aktifkan API Kubernetes Engine and Secret Manager:

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  7. Install the Google Cloud CLI.
  8. To initialize the gcloud CLI, run the following command:

    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. Make sure that billing is enabled for your Google Cloud project.

  11. Aktifkan API Kubernetes Engine and Secret Manager:

    gcloud services enable container.googleapis.com secretmanager.googleapis.com
  12. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/secretmanager.admin, roles/container.clusterAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

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.

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 membuat akun layanan Kubernetes di setiap namespace untuk digunakan dengan Workload Identity Federation untuk 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
    

Membuat kebijakan izin IAM

  1. Beri akun layanan readonly-sa akses hanya baca ke secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/readonly-ns/sa/readonly-sa \
        --role='roles/secretmanager.secretAccessor' \
        --condition=None
    

    Ganti kode berikut:

    • PROJECT_NUMBER: nomor project Google Cloud angka Anda.
    • PROJECT_ID: Project ID Google Cloud Anda.
  2. Beri akun layanan admin-sa akses baca-tulis ke secret:

    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \
        --role='roles/secretmanager.secretAccessor' \
        --condition=None
    gcloud secrets add-iam-policy-binding bq-readonly-key \
        --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/admin-ns/sa/admin-sa \
        --role='roles/secretmanager.secretVersionAdder' \
        --condition=None
    

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 yang 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 yang 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 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 petunjuk, 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 cluster:

    gcloud container clusters delete secret-cluster \
        --region=us-central1
    
  2. 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