自動タスクを実行するためにインスタンスでサービス アカウントを使用して、他の Google Cloud Platform API とやり取りする場合、そのサービス アカウントには他の Compute Engine インスタンスへの SSH アクセスも必要になることがあります。このチュートリアルでは、SSH 接続を介してインスタンスにアクセスするようにアプリケーションを構成する方法について説明します。このチュートリアルのサンプル アプリケーションは、SSH 認証鍵の管理にサービス アカウントと OS ログインを使用します。
演習をスキップして完全なコードサンプルを確認する場合は、GitHub ページの GoogleCloudPlatform/python-docs-samples をご覧ください。
目標
このチュートリアルでは、次の目的を達成する方法について説明します。
- サービス アカウントを作成し、インスタンスに接続するアプリケーションのための OS ログイン、SSH アクセスを提供するようにサービス アカウントを構成する。
- サービス アカウントに関連付けるインスタンスを作成する。
- インスタンス上のサンプル アプリケーションを構成して、独自の SSH 認証鍵の管理と、SSH 接続の確立にサービス アカウントが使用されるようにする。
- サービス アカウントが関連付けられたインスタンスでアプリケーションを実行する。
- アプリケーションを Compute Engine の外部で実行する。これにはサービス アカウント キーを手動で指定し、追加の SSH パラメータを指定する必要があります。
料金
このチュートリアルでは、Cloud Platform の課金対象となるコンポーネント(Compute Engine を含む)を使用しています。
Cloud Platform を初めて使用される方は、無料トライアルをご利用いただけます。始める前に
-
Google アカウントにログインします。
Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。
-
GCP プロジェクトを選択または作成します。
-
Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。
- ユーザー アカウントには、複数の Compute Engine リソースを作成、削除、および変更する権限が必要です。このチュートリアルでは、自分のプロジェクトに対する次の IAM 役割がユーザーにあることを前提としています。
compute.instanceAdmin.v1
compute.networkAdmin
compute.osAdminLogin
iam.serviceAccountAdmin
iam.serviceAccountKeyAdmin
iam.serviceAccountUser
-
このチュートリアルでは、
gcloud
コマンドの実行に Cloud Shell を使用することを前提としています。
サービス アカウントとサンプル インスタンスを作成および構成する
このチュートリアルでは、1 つのサービス アカウントと 2 つのインスタンスを使用して、アプリケーションがリモート インスタンスで SSH コマンドを実行できるようにする方法について説明します。
次のコマンドを使用して、テスト環境を構成します。
コンソールで Cloud Shell を開きます。
将来のコマンドに備えてプロジェクト ID を設定する環境変数をエクスポートします。
export PROJECT_ID='[PROJECT_ID]'
プロジェクトに新しいサービス アカウントを作成します。この例では、
ssh-account
という名前のサービス アカウントを作成します。gcloud iam service-accounts create ssh-account --project $PROJECT_ID \ --display-name "ssh-account"
この例のためだけに使用する
ssh-example
という名前の一時的なネットワークを作成します。gcloud compute networks create ssh-example --project $PROJECT_ID
ssh-example
ネットワーク上のインスタンスへのすべての SSH 接続を許可するファイアウォール ルールを作成します。gcloud compute firewall-rules create ssh-all --project $PROJECT_ID \ --network ssh-example --allow tcp:22
us-central1-f
内にtarget
という名前のインスタンスを作成します。このインスタンスは、サービス アカウントが SSH 経由で接続するリモート インスタンスとして機能します。このインスタンスでは、プロジェクト レベルまたはインスタンス レベルで OS ログインが有効化されている必要があります。この例では、--metadata
フラグを使用してこの特定のインスタンスで OS ログインを有効にする方法を示しています。特にこの例では、このインスタンスで API リクエストを実行する必要がないため、--no-service-account
フラグと--no-scopes
フラグを含めます。gcloud compute instances create target --project $PROJECT_ID \ --zone us-central1-f --network ssh-example \ --no-service-account --no-scopes \ --machine-type f1-micro --metadata=enable-oslogin=TRUE
target
という名前のインスタンス専用の SSH 接続を確立できるようにするため、compute.osAdminLogin
の IAM 役割をサービス アカウントに付与します。compute.osAdminLogin
役割は、サービス アカウントにインスタンスのスーパーユーザー権限も付与します。この役割をプロジェクト レベルで付与してプロジェクト内のすべてのインスタンスに適用することもできますが、この例では権限の制限を保持するために、役割を特定のインスタンス レベルで付与します。gcloud compute instances add-iam-policy-binding target \ --project $PROJECT_ID --zone us-central1-f \ --member serviceAccount:ssh-account@$PROJECT_ID.iam.gserviceaccount.com \ --role roles/compute.osAdminLogin
us-central1-f
内にsource
という名前のインスタンスを作成します。インスタンスをssh-account
サービス アカウントに関連付けます。また、このインスタンスでの API リクエストを実行するためにサービス アカウントで必要になるcloud-platform
スコープを指定します。gcloud compute instances create source \ --project $PROJECT_ID --zone us-central1-f \ --service-account ssh-account@$PROJECT_ID.iam.gserviceaccount.com \ --scopes https://www.googleapis.com/auth/cloud-platform \ --network ssh-example --machine-type f1-micro
サービス アカウントは独自の SSH 認証鍵ペアを管理できるようになり、SSH を使用して target
インスタンスに限定して接続できるようになります。source
インスタンスは、作成した ssh-account
サービス アカウントに関連付けられているため、Python クライアント ライブラリはアプリケーションのデフォルト認証情報を使用してサービス アカウントとして認証し、そのサービス アカウントに前述の手順で付与した役割を使用できます。
次に、あるインスタンスから別のインスタンスに SSH 接続できるアプリケーションを構成して実行します。
インスタンス上で SSH アプリケーションを実行する
インスタンス上で動作中のアプリケーションが他のインスタンスへの SSH アクセスを必要とする場合は、サービス アカウントの SSH 認証鍵ペアを管理し、プログラムで SSH コマンドを実行できます。この例では、次の手順を使用してサンプル アプリケーションを実行します。
gcloud
コマンドライン ツールを使用してsource
インスタンスに接続します。gcloud compute ssh source --project $PROJECT_ID --zone us-central1-f
source
インスタンス上に、pip
および Python クライアント ライブラリをインストールします。my-username@source:~$ sudo apt update && sudo apt install python-pip -y && pip install --upgrade google-api-python-client
GoogleCloudPlatform/python-docs-samples から
service_account_ssh.py
サンプル アプリケーションをダウンロードします。my-username@source:~$ curl -O https://raw.githubusercontent.com/GoogleCloudPlatform/python-docs-samples/master/compute/oslogin/service_account_ssh.py
サンプル アプリケーションを実行します。このときコマンドラインからの変数の受け取りに
argparse
が使用されます。この例では、target
インスタンスにcowsay
をインストールして実行するようにアプリケーションに指示します。このコマンドでは、プロジェクト ID を手動で追加します。my-username@source:~$ python service_account_ssh.py \ --cmd 'sudo apt install cowsay -y && cowsay "It works!"' \ --project [PROJECT_ID] --zone us-central1-f --instance target ⋮ ___________ It works! ----------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
アプリケーションが正しく実行されると、cowsay
アプリケーションからの出力を受け取ることになります。--cmd
フラグを変更して、必要なコマンドを含めることができます。あるいは、service_account_ssh.py
をインポートして直接呼び出す独自のアプリケーションを作成することもできます。
exit
を実行して source
インスタンスから切断し、Cloud Shell に戻ります。
Compute Engine の外部で SSH アプリケーションを実行する
前の例では Compute Engine インスタンス上でアプリケーションを実行しましたが、その際 Python クライアント ライブラリがアプリケーションのデフォルト認証情報を使用して、source
インスタンスに関連付けられているサービス アカウントを使用できました。このアプリケーションを Compute Engine インスタンスの外部で実行した場合、サービス アカウント キーを手動で入力しない限り、クライアント ライブラリからサービス アカウントとその権限にアクセスできません。
このチュートリアルの前述部分で作成した
target
インスタンスの外部 IP アドレスを取得します。このアドレスは、Console の [インスタンス] ページで見つけるか、gcloud
コマンドライン ツールから次のコマンドを実行して見つけることができます。gcloud compute instances describe target \ --project $PROJECT_ID --zone us-central1-f
前の例で使用した
ssh-account
サービス アカウント用のサービス アカウント キーを作成し、そのキーファイルをローカル ワークステーションにダウンロードします。この例を実行するシステムにサービス アカウント キーをコピーします。
この例を実行するシステム上のターミナルを開きます。
GOOGLE_APPLICATION_CREDENTIALS
環境変数を設定して、サービス アカウント キーの.json
ファイルの場所へのパスを指定します。キーがDownloads
フォルダにある場合、環境変数は次の例のように設定できます。$ export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/key.json"
このシステムに前提条件をインストールします。
サンプル アプリケーションをダウンロードします。
$ curl -O https://raw.githubusercontent.com/GoogleCloudPlatform/python-docs-samples/master/compute/oslogin/service_account_ssh.py
サンプル アプリケーションを実行します。Compute Engine の外部でアプリケーションを実行すると、メタデータ サーバーを利用できないため、サービス アカウントのメールを手動で指定する必要があります。また、前述の手順で取得した
target
インスタンスの外部 IP アドレスも指定する必要があります。$ python service_account_ssh.py \ --cmd 'sudo apt install cowsay -y && cowsay "It works!"' \ --account ssh-account@[PROJECT_ID].iam.gserviceaccount.com \ --project [PROJECT_ID] --hostname [TARGET_EXTERNAL_IP] ⋮ ___________ It works! ----------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
アプリケーションが正しく実行されると、cowsay
アプリケーションからの出力を受け取ることになります。
サンプル アプリケーションの仕組み
service_account_ssh.py
サンプル アプリケーションは、次のプロセスを使用して動作します。
- OS ログイン API オブジェクトを初期化します。
- サービス アカウントのメールアドレスを手動で入力しない場合、アプリケーションはインスタンス メタデータを読み取り、インスタンスに関連付けられているサービス アカウントを識別します。このアプリケーションを Compute Engine の外部で実行する場合は、サービス アカウントのアドレスを手動で指定する必要があります。
create_ssh_key()
メソッドを呼び出して、この例が実行されているインスタンス上でサービス アカウントの一時 SSH 認証鍵を生成し、指定可能な有効期限タイマーを指定して公開鍵をサービス アカウントに追加します。- OS Login API から
getLoginProfile()
メソッドを呼び出して、サービス アカウントが使用する POSIX ユーザー名を取得します。 run_ssh()
メソッドを呼び出して、サービス アカウントとしてリモート SSH コマンドを実行します。- リモート SSH コマンドからのレスポンスを出力します。
- 一時 SSH 認証鍵ファイルを削除します。
- OS ログインは、有効期限が過ぎると公開鍵ファイルを自動的に削除します。
create_ssh_key()
メソッドは新しい SSH 認証鍵ペアを生成します。次に、このメソッドは OS ログイン API から users().importSshPublicKey()
を呼び出して、公開鍵をサービス アカウントに関連付けます。users().importSshPublicKey()
メソッドも有効期限値を受け入れます。この値は公開鍵が有効である期間を示します。
ベスト プラクティスとして、新しい鍵ペアを自分用に定期的に生成するようにサービス アカウントを構成します。この例では、サービス アカウントは確立する SSH 接続ごとに新しい鍵ペアを作成しますが、これはアプリケーションのニーズにより適したスケジュールに従って実行するように変更できます。
users().importSshPublicKey()
のリクエストの本文には expirationTimeUsec
値が含まれ、鍵の有効期限が切れる時点を OS ログインに伝えます。各アカウントで保持可能な SSH 認証鍵データは最大 32 KB です。そのため、サービス アカウントが操作を完了したらあまり時間をおかずに有効期限が切れるように公開 SSH 認証鍵を構成することをおすすめします。
サービス アカウントが SSH 認証鍵を構成すると、リモート コマンドを実行できます。この例では、アプリケーションは run_ssh()
メソッドを使用してリモート インスタンス上でコマンドを実行し、コマンド出力を返します。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。
次のコマンドを使用して、テスト環境のリソースをクリーンアップします。
コンソールで Cloud Shell を開きます。
source
という名前のインスタンスを削除します。gcloud compute instances delete source \ --project $PROJECT_ID --zone us-central1-f
target
という名前のインスタンスを削除します。gcloud compute instances delete target \ --project $PROJECT_ID --zone us-central1-f
ssh-account
サービス アカウントを削除します。gcloud iam service-accounts delete ssh-account --project $PROJECT_ID
ssh-example
という名前のネットワークを削除します。gcloud compute networks delete ssh-example --project $PROJECT_ID
次のステップ
- 完全なコードサンプルをダウンロードして確認する。完全なサンプルには、これらすべてのメソッドを同時に使用する一例が含まれています。自由にダウンロードし、ニーズに合わせて変更し、実行してください。
- Compute Engine API リファレンスと OS Login API リファレンスで、API を使用した他のタスクの実行方法を確認する。
- 独自のアプリケーションを作成する。