🔑

Service Account Key をできるだけ使わないように工夫する

https://youtube.com/shorts/9AcSHOt7Sos

こんにちは、流行りに乗りたくなる、Google Cloud Japan Advent Calendar 2023 運営です。
この記事は Google Cloud Japan Advent Calendar 2023 5 日目の記事です。

みなさん、Google Cloud を使う際、 Service Account の Key を発行していませんか?そしてその Key は正しく管理運用されていますか?Key を発行すると非常に管理運用にコストが掛かり、、端的に言うと非常にめんどいです。

本記事ではどのようにできるだけ Service Account Key の作成を避け、効率的に認証をするかを解説します

そもそもなぜ Service Account Key を使うことを避けたいのか

「端的に言うと非常にめんどい」と言いましたが、一体どのような脅威が考えられるでしょうか。

認証情報の漏えい

Service Account Key が、本来保管すべきではない場所に誤って保存される可能性があります。漏えいした Service Account Key が悪用され、ユーザーの環境内に攻撃の足場が作られる可能性があります。GitHub の公開リポジトリにうっかり Push してしまったとき、どんなにマイナーなリポジトリでもかなりの確率で補足されます。

権限昇格

Service Account Key が流出してしまうと、他のアカウントの権限の昇格に利用される可能性があります。

なりすまし

流出した Service Account Key を使用して認証を行い、サービス アカウントでオペレーションを実行すると、攻撃者が身元を隠して操作を実行できてしまいます。この判断は一見すると通常のアクセスと見分けがつかないため、攻撃者にとって非常に有効な攻撃手段になり得ます。

Service Account Key の利用を避ける方法

Service Account Key の利用を避けるためには、コード内で Google Cloud API にアクセスする際は SDK と ADC を用いて実装するとよいでしょう。
ADC とは Application Default Credentials の略で、認証情報を解決するフローと、得られた認証情報の2つの意味を用いられます。SDK を用いて Google Cloud API を使う場合、例えば下記のように行うことが一般的です。

func uploadFileToGCS(bucketName, objectName, localPath string) error {
    // Create a new GCS client.
    ctx := context.Background()
    client, err := storage.NewClient(ctx)
    if err != nil {
        return fmt.Errorf("Failed to create GCS client: %v", err)
    }
    defer client.Close()

    // Open the local file.
    f, err := os.Open(localPath)
    if err != nil {
        return fmt.Errorf("Failed to open local file: %v", err)
    }
    defer f.Close()

    // Upload the file to GCS.
    wc := client.Bucket(bucketName).Object(objectName).NewWriter(ctx)
    if _, err := io.Copy(wc, f); err != nil {
        return fmt.Errorf("Failed to upload file to GCS: %v", err)
    }
    if err := wc.Close(); err != nil {
        return fmt.Errorf("Failed to close GCS writer: %v", err)
    }

    return nil
}

ちなみにこのコードは先日一般公開となった Duet AI for Developers をいつも使っているVSCode上で実行して生成しました。ちなみに IntelliJ にも対応しています。20以上のプログラミング言語と、KRM、Terraformにも対応しています!そしてなんと2024年の2月まで無料です!こっちもおすすめですよ!

それはさておき、このコードを実行するとコードは認証情報を次のような場所を確認し、認証します。

  1. GOOGLE_APPLICATION_CREDENTIALS 環境変数
  2. Google Cloud CLI で設定されたユーザー認証情報
  3. 接続済みのサービス アカウント(メタデータ サーバーから返されます)

この中で、できるだけ限り2と3の情報を使って開発・実装を行うことをおすすめします。2の設定は、
gcloud auth application-default login
こうすることで、自分のADCが既定の場所に保存されます。
Service Account を用いてログインしたい場合は、

gcloud auth application-default login --impersonate-service-account SERVICE_ACCT_EMAIL

このようなコマンドで Service Account の ADC が既定のパスに保存されます。

もしこのコードを Cloud Run や GCE などの Google Cloud 上のリソースで実行している場合は、3の通り、そのリソースに接続されている Service Account の認証を用いて実行されます。よって Service Account Key を一緒にデプロイしたりする必要はないのです。

Service Account Key の作成を禁止する

Google Cloud の管理者の皆さん、実は Service Account Key の作成を禁止することができます。どのようにやるかというと、組織ポリシーを設定します。

iam.disableServiceAccountKeyCreationiam.disableServiceAccountKeyUpload この2つの設定を変更すればよいでしょう。
ちなみに Terraform で書くとこのような感じです

resource "google_organization_policy" "disableServiceAccountKeyCreation" {
  org_id     = var.org_id
  constraint = "constraints/iam.disableServiceAccountKeyCreation"

  boolean_policy {
    enforced = true
  }
}

Service Account Key の利用状況を確認する

もうすでにたくさん Service Account Key が使われているかもしれない…!という場合は、まずは状況を確認してみましょう。Policy Intelligence の Activity Analyzer を使うことで、認証アクティビティを確認できます。使用開始する前に、 Policy Analyzer API を有効にし、下記のようなコマンドを実行します。

gcloud policy-intelligence query-activity --activity-type=serviceAccountKeyLastAuthentication --project=PROJECT_ID

もしくはすでに調べたい Service Account が決まっている場合は、 https://console.cloud.google.com/iam-admin/analyzer ここから調べることが可能です。

まとめ

入門編として書こうかと思ったのですが、案外 Service Account Key が使われていることが多いので、今回は通常版で書かせていただきました。
Google Cloud はこちらのドキュメントのような、どのような認証方式を用いたほうがよいかを判断するデシジョンツリーを公開しています。アプリケーションを作成されている皆様は人はこちらをご覧いただき、どの認証方式を用いるのが最も良いかを判断してみてください。
Google Cloud の管理者の皆様はぜひこちらを読んでいただき、Service Account Key からの移行を検討してみてください。

それではまた来年!

Google Cloud Japan

Discussion