🚀

Terraformで自分のIPアドレスを取得してSGに設定する方法:HTTPプロバイダーの活用

2024/07/08に公開

やりたいこと

現在自分が使っているパブリックIPをTerraform構築時に取得し、それをセキュリティグループ(SG)に設定します。AWSマネジメントコンソールでの"myip"と同じようなことをTerraformで実現。

実装方針

自分のIPアドレスを取得するために、HTTPプロバイダーを使用して外部のIP取得サービスにリクエストを送信し、そのレスポンスを利用してセキュリティグループに反映させます。

ゴール

  • プロバイダーの設定
  • 自分のpublic ip取得
  • VPCの構築
  • SG作成・設定(自分のpublic ipを反映)

前提条件

以下が完了していること:

  • AWS CLIのインストール
  • direnvのインストール
  • Terraformのインストール・初期設定

参考:
WSL2上のUbuntuでTerraformを使用するためのセットアップガイド

前提知識

Terraformプロバイダーとは:

Terraformプロバイダーは、Terraformが異なるクラウドサービスやAPIとやり取りするためのプラグインです。プロバイダーは、リソースの作成、変更、削除を管理し、Terraformがさまざまなサービスと統合できるようにします。
https://registry.terraform.io/browse/providers

HTTPプロバイダーとは:

HTTPプロバイダーは、HTTPリクエストを介して外部のAPIからデータを取得するために使用されるTerraformプロバイダーです。これにより、外部サービスから動的にデータを取得し、Terraformの設定に組み込むことができます。
https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http

手順

ステップ1: プロバイダーの設定

まず、TerraformプロジェクトでHTTPプロバイダーを使用できるように設定します。

terraform {
  required_providers {
    http = {
      source  = "hashicorp/http"
      version = "~> 3.0"
    }
    aws = {
      source = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "http" {}
provider "aws" {
  region = "ap-northeast-1"  
}
  • terraformブロック: 使用するプロバイダーを定義します。
  • required_providersブロック: HTTPプロバイダーとAWSプロバイダーを指定し、それぞれのバージョンを設定します。
  • version = ~> 3.0は、3.0系の最新バージョンを使用することを意味します。
  • provider "http"ブロック: HTTPプロバイダーを設定します。
  • provider "aws"ブロック: AWSプロバイダーを設定します。

ステップ2: HTTPデータソースの定義

次に、HTTPプロバイダーを使用して自分のIPアドレスを取得するためのデータソースを定義します。ここでは、ipifyというサービスを使用します。

data "http" "my_ip" {
  url = "https://api.ipify.org?format=json"
}
  • data "http"ブロック: HTTPデータソースを定義します。dataブロックは、Terraformが外部からデータを取得するために使用されます。
  • urlパラメータ: IPアドレスを取得するためのAPIエンドポイントを指定します。URLにGETリクエストを送信してIPアドレスを取得します。

※IP取得のイメージがわかなければブラウザで実際にhttps://api.ipify.org?format=jsonをいれてみて実行してみてください。

ステップ3: ローカル変数に設定

取得したIPアドレスをローカル変数に設定します。

locals {
  my_ip = "${jsondecode(data.http.my_ip.response_body)["ip"]}/32"
  }
  • localsブロック: 取得したIPアドレスに/32を追加してCIDR形式に変換し、ローカル変数my_ipに設定します。

ステップ4: VPCの設定

セキュリティグループを定義する前に、VPCを設定します。

resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "example-vpc"
  }
}
  • resource "aws_vpc"ブロック: AWS VPCを定義します。cidr_blockでIPアドレス範囲を設定し、tagsでリソースにタグを付けます。

ステップ5: SG作成・設定(取得したIPアドレスの使用)

ローカル変数my_ipを使用してセキュリティグループのルールを設定します。

resource "aws_security_group" "example" {
  name        = "allow_my_ip"
  description = "Allow inbound traffic from my IP"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [local.my_ip]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  vpc_id = aws_vpc.example.id
}
  • resource "aws_security_group"ブロック: AWSのセキュリティグループを定義します。
  • aws_security_groupリソースは、インバウンドおよびアウトバウンドトラフィックを制御します。
  • name: セキュリティグループの名前を指定します。
  • description: セキュリティグループの説明を指定します。
  • ingressブロック: インバウンドトラフィックのルールを定義します。ここでは、ポート22(SSH)へのトラフィックを許可します。
  • from_port: 開始ポートを指定します。
  • to_port: 終了ポートを指定します。
  • protocol: 使用するプロトコルを指定します(tcp)。
  • cidr_blocks: 許可するIP範囲を指定します。ここでは、ローカル変数my_ipを使用して自分のIPアドレスを指定します。
  • egressブロック: アウトバウンドトラフィックのルールを定義します。ここでは、全てのアウトバウンドトラフィックを許可します。
  • protocol: -1を指定することで、全てのプロトコルを対象にします。
  • vpc_id: セキュリティグループを関連付けるVPCのIDを指定します。

ステップ6: Terraformを実行

上記ステップ1~5のコードを.tfファイル(例えば、main.tf)に貼り付けます。以下のコマンドを実行して、Terraformの計画と適用を行います。

Terraformの初期化

terraform init

Terraformの初期化を行い、必要なプラグインをダウンロードします。

プランの確認

$ terraform plan

terraform planコマンドは、現在の設定に基づいてTerraformが実行するアクションを表示します。AWSリソースを作成、変更、削除する前に、どのような変更が行われるかを確認することができます。これにより、予期しない変更が行われないように確認することができます。

適用

$ terraform apply

terraform applyコマンドは、terraform planで確認した変更を実際に適用し、AWSリソースを作成、変更、削除します。設定した通りにリソースがプロビジョニングされ、AWSに展開されます。

ステップ7: SGの確認

方法1:マネジメントコンソール上で確認
方法2:AWS CLIを利用して確認

aws ec2 describe-security-groups --filters Name=group-name,Values=allow_my_ip

まとめ

HTTPプロバイダーを使用して自分のIPアドレスを取得し、ローカル変数に設定してからそのIPアドレスをTerraformの設定に組み込む方法を紹介しました。また、VPCの設定を行い、そのVPCにセキュリティグループを関連付ける手順も説明しました。これにより、動的に自分のIPアドレスを取得し、セキュリティグループなどで活用することができます。プロバイダーは他にもたくさんあるので、活用できるようにしていきたいです。

Discussion