ノート:

Nginxイングレス・コントローラ、OAuth2プロキシおよびOracleアイデンティティ・ドメインを使用した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イングレス・コントローラ・ヘルム・リポジトリを追加します。詳細は、「イングレス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イングレス・コントローラをデプロイします。

    helm install ingress-nginx ingress-nginx/ingress-nginx -f values-override.yaml
    
  6. 次のyamlファイルをapplication.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を使用します。

    この場合、FQDN158-180-61-74.nip.ioです。

  9. 次のyamlファイルをingress.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アイデンティティ・ドメインに移動し、OracleIdentityCloudServiceドメインをクリックします。

  2. 左側のメニューから「統合アプリケーション」を選択し、「アプリケーションの追加」をクリックします。

  3. 「Confidential Application」を選択し、「Launch workflow」をクリックします。

    新しい機密アプリケーション

  4. アプリケーションの名前説明を入力し、「次」をクリックします。

    アプリケーションの詳細

  5. アプリケーションのoAuthパラメータを構成します。

    1. 「認可」セクションで、「認可コード」を選択します。

    2. 次のURLを入力して、「次」をクリックします。

      • リダイレクトURL: https://<YOUR-FQDN>/oauth2/callback
      • ログアウト後のリダイレクトURL: https://<YOUR-FQDN>
      • ログアウトURL: https://<YOUR-FQDN>/oauth2/sign_out

    アプリケーションauthのパラメータ

  6. 「Web層ポリシー」で、「スキップして後で実行」を選択し、「終了」をクリックします。

    Web層ポリシー

  7. [アクティブ]をクリックして、アプリケーションを使用可能にします。

    アプリケーションのアクティブ化

  8. 左側のメニューの「グループ」にナビゲートし、このアプリケーションとの認証を許可されたユーザーのグループを関連付けます。

    ユーザー・グループをアプリケーションに関連付けます。

  9. 「Client ID」および「Client Secret」をメモします。

    アプリケーション・クライアントIDおよびシークレット

  10. OracleIdentityCloudServiceドメインをクリックし、「ドメインURL」を展開します。

    アイデンティティ・ドメインURL

    例: 「アイデンティティ・ドメインURL」https://idcs-01234567890abcdef.identity.oraclecloud.comになります(ポート番号を削除します)。

タスク4: OAuth2プロキシのデプロイ

OAuth2プロキシを使用して、OAuth2またはOpenID Connect (OIDC)の複雑さを処理し、アプリケーションに転送されるすべてのリクエストが認証されるようにしています。

  1. 次のyamlファイルをoauth2-proxy.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
    

    ポッドが実行中であることを確認します。

    kubectl get pods -l k8s-app=oauth2-proxy
    
  3. リクエスト認証にOAuth2プロキシを使用するようにNginxを構成します。

    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認証ページにリダイレクトされます。認証が成功したら、アプリケーションにリダイレクトされます。

    認証

    認証済ユーザーを識別する2つのヘッダーがあります。

    "x-auth-request-user": "xxxx@oracle.com"
    "x-auth-request-email": "xxxx@oracle.com"
    
  5. アプリケーションからサインアウトするには、ページの/oauth2/sign_outに移動します。

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

    既知の問題:サインアウト後のリダイレクトが機能しません。この問題は、OIDCプロバイダのログアウト・プロバイダURLにid_token_hintパラメータを追加して追跡されます。

タスク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を参照してください。