TerraformでGitLab Self Managedに接続するAWS CodePipelineを自動構築する

# はじめに
AWS CodeCommitが他のコードリポジトリのサービスに機能的に水をあけられて久しいが、AWS CodePipelineはV2でそれらのコードリポジトリとの接続性を高めて利便性を上げようとしている。
そんな中、[セルフマネージドのGitLabについても2023/12/28に接続可能になった](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)ので、今回は
再現性高く接続できるよう、Terraformで動かしてみることする。

なお、この接続の実態としてはAWS CodeConnectionsのサービスを使うようである。この後の記述で何度かAWS CodeConnectionsと記載するが、マネージメントコンソール上では「接続」という名前になっているので、間違えないよう注意していただきたい。

:::note
本記事執筆後に、AWS CodeStar ConnectionsはAWS CodeConnectionsに名前が変わっている。
AWS CodeStarのサイトで以下の通りアナウンスされている。

> AWS CodeStar サポートの終了
> 2024 年 7 月 31 日をもって、Amazon Web Services (AWS) は AWS CodeStar プロジェクトの作成と閲覧のサポートを終了します。2024 年 7 月 31 日以降、AWS CodeStar コンソールへのアクセス、新しいプロジェクトの作成はできません。ただし、ソースリポジトリ、パイプライン、ビルドなど、AWS CodeStar によって作成された AWS リソースは、この変更の影響は受けず、引き続き機能します。AWS CodeStar 接続は、この終了による影響を受けません。

記事中には、その名残でAWS CodePipelineの設定やTerraformのリソース名に"CodeStar"といったワードが残っているが、いずれ置換されていくと考えられるため、読み替えてよんでいただきた。サービスとして表現する箇所については記載を見直した。
:::

https://aws.amazon.com/jp/codestar/features/

https://aws.amazon.com/jp/about-aws/whats-new/2024/03/aws-codeconnections-formerly-codestar-connections/


# 準備
以下のように、いくつかGitLab側での設定をしておく必要がある。

## GitLabのHTTPS化
まずは、Self ManagedなGitLabが正しくHTTPS化されていないといけない(HTTPのままだとAWS CodeConnections接続時にエラーになる)。
特に制限事項等の記載は見つけられなかったが、AWS CodeConnectionsのホスト設定がHTTPSでアクセスすることが前提になっているようだ。

HTTPS化についてはLet's Encryptあたりを使うと無料で証明をしてくれるが、今回はACMを利用して作成した。ACMでAWSが管理するプライベート認証局を使って証明書発行する方法は[別の記事](https://qiita.com/neruneruo/items/af3944fa785713ee41bb)で書いているので、そちらを参考にしていただきたい。

:::note
認証局に自己署名認証局(オレオレ認証局)を用いても接続可能なことは確認した。安全性を考慮すると、正式な認証局を経由するのが正しいため推奨しないが、検証等でお手軽に実施する場合は選択の余地はあるだろう。
:::

# GitLabのトークン払い出し
GitLabのトークンを以下の画面で払い出す。
この際作成するトークンはリポジトリのトークンではなくて、ユーザに紐づくトークンが必要になる。リポジトリのトークンではPermissionDeniedでエラーになるので、注意しよう。以下のEdit ProfileのAccess Tokensのメニューから作成可能だ。
あとは、```api```のパーミッションが必要になるので、画像の箇所にチェックを入れておく。

![キャプチャ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/86a74e89-6fca-c900-38fa-e4c8da653a60.png)


# 接続(AWS CodeConnections)の設定
## リソースの作成
以下の通りにリソースを作成する。
今回、Self ManagedなGitLabはEC2で起動しているので、そのリソースをデータソースで参照している。
インターネットからのアクセスを前提にしているならVPC設定不要では？と思ったが、設定しないとエラーになる。理由はよく分からない……。

:::note
自己署名認証局および自己署名証明書(オレオレ認証局/証明書)を使用する場合は、```tls_certificate```にサーバ証明書を設定すれば良い。
:::

```HCL
resource "aws_codestarconnections_host" "example" {
  name              = local.codestar_connection_host_name
  provider_endpoint = "https://${data.aws_instance.smgitlab.public_dns}"
  provider_type     = "GitLabSelfManaged"

  vpc_configuration {
    vpc_id             = data.aws_security_group.ec2.vpc_id
    subnet_ids         = [data.aws_instance.smgitlab.subnet_id]
    security_group_ids = [data.aws_security_group.ec2.id]
    tls_certificate    = aws_acmpca_certificate_authority.example.certificate
  }
}

resource "aws_codestarconnections_connection" "example" {
  name     = local.codestar_connection_name
  host_arn = aws_codestarconnections_host.example.arn
}
```

## 保留中の接続の更新
AWS CodeConnectionsはリソースを作成しただけでは使い始めることができない。
コンソールの以下の画面で接続の更新を行う。
リダイレクトが多いからか、この処理はTerraformはおろかCLIでも提供されていないので、仕方ないがマネージメントコンソールからやっておこう。

デベロッパー用ツール(Codeシリーズのコンソール画面)のメニューの設定→接続の以下の画面で、「保留中の接続の更新」のボタンを押す。

![キャプチャ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/16b45940-4d86-bfcf-b14a-05520e1eda6d.png)

すると、以下の画面が出てくるので、準備段階で作成したトークンのIDを入力しよう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/11a9d841-ecd3-2c64-b746-b6aeae818eb3.png)

トークンIDを入力したら、以下の画面でAuthorizeのボタンを押せば、接続の設定が完了する。

![キャプチャ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111314/59886a23-a9d5-2414-4362-a48d22ae1126.png)

接続設定画面のステータスが、「利用可能」になっていればOKだ。

# AWS CodePipelineに組み込む
## IAMロールの設定
さて、AWS CodePipelineに組み込みたいところだが、その前にAWS CodePipelineのIAMロールに以下の権限を付与しておく必要がある。設定しない場合はソースステージでエラーになる。

```HCL
data "aws_iam_policy_document" "codepipeline_custom" {
  (中略)
  statement {
    sid = "AllowCodeStarConnections"

    effect = "Allow"

    actions = [
      "codestar-connections:UseConnection",
    ]

    resources = [
      aws_codestarconnections_connection.example.arn,
    ]
  }
  (中略)
}
```

# AWS CodePipelineの設定
AWS CodePipelineは以下のように設定すれば良い。ここは特に難しいことはないだろう。
あとは、ソースアーティファクトをAWS CodeCommitと同じように扱っておけば良いだけである。
```FullRepositoryId```だけ厄介で、その名の通り、リポジトリ名だけでなくグループも書いておかないとエラーになるため注意しよう。

```HCL
resource "aws_codepipeline" "example" {
  name     = local.codepipeline_pipeline_name
  role_arn = aws_iam_role.codepipeline.arn
  (中略)
  stage {
    name = "Source"

    action {
      run_order        = 1
      name             = "Source"
      category         = "Source"
      owner            = "AWS"
      provider         = "CodeStarSourceConnection"
      version          = "1"
      output_artifacts = ["SourceArtifact"]

      configuration = {
        ConnectionArn    = aws_codestarconnections_connection.example.arn
        FullRepositoryId = "root/test"
        BranchName       = "main"
      }
    }
  }
  (中略)
}
```

これで、Self ManagedなGitLabからのCI/CD起動が簡単になった！

なお、[2024/2/9にはAWS CodePipeline V2に機能が追加され、GitLabであればタグやブランチをフィルタしてパイプラインを起動できるようになった](https://aws.amazon.com/about-aws/whats-new/2024/02/codepipeline-trigger-filters-execution-modes/)ので、今後より便利にCI/CDをできるようになっていくだろう。