CodeConnectionsでGitLab Self-Managedに閉域接続する|Invalid host endpoint providedの原因とVPC・証明書・認証の設計ポイント

AWS

AWS CodeBuildとGitLab Self-Managedを連携させる。AWSのマネージドサービスを利用すれば、比較的簡単に実現できそうに思えます。

しかし、GitLabがプライベートネットワーク内にあり、AWSアカウントも異なるとなると、話はそう単純ではありません。

今回、EC2上のGitLab Self-ManagedとCodeBuildを連携するため、AWS CodeConnectionsの設定を進める過程で、次のエラーが問題となりました。

Invalid host endpoint provided.

当初は、Transit Gateway(TGW)でVPC間の通信経路を確保すれば、あとはCodeConnectionsの設定だけで済むと考えていました。ところが、AWSサポートへの問い合わせを通じて、VPC接続、自己署名証明書、GitLabの認証、さらにCodeBuildのソース取得方式まで、切り分けるべき論点が次々と出てきました。

本記事では、この事例を基に、閉域環境でCodeConnectionsを利用する際の設計ポイントを整理します。

本記事の検証範囲

区分 内容
確認済み Invalid host endpoint provided. の発生、AWSサポートの回答、CodeConnectionsのAvailable表示
サポート回答に基づく経緯 VPC無効の状態でプライベートIPを指定するとエラーとなり、VPC設定の有効化によって接続可能になった
未検証 CodeBuildからのソース取得・ビルド実行、CodeBuild側の追加VPC・TLS設定の要否

1. GitLabとCodeBuildを別AWSアカウントで連携する

今回の構成は、次のとおりです。

項目 構成
ソースコード管理 GitLab Self-Managed
GitLabの稼働環境 Amazon EC2
ビルドサービス AWS CodeBuild
AWSアカウント GitLabとCodeBuildで別アカウント
VPC間接続 Transit Gateway
GitLabの公開範囲 プライベートネットワークのみ
通信プロトコル HTTPS
TLS証明書 自己署名証明書
接続サービス AWS CodeConnections

GitLabにはパブリックIPアドレスがなく、インターネットから直接アクセスできない構成です。

VPC間はTGWで接続されていますが、TGWの接続が存在することと、CodeConnectionsからGitLabへ通信できることは別の話です。

さらに、CodeConnectionsの接続設定、GitLab側での認可、CodeBuildによるソース取得では、それぞれ異なる通信や権限が関係します。

最初はネットワークの問題だと思っていたものが、調べていくと認証や証明書の問題にも広がっていく。複数のAWSサービスを組み合わせる際に、こうした切り分けの難しさを感じる場面は少なくありません。

2. CodeConnectionsの「ホスト」と「接続」は別物

エラーの原因を考える前に、CodeConnectionsの仕組みを整理しておきます。

GitLab Self-Managedとの連携では、「ホスト」と「接続」という2種類のリソースを扱います。

ホストはGitLabの設置環境を表すリソースで、GitLabのURL、VPC、サブネット、セキュリティグループ、必要に応じたTLS証明書などを設定します。

一方、接続はGitLabアカウントによる認可を受け、AWSサービスからリポジトリへアクセスするためのリソースです。

両者を区別すると、ネットワークや証明書の設定と、GitLabへのアクセス認可を分けて考えられます。

PATはホストの認可に使用する

GitLab Self-Managedのホストをセットアップする際には、Personal Access Token(PAT)を使用します。

AWS公式ドキュメントによれば、PATには次の要件があります。

  • GitLab管理者が作成・使用する
  • apiスコープが必要
  • GitLabのAdmin Modeが有効な場合はadmin_modeも必要
  • PATはホストの認可に使用され、接続では保存・使用されない
  • ホストのセットアップ後にPATを削除できる

つまり、ホストの認可に使用したPATを、そのまま継続的なリポジトリアクセス用の認証情報として保持する必要はありません。

参考:AWS公式|GitLab Self-Managedへの接続作成

3. Invalid host endpoint provided. とVPC設定の関係

今回のエラーは、CodeConnectionsでGitLab Self-Managedのエンドポイントを設定する際に発生したものです。

Invalid host endpoint provided.

AWSサポートからは、「VPCを使用する」が無効の状態でプライベートIPを指定すると、このエラーが発生するという説明がありました。

また、VPC接続を有効にして必要なネットワーク設定を行うことで、Availableに至ったという経緯も示されています。

このため、今回のエラーを切り分けるうえでは、接続先URLだけでなく、VPC接続の設定が有力な確認ポイントになります。

プライベートIPのGitLabにはVPC接続を検討する

AWS公式ドキュメントでは、GitLab Self-Managedがプライベートネットワーク内に存在する場合、ホストの作成時に「Use a VPC」を選択する構成が示されています。

設定する主な項目は、VPC ID、サブネットID、セキュリティグループIDです。

ここで注意したいのは、GitLabが稼働するVPCと、CodeConnectionsに設定するVPCが必ずしも同一とは限らないことです。

AWS公式手順では、VPNやDirect Connectを経由してGitLabへアクセスできるVPCの例が示されています。一方、今回のような別アカウント間のTGW構成については、同じ手順の中で明示的な例示がありません。

今回の構成ではTGWを利用し、CodeConnectionsのAvailable表示まで到達しています。ただし、これだけでTGW経由のあらゆる構成がサポートされると判断することはできません。

エラーが発生した場合の切り分け

同じエラーに遭遇した場合、まず次の4点を調べます。

  1. GitLabのエンドポイントURLが適切か
  2. プライベートIPへの接続に対応したVPC設定になっているか
  3. 設定したVPC・サブネットからGitLabへの経路があるか
  4. HTTPSの証明書が接続先と整合しているか

特に、プライベートIPを指定しているにもかかわらずVPC接続を使用していない場合は、最初に見直したい設定です。

4. 閉域接続では、作業端末からのアクセスも必要になる

AWSからGitLabへのネットワーク疎通を考える際、見落としやすいのが接続の認可操作です。

CodeConnectionsの公式手順では、接続を作成した後、ブラウザでGitLabにサインインし、「Authorize」を選択して認可します。

AWS CLIやCloudFormationで接続リソースを作成した場合も、初期状態はPENDINGとなり、コンソールで認可を完了させる必要があります。

ここで問題になるのが、設定作業を行う端末からGitLabへアクセスできるかという点です。

例えば、AWS側のVPCからGitLabへ通信できても、作業PCが社内ネットワーク外にあり、GitLabのプライベートIPに到達できなければ、ブラウザで認可操作を進められない可能性があります。

この場合は、社内VPNや管理用端末など、GitLabへアクセスできる正規の操作環境を用意する必要があります。

AWSサービス間の通信経路だけを考えていたところに、作業端末からのアクセスという別の問題が出てくる。閉域ネットワークの設計では、こうした運用面まで含めて考える必要があります。

5. TGW経由の通信と自己署名証明書をどう扱うか

今回の構成では、GitLabとCodeBuildが異なるAWSアカウントに存在します。

VPC間はTGWで接続されていますが、TGWが存在するだけでは通信は成立しません。

少なくとも、次の項目を整理する必要があります。

対象 設計上の論点
VPCルートテーブル GitLab側ネットワークへの経路
TGWルートテーブル 接続元・接続先への転送経路
戻り経路 GitLabから接続元へ応答できるか
セキュリティグループ HTTPS通信の接続元を許可しているか
ネットワークACL 必要な通信が遮断されていないか

特に、CodeConnectionsとCodeBuildを同じ通信元として扱わないことが大切です。

どのコンポーネントがGitLabに接続するかによって、必要なネットワーク設定は変わります。

自己署名証明書の設定先

今回のGitLabでは、HTTPS通信に自己署名証明書を使用しています。

AWS CodeConnectionsには、非公開認証局を利用する環境向けにTLS証明書を指定する設定があります。

ただし、証明書を登録することと、TLS接続が正常に検証されることは同じではありません。

接続先としてIPアドレスを使用する場合、証明書のSubject Alternative Name(SAN)に、そのIPアドレスが登録されているかが論点になります。

証明書を信頼できても、接続先のIPアドレスが証明書と一致しなければ、ホスト名検証で失敗する可能性があります。

この点は、実際の証明書をopenssl x509 -textなどで調べることで確認できます。

6. CodeBuild側にもVPCや証明書の設定が必要なのか

今回、最も気になったのが、CodeBuild側の証明書設定に関するAWSサポートの回答です。

サポートからは、CodeConnections側で証明書を設定していれば、CodeBuild側に特別な証明書設定は必要ないという趣旨の説明がありました。

当初は、CodeConnectionsがGitLabとの通信を担うのであれば、その説明で理解できそうに思えました。しかし、CodeBuildの公式仕様を調べていくと、一つ疑問が残りました。

CodeBuildが実際にGitLabからソースを取得する際、HTTPS通信はどのコンポーネントが実行するのでしょうか。

この点を整理しないまま、CodeBuild側の証明書設定が不要と判断するのは早いと感じました。

ビルド環境からGitLabへ接続するならVPC設定が必要

CodeBuildのビルド環境から直接GitLabへGit cloneを実行する方式であれば、プライベートIPしか持たないGitLabへ到達できるネットワーク経路が必要です。

通常、VPC設定のないCodeBuildのビルド環境はAWS管理のネットワークで動作するため、TGWで接続されたプライベートVPCへ、そのままアクセスできるわけではありません。

したがって、ビルド環境が直接GitLabへ接続する方式なら、CodeBuild側にも到達可能なVPC設定と通信経路が必要になります。

一方、CodeConnections側の仕組みでソース取得が完結する方式なら、必要なネットワーク構成は異なります。

残る論点は、今回のCodeConnectionsを利用したソース取得が、どちらの方式で動作するかです。

GetConnectionTokenから読み取れること

AWSのCodeBuild向けGitHub App接続手順では、サービスロールに次のIAM権限を付与する例が示されています。

{
  "Effect": "Allow",
  "Action": [
    "codeconnections:GetConnectionToken",
    "codeconnections:GetConnection"
  ],
  "Resource": "arn:aws:codeconnections:<region>:<account-id>:connection/<id>"
}

GetConnectionTokenは、接続に関連する認証トークンを取得するためのアクションです。

この仕組みから、CodeBuildが接続を通じて認証情報を取得し、ソース取得処理に利用する構成が考えられます。

ただし、認証トークンを取得することと、ビルド環境から直接GitLabへ通信することは同義ではありません。IAM権限だけで実際の通信元を特定することはできません。

なお、上記はGitHub App向け公式手順を基にした説明用のポリシー例です。実際のGitLab Self-Managed構成では、接続方式と必要権限に合わせて調整する必要があります。

参考:AWS公式|GitHub App connections

証明書検証を無効化すればよいのか

CodeBuildのProjectSource APIには、insecureSslという設定項目があります。

ただし、この設定はCodeConnectionsのホスト側で実施するTLS検証とは別のものです。今回のGitLab Self-Managed+CodeConnections構成に適用できるかも、ソース取得方式によって異なります。

AWSサポートからは、CodeConnections側のTLS証明書検証を無効化することはできないとの説明がありました。

いずれにしても、証明書検証を無効化してエラーを回避するのは、セキュリティ上望ましい対応ではありません。

自己署名証明書を使用する場合でも、適切なCA証明書の信頼設定と、接続先のホスト名またはIPアドレスとの整合性を確保することが基本です。

実際の通信元をどう調べるか

CodeBuildの実行結果が得られるなら、まずDOWNLOAD_SOURCEフェーズのログを調べます。

ソース取得の段階で失敗しているのか、取得後のビルド処理で失敗しているのかを分けるためです。

さらに、GitLab側のVPC Flow Logsを利用し、通信元IPアドレスを調べる方法があります。

通信元IPとENIの対応関係を照合すれば、CodeConnections側のネットワークコンポーネントからの通信なのか、CodeBuild側からの通信なのかを判断する手掛かりになります。

必要に応じてGitLab側のアクセスログとも突き合わせれば、より具体的に切り分けられます。

今回、CodeBuildの実行検証はできていませんが、設計段階では次の4点を整理しておきたいところです。

確認項目 調査する内容
ソース取得方式 GitLabへの通信をどのコンポーネントが実行するか
ネットワーク CodeBuild側にVPC・TGW経路が必要か
TLS証明書 どの実行環境で証明書を信頼させる必要があるか
IAM権限 接続の利用に必要な権限が付与されているか

7. AWSサポートへの問い合わせで重要なのは、設定値より前提条件

今回の問い合わせを整理する中で、改めて感じたのは、エラーメッセージだけを伝えても、問題の本質にはなかなかたどり着けないということです。

最初は「GitLabに接続できない」という問題でも、構成を整理すると、プライベートIP、TGW、自己署名証明書、GitLabの認可など、複数の条件が関係しています。

そこで、問い合わせの前提として、次の情報を整理することが有効になります。

  • GitLab Self-ManagedがEC2上で稼働している
  • GitLabはプライベートIPのみを使用している
  • AWSアカウント間をTGWで接続している
  • HTTPSには自己署名証明書を使用している
  • CodeConnectionsのエンドポイント設定時にエラーが発生している

このように整理すると、単なる接続エラーではなく、どのコンポーネント間の通信に問題があるのかを議論しやすくなります。

さらに、AWSサポートには設定方法だけでなく、設定が必要になる条件まで尋ねたいところです。

例えば、CodeBuild側の証明書設定について疑問が残るなら、次のように質問します。

GitLab Self-Managedへのソース取得にCodeConnectionsを利用する場合、GitLabへのHTTPS通信はどのコンポーネントが実行するのでしょうか。CodeBuild側にVPC設定やCA証明書の登録が必要になる条件を教えてください。

これは、単に「CodeBuild側の証明書設定は必要ですか」と聞くよりも、通信経路と責任分界を明確にできる質問です。

長年、基盤設計やシステム間連携に関わってきましたが、複数の製品やサービスが絡む問題では、個々の設定よりも、サービス間の境界に原因が潜んでいることが少なくありません。

今回のCodeConnectionsも、そうした視点で考える必要がある事例でした。

8. まとめ|マネージドサービスでも基盤設計は不要にならない

今回、CodeConnectionsでGitLab Self-Managedへの閉域接続を構成する過程で、Invalid host endpoint provided. というエラーが問題となりました。

AWSサポートからは、プライベートIPを使用する場合のVPC接続設定が有力な原因として示され、CodeConnectionsのAvailable表示まで到達しています。

今回の検討から得られる教訓は、次の3つです。

第一に、AWSサービス間の接続でも通信経路を明確にする必要があります。 TGWが接続されているだけでは不十分で、ルートテーブル、セキュリティグループ、通信元の整理が欠かせません。

第二に、ネットワークと認証は別の問題です。 AWS側からGitLabへ到達できても、作業端末から認可画面へアクセスできなければ、接続のセットアップを完了できない場合があります。

第三に、接続ステータスと実際の処理成功は区別します。 CodeConnectionsがAvailableでも、CodeBuildのソース取得やビルド成功まで保証されたわけではありません。

AWSのマネージドサービスは、インフラの構築・運用負担を減らしてくれます。しかし、複数サービスを組み合わせた際の通信経路、認証、TLS証明書、IAM権限まで自動的に設計してくれるわけではありません。

マネージドサービスを利用することと、基盤設計が不要になることは別の話です。

今回の事例は、その基本を改めて考える機会になりました。


参考資料

 

コメント

タイトルとURLをコピーしました