1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Lambda から Vertex AI(Gemini)をセキュアに呼び出す!

Posted at

概要

Google Cloud の Vertex AI(Gemini)を、AWS Lambda から呼び出します!
Workload Identity Federation でセキュアな認証を実装します。

なぜ AWS Lambda × Vertex AI?

Amazon Bedrock エージェント に Gemini を組み込みたいからです!

Gemini API を直接利用する方法ありますが、セキュリティ的にAPIキーを管理したくないので Workload Identity Federation で認証します。

せっかくなので技術検証も兼ねて Vertex AI をさわってみよう思った次第です!

AWS から Vertex AI アクセス許可フロー

アクセス許可フローは下記の通りです。

  • AWS STS を利用し Google Cloud のサービスアカウントにアクセス許可する
  • Google Cloud 側で、Workload Identity Pool とその Provider を設定し、AWS IAM ロールが認証を通じ Google Cloud サービスアカウント にアクセス許可する
  • Google Cloud サービスアカウントに、Vertex AI アクセス権限付与する
  • 結果 AWS から Vertex AI へアクセス可能になる!!!

Workload Identity Federation

Google Cloud で下記設定を実施し、特定のAWSアカウントからのみアクセスを許可します。

  • Service Account (人ではなくプログラム等が Google Cloud のリソースにアクセスするためのアカウント)
  • Workload Identity
  • IAM
main.tf
data "google_project" "current" {}
data "aws_caller_identity" "self" {}

locals {
  project_id     = data.google_project.current.project_id
  project_number = "************"
  services = toset([
    "iam.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "iamcredentials.googleapis.com",
    "sts.googleapis.com",
    "aiplatform.googleapis.com"
  ])
}

#######################################
# Service Account
#######################################
# Google Cloud で利用する API の 有効化
resource "google_project_service" "main" {
  for_each                   = local.services
  project                    = local.project_id
  service                    = each.value
  disable_dependent_services = true
}

resource "google_service_account" "main" {
  project      = local.project_id
  account_id   = local.project_id
  display_name = local.project_id
}

#######################################
# Workload Identity
#######################################
resource "google_iam_workload_identity_pool" "main" {
  project                   = local.project_id
  workload_identity_pool_id = "aws"
  display_name              = "aws"
}

resource "google_iam_workload_identity_pool_provider" "main" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.main.workload_identity_pool_id
  workload_identity_pool_provider_id = "aws"
  display_name                       = "aws"
  
  # AWS Lambda をデプロイするアカウントのみ許可
  aws {
    account_id = data.aws_caller_identity.self.id
  }
}

#######################################
# IAM
#######################################
# サービスアカウントに Vertex AI アクセス権限付与
resource "google_project_iam_member" "main" {
  project = local.project_id
  role    = "roles/aiplatform.user"
  member  = "serviceAccount:${google_service_account.main.email}"
}

# AWS がサービスアカウントの権限借用許可
resource "google_service_account_iam_binding" "main" {
  service_account_id = google_service_account.main.name
  role               = "roles/iam.workloadIdentityUser"
  members = [
    "principalSet://iam.googleapis.com/projects/${local.project_number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.main.workload_identity_pool_id}/*",
  ]
}

Google Cloud 認証情報設定

Google Cloud 認証情報取得

  • コンソールから IAMと管理 → Workload Identity 連携を選択
  • 利用するプールを選択
  • 接続済みサービス アカウントから構成をダウンロード
    スクリーンショット 2025-05-02 20.18.57.png

AWS Systems Manager Parameter Store へ Google Cloud 認証情報保存

Google Cloud 認証情報ファイルの内容を、AWS Systems Manager Parameter Storeへ登録します。
パラメータ名は GOOGLE_APPLICATION_CREDENTIALS で登録します。

AWS Lambda

Vertex AI SDK for Pythonを利用する為、コンテナイメージで Lambda をデプロイします。
※ Lambda レイヤーでは容量制限に引っかかる為

メモリーサイズは 最小 128 MB の場合、メモリ不足でエラーになる場合があります。

main.tf
#######################################
# Lambda Function
#######################################
resource "aws_lambda_function" "main" {
  function_name = "gemini"
  package_type  = "Image"
  image_uri     = "${aws_ecr_repository.main.repository_url}:latest"
  memory_size   = 512
  timeout       = 900
  role          = aws_iam_role.main.arn
  environment {
    variables = {
      GOOGLE_APPLICATION_CREDENTIALS_PATH = "GOOGLE_APPLICATION_CREDENTIALS" # SSM Parameter Storeのパラメータ名
      GCP_PROJECT_ID                      = data.google_project.current.project_id
    }
  }
}

#######################################
# ECR
#######################################
resource "aws_ecr_repository" "main" {
  name = "gemini"
}

#######################################
# IAM
#######################################
resource "aws_iam_role" "main" {
  name               = "LambdaRoleForGemini"
  assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}

resource "aws_iam_role_policy_attachment" "main" {
  role       = aws_iam_role.main.name
  policy_arn = aws_iam_policy.main.arn
}

resource "aws_iam_policy" "main" {
  name   = "LambdaRoleForGemini"
  policy = data.aws_iam_policy_document.lambda_role.json
}
data.tf
data "aws_caller_identity" "self" {}
data "aws_region" "current" {}
data "google_project" "current" {}

#######################################
# IAM
#######################################
data "aws_iam_policy_document" "lambda_assume_role" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
    actions = ["sts:AssumeRole"]
  }
}

data "aws_iam_policy_document" "lambda_role" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      "ssm:GetParameter",
      "ssm:GetParameters",
    ]
    resources = [
      "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.self.id}:parameter/*",
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "kms:Decrypt",
      "kms:Encrypt",
      "kms:GenerateDataKey",
    ]
    resources = [
      "arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.self.id}:key/*"
    ]
  }
  statement {
    effect = "Allow"
    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents",
    ]
    resources = ["arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.self.id}:log-group:/aws/lambda/${aws_lambda_function.main.function_name}:*"]
  }
}

AWS Lambda コンテナ設定

Lambda の処理で利用するライブラリを定義します。

requirements.txt
boto3==1.37.17
google-cloud-aiplatform==1.90.0
google-auth==2.39.0

Dockerfile を記述しビルドします。

Dockerfile
FROM public.ecr.aws/lambda/python:3.13

WORKDIR /var/task

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Lambdaの処理が存在するディレクトリ
COPY src .

CMD ["lambda_function.lambda_handler"]

ビルドが完了したら、ECRへプッシュします。

AWS Lambda の 処理

コンテナ内部に環境変数 GOOGLE_APPLICATION_CREDENTIALS を設定し、Google Cloud 認証情報ファイルを埋め込む必要があります。

lambda_function.py

import os

import boto3
import vertexai
from vertexai.generative_models import GenerationConfig, GenerativeModel

def lambda_handler(event, _):
    try:
        credentials = boto3.client("ssm").get_parameter(
            Name=os.environ.get("GOOGLE_APPLICATION_CREDENTIALS_PATH"),
            WithDecryption=True
        )

        # コンテナ内部に google cloud 認証情報を json で保持する
        credentials_path = "/tmp/gcloud-credential.json"
        with open(credentials_path, "w") as f:
            f.write(credentials)

        # json のパスを環境変数に設定する
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credentials_path

        # GOOGLE_APPLICATION_CREDENTIALS を読み取り認証を実施
        gcp_project_id = os.environ.get("GCP_PROJECT_ID")
        vertexai.init(project=gcp_project_id, location="us-central1")
        model = GenerativeModel("gemini-2.5-flash-preview-04-17")

        # モデルに対しての詳細な設定を調整
        generation_config = GenerationConfig(
            temperature=0.9,
            top_k=40,
            top_p=0.9,
            candidate_count=1,
            max_output_tokens=8192,
        )

        text = "自己紹介してください"
        response = model.generate_content(
            text,
            generation_config=generation_config,
        )
        return {"status_code": 200, "message": "処理成功", "text": response.text}
    except Exception as e:
        return {"status_code": 500, "message": "処理失敗", "error": str(e)}

AWS Lambda のコンソールから実行し、Gemini から回答があれば成功です!!
スクリーンショット 2025-05-03 16.05.24.png

まとめ

AWS と Google Cloud の認証関連や、本記事には記述していないですがコンテナイメージ Lambda の CD 関連の知見が増えてよかったです。

次は AWS Lambda から Azure OpenAI Service 経由で GPT を呼び出したい!!!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?