このチュートリアルでは、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 連携を使用する認証プロセスは次のとおりです。
- 認証(AUTHN)ライブラリが IdP に JSON ウェブトークン(JWT)リクエストを送信します。
- IdP が JSON ウェブトークン(JWT)に署名します。AUTHN ライブラリが変数からこのデータを読み取ります。
- ライブラリが、署名付きトークンを含む POST コマンドをセキュリティ トークン サービスに送信します。
- セキュリティ トークン サービスが、信頼構築用に構成した Workload Identity プール プロバイダを調べて、認証情報の ID を検証します。
- Security Token Service が連携トークンを返します。
- ライブラリがトークンを IAM に送信します。
- IAM は、トークンをサービス アカウントの OpenID Connect トークンと交換します。詳細については、OpenID Connect ID トークンの生成をご覧ください。
- このライブラリは、OpenID Connect トークンを Jenkins に提供します。
- 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 の次の課金対象のコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
-
In the Google Cloud console, go to the project selector page.
-
Select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Cloud Run でマイクロサービスを設定します。詳細については、クイックスタート: Cloud Run にコンテナをデプロイするをご覧ください。
Jenkins を構成する
これらのタスクは、オンプレミス環境や別のクラウドなど、Google Cloud 以外の環境で行います。
OpenID Connect をサポートする ID プロバイダと外部ワークロードがすでにある場合は、この手順をスキップして、Cloud クライアント ライブラリのインストールに進みます。
外部ワークロードをシミュレートするには、Jenkins がインストールされている VM を使用します。Jenkins は Docker イメージとして実行することも、サーバーに直接インストールすることもできます。次の手順では、サーバーに直接インストールする方法について説明します。
- 任意の VM でコマンドラインを開きます。
Java をインストールします。
$ sudo apt update $ sudo apt install openjdk-11-jre $ java -version
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
ポート 8080 で Jenkins サーバーにアクセスできることを確認します。ファイアウォールの背後にある VM を使用している場合は、適切なポートが開いていることを確認します。
管理者パスワードを入手して Jenkins を設定します。手順については、インストール後の設定ウィザードをご覧ください。
SSL を設定するには、次の操作を行います。
- ドメイン プロバイダがある場合は、その認証局(CA)を使用して署名付き証明書をリクエストできます。または、zerossl.com から 90 日間持続する無料の署名証明書を入手することもできます。
証明書の zip ファイルをダウンロードして、Jenkins を実行しているサーバーに転送します。
scp -i CERTFILE.pem -r CERTFILE.zip VM_FQDN:/home/USERNAME
次のように置き換えます。
CERTFILE
は、公開鍵を含む証明書ファイルの名前に置き換えます。VM_FQDN
は、Google Cloud の外部にあるサーバーの FQDN に置き換えます。USERNAME
は、ユーザー名に置き換えます。
ファイル名を変更して、Jenkins で使用できる .pkcs12 ファイルを生成します。
openssl rsa -in KEYFILE.com.key -out KEYFILE.com.key
KEYFILE
は、証明書ファイルの名前に置き換えます。
/etc/sysconfig/jenkins
ファイルを更新します。テキスト エディタでファイルを開きます。
vi /etc/sysconfig/jenkins
JENKINS_PORT
を-1
に設定します。JENKINS_HTTPS_PORT
を8443
に設定します。ファイルの最後に次の引数を追加します。
JENKINS_ARGS="--httpsCertificate=/var/lib/jenkins/.ssl/CERTFILE.crt --httpsPrivateKeys=/var/lib/jenkins/.ssl/KEYFILE.pkcs1.key"
次のように置き換えます。
CERTFILE
は、.crt 形式を使用する証明書ファイルの名前に置き換えます。KEYFILE
は、PKCS 鍵のファイル名に置き換えます。
Jenkins サーバーを再起動します。
ファイアウォールでポート 8443 が開いていることを確認し、ポート 8443 で Jenkins にアクセスします。
Keycloak を Jenkins と統合するために必要な Jenkins プラグインをインストールします。次のいずれかを選択できます。
プラグインのインストールは、次のようにします。
- Jenkins ダッシュボードで、[Manage Jenkins] > [Manage Plugins] に移動します。
[Available] を選択して、任意のプラグインを検索します。次のスクリーンショットでは、プラグイン マネージャーが [Available] タブで選択されています。
プラグインをインストールします。
Keycloak を構成する
このチュートリアルでは、Keycloak がユーザー、グループ、ロールを管理します。Keycloak では、レルムを使用してユーザーを管理します。
Google Cloud の外部で実行されている VM に Keycloak サーバーをインストールします。このチュートリアルでは、Docker コンテナから Keycloak をインストールすることをおすすめします。
Keycloak の管理コンソールを開きます。
[Realm settings] に移動します。
[General] タブで、フィールドの設定を確認します。
- Enabled: ON
- User-Managed Access: OFF
- Endpoints: OpenID Endpoint Configuration と SAML 2.0 Identity Provider Metadata
次のスクリーンショットは、構成する必要があるフィールドを示しています。
クライアントを作成して、Keycloak でユーザーの認証をリクエストできるエンティティを作成します。クライアントは通常、Keycloak を使用してシングル サインオン(SSO)ソリューションを提供するアプリケーションとサービスです。
- Keycloak 管理コンソールで、[Clients] > [Create] をクリックします。
次のように入力します。
- Client ID: jenkins
- Client Protocol: openid-connect
- Root URL: http://JENKINS_IP_ADDRESS:8080(JENKINS_IP_ADDRESS は、Jenkins サーバーの IP アドレス)
次のスクリーンショットは、構成する必要があるフィールドを示しています。
[Save] をクリックします。
[Installation] タブで、トークンの形式が「Keycloak OIDC JSON」であることを確認します。Jenkins のセットアップを完了するために必要になるため、このトークンのコピーを作成します。
テストグループを作成する方法は次のとおりです。
- Keycloak 管理コンソールで、[Groups] > [New] をクリックします。
- グループの名前を入力して、[Save] をクリックします。
- テストグループをもう 1 つ作成します。グループにロールを割り当てることができますが、このチュートリアルではそれらのロールを必要としません。
グループに追加するテストユーザーを作成する手順は次のとおりです。
- Keycloak 管理コンソールで、[Manage user] > [Add users] をクリックします。
ユーザー情報を入力して、[Save] をクリックします。
次のスクリーンショットは、ユーザー アカウントの情報の例を示しています。
[Credentials] タブをクリックし、[Temporary] が [Off] に設定されていることを確認します。
パスワードをリセットします。
このアカウントは、後ほど JWT で認証に使用します。
次のスクリーンショットは、構成する必要があるフィールドを含む [Credentials] タブを示しています。
[Groups] タブをクリックし、前に作成したグループのいずれかを選択します。
[Join] をクリックします。
この手順を繰り返して、テストユーザーをさらに作成します。
OpenID Connect 構成用に Jenkins を構成する
このセクションでは、Jenkins の OpenID Connect プラグインを構成する方法について説明します。
- Jenkins サーバーで、[Manage Jenkins] > [Configure Global Security] に移動します。
[Security Realm] で [Keycloak Authentication Plugin] を選択します。[Save] をクリックします。
[Configure System] をクリックします。
[Global Keycloak] の設定で、Keycloak の構成で作成した Keycloak インストール JSON をコピーします。JSON データを再度取得する必要がある場合は、次の操作を行います。
Keycloak 管理コンソールの [Clients] に移動します。
クライアントの名前をクリックします。
[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 です。
OIDC 構成を保存するには、[保存] をクリックします。
これで、Jenkins が Keycloak にリダイレクトしてユーザー情報を取得できるようになりました。
Cloud クライアント ライブラリをインストールする
Keycloak から Google Cloud に JWT を送信するには、Jenkins サーバーに Cloud クライアント ライブラリをインストールする必要があります。このチュートリアルでは、Python を使用して SDK で Google Cloud を操作します。
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
pip3 をインストールします。Cloud クライアント ライブラリをダウンロードしてインポートできるようにします。
pip3 –version sudo apt update sudo apt install python3-pip pip3 –version
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 をユーザー名と置き換えます。
Jenkins サーバーに Google Cloud CLI をインストールします。手順については、クイックスタート: gcloud CLI のインストールをご覧ください。
Google Cloud 環境を構成する
このセクションでは、サーバーレス コンテナをホストする Google Cloud 環境を Jenkins と Keycloak に接続できるようにするために必要な手順について説明します。
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 のサービス アカウントを作成する手順については、サービス アカウントの作成と管理をご覧ください。
Workload Identity プールを作成します。gcloud CLI を使用してプールを作成するには、次のコマンドを実行します。
gcloud iam workload-identity-pools create cloudrun-oidc-pool \ --location="global" \ —-description="cloudrun-oidc" \ —-display-name="cloudrun-oidc"
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 を取得する
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 スクリプトを作成して、このステップを自動化できます。
トークンを jwt.io で検証します。
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
はプロジェクト番号です。VM で、
sts.creds.json
ファイルを ADC の変数として設定します。export GOOGLE_APPLICATION_CREDENTIALS=/Users/USERNAME/sts-creds.json
USERNAME は、UNIX ユーザー名で置き換えます。
Workload Identity 連携がリリースされる前は、この値はサービス アカウント キーでした。Workload Identity 連携では、この値は新しく作成された認証情報ファイルになります。
サービス アカウントの権限を借用するロール バインディングを作成します。
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
次のように置き換えます。
SERVICE_ACCOUNT
は、Google Cloud 環境の構成で作成したサービス アカウントのメールアドレスに置き換えます。詳細については、ggcloud iam service-accounts add-iam-policy-binding をご覧ください。USER_EMAIL
は、メールアドレスに置き換えます。
サービス アカウントで 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 をご覧ください。
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 アカウントへの課金を回避するには、プロジェクトを削除します。
プロジェクトを削除する
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
次のステップ
- Workload Identity 連携について確認する。
- Cloud アーキテクチャ センターで、リファレンス アーキテクチャ、図、ベスト プラクティスを確認する。