AWS Secrets Manager EndpointConnectionErrorの修正:エンドポイントURLに接続できない(VPCエンドポイント未設定)

intermediate☁️ AWS2026-04-07| プライベートVPCサブネット内で動作するAWS Lambda / EC2 / ECS(NATゲートウェイなし、インターネットゲートウェイなし)、AWS SDK(boto3、AWS CLI、各種SDK)

Error Message

EndpointConnectionError: Could not connect to the endpoint URL: https://secretsmanager.us-east-1.amazonaws.com / ConnectionError: HTTPSConnectionPool: Max retries exceeded
#aws#secrets-manager#vpc#endpoint#プライベートサブネット#接続エラー

エラーの内容

アプリはプライベートVPCサブネット内で動作しています。AWS Secrets Managerを呼び出すと、以下のエラーが発生します:

EndpointConnectionError: Could not connect to the endpoint URL: https://secretsmanager.us-east-1.amazonaws.com
ConnectionError: HTTPSConnectionPool(host='secretsmanager.us-east-1.amazonaws.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object>: Failed to establish a new connection: [Errno -2] Name or service not known'))

Lambdaのログ、プライベートサブネット上のEC2インスタンス、ECSタスク内など、パブリックインターネットへの経路がない場所であればどこでも発生します。

原因

AWS SDKはデフォルトでsecretsmanager.<region>.amazonaws.comというパブリックエンドポイントを対象としています。NATゲートウェイやインターネットゲートウェイのないプライベートサブネットには、そこへのルートがありません。DNSによる名前解決に失敗するか、TCPハンドシェイクが完了しないかのどちらかです。

解決策は、Secrets Manager用のVPCインターフェイスエンドポイント(AWS PrivateLink)を作成することです。これにより、10.0.1.45のようなプライベートIPがVPCのDNSに注入されます。設定後は、secretsmanager.us-east-1.amazonaws.comがVPC内のアドレスに解決されます。インターネット接続は不要です。

手順

ステップ1 — 根本原因を確認する

対象のインスタンスにSSH接続(またはECS Exec / Lambdaテストを使用)して、エンドポイントに直接アクセスを試みます:

# パブリックエンドポイントに到達できるか確認
curl -v https://secretsmanager.us-east-1.amazonaws.com

# DNS解決を確認
nslookup secretsmanager.us-east-1.amazonaws.com

Could not resolve hostが表示されるか接続がハングする場合、VPCからAWS APIへのルートがなく、プライベートエンドポイントが必要であることが確認できます。

ステップ2 — VPCインターフェイスエンドポイントを作成する

AWSコンソールで操作する場合:

  • VPC → エンドポイント → エンドポイントの作成に移動
  • サービスカテゴリ:AWSサービス
  • secretsmanagerを検索し、com.amazonaws.<region>.secretsmanagerを選択
  • 使用するVPCを選択
  • ワークロードが動作するすべてのプライベートサブネットを選択
  • ワークロードのセキュリティグループからのインバウンドHTTPS(ポート443)を許可するセキュリティグループをアタッチ
  • プライベートDNSを有効化 — これが最も重要な設定です

CLIで操作する場合はこちら:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0abc123def456 \
  --vpc-endpoint-type Interface \
  --service-name com.amazonaws.us-east-1.secretsmanager \
  --subnet-ids subnet-0aaa111 subnet-0bbb222 \
  --security-group-ids sg-0xxxxxx \
  --private-dns-enabled \
  --region us-east-1

--private-dns-enabledを省略しないでください。これがないと、SDKは引き続きパブリックエンドポイントへのアクセスを試み、元の状態に戻ってしまいます。

ステップ3 — VPCのDNSホスト名を有効にする

プライベートDNSは、VPCでDNSホスト名とDNS解決の両方が有効な場合にのみ機能します。古いVPCではこれらが無効になっていることがあります。まず確認してください:

# 現在の設定を確認
aws ec2 describe-vpc-attribute \
  --vpc-id vpc-0abc123def456 \
  --attribute enableDnsHostnames

aws ec2 describe-vpc-attribute \
  --vpc-id vpc-0abc123def456 \
  --attribute enableDnsSupport

# 無効の場合は有効化
aws ec2 modify-vpc-attribute \
  --vpc-id vpc-0abc123def456 \
  --enable-dns-hostnames

aws ec2 modify-vpc-attribute \
  --vpc-id vpc-0abc123def456 \
  --enable-dns-support

ステップ4 — エンドポイントのセキュリティグループを更新する

インターフェイスエンドポイントは実際のネットワークインターフェイスであり、独自のセキュリティグループを持っています。Lambda、EC2、またはECSのワークロードからポート443のインバウンドを許可する必要があります:

aws ec2 authorize-security-group-ingress \
  --group-id sg-0endpoint-sg \
  --protocol tcp \
  --port 443 \
  --source-group sg-0your-workload-sg \
  --region us-east-1

セキュリティグループのルール設定漏れは、エンドポイントが存在するにもかかわらず接続が失敗する主な原因の一つです。

ステップ5 — エンドポイントポリシーを設定する(任意だが推奨)

デフォルトでは、エンドポイントはアカウント内のすべてのプリンシパルにSecretsManagerへのフルアクセスを許可します。アプリが必要とする権限のみに絞り込みましょう:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/MyAppRole"
      },
      "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MyApp/*"
    }
  ]
}

コンソール(エンドポイント → ポリシータブ)またはCLIから適用します:

aws ec2 modify-vpc-endpoint \
  --vpc-endpoint-id vpce-0xxxxxxxxx \
  --policy-document file://endpoint-policy.json

動作確認

エンドポイントが利用可能状態になるまで1〜2分かかります。その後、プライベートサブネット内からテストします:

# DNSがプライベートIP(10.x.x.xまたは172.x.x.x)に解決されることを確認
nslookup secretsmanager.us-east-1.amazonaws.com

# シークレットを取得 — すぐに結果が返るはず
aws secretsmanager get-secret-value \
  --secret-id MyApp/prod/database \
  --region us-east-1

# またはboto3を使用
python3 -c "
import boto3
client = boto3.client('secretsmanager', region_name='us-east-1')
resp = client.get_secret_value(SecretId='MyApp/prod/database')
print(resp['SecretString'][:50])
"

nslookupがパブリックAWS IPではなくVPC範囲内のIP(例:10.0.1.45)を返し、シークレットの値が正常に取得できれば、設定は完了です。

補足情報

他に必要になる可能性の高いエンドポイント

プライベートなワークロードが呼び出すAWSサービスはSecretsManagerだけではないことがほとんどです。各サービスにはそれぞれVPCエンドポイントが必要です。そうでなければ、NATゲートウェイが必要になります。よく追加されるサービスは以下の通りです:

  • com.amazonaws.<region>.kms — シークレットにカスタマーマネージドキーを使用する場合
  • com.amazonaws.<region>.sts — IAMロールの引き受けに使用
  • com.amazonaws.<region>.ssm — Parameter Storeに使用

サブネットCIDRの設計

複数のAZにエンドポイントをアタッチする前に、サブネットのCIDRが適切なサイズであり、重複がないことを確認してください。ブラウザベースのToolCraftのサブネット計算ツールは、2進数の計算をせずにアドレス範囲の確認や使用可能IPのカウントに便利です。

コストの考慮

インターフェイスエンドポイントは無料ではありません:AZあたり約$0.01/時間に加え、データ転送料金がかかります。3つのAZに展開すると、エンドポイント1つあたり月額約$21になります。プライベートサブネットで十数個のサービスを運用している場合、月額固定$32のNATゲートウェイ1台の方が実際にはコストが安くなる可能性があります。エンドポイントをサービスごとに追加する前に、トラフィック量を元にコストを計算してみてください。

Terraformスニペット

インフラをコードで管理する場合:

resource "aws_vpc_endpoint" "secretsmanager" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.${var.region}.secretsmanager"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = aws_subnet.private[*].id
  security_group_ids  = [aws_security_group.vpc_endpoint.id]
  private_dns_enabled = true

  tags = {
    Name = "secretsmanager-endpoint"
  }
}

Related Error Notes