附註:

使用 Nginx Ingress Controller、OAuth2 Proxy 和 Oracle Identity Domains 保護 Kubernetes Web 服務

簡介

保護 Kubernetes 代管的 Web 服務應該很容易。無論您的應用程式缺乏外部身分識別提供者 (IdP) 整合的內建支援,或您需要單一登入 (SSO) 解決方案來簡化管理並減少每個服務的個別認證機制的需求,OAuth2 代理主機都提供將任何應用程式連線至幾乎任何身分識別提供者 (IdP) 的彈性。

OAuth2 代理主機可作為位於您 Kubernetes 服務前的反向代理主機。它會攔截流量、將使用者重新導向至外部授權伺服器 (例如 Okta 或 GitHub) 以進行登入,並在將要求轉送至後端服務之前驗證存取記號。

目標

必要條件

作業 1:建立 OKE 叢集

  1. 登入 OCI 主控台,瀏覽至 Oracle Container Engine for Kubernetes ,然後按一下建立。

  2. 在建立叢集精靈中,按一下快速建立。

    快速建立

  3. 輸入下列資訊,然後按一下下一步。

    • 名稱:輸入叢集名稱。
    • Kubernetes 版本:選取想要使用的版本。
    • Kubernetes API 端點:選取公用端點。
    • 節點類型:選取受管理。
    • Kubernetes 工作節點:選取專用工作者。
    • 節點計數:1。

    建立叢集

  4. 複查並按一下建立叢集。等待叢集變成可用。

  5. 更新與服務子網路關聯的安全清單。

    1. 按一下服務子網路。

      服務子網路

    2. 按一下安全清單,然後新增下列規則。

      • 傳入:

        安全清單輸入規則

      • 傳出:

        安全清單傳出規則

  6. 更新與工作節點子網路關聯的安全清單,以允許來自負載平衡器的連線。

    1. 按一下 VCN 名稱。

      OKE 叢集 VCN

    2. 在資源下,選取安全清單,然後按一下節點安全清單。

      安全清單

    3. 將下列輸入規則新增至節點安全清單。

      節點安全清單輸入

    4. 按一下新增傳入規則。

作業 2:設定 Nginx 傳入控制器

  1. 叢集可用之後,您便可以使用 OCI Cloud Shell 存取叢集。按一下存取叢集,然後在 OCI Cloud Shell 中複製並執行下列命令。

    存取叢集

  2. 執行 kubectl get node 命令以取得可用節點清單。

    取得節點

  3. 新增 Nginx Ingress Controller helm 儲存區域。如需詳細資訊,請參閱傳入 NGINX 控制器簡介和 helm 。

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    
  4. 建立 values-override.yaml 檔案。

    controller:
      allowSnippetAnnotations: true
      service:
        annotations:
          oci.oraclecloud.com/load-balancer-type: "lb"
          service.beta.kubernetes.io/oci-load-balancer-backend-protocol: "TCP"
          service.beta.kubernetes.io/oci-load-balancer-shape: "flexible"
          service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10"
          service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "10"
    
  5. 部署 Nginx Ingress Controller。

    helm install ingress-nginx ingress-nginx/ingress-nginx -f values-override.yaml
    
  6. 儲存下列名為 application.yaml 的 yaml 檔案。

    ---
    # Create ClusterIP service
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
    spec:
      ports:
      - port: 5000
        targetPort: 5000
      selector:
        app: httpbin
    ---
    # Deployment of a sample web application
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          containers:
          - image: mendhak/http-https-echo
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 5000
            env:
            - name: HTTP_PORT
              value: "5000"
    
  7. 建立應用程式資源。

    kubectl apply -f application.yaml
    
  8. 為與負載平衡器關聯的公用 IP 位址建立 DNS 記錄。

    • 取得負載平衡器的公用 IP 位址。

      $ kubectl get svc ingress-nginx-controller
      NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
      ingress-nginx-controller   LoadBalancer   10.96.152.30   158.180.61.74   80:31957/TCP,443:30838/TCP   32s
      
    • 建立 DNS 記錄。如果您沒有 DNS 伺服器,我們將會使用免費的萬用字元 DNS 服務 nip.io 。

    在此情況下, FQDN 為 158-180-61-74.nip.io。

  9. 儲存下列名為 ingress.yaml 的 yaml 檔案。

    注意:請務必使用您的 FQDN 更新主機項目。

    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: httpbin-ingress-nginx
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
          - "<YOUR-FQDN>"
      rules:
        - host: "<YOUR-FQDN>"
          http:
            paths:
              - pathType: Prefix
                path: "/"
                backend:
                  service:
                    name: httpbin
                    port:
                      number: 5000
    
  10. 請執行下列命令來建立傳入資源。

    kubectl apply -f ingress.yaml
    
  11. 測試服務的連線。

    $ curl -k https://<YOUR-FQDN> 
    {
      "path": "/",
      "headers": {
        "host": "158-180-61-74.nip.io",
        "x-request-id": "b0320217391a922acecbfe10758b3ffe",
        "x-real-ip": "10.0.10.167",
        "x-forwarded-for": "10.0.10.167",
        "x-forwarded-host": "158-180-61-74.nip.io",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https",
        "x-forwarded-scheme": "https",
        "x-scheme": "https",
        "user-agent": "curl/7.87.0",
        "accept": "*/*"
      },
      "method": "GET",
      "body": "",
      "fresh": false,
      "hostname": "158-180-61-74.nip.io",
      "ip": "10.0.10.167",
      "ips": [
        "10.0.10.167"
      ],
      "protocol": "https",
      "query": {},
      "subdomains": [
        "158-180-61-74"
      ],
      "xhr": false,
      "os": {
        "hostname": "httpbin-644874bcdb-ll4mb"
      },
      "connection": {}
    }
    

工作 3:在 Oracle 識別網域中設定機密應用程式

  1. 瀏覽至 OCI 主控台中的 Oracle Identity Domains ,然後按一下 OracleIdentityCloudService 網域。

  2. 從左側功能表中選取整合的應用程式,然後按一下新增應用程式。

  3. 選取機密應用程式,然後按一下啟動工作流程。

    新的機密應用程式

  4. 輸入應用程式名稱、描述,然後按一下下一步。

    應用程式詳細資訊

  5. 設定應用程式 oAuth 參數。

    1. 在授權區段中,選取授權代碼。

    2. 輸入下列 URL,然後按一下下一步。

      • 重新導向 URL:https://<YOUR-FQDN>/oauth2/callback。
      • 登出後重新導向 URL:https://<YOUR-FQDN>。
      • 登出 URL:https://<YOUR-FQDN>/oauth2/sign_out。

    應用程式作業系統參數

  6. 在 Web 層原則中,選取略過並稍後執行,然後按一下完成。

    Web 層原則

  7. 按一下啟動來啟用應用程式。

    啟用應用程式

  8. 瀏覽至左側功能表中的群組,並將允許認證的使用者群組與此應用程式建立關聯。

    將使用者群組與應用程式建立關聯

  9. 請注意用戶端 ID 和用戶端密碼。

    應用程式從屬端 ID 和密碼

  10. 按一下 OracleIdentityCloudService 網域,然後展開網域 URL 。

    識別網域 URL

    例如:識別網域 URL 將會是 https://idcs-01234567890abcdef.identity.oraclecloud.com (我們會將連接埠號碼刪除)。

工作 4:部署 OAuth2 代理主機

我們使用 OAuth2 代理主機來處理 OAuth2 或 OpenID Connect (OIDC) 複雜性,並確保所有轉送至應用程式的要求都會經過認證。

  1. 儲存下列名為 oauth2-proxy.yaml 的 yaml 檔案,並以適用的值取代預留位置。

    注意:

    • <Identity Domain URL>: https://idcs-01234567890abcdef.identity.oraclecloud.com/

    • <Identity Domain FQDN>: idcs-01234567890abcdef.identity.oraclecloud.com

    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        k8s-app: oauth2-proxy
      name: oauth2-proxy
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: oauth2-proxy
      template:
        metadata:
          labels:
            k8s-app: oauth2-proxy
        spec:
          containers:
          - args:
            - --provider=oidc
            - --provider-display-name="Oracle Identity Domains"
            - --oidc-issuer-url=<Identity Domain URL>
            - --redirect-url=https://<YOUR-FQDN>/oauth2/callback
            - --upstream=file:///dev/null
            - --http-address=0.0.0.0:4180
            - --email-domain=*
            - --set-xauthrequest=true
            - --session-cookie-minimal=true
            - --whitelist-domain=<Identity Domain FQDN>
            env:
            - name: OAUTH2_PROXY_CLIENT_ID
              value: "<APPLICATION_CLIENT_ID>"
            - name: OAUTH2_PROXY_CLIENT_SECRET
              value: "<APPLICATION_CLIENT_SECRET>"
            # docker run -ti --rm python:3-alpine python -c 'import secrets,base64; print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))));'     
            - name: OAUTH2_PROXY_COOKIE_SECRET
              value: "<OUTPUT_OF_THE_ABOVE_DOCKER_COMMAND>"
            image: quay.io/oauth2-proxy/oauth2-proxy:latest
            imagePullPolicy: Always
            name: oauth2-proxy
            ports:
            - containerPort: 4180
              protocol: TCP
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        k8s-app: oauth2-proxy
      name: oauth2-proxy
    spec:
      ports:
      - name: http
        port: 4180
        protocol: TCP
        targetPort: 4180
      selector:
        k8s-app: oauth2-proxy
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: oauth2-proxy
      annotations:
        nginx.ingress.kubernetes.io/configuration-snippet: |
          set $xheader "";
          if ( $request_uri = "/oauth2/sign_out" ){
            set $xheader "https://<Identity Domain FQDN>/oauth2/v1/userlogout;
          }
          proxy_set_header X-Auth-Request-Redirect ${xheader};
    spec:
      ingressClassName: nginx
      rules:
      - host: <YOUR-FQDN>
        http:
          paths:
          - path: /oauth2
            pathType: Prefix
            backend:
              service:
                name: oauth2-proxy
                port:
                  number: 4180
      tls:
      - hosts:
        - <YOUR-FQDN>
    
  2. 將 OAuth2 代理主機建置到 OKE。

    kubectl apply -f oauth2-proxy.yaml
    

    確認 Pod 正在執行中。

    kubectl get pods -l k8s-app=oauth2-proxy
    
  3. 將 Nginx 設定為使用 OAuth2 代理主機進行要求認證。

    以認證註解更新 ingress.yaml 檔案。

    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: httpbin-ingress-nginx
      annotations:
        nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
        nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
        nginx.ingress.kubernetes.io/auth-response-headers: "x-auth-request-user, x-auth-request-email"
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
          - "<YOUR-FQDN>"
      rules:
        - host: "<YOUR-FQDN>"
          http:
            paths:
              - pathType: Prefix
                path: "/"
                backend:
                  service:
                    name: httpbin
                    port:
                      number: 5000
    
  4. 嘗試連線您的應用程式。您應該被重導至 Oracle 認證頁面。驗證成功後,您應重新導向至您的應用程式。

    「認證」頁面

    識別認證的使用者有兩個標頭。

    "x-auth-request-user": "xxxx@oracle.com"
    "x-auth-request-email": "xxxx@oracle.com"
    
  5. 若要從應用程式登出,您可以前往頁面上的 /oauth2/sign_out。

    https://<YOUR-FQDN>/oauth2/sign_out
    

    已知問題:登出後重新導向無法運作。此處會追蹤此問題:新增 id_token_hint 參數至 OIDC 提供者的登出提供者 URL 。

作業 5:清除資源

  1. 請執行下列命令以刪除所有 Kubernetes 部署的資源。

    kubectl delete -f oauth2-proxy.yaml -f ingress.yaml -f application.yaml
    helm uninstall ingress-nginx
    
  2. 從 Oracle Identity Domains 刪除應用程式。

  3. 刪除 OKE 叢集。

  4. 刪除為 OKE 叢集建立的 VCN。

    注意:

    • 您必須等待 OKE 叢集與節點集區刪除結束。

    • VCN 名稱包含 OKE 叢集的名稱:oke-vcn-quick-<oke-cluster-name>-<random-string>。

認可

其他學習資源

瀏覽 docs.oracle.com/learn 的其他實驗室,或前往 Oracle Learning YouTube 頻道存取更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請造訪 Oracle Help Center 。