Cloud Run と Workload Identity 連携を統合する


このチュートリアルでは、Workload Identity 連携を使用して Google Cloud の外部で実行されるワークロードを認証し、Cloud Run でホストされているマイクロサービスにアクセスできるようにする方法について説明します。このチュートリアルは、Workload Identity 連携を既存の ID プロバイダ(IdP)と統合する管理者を対象としています。Workload Identity 連携を使用すると、外部ワークロードを Google Cloud 内で実行されるワークロードに接続できます。Cloud Run では、ステートレスのコンテナ化されたマイクロサービスを実行できます。

このチュートリアルでは、Jenkins(外部ワークロードとして)、Keycloak(IdP として)、Cloud Run、Workload Identity 連携を構成する方法について説明します。このチュートリアルを完了すると、OpenID Connect 認証を使用して、Workload Identity 連携によって Google Cloud で Jenkins アプリケーションを認証できるようになります。

Workload Identity 連携を使用した外部ワークロード認証

Workload Identity 連携を使用すると、静的サービス アカウント キーを使用せずに Google Cloud の外部にあるワークロードを認証できます。Google Cloud のサービスを利用する必要がある外部ワークロードについて、この機能によるメリットを得られます。

Workload Identity 連携を使用すると、IdP を使用して Google Cloud で直接認証できます。認証には、OpenID Connect を使用します。Cloud Run は、認証のために IdP から OpenID Connect トークンを受け入れます。

Workload Identity 連携を使用する認証プロセスは次のとおりです。

  1. 認証(AUTHN)ライブラリが IdP に JSON ウェブトークン(JWT)リクエストを送信します。
  2. IdP が JSON ウェブトークン(JWT)に署名します。AUTHN ライブラリが変数からこのデータを読み取ります。
  3. ライブラリが、署名付きトークンを含む POST コマンドをセキュリティ トークン サービスに送信します。
  4. セキュリティ トークン サービスが、信頼構築用に構成した Workload Identity プール プロバイダを調べて、認証情報の ID を検証します。
  5. Security Token Service が連携トークンを返します。
  6. ライブラリがトークンを IAM に送信します。
  7. IAM は、トークンをサービス アカウントの OpenID Connect トークンと交換します。詳細については、OpenID Connect ID トークンの生成をご覧ください。
  8. このライブラリは、OpenID Connect トークンを Jenkins に提供します。
  9. Jenkins は Cloud Run での認証にこのトークンを使用します。

次の図は、認証フローを示しています。

認証フロー。

目標

  • Jenkins を外部ワークロードとして構成します。
  • Keycloak を OpenID Connect と互換性のある IdP として構成します。
  • Jenkins を Keycloak に接続します。
  • Cloud クライアント ライブラリをインストールして、Keycloak から Google Cloud に JWT トークンを取得します。
  • Google Cloud を Keycloak と Jenkins に接続します。
  • Keycloak で認証済みユーザーの JWT を取得します。

このチュートリアルでは Keycloak を使用しますが、GitLab、Okta、OneLogin など、OpenID Connect をサポートする他の ID プロバイダも使用できます。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Cloud Run でマイクロサービスを設定します。詳細については、クイックスタート: Cloud Run にコンテナをデプロイするをご覧ください。

Jenkins を構成する

これらのタスクは、オンプレミス環境や別のクラウドなど、Google Cloud 以外の環境で行います。

OpenID Connect をサポートする ID プロバイダと外部ワークロードがすでにある場合は、この手順をスキップして、Cloud クライアント ライブラリのインストールに進みます。

外部ワークロードをシミュレートするには、Jenkins がインストールされている VM を使用します。Jenkins は Docker イメージとして実行することも、サーバーに直接インストールすることもできます。次の手順では、サーバーに直接インストールする方法について説明します。

  1. 任意の VM でコマンドラインを開きます。
  2. Java をインストールします。

    $ sudo apt update
    $ sudo apt install openjdk-11-jre
    $ java -version
    
  3. Jenkins をインストールします。

    curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee \
    /usr/share/keyrings/jenkins-keyring.asc > /dev/null
    echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
    https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
    /etc/apt/sources.list.d/jenkins.list > /dev/null
    sudo apt-get update
    sudo apt-get install jenkins
    
  4. ポート 8080 で Jenkins サーバーにアクセスできることを確認します。ファイアウォールの背後にある VM を使用している場合は、適切なポートが開いていることを確認します。

  5. 管理者パスワードを入手して Jenkins を設定します。手順については、インストール後の設定ウィザードをご覧ください。

  6. SSL を設定するには、次の操作を行います。

    1. ドメイン プロバイダがある場合は、その認証局(CA)を使用して署名付き証明書をリクエストできます。または、zerossl.com から 90 日間持続する無料の署名証明書を入手することもできます。
    2. 証明書の zip ファイルをダウンロードして、Jenkins を実行しているサーバーに転送します。

      scp -i CERTFILE.pem -r CERTFILE.zip VM_FQDN:/home/USERNAME
      

      次のように置き換えます。

      • CERTFILE は、公開鍵を含む証明書ファイルの名前に置き換えます。
      • VM_FQDN は、Google Cloud の外部にあるサーバーの FQDN に置き換えます。
      • USERNAME は、ユーザー名に置き換えます。
    3. ファイル名を変更して、Jenkins で使用できる .pkcs12 ファイルを生成します。

      openssl rsa -in KEYFILE.com.key -out KEYFILE.com.key

      KEYFILE は、証明書ファイルの名前に置き換えます。

  7. /etc/sysconfig/jenkins ファイルを更新します。

    1. テキスト エディタでファイルを開きます。

      vi /etc/sysconfig/jenkins
      
    2. JENKINS_PORT-1 に設定します。

    3. JENKINS_HTTPS_PORT8443 に設定します。

    4. ファイルの最後に次の引数を追加します。

      JENKINS_ARGS="--httpsCertificate=/var/lib/jenkins/.ssl/CERTFILE.crt --httpsPrivateKeys=/var/lib/jenkins/.ssl/KEYFILE.pkcs1.key"

      次のように置き換えます。

      • CERTFILE は、.crt 形式を使用する証明書ファイルの名前に置き換えます。
      • KEYFILE は、PKCS 鍵のファイル名に置き換えます。
  8. Jenkins サーバーを再起動します。

  9. ファイアウォールでポート 8443 が開いていることを確認し、ポート 8443 で Jenkins にアクセスします。

  10. Keycloak を Jenkins と統合するために必要な Jenkins プラグインをインストールします。次のいずれかを選択できます。

    プラグインのインストールは、次のようにします。

    1. Jenkins ダッシュボードで、[Manage Jenkins] > [Manage Plugins] に移動します。
    2. [Available] を選択して、任意のプラグインを検索します。次のスクリーンショットでは、プラグイン マネージャーが [Available] タブで選択されています。

      Jenkins プラグイン マネージャー。

    3. プラグインをインストールします。

Keycloak を構成する

このチュートリアルでは、Keycloak がユーザー、グループ、ロールを管理します。Keycloak では、レルムを使用してユーザーを管理します。

  1. Google Cloud の外部で実行されている VM に Keycloak サーバーをインストールします。このチュートリアルでは、Docker コンテナから Keycloak をインストールすることをおすすめします。

  2. Keycloak の管理コンソールを開きます。

  3. [Realm settings] に移動します。

  4. [General] タブで、フィールドの設定を確認します。

    • Enabled: ON
    • User-Managed Access: OFF
    • Endpoints: OpenID Endpoint ConfigurationSAML 2.0 Identity Provider Metadata

    次のスクリーンショットは、構成する必要があるフィールドを示しています。

    Keycloak の全般設定。

  5. クライアントを作成して、Keycloak でユーザーの認証をリクエストできるエンティティを作成します。クライアントは通常、Keycloak を使用してシングル サインオン(SSO)ソリューションを提供するアプリケーションとサービスです。

    1. Keycloak 管理コンソールで、[Clients] > [Create] をクリックします。
    2. 次のように入力します。

      • Client ID: jenkins
      • Client Protocol: openid-connect
      • Root URL: http://JENKINS_IP_ADDRESS:8080JENKINS_IP_ADDRESS は、Jenkins サーバーの IP アドレス)

      次のスクリーンショットは、構成する必要があるフィールドを示しています。

      Keycloak でクライアントを追加します。

    3. [Save] をクリックします。

  6. [Installation] タブで、トークンの形式が「Keycloak OIDC JSON」であることを確認します。Jenkins のセットアップを完了するために必要になるため、このトークンのコピーを作成します。

  7. テストグループを作成する方法は次のとおりです。

    1. Keycloak 管理コンソールで、[Groups] > [New] をクリックします。
    2. グループの名前を入力して、[Save] をクリックします。
    3. テストグループをもう 1 つ作成します。グループにロールを割り当てることができますが、このチュートリアルではそれらのロールを必要としません。
  8. グループに追加するテストユーザーを作成する手順は次のとおりです。

    1. Keycloak 管理コンソールで、[Manage user] > [Add users] をクリックします。
    2. ユーザー情報を入力して、[Save] をクリックします。

      次のスクリーンショットは、ユーザー アカウントの情報の例を示しています。

      Keycloak でユーザーを追加します。

    3. [Credentials] タブをクリックし、[Temporary] が [Off] に設定されていることを確認します。

    4. パスワードをリセットします。

      このアカウントは、後ほど JWT で認証に使用します。

      次のスクリーンショットは、構成する必要があるフィールドを含む [Credentials] タブを示しています。

      Keycloak でパスワードを変更。

    5. [Groups] タブをクリックし、前に作成したグループのいずれかを選択します。

    6. [Join] をクリックします。

    7. この手順を繰り返して、テストユーザーをさらに作成します。

OpenID Connect 構成用に Jenkins を構成する

このセクションでは、Jenkins の OpenID Connect プラグインを構成する方法について説明します。

  1. Jenkins サーバーで、[Manage Jenkins] > [Configure Global Security] に移動します。
  2. [Security Realm] で [Keycloak Authentication Plugin] を選択します。[Save] をクリックします。

  3. [Configure System] をクリックします。

  4. [Global Keycloak] の設定で、Keycloak の構成で作成した Keycloak インストール JSON をコピーします。JSON データを再度取得する必要がある場合は、次の操作を行います。

    1. Keycloak 管理コンソールの [Clients] に移動します。

    2. クライアントの名前をクリックします。

    3. [Installation] タブで [Format Option] をクリックし、[Keycloak OIDC JSON] を選択します。

    Keycloak JSON の例を次に示します。

    {
        "realm":"master"
        "auth-server-url":"AUTHSERVERURL"
        "ssl-required":"none"
        "resource":"jenkins"
        "public-client":true
        "confidential-port":0
    }
    

    AUTHSERVERURL は、認証サーバーの URL です。

  5. OIDC 構成を保存するには、[保存] をクリックします。

これで、Jenkins が Keycloak にリダイレクトしてユーザー情報を取得できるようになりました。

Cloud クライアント ライブラリをインストールする

Keycloak から Google Cloud に JWT を送信するには、Jenkins サーバーに Cloud クライアント ライブラリをインストールする必要があります。このチュートリアルでは、Python を使用して SDK で Google Cloud を操作します。

  1. Jenkins サーバーに Python をインストールします。python3 をインストールする手順は次のとおりです。

    sudo apt update
    sudo apt install software-properties-common
    sudo add-apt-repository ppa:deadsnakes/ppa
    sudo apt update
    sudo apt install python3.8
    
  2. pip3 をインストールします。Cloud クライアント ライブラリをダウンロードしてインポートできるようにします。

    pip3 –version
    sudo apt update
    sudo apt install python3-pip
    pip3 –version
    
  3. pip3 を使用して Python 用 Cloud クライアント ライブラリをインストールします。

    pip3 install –upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    

    次に例を示します。

    pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
    Collecting google-api-python-client
        Downloading google_api_python_client-2.42.0-py2.py3-none-any.whl (8.3 MB)
            USERNAME | 8.3 MB 19.9 MB/s
    Collecting google-auth-httplib2
        Downloading google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 MB)
    Collecting google-auth-oauthlib
    Downloading google_auth_oauthlib-0.5.1-py2.py3-non-any.whl (19 KB)
    

    USERNAME をユーザー名と置き換えます。

  4. Jenkins サーバーに Google Cloud CLI をインストールします。手順については、クイックスタート: gcloud CLI のインストールをご覧ください。

Google Cloud 環境を構成する

このセクションでは、サーバーレス コンテナをホストする Google Cloud 環境を Jenkins と Keycloak に接続できるようにするために必要な手順について説明します。

  1. Google Cloud でサービス アカウントを作成し、Cloud Run のマイクロサービスから関連する権限にアクセスできるようにします。たとえば、gcloud CLI を使用してサービス アカウントを作成するには、次の操作を行います。

    gcloud iam service-accounts create cloudrun-oidc \
      –-description="cloud run oidc sa"  \
      –-display-name="cloudrun-oidc"
    

    デフォルトでは、Cloud Run はデフォルトのサービス アカウントを作成します。ただし、このアカウントには広範な権限セットがあるため、デフォルトのサービス アカウントを使用することは、セキュリティのベスト プラクティスではありません。そのため、マイクロサービス用に別のサービス アカウントを作成することをおすすめします。Cloud Run のサービス アカウントを作成する手順については、サービス アカウントの作成と管理をご覧ください。

  2. Workload Identity プールを作成します。gcloud CLI を使用してプールを作成するには、次のコマンドを実行します。

    gcloud iam workload-identity-pools create cloudrun-oidc-pool \
      --location="global" \
      —-description="cloudrun-oidc" \
      —-display-name="cloudrun-oidc"
    
  3. OpenID Connect 用の Workload Identity プール プロバイダを作成します。

    gcloud iam workload-identity-pools providers create-oidc cloud-run-provider \
      --workload-identity-pool="cloudrun-oidc-pool" \
      --issuer-uri="VAR_LINK_TO_ENDPOINT" \
      --location="global" \
      --attribute-mapping ="google.subject=assertion.sub,attribute.isadmin-assertion.isadmin,attribute.aud=assertion.aud" \
      --attribute-condition="attribute.isadmin=='true'"
    

    VAR_LINK_TO_ENDPOINT は、Keycloak OIDC エンドポイントへのリンクを含む変数に置き換えます。このリンクを見つけるには、KeyCloud 管理コンソールの [Realm] ウィンドウで [General] タブをクリックします。エンドポイントは HTTPS である必要があります。つまり、Keycloak サーバーは HTTPS で構成する必要があります。

Keycloak で認証済みユーザーの JWT を取得する

  1. Keycloak を実行している VM で、トークンをテキスト ファイルにダウンロードします。たとえば、Linux の場合は次のコマンドを実行します。

    curl -L -X POST 'https://IP_FOR_KEYCLOAK:8080/auth/realms/master/protocol/openid-connect/token' -H 'Content-Type: application/x-www-form-urlencoded' \
      --data-urlencode 'client_id=jenks' \
      --data-urlencode 'grant_type=password' \
      --data-urlencode 'client_secret=CLIENT_SECRET \
      --data-urlencode 'scope=openid' \
      --data-urlencode 'username=USERNAME' \
      --data-urlencode 'password=PASSWORD' | grep access_token | cut -c18-1490 > token.txt
    

    次のように置き換えます。

    • IP_FOR_KEYCLOAK は、Keycloak サーバーの IP アドレスに置き換えます。
    • CLIENT_SECRET は、Keycloak クライアント シークレットに置き換えます。
    • USERNAME は、Keycloak ユーザーに置き換えます。
    • PASSWORD は、Keycloak ユーザーのパスワードに置き換えます。

    このコマンドには、クライアント ID、クライアント シークレット、ユーザー名、パスワードが含まれます。セキュリティのベスト プラクティスとして、これらの値をマスクする場合は、コマンドラインではなく、環境変数を使用することをおすすめします。このコマンドの例では、認証情報を token.txt という名前のファイルにリダイレクトします。

    必要であれば、bash スクリプトを作成して、このステップを自動化できます。

  2. トークンを jwt.io で検証します。

  3. VM で認証情報ファイルを作成します。

    gcloud iam workload-identity-pools create-cred-config \
    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/providers/cloud-run/provider \
      --output-file=sts-creds.json \
      --credential-source-file=token.txt
    

    詳細については、gcloud iam workload-identity-pools create-cred-config をご覧ください。

    出力ファイルは次のようになります。

    {
        "type": "external_account",
        "audience": "//iam.google.apis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL",
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
        "token_url": "https://sts.googleapis.com/v1/token",
        "credential_source": {
            "file" "token.txt" }
    }
    

    PROJECT_NUMBER はプロジェクト番号です。

  4. VM で、sts.creds.json ファイルを ADC の変数として設定します。

    export GOOGLE_APPLICATION_CREDENTIALS=/Users/USERNAME/sts-creds.json
    

    USERNAME は、UNIX ユーザー名で置き換えます。

    Workload Identity 連携がリリースされる前は、この値はサービス アカウント キーでした。Workload Identity 連携では、この値は新しく作成された認証情報ファイルになります。

  5. サービス アカウントの権限を借用するロール バインディングを作成します。

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT \
        --role roles/iam.workloadIdentityUser \
        --member "principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/cloudrun-oidc-pool/subject/USER_EMAIL
    

    次のように置き換えます。

  6. サービス アカウントで Cloud Run サービスを呼び出すことができるようにします。

    gcloud run services add-iam-policy-binding SERVICE_NAME
      --member-"serviceAccount:SERVICE_ACCOUNT" \
      --role="roles/run.invoker"
    

    次のように置き換えます。

    • SERVICE_NAME は、Cloud Run で実行されているマイクロサービスの名前に置き換えます。

    • SERVICE_ACCOUNT は、Cloud Run のサービス アカウントのメールアドレスに置き換えます。

    詳細については、gcloud run services add-iam-policy-binding をご覧ください。

  7. ID トークンを生成します。

    #!/usr/bin/python
    from google.auth import credentials
    from google.cloud import  iam_credentials_v1
    
    import google.auth
    import google.oauth2.credentials
    
    from google.auth.transport.requests import AuthorizedSession, Request
    
    url = "https://WORKLOAD_FQDN"
    aud = "https://WORKLOAD_FQDN"
    service_account = 'SERVICE_ACCOUNT'
    
    name = "projects/-/serviceAccounts/{}".format(service_account)
    id_token = client.generate_id_token(name=name,audience=aud, include_email=True)
    
    print(id_token.token)
    
    creds = google.oauth2.credentials.Credentials(id_token.token)
    authed_session = AuthorizedSession(creds)
    r = authed_session.get(url)
    print(r.status_code)
    print(r.text)
    

    次のように置き換えます。

    • WORKLOAD_FQDN は、ワークロードの FQDN に置き換えます。

    • SERVICE_ACCOUNT は、Cloud Run のサービス アカウントのメールアドレスに置き換えます。

使用するトークンは Identity and Access Management API を呼び出すことができ、Cloud Run サービスの呼び出しに必要な新しい JWT を取得できます。

トークンを Jenkins パイプライン内で使用して、Cloud Run で実行しているサーバーレス コンテナを呼び出すことができます。これらの手順は、このチュートリアルでは説明しません。

クリーンアップ

このチュートリアルで使用したリソースに対する Google Cloud アカウントへの課金を回避するには、プロジェクトを削除します。

プロジェクトを削除する

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

次のステップ