附註:

使用 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.yamlyaml 檔案。

    ---
    # 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

    在此情況下, FQDN158-180-61-74.nip.io

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

    注意:請務必使用您的 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.yamlyaml 檔案,並以適用的值取代預留位置。

    注意:

    • <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