Mengonfigurasi autentikasi pengguna Cloud Service Mesh

Jika Anda memiliki TRAFFIC_DIRECTOR implementasi bidang kontrol, maka fitur ini hanya didukung oleh daftar yang diizinkan. Hubungi tim dukungan untuk meminta agar fitur ini dimasukkan ke daftar yang diizinkan untuk organisasi Anda

Autentikasi pengguna Cloud Service Mesh adalah solusi terintegrasi untuk autentikasi pengguna akhir berbasis browser dan kontrol akses ke beban kerja yang di-deploy. Layanan ini memungkinkan Anda berintegrasi dengan Penyedia Identitas (IDP) yang ada untuk autentikasi pengguna dan menggunakan Istio API dan kebijakan otorisasi untuk pengelolaan akses. Fitur ini adalah alternatif yang mudah digunakan untuk autentikasi Token Web JSON (JWT) Istio.

Kasus penggunaan umum adalah saat organisasi menggunakan Cloud Service Mesh untuk menghosting aplikasi web agar dapat diakses oleh karyawan melalui browser web. Selain itu, organisasi harus menggunakan penyedia identitas yang sudah ada untuk mengelola identitas pengguna. Autentikasi pengguna Cloud Service Mesh memudahkan pengguna untuk melakukan autentikasi menggunakan alur login dan pemberian izin OpenID Connect (OIDC) berbasis web standar. Saat pengguna melakukan autentikasi, Cloud Service Mesh akan menerapkan kebijakan otorisasi Istio, dan setelah otorisasi berhasil, Cloud Service Mesh akan mengirimkan identitas ke beban kerja dalam format kredensial yang aman.

Cara kerjanya

Autentikasi pengguna Cloud Service Mesh memperkenalkan komponen baru, authservice. Komponen ini terintegrasi dengan ingress berbasis Envoy sebagai layanan otorisasi eksternal yang mencegat semua permintaan masuk untuk autentikasi. authservice mengimplementasikan sisi klien protokol OIDC dan memungkinkan akses pengguna ke aplikasi melalui browser, tempat pengguna menyelesaikan alur autentikasi dan izin interaktif untuk membuat sesi singkat. authservice menerapkan protokol standar industri untuk berintegrasi dengan penyedia identitas mana pun yang dapat bertindak sebagai server otorisasi OIDC. Saat pengguna diautentikasi, informasi utama dienkapsulasi dalam RCToken dalam format JWT, yang ditandatangani oleh authservice yang meneruskannya ke lapisan otorisasi Istio di ingress. Model ini menyediakan kontrol akses perimeter untuk traffic ke dalam mesh. Jika pengguna diberi otorisasi untuk mengakses resource, RCToken ini juga diteruskan ke microservice untuk mendapatkan informasi utama dan menerapkan kontrol akses terperinci.

Diagram berikut menunjukkan lokasi authservice dalam mesh dan hubungannya dengan bagian lain dari mesh, seperti ingress, beban kerja, browser pengguna, dan IDP yang ada.

autentikasi pengguna akhir

Administrator dapat menginstal authservice sebagai add-on di atas penginstalan Cloud Service Mesh. Saat diinstal, authservice membaca konfigurasi endpoint OIDC dan setelan terkait lainnya yang ditentukan dalam resource kustom UserAuth. Administrator dapat menggunakan API ExternalAuthorization Cloud Service Mesh untuk mengonfigurasi auth_server sebagai filter pada ingress.

Menginstal layanan autentikasi pengguna

Langkah-langkah berikut menjelaskan cara mengonfigurasi authservice.

Prasyarat

Ikuti langkah-langkah di Menginstal alat dependen dan memvalidasi cluster untuk:
  • Jika Anda menggunakan Cloud Service Mesh terkelola di cluster pribadi, pastikan cluster dapat mengirim traffic keluar ke IDP.

Selain itu, pastikan Anda memenuhi prasyarat dengan menggunakan langkah-langkah berikut.

Menyesuaikan overlay autentikasi pengguna penginstalan

Untuk menginstal layanan autentikasi pengguna, Anda harus menyesuaikan penginstalan Cloud Service Mesh untuk menambahkan penyedia otorisasi eksternal tingkat mesh. Langkah-langkah yang diperlukan bergantung pada apakah Anda menggunakan Cloud Service Mesh terkelola atau dalam cluster.

Terkelola

  1. Perbarui ConfigMap untuk menyertakan MeshConfig autentikasi pengguna. Dalam perintah berikut, gunakan REVISION_LABEL yang sama dengan yang Anda gunakan saat menyediakan Cloud Service Mesh terkelola (seperti, asm-managed, asm-managed-rapid, atau asm-managed-stable):

    kubectl edit configmap istio-REVISION_LABEL -n istio-system
    
  2. Tambahkan teks berikut di bawah kolom mesh di MeshConfig:

    mesh: |-
    ...
      extensionProviders:
      - name: "asm-userauth-grpc"
        envoyExtAuthzGrpc:
          service: "authservice.asm-user-auth.svc.cluster.local"
          port: "10003"
    
  3. Buat namespace asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. Aktifkan namespace untuk injeksi. Langkah-langkahnya bergantung pada implementasi bidang kontrol Anda.

    Terkelola (TD)

    Terapkan label injeksi default ke namespace:

    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    

    Dikelola (Istiod)

    Direkomendasikan: Jalankan perintah berikut untuk menerapkan label injeksi default ke namespace:

    ```sh
    kubectl label namespace asm-user-auth \
        istio.io/rev- istio-injection=enabled --overwrite
    ```
    

    Jika Anda adalah pengguna lama dengan Managed Istiod control plane: Sebaiknya gunakan injeksi default, tetapi injeksi berbasis revisi didukung. Gunakan petunjuk berikut:

    1. Jalankan perintah berikut untuk menemukan saluran rilis yang tersedia:
    kubectl -n istio-system get controlplanerevision
    

    Outputnya mirip dengan hal berikut ini:

    NAME                AGE
    asm-managed-rapid   6d7h
    

    Dalam output, nilai di kolom NAME adalah label revisi yang sesuai dengan saluran rilis yang tersedia untuk versi Cloud Service Mesh.

    1. Terapkan label revisi ke namespace:

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. Instal gateway Istio di namespace asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

Dalam cluster

  1. Dapatkan contoh overlay autentikasi pengguna dan perbarui jika ada penyesuaian dalam mesh Anda. Sebaiknya Anda mempertahankan file overlay ini dalam kontrol sumber.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/asm-user-auth/v1.2.5/overlay/user-auth-overlay.yaml > user-auth-overlay.yaml
    
  2. Ikuti menginstal Cloud Service Mesh dengan overlay untuk menggunakan skrip yang disediakan Google guna menginstal Cloud Service Mesh dengan overlay autentikasi pengguna. Contoh:

    ./asmcli install \
      --project_id PROJECT_ID \
      --cluster_name CLUSTER_NAME \
      --cluster_location CLUSTER_LOCATION \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --custom_overlay user-auth-overlay.yaml
    

    Paket autentikasi pengguna kpt membuat AuthorizationPolicy untuk merujuk penyedia otorisasi eksternal yang ditentukan oleh pkg/ext-authz.yaml.

  3. Buat namespace asm-user-auth.

    kubectl create namespace asm-user-auth
    
  4. Aktifkan namespace untuk injeksi.

    Direkomendasikan: Jalankan perintah berikut untuk menerapkan label injeksi default ke namespace:

      kubectl label namespace asm-user-auth \
          istio.io/rev- istio-injection=enabled --overwrite
    

    Sebaiknya gunakan penyisipan default, tetapi penyisipan berbasis revisi didukung: Gunakan petunjuk berikut:

    1. Gunakan perintah berikut untuk menemukan label revisi di istiod:

      kubectl get deploy -n istio-system -l app=istiod -o \
        jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
      
    2. Terapkan label revisi ke namespace. Dalam perintah berikut, REVISION_LABEL adalah nilai label revisi istiod yang Anda catat di langkah sebelumnya.

      kubectl label namespace asm-user-auth \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  5. Instal gateway Istio di namespace asm-user-auth.

    kubectl apply -n asm-user-auth -f DIR_PATH/samples/gateways/istio-ingressgateway
    

Menyiapkan konfigurasi klien OIDC

Tetapkan konfigurasi klien OIDC Anda menggunakan langkah-langkah berikut. Panduan ini menggunakan Google sebagai IDP, tetapi Anda dapat menggunakan IDP apa pun yang mendukung autentikasi OIDC.

  1. Di Google Cloud konsol, buka API & Layanan > Kredensial.

    Buka Kredensial

  2. Buka Create Credentials, lalu pilih OAuth client ID. Jika diperlukan, tetapkan opsi layar izin OAuth Anda, lalu konfigurasi opsi berikut:

    • Tetapkan Application type ke Web application.
    • Tetapkan Authorized redirect URI ke https://REDIRECT_HOST/REDIRECT_PATH. Misalnya, untuk localhost, Anda dapat menetapkannya ke https://localhost:8443/_gcp_asm_authenticate.

    Selanjutnya, klik Save.

  3. Selain itu, simpan konfigurasi klien OIDC Anda untuk digunakan nanti.

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    

Mendapatkan paket kpt

Gunakan langkah-langkah berikut untuk menginstal konfigurasi authservice yang direkomendasikan dari repositori publik. Perintah ini mengambil container authservice terbaru dan memulainya sebagai Pod di namespace asm-user-auth. Perintah ini juga mengonfigurasi ingress untuk mencegat semua permintaan.

Dapatkan paket kpt:

kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
cd asm-user-auth/

Menetapkan URL pengalihan dan secret untuk gateway masuk

OAuth2 memerlukan URL pengalihan yang dihosting di endpoint yang dilindungi HTTPS. Perintah ini diberikan sebagai contoh dan menyederhanakan penyiapan dengan membuat sertifikat yang ditandatangani sendiri untuk gateway traffic masuk Istio.

  1. Buat sertifikat yang ditandatangani sendiri:

    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
     -days 365 -nodes -subj '/CN=localhost'
    
  2. Buat secret untuk gateway ingress guna menghosting traffic HTTPS:

    kubectl create -n asm-user-auth secret tls userauth-tls-cert --key=key.pem \
    --cert=cert.pem
    

Menerapkan kunci enkripsi dan penandatanganan

authservice memerlukan dua set kunci agar dapat beroperasi dengan berhasil. Yang pertama adalah kunci simetris untuk enkripsi dan dekripsi. Kunci ini digunakan untuk mengenkripsi status sesi sebelum menetapkannya sebagai cookie.

Kumpulan kunci kedua adalah pasangan kunci publik/pribadi. Kunci ini digunakan untuk menandatangani informasi pengguna terautentikasi dalam format JWT sebagai RCToken. Kunci publik dari pasangan ini dipublikasikan di endpoint yang telah ditentukan sebelumnya yang dapat digunakan oleh file bantuan untuk memvalidasi JWT.

Paket autentikasi pengguna kpt berisi dua kunci contoh untuk penyiapan cepat. Namun, Anda dapat menggunakan sistem pengelolaan kunci pilihan Anda untuk membuat kunci ini.

  1. Siapkan kunci enkripsi sesi dengan format berikut atau gunakan contoh dari pkg, yang dapat Anda lihat dengan cat ./samples/cookie_encryption_key.json.

    {
      "keys":[
         {
            "kty":"oct",
            "kid":"key-0",
            "K":"YOUR_KEY",
            "useAfter": 1612813735
         }
      ]
    }
    

    Anda dapat membuat kunci AES pengujian dengan perintah berikut:

    openssl enc -aes-256-cbc -k mycustomkey -P -md sha1 | grep key
    
  2. Siapkan kunci penandatanganan RCToken dengan format berikut atau gunakan contoh dari pkg, yang dapat Anda lihat dengan cat ./samples/rctoken_signing_key.json.

    {
      "keys":[
         {
            "kty":"RSA",
            "kid":"rsa-signing-key",
            "K":"YOUR_KEY",  # k contains a Base64 encoded PEM format RSA signing key.
            "useAfter": 1612813735  # unix timestamp
         }
      ]
    }
    

    Anda dapat membuat kunci pribadi RSA 512-bit untuk pengujian dengan perintah berikut:

    openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:512
    
  3. Buat secret kubernetes, yang akan dipasang authservice ke dalam sistem filenya sendiri.

    kubectl create secret generic secret-key  \
        --from-file="session_cookie.key"="./samples/cookie_encryption_key.json" \
        --from-file="rctoken.key"="./samples/rctoken_signing_key.json"  \
        --namespace=asm-user-auth
    

Men-deploy layanan autentikasi pengguna

Perintah berikut membuat layanan dan deployment autentikasi pengguna di namespace asm-user-auth.

Tetapkan nilai yang diperlukan untuk konfigurasi User Auth. ID dan secret klien disimpan sebagai secret Kubernetes, jadi kita menggunakan Base64 untuk mengenkodenya. Buka repositori publik untuk melihat semua setter yang tersedia.

kpt fn eval pkg --image gcr.io/kpt-fn/apply-setters:v0.2 --truncate-output=false -- \
  client-id="$(echo -n ${OIDC_CLIENT_ID} | base64 -w0)" \
  client-secret="$(echo -n ${OIDC_CLIENT_SECRET} | base64 -w0)" \
  issuer-uri="${OIDC_ISSUER_URI}" \
  redirect-host="${OIDC_REDIRECT_HOST}" \
  redirect-path="${OIDC_REDIRECT_PATH}"

Terapkan paket kpt:

# Remove the potential alpha version CRD if exists.
kubectl delete crd userauthconfigs.security.anthos.io
kubectl apply -f ./pkg/asm_user_auth_config_v1beta1.yaml
kubectl apply -f ./pkg

authservice menggunakan CRD UserAuthConfig untuk menyediakan autentikasi pengguna akhir. UserAuthConfig dapat dikonfigurasi di waktu proses, dan Anda dapat memperbaruinya untuk mengubah perilaku authservice dan mengonfigurasinya dengan endpoint untuk server otorisasi OIDC apa pun.

Anda dapat melihat file berdasarkan cat pkg/user_auth_config.yaml, yang berisi kolom berikut:

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}

Lihat detail konfigurasi autentikasi pengguna untuk mengetahui deskripsi mendetail tentang kolom user_auth_config.yaml.

Mengonfigurasi ID Permintaan API

ID permintaan API adalah serangkaian ekspresi Common Expression Language (CEL) yang digunakan oleh autentikasi pengguna Cloud Service Mesh untuk mengidentifikasi permintaan API. Dengan menentukan ID ini, Anda mengaktifkan autentikasi pengguna Cloud Service Mesh untuk menangani kegagalan autentikasi permintaan API secara semantik.

Secara khusus, saat Anda memberikan ekspresi CEL yang mengidentifikasi permintaan API Anda, Anda mengizinkan autentikasi pengguna Cloud Service Mesh gagal mengautentikasi permintaan API dengan kode status 401-Tidak Sah. Hal ini sangat penting untuk klien seperti CLI dan akun layanan, yang mengharapkan kode status ini untuk permintaan API yang tidak diautentikasi.

Tanpa ID permintaan API, autentikasi pengguna Cloud Service Mesh akan mengarahkan ulang semua permintaan yang tidak diautentikasi ke penyedia OpenID Connect (OIDC) yang dikonfigurasi, dengan menampilkan kode status 302-Found. Perilaku pengalihan ini umumnya tidak diinginkan untuk permintaan API, yang mengharapkan 401-Tidak Sah jika gagal.

Untuk menentukan ID permintaan API, tambahkan bagian apiRequestIdentifier ke UserAuthConfig CR Anda. Hal ini memungkinkan penambahan beberapa ekspresi CEL. Jika ada beberapa ekspresi CEL yang diberikan, permintaan dianggap sebagai permintaan API jika cocok dengan setidaknya salah satunya.

Contoh berikut menunjukkan cara menetapkan sebagai permintaan API: permintaan apa pun yang berisi header example-api-header, permintaan apa pun yang diarahkan ke host api.example.com, atau permintaan apa pun yang menargetkan jalur di /v1/api/.

apiVersion: security.anthos.io/v1beta1
kind: UserAuthConfig
metadata:
  name: user-auth-config
  namespace: asm-user-auth
spec:
  authentication:
    oidc:
      certificateAuthorityData: ""  # kpt-set: ${ca-cert}
      issuerURI: "<your issuer uri>"  # kpt-set: ${issuer-uri}
      proxy: ""  # kpt-set: ${proxy}
      oauthCredentialsSecret:
        name: "oauth-secret"  # kpt-set: ${secret-name}
        namespace: "asm-user-auth"  # kpt-set: ${secret-namespace}
      redirectURIHost: ""  # kpt-set: ${redirect-host}
      redirectURIPath: "/_gcp_asm_authenticate"  # kpt-set: ${redirect-path}
      scopes: ""  # kpt-set: ${scopes}
      groupsClaim: ""  # kpt-set: ${groups}
  outputJWTAudience: "test_audience"  # kpt-set: ${jwt-audience}
  apiRequestIdentifier: 
    name: "api-request-identifiers"
    expressions: 
    - "'example-api-header' in http_request.headers"
    - "http_request.host == api.example.com"
    - "matches(http_request.path, '/v1/api/(.*)')"
    # other expressions go here

Ekspresi CEL autentikasi pengguna Cloud Service Mesh dapat dibuat dari kolom berikut:

  1. http_request.headers: Peta header permintaan HTTP, dengan kunci berupa string huruf kecil dan nilai berupa vektor string.

    Gunakan kolom ini dalam ekspresi CEL untuk menetapkan permintaan dengan header tertentu sebagai permintaan API.

  2. http_request.host: Host URL HTTP yang diminta (misalnya, api.example.com).

    Gunakan kolom ini dalam ekspresi CEL untuk menetapkan permintaan ke host tertentu sebagai permintaan API.

  3. http_request.path: Jalur URL HTTP yang diminta (misalnya, /example-api-path). Jalur ini selalu dimulai dengan '/' dan tidak berisi komponen kueri dari URL permintaan.

    Gunakan kolom ini dalam ekspresi CEL untuk menetapkan permintaan dengan jalur tertentu sebagai permintaan API.

Bagian berikutnya menunjukkan contoh ekspresi CEL yang memeriksa dan mencocokkan bagian dari kolom ini untuk memberi tahu autentikasi pengguna Cloud Service Mesh tentang cara menentukan permintaan mana yang merupakan permintaan API.

Contoh Ekspresi

Mencocokkan semua permintaan yang berisi header X-API-Key:

"'x-api-key' in http_request.headers"

Mencocokkan semua permintaan dengan header X-API-Key yang ditetapkan ke nilai tertentu:

"'x-api-key' in http_request.headers && http_request.headers['x-api-key'].values == ['example-value ']"

Mencocokkan semua permintaan ke host api.example.com:

"http_request.host == api.example.com"

Mencocokkan semua permintaan ke jalur /api/query:

"http_request.path == /api/query"

Mencocokkan semua permintaan ke jalur mana pun di /api/:

"matches(http_request.path, '/api/(.*)')"

Melakukan tugas pasca-penginstalan

Tugas berikut diperlukan setelah Anda menyelesaikan langkah-langkah penginstalan sebelumnya.

Mengaktifkan autentikasi pengguna untuk aplikasi Anda

Bagian ini menunjukkan cara mengaktifkan autentikasi pengguna, dengan menggunakan httpbin sebagai contoh.

Autentikasi pengguna Cloud Service Mesh menggunakan kebijakan otorisasi yang diketik CUSTOM untuk memicu alur OIDC.

Setelah menginstal gateway Istio, konfigurasikan gateway tersebut untuk menyalurkan traffic HTTPS menggunakan sertifikat TLS userauth-tls-certyang Anda buat di atas. Berikut adalah konfigurasi pkg/gateway.yaml yang baru saja Anda instal.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: userauth
  namespace: asm-user-auth
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: userauth-tls-cert
---
# This ensures the OIDC endpoint has at least some route defined.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: userauth-oidc
  namespace: asm-user-auth
spec:
  gateways:
  - userauth
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: "your-oidc-redirect-path"
    name: user-auth-route
    route:
    - destination:
        host: authservice
        port:
          number: 10004
  1. Beri label namespace default untuk mengaktifkan injeksi otomatis istio-proxy untuk deployment.

    kubectl label namespace default istio.io/rev=REVISION --overwrite
    
  2. Deploy httpbin ke namespace default.

    kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml -n default
    
  3. Perbarui httpbin untuk menggunakan gateway ini dalam menyajikan traffic HTTPS, dan gunakan penerusan port untuk mengakses aplikasi secara lokal:

    kubectl apply -f./samples/httpbin-route.yaml -n default
    kubectl port-forward service/istio-ingressgateway 8443:443 -n asm-user-auth
    
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
      - asm-user-auth/userauth
      hosts:
      - '*'
      http:
      - match:
        - uri:
            prefix: /ip
        - uri:
            prefix: /headers
        name: httpbin-routes
        route:
        - destination:
            host: httpbin.default.svc.cluster.local
            port:
              number: 8000
    

    Gateway ingress di port 8443 akan diteruskan ke localhost agar aplikasi dapat diakses secara lokal.

  4. Deploy samples/rctoken-authz.yaml untuk mengaktifkan RequestAuthentication dan AuthorizationPolicy guna memverifikasi RCToken untuk permintaan.

    kubectl apply -f ./samples/rctoken-authz.yaml -n asm-user-auth
    

    Contoh samples/rctoken-authz.yaml:

    apiVersion: security.istio.io/v1beta1
    kind: RequestAuthentication
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      jwtRules:
      - issuer: "authservice.asm-user-auth.svc.cluster.local"
        audiences:
        - "test_audience"
        jwksUri: "http://authservice.asm-user-auth.svc.cluster.local:10004/_gcp_user_auth/jwks"
        fromHeaders:
        - name: X-ASM-RCTOKEN
        forwardOriginalToken: true
    ---
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      action: ALLOW
      rules:
      - when:
        - key: request.auth.claims[iss]
          values:
          - authservice.asm-user-auth.svc.cluster.local
        - key: request.auth.claims[aud]
          values:
          - test_audience
    

Memverifikasi autentikasi pengguna

httpbin melayani dua jalur, /ip dapat diakses secara publik dan /headers memerlukan pengguna akhir untuk login melalui IDP yang dikonfigurasi.

  1. Pastikan Anda dapat mengakses /ip secara langsung dengan membuka https://localhost:8443/ip.

  2. Pastikan Anda melihat halaman login OIDC dengan membuka https://localhost:8443/headers.

  3. Setelah Anda login, klik Berikutnya dan verifikasi bahwa Anda dialihkan ke halaman /headers.

Mengonfigurasi kebijakan otorisasi

Setelah Anda menyelesaikan konfigurasi pada langkah-langkah sebelumnya, setiap pengguna akan dialihkan melalui alur autentikasi berbasis web. Setelah alur selesai, authservice akan membuat RCToken dalam format JWT, yang digunakannya untuk mengirimkan informasi pengguna yang diautentikasi.

  1. Tambahkan kebijakan otorisasi Istio di ingress untuk memastikan bahwa pemeriksaan otorisasi terjadi untuk setiap pengguna yang diautentikasi:

    kubectl apply -f ./samples/httpbin-authz.yaml -n asm-user-auth
    
  2. File httpbin-authz.yaml mengonfigurasi gateway ingress untuk memvalidasi token RC yang dikeluarkan oleh authservice, dan hanya memberikan otorisasi jika JWT berisi kolom yang diinginkan, seperti audiens dan penerbit.

    Lihat contoh kebijakan otorisasi berikut:

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-rc-token
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      action: ALLOW
      rules:
      - to:
        - operation:
            paths: ["/ip"]
      - to:
        when:
        - key: request.auth.claims[iss]
          values:
          - authservice.asm-user-auth.svc.cluster.local
        - key: request.auth.claims[aud]
          values:
          - test_audience
        - key: request.auth.claims[sub]
          values:
          - allowed_user_sub_1  # Change this with the "sub" claim in the RC token. Wildcard '*' will match everything.
    

Mengonfigurasi setelan khusus lingkungan

Langkah-langkah sebelumnya menggunakan localhost dan sertifikat HTTPS yang ditandatangani sendiri untuk penyiapan cepat. Untuk penggunaan produksi yang sebenarnya, gunakan domain Anda sendiri, seperti example.com.

Selain itu, pastikan certificateAuthorityData memiliki konten sertifikat root yang dimaksud. Misalnya, jika IDP dipercaya dengan sertifikat root sistem, Anda dapat mengosongkannya. Jika ada proxy HTTPS yang mengakhiri koneksi HTTPS, setel ke sertifikat root proxy.

Mengelola dan merotasi kunci

Ada dua set kunci yang digunakan oleh authservice. Anda dapat merotasi setiap kunci secara independen. Namun, sebelum Anda merotasi kunci, penting untuk memahami cara kerja rotasi.

Kedua kunci tersebut dalam format JSON. Kolom useAfter menentukan stempel waktu sejak kapan kunci akan dianggap dapat digunakan. Selama rotasi kunci, Anda harus menyertakan kunci lama dan baru dalam JSON. Misalnya, pada contoh berikut, new-key hanya akan digunakan setelah stempel waktu 1712813735.

{
   "keys":[
      {
         "kty":"RSA",
         "kid":"old-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1612813735, # unix timestamp
      }
      {
      "kty":"RSA",
         "kid":"new-key",
         "K":"...", # k contains a Base64 encoded PEM format RSA signing key.
         "useAfter": 1712813735, # unix timestamp
      }
   ]
}

Cloud Service Mesh menggunakan kunci simetris untuk mengenkripsi data sesi yang disimpan dalam cookie browser. Untuk memastikan validitas sesi yang ada, authservice mencoba mendekripsi dengan semua kunci dalam set kunci. Saat rotasi, authservice akan menggunakan kunci baru untuk mengenkripsi sesi baru, dan akan terus mencoba dekripsi dengan kunci lama.

Pasangan kunci publik/pribadi digunakan untuk menandatangani RCToken. Kunci publik dikirim ke sidecar oleh istiod untuk verifikasi JWT. Sidecar harus menerima kunci publik baru sebelum authservice mulai menggunakan kunci pribadi baru untuk menandatangani RCToken. Untuk itu, authservice mulai memublikasikan kunci publik segera setelah kunci ditambahkan, tetapi menunggu dalam jangka waktu yang cukup lama sebelum mulai menggunakannya untuk menandatangani RCToken.

Singkatnya, saat melakukan rotasi kunci, sebaiknya:

  1. Lakukan rotasi kunci secara rutin atau sesuai permintaan jika diperlukan.
  2. Dalam format JSON, sertakan kunci saat ini dan kunci baru. Kunci baru harus dikaitkan dengan stempel waktu di masa mendatang. Sebaiknya Anda menentukan stempel waktu setidaknya beberapa jam sebelum waktu saat ini.
  3. Pantau dan pastikan layanan tetap responsif setelah kunci baru digunakan. Tunggu setidaknya satu hari setelah kunci baru digunakan sebelum melanjutkan ke langkah berikutnya.
  4. Hapus kunci lama dari entri JSON. Fungsi tersebut tidak diperlukan lagi.

Deployment Multi-Cluster

Autentikasi pengguna Cloud Service Mesh mendukung deployment multi-cluster. Anda harus men-deploy autentikasi pengguna di setiap cluster seperti yang dijelaskan di atas. Konfigurasi autentikasi pengguna seperti resource kustom UserAuth, rahasia klien OIDC, kunci enkripsi, semuanya harus direplikasi di setiap cluster.

Secara default, gateway ingress akan menyeimbangkan beban permintaan autentikasi ke salah satu instance authservice. Anda dapat menggunakan aturan tujuan untuk mengonfigurasi gateway ingress agar mengirim permintaan ke authservice di cluster yang sama, dan hanya melakukan failover ke authservice cluster lain.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: authservice-fail-over
  namespace: asm-user-auth
spec:
  host: authservice.asm-user-auth.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        enabled: true
        failover:
        - from:  us-east
          to: us-west
        - from: us-west
          to: us-east

Sama seperti konfigurasi lainnya, hal ini perlu dikonfigurasi di setiap cluster.

Pemetaan klaim kustom

Untuk mengonfigurasi pemetaan klaim kustom, konfigurasi spec.authentication.oidc.attributeMapping untuk menentukan pemetaan dari IDToken penyedia identitas asli. Kuncinya adalah nama klaim di RCToken dan nilainya adalah ekspresi CEL tentang cara mengurai klaim dari IDToken, gunakan assertion untuk mereferensikan IDToken.

Contoh:

spec:
  authentication:
    oidc:
      attributeMapping:
        aud_copy: assertion.aud
        decision: 'assertion.sub.startsWith("123") ? "success" : "fail"'

Dalam RCToken, klaim bertingkat attributes berisi klaim yang telah dikonfigurasi:

"attributes": {
    "aud_copy": "foo.googleusercontent.com",
    "decision": "success"
}

Jika ekspresi CEL gagal mengurai nilai dari IDToken, klaim akan diabaikan tanpa membuat alur autentikasi gagal.

Upgrade Autentikasi Pengguna

  1. Instal paket user-auth lagi karena berisi biner yang diupdate untuk versi user-auth baru:

    kpt pkg get https://github.com/GoogleCloudPlatform/asm-user-auth.git/@v1.2.5 .
    cd asm-user-auth/
    
  2. Simpan konfigurasi klien OIDC Anda:

    export OIDC_CLIENT_ID=CLIENT_ID
    export OIDC_CLIENT_SECRET=CLIENT_SECRET
    export OIDC_ISSUER_URI=ISSUER_URI
    export OIDC_REDIRECT_HOST=REDIRECT_HOST
    export OIDC_REDIRECT_PATH=REDIRECT_PATH
    
  3. Deploy layanan autentikasi pengguna untuk mengupgrade ke versi baru.

Detail konfigurasi autentikasi pengguna

Tabel berikut menjelaskan setiap kolom di CRD:

Nama kolom Deskripsi
authentication.oidc Bagian ini menyimpan konfigurasi endpoint OIDC dan parameter yang digunakan dalam alur OIDC.
authentication.oidc.certificateAuthorityData Ini adalah sertifikat root SSL dari domain server otorisasi OIDC atau proxy HTTPS jika ada.
authentication.oidc.oauthCredentialsSecret Referensi rahasia ke rahasia jenis Opaque Kubernetes yang berisi client_id dan client_secret OAuth2 OIDC dalam payload JSON.
authentication.oidc.issuerURI URI yang akan digunakan sebagai penerbit di RCToken output.
authentication.oidc.proxy Server proxy ke IDP OIDC, jika ada. Dengan format http://user:password@10.10.10.10:8888.
authentication.oidc.redirectURIHost Host yang akan digunakan untuk URI penghentian OAuth. Jika Anda mengosongkannya, host dari URL target akan digunakan dan URI pengalihan akan dirakit secara dinamis.
Nilai ini dapat digunakan jika sesi SSO autentikasi pengguna diinginkan di domain tingkat yang lebih tinggi. Misalnya, untuk mengaktifkan SSO antara profile.example.com/ dan admin.example.com/, nilai ini dapat ditetapkan ke example.com. Tindakan ini akan memungkinkan sesi autentikasi pengguna dibuat di example.com yang akan dibagikan di antara semua subdomain. Catatan: Jika beberapa domain ditayangkan dari mesh yang sama, example1.com dan example2.com, fitur ini tidak dapat digunakan, dan sebaiknya dibiarkan kosong.
authentication.oidc.redirectURIPath Jalur endpoint tempat authservice akan mengakhiri alur OAuth. Anda harus mendaftarkan jalur URI ini beserta host sebagai URI pengalihan yang diotorisasi di server otorisasi untuk authentication.oidc.clientID.
Selain itu, URI ini harus ditayangkan dari mesh layanan dan ingress yang sama tempat authservice diaktifkan.
authentication.oidc.scopes Cakupan OAuth yang harus diminta dalam permintaan autentikasi. Daftar ID yang dipisahkan koma yang digunakan untuk menentukan hak akses yang diminta selain cakupan "openid", misalnya. "groups,allatclaim".
authentication.oidc.groupsClaim Jika idtoken berisi klaim grup, gunakan kolom ini untuk menunjukkan namanya. Jika ditentukan, layanan akan meneruskan data dalam klaim ini ke klaim groups dalam RCToken output. Klaim ini harus berisi daftar string yang dipisahkan koma, misalnya. ["group1", "group2"].
authentication.oidc.attributeMapping Berisi satu atau beberapa pemetaan klaim dari idtoken yang diikuti dengan ekspresi CEL. Semua klaim harus dirujuk oleh assertion.X, assertion dirujuk ke IDToken asli, misalnya aud_copy: assertion.aud.
authentication.outputJWTAudience Audiens RCToken yang dibuat oleh authservice. Sidecar dapat memvalidasi RCToken masuk terhadap nilai audiens ini.

Memecahkan masalah

  1. Aksesibilitas jaringan ke IDP.

    Kemungkinan log: error: TLS handshake failed..

    Verifikasi dengan menjalankan curl dari penampung sementara yang terlampir ke istio-proxy untuk memanggil URI penerbit IDP. Misalnya, lihat Mengumpulkan log Cloud Service Mesh.

    Jika Anda tidak dapat terhubung, periksa aturan firewall atau konfigurasi jaringan lainnya untuk cluster.

  2. Sertifikat CA root.

    Kemungkinan log: error: The server's TLS certificate did not match expectations. atau error: TLS handshake failed..

    Pastikan certificateAuthorityData menyimpan sertifikat CA root yang benar. Jika tidak ada proxy HTTPS yang menghentikan traffic HTTPS, parameter ini harus menyimpan sertifikat CA root untuk IDP. Jika ada, variabel ini akan menyimpan proxy.

  3. Konfigurasi jalur pengalihan.

    Kemungkinan pengamatan: menerima halaman error 404 selama alur autentikasi OIDC.

    Autentikasi Pengguna menampilkan header "Set-Cookie" tanpa menggunakan atribut jalur, yang secara default browser menggunakan direktori URL permintaan sebagai jalur cookie (cakupan cookie yang terkait dengan jalur). Jadi, sebaiknya jangan sertakan "/" di jalur pengalihan kecuali jika Anda memang ingin melakukannya.

  4. Sidecar tidak dapat mengambil jwksUri.

    Dalam beberapa skenario, pembatasan sidecar dapat menyebabkan kegagalan pengambilan jwksUri. Jika namespace tidak ada menggunakan karakter pengganti (misalnya, ./* atau istio-system/*), maka hal ini tidak akan berfungsi. Anda harus menambahkan namespace-nya secara manual di sidecar keluar.

FAQ

  1. Bagaimana cara mengupgrade Cloud Service Mesh dengan User Auth yang diaktifkan?

    Ikuti proses upgrade Cloud Service Mesh dan tentukan file overlay dengan menambahkan --custom_overlay user-auth-overlay.yaml di command line ke asmcli install.

  2. Berapa banyak resource yang harus kita sediakan untuk authservice? Dan berapa banyak permintaan per detik yang dapat ditangani?

    Secara default, authservice dikonfigurasi dengan 2,0 vCPU, memori 256 Mi. Dengan konfigurasi tersebut, authservice dapat menangani 500 permintaan per detik. Untuk menangani jumlah permintaan yang lebih besar, Anda harus menyediakan lebih banyak CPU, yang kira-kira sebanding dengan kapasitas penanganan permintaannya. Anda juga dapat mengonfigurasi beberapa replika authservice untuk meningkatkan skalabilitas horizontal.