Terraformを使ったGitHubの権限管理

# はじめに
新たな開発プロジェクトの始動時に、「必要なレポジトリとチームをGitHubで作って、適切な権限の付与をTerafformで構成して」と言われて、Terraformを触り始めたときのメモです。

# なぜTerraformを使うのか
以下の課題感はあるあるだと思いますが、解決策としてIaC(Infrastructure as Code)の代表格であるTerraformを使いました。

| 課題                     | 解決策（Terraformのメリット）                          |  
|--------------------------|--------------------------------------------------|  
| 一貫性の欠如             | コードとして権限設定を管理し、一貫性を保つことができる。 |  
| 変更履歴の追跡が困難     | バージョン管理システムで変更履歴を追跡し、透明性を向上。 |  
| 手動作業による非効率性   | 権限設定の自動化により、時間と労力を節約。             |  
| スケーラビリティの問題   | 大規模な権限管理をスケーラブルに実施可能。             |  
| 再利用性の欠如           | 再利用可能なモジュールとして設定を構築し、適用を簡易化。 |  

![](https://storage.googleapis.com/zenn-user-upload/43519f756a98-20241222.png)

# ディレクトリ構成
先に全体像のイメージをしやすくするために、ディレクトリ構成の例を載せます。

https://github.com/channnnsm/GitHub-IaC

```
team/    
├── team1/    
│   ├── backend.tf  
│   ├── locals.tf    
│   ├── main.tf    
│   ├── provider.tf      
│   └── variables.tf    
└── team2/    
    ├── backend.tf    
    ├── locals.tf    
    ├── main.tf    
    ├── provider.tf    
    └── variables.tf    
product_global.tf    
```

# それぞれのtfファイルの役割
Terraformを使用してGitHubの権限管理を行う場合、ファイル構成は以下のような役割を持ちます。

## 1. **provider.tf**:
   - Terraformプロバイダーの設定を行うファイルです。GitHubプロバイダーを使用するために必要なアクセス情報や認証情報を設定します。GitHubアカウントに対するアクセスを行うためのトークン情報などが設定されています。
  
https://github.com/channnnsm/GitHub-IaC/blob/main/team/team1/provider.tf

## 2. **backend.tf**:
   - Terraformの全体設定を管理するためのファイルです。ワークスペースの設定やバックエンドの設定（状態管理のためのリモートストレージの設定など）を記述します。

https://github.com/channnnsm/GitHub-IaC/blob/main/team/team1/backend.tf

## 3. **variables.tf**:
   - 変数を定義するファイルです。Terraformのコンフィギュレーションで使用する変数の宣言が書かれており、これらは後で変数を設定する際に利用されます。変数を使用することで、再利用性と柔軟性を高めることができます。
  
https://github.com/channnnsm/GitHub-IaC/blob/main/team/team1/variables.tf

## 4. **locals.tf**:
   - プロジェクト内で使用するローカル変数を定義するファイルです。ローカル変数は、そのファイルまたはモジュール内でのみ使用され、コードの可読性や再利用性を向上させるために使用されます。

https://github.com/channnnsm/GitHub-IaC/blob/main/team/team1/locals.tf

## 5. **main.tf**:
   - Terraformの主要なリソースおよび設定を記述するファイルです。リソースの作成や設定を行うためのコードが含まれており、GitHubの組織、リポジトリ、チーム、メンバーシップなどを管理するリソースが記述されています。
  
https://github.com/channnnsm/GitHub-IaC/blob/main/team/team1/main.tf

1～5までのファイルが、コードのモジュール化を促進し、管理や保守性を向上させるために、使用したものです。

## 6. **product_global.tf**:
   - 出力変数の定義: このファイルは、特定のリソースやその属性を他のモジュールやTerraformの実行後に利用できるように出力するための変数を定義しています。
   - リポジトリ一覧の集約: 各種プロダクトや機能に関連するリポジトリ名を一括で管理し、他のTerraformコンフィギュレーションから参照しやすくしています。

6のファイルは、他のチームも閲覧できるようにしたり、リポジトリが一覧で確認できて分かりやすくなるといったメリットがあります。

https://github.com/channnnsm/GitHub-IaC/blob/main/team/product_global.tf

# Terraform の基本構文を抽象化して整理
### プロバイダ (provider)
Terraformの設定を始める際に最初に行うべきことは、どのクラウドサービスやプラットフォームを使用するかを指定することです。これを行うのがプロバイダです。プロバイダは、Terraformが特定のサービスと対話するためのプラグインであり、設定の基盤となります。例えば、AWSを使用する場合は、AWSプロバイダを設定します。

```hcl
provider "aws" {
  region = "us-west-2"
}
```

### 変数 (variable)
次に、設定で使用する変数を定義します。変数を使用することで、設定を柔軟に変更でき、再利用性が向上します。変数は`variable`ブロックで定義され、デフォルト値や説明を設定することができます。これにより、環境ごとに異なる設定を簡単に切り替えることが可能です。

```hcl
variable "instance_type" {
  description = "EC2インスタンスのタイプ"
  default     = "t2.micro"
}
```

### ローカル変数 (locals)
ローカル変数は、変数を組み合わせたり、計算したりするために使用されます。`locals`ブロックを使って、計算された値や複数の値を組み合わせた結果を格納することができます。これにより、設定の複雑さを軽減し、コードの重複を避けることができます。

```hcl
locals {
  instance_name = "${var.environment}-web-server"
}
```

### データソース (data)
データソースは、既存のリソースや外部情報を取得するために使用されます。`data`ブロックを使用して、他のリソースの情報を参照し、それを設定に組み込むことができます。これにより、動的な設定が可能になり、既存のインフラストラクチャを活用できます。

```hcl
data "aws_ami" "latest" {
  most_recent = true
  owners      = ["amazon"]
  filters = [{
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }]
}
```

### 参照 (resource)
参照は、Terraformが管理するインフラストラクチャの具体的な構成要素を定義します。`resource`ブロックを使用して、クラウド上のリソースを定義し、設定します。リソースは、プロバイダによって提供されるさまざまなタイプがあり、インフラストラクチャの構築に必要な要素を表します。

```hcl
resource "aws_instance" "example" {
  ami           = data.aws_ami.latest.id
  instance_type = var.instance_type
}
```

### 出力値 (output)
最後に、実行結果として必要な情報を出力します。`output`ブロックを使って、リソースの属性や計算結果を表示することができます。これにより、他の設定や外部システムで使用するための情報を簡単に取得できます。

```hcl
output "instance_ip" {
  description = "EC2インスタンスのパブリックIPアドレス"
  value       = aws_instance.example.public_ip
}
```

# おわりに
Terraformを使ってGitHubの権限管理を行う方法について、学びを整理しました。ディレクトリ構成とファイルの役割、基本構文などが理解できたので、良い機会になりました！